sijms/go-ora

All data types are cast to string when query results are parsed

cat1s-smile opened this issue · 5 comments

Hello! I'm using go_ora and facing the issue when all query results are represented as string (with both go_ora and database/sql interfaces)
The problem appears in 2.8.11, but in 2.8.7 everything works fine

My code:

url := go_ora.BuildUrl("localhost", 1521, "oradb12345", "system", "oradb", make(map[string]string))
conn, _ := go_ora.NewConnection(url)
conn.Open()
query := "SELECT NULL as a, TO_NUMBER('1234567890123456789') as b, 'asdasd' as c, JSON('{\"name\":\"Beda\"}') as d FROM dual"
r, err := conn.QueryContext(context.Background(), query, []driver.NamedValue{})
dst := make([]driver.Value, len(r.Columns()))
r.Next(dst)

2.8.7:
image
2.8.11:
image

Also in 2.8.7 (in 2.8.11 JSON is broken) I got JSON as []uint8
In debug mode I can see that go_ora detects its type as OCIBlobLocator and sets isJson=false (because uds_flags=1024)
For json column, is there some kind of query which go_ora will unmarshal as map[string]any or []map[string]any (for json array) ?
My service gets sql query from from user, so it's impossible to determine if it should unmarshal some result or not

Hi @cat1s-smile
json and LONG issue is fixed in v2.8.13 you can check
using string to represent numbers is discussed at #533

Thank you for answering
But for JSON select queries (introduced in Oracle 21) the problem still exists
(I can see that insert discussed in #540 )
2 ways to reproduce:

SELECT NULL as a, TO_NUMBER('1234567890123456789') as b, 'asdasd' as c, JSON('{\"name\":\"Beda\"}') as d FROM dual

This query causes ORA-40569: Unimplemented JSON feature.
Also when I try to select it from table:

CREATE TABLE mytable (
    id NUMBER PRIMARY KEY,
    data JSON
)
tablespace USERS;

INSERT INTO mytable (id, data)
VALUES (1, '{"name": "John", "age": 30}');

SELECT id, data
FROM mytable;

I get 0 rows (EOF in error message)

to explain the code:
client version is lower than 21 (which is the version that support pure json type). before 21 json is a special type of BLOB
so server will downgrade its version to client version.
I get the implementation of IsJson from python driver = uds_flags & 0x100
now I see the server sending uds_flags = 0x400 so to solve the issue I will use both uds_flags & 0x500
after make this change both code (you describe above) run without errors.

I push a new commit contain this change to test

Thanks, this fix works
But is there a way to automatically unmarshal json to map[string]any / []map[string]any on go-ora side?
I see in parameter.go that it has JSON TNSType = 119
But I get json columns as OCIBlobLocator (TNSType = 113)
In debug I can see that now isJson = true, but this info inaccessible in sql.ColumnType

yes I take definition for json data type from python driver but to use it I should upgrade client version to be >= 21 which is a big deal