Closed mihaitodor closed 1 year ago
to solve the problem I will implement methods MarshalJSON and UnmarshalJSON
I add new release that solve the problem I add json support for the following types: TimeStamp, NullTimeStamp, NvarChar, NullNVarchar, Clob, NClob, Blob
Hey @sijms, thank you so much for the quick fix! That approach works for me.
Unfortunately, I think something went wrong when you pushed v2.5.21 and, while the git repo looks correct, the code for this version that got cached on https://proxy.golang.org/ doesn't contain the new MarshalJSON
and UnmarshalJSON
methods. My best guess is that the tag was overwritten somehow after it was first pushed to GitHub, but tags are immutable on this proxy, so go get
won't fetch the updated code, since it doesn't use GitHub directly as the source of truth. Would you mind bumping the version again? I think that will fix it.
@sijms not sure if you saw my note above, but have a look on https://pkg.go.dev/github.com/sijms/go-ora/v2@v2.5.21. The new JSON methods aren't available in the v2.5.21 tag that go fetches through its proxy. I think a new tag has to be released for this stuff to work...
I have the same problem. v2.5.21 seems not to fix this.
The issue has been resolved in v2.5.22. Thanks @sijms!
I add new release that solve the problem I add json support for the following types: TimeStamp, NullTimeStamp, NvarChar, NullNVarchar, Clob, NClob, Blob
While this fixes specific support for encoding/json, is there any reason for not returning the native types as documented by sql.Scanner? Otherwise this would still cause issues with any other package that expects drivers to conform to what database/sql expects (and may even break in future versions of Go if the database/sql interfaces start to rely on the documented functionality from drivers)
I agree with nvx. This is still an issue.
Is there a plan to conform to the database/sql
package interface?
could you please specify which interface is not support?
hi @sijms. refer to the doc link @mihaitodor provided in the original post. It provides the list of expected return types to the Scan
function. As of now, Scan
returns custom type TimeStamp
instead of time.Time
.
Caveat: I haven't studied Go SQL drivers in detail, so not sure if it's common for people to obey the docs of that Scanner
interface and what problems they're trying to address when returning custom types like TimeStamp
here. Didn't mean for my issue report to sound authoritative.
As background, I was looking to make a transition from godror/godror
to go-ora/v2
but ran into the custom type TimeStamp
issue. Older versions of godror/godror
used to support the Scan interface
types outlined in the docs, however the latest version deviates from this as well. I'm not sure if this is a "miss" in newer development, or if the approach has changed.
if you talk about Scanner.Scan its definition as follow
Scan(src any) error
so it will return error
if you talk about Rows.Scan it should return one of the following
*string
*[]byte
*int, *int8, *int16, *int32, *int64
*uint, *uint8, *uint16, *uint32, *uint64
*bool
*float32, *float64
*interface{}
*RawBytes
*Rows (cursor value)
any type implementing Scanner (see Scanner docs)
and TimeStamp
implement Scanner interface
if you talk about Scanner.Scan its definition as follow
Scan(src any) error
so it will return error
if you talk about Rows.Scan it should return one of the following
*string *[]byte *int, *int8, *int16, *int32, *int64 *uint, *uint8, *uint16, *uint32, *uint64 *bool *float32, *float64 *interface{} *RawBytes *Rows (cursor value) any type implementing Scanner (see Scanner docs)
and
TimeStamp
implement Scanner interface
The problem is the docs say stuff like this:
If an argument has type *interface{}, Scan copies the value provided by the underlying driver without conversion. When scanning from a source value of type []byte to *interface{}, a copy of the slice is made and the caller owns the result.
Source values of type time.Time may be scanned into values of type *time.Time, *interface{}, *string, or *[]byte. When converting to the latter two, time.RFC3339Nano is used.
Which read together makes it sounds like if you scan a timestamp out of a database into any or interface{} that you'd expect it to be set to a time.Time. This is the sort of assumption packages like github.com/joho/sqltocsv
make.
In theory you could implement every interface the out of the box types do, but it still means that code would have to then explicitly depend on go-ora if it needs to eg handle timestamps specially.
I can't think of anything preventing the use of the basic Go types when scanning to any/interface{} pointers.
now I get your point you mean when the receiver is of type *interface{} I should return regular types. I will add it and update release
I fix it in v2.5.28
According to the docs of the
Scanner
interface in thedatabase/sql
package:However, this code assigns a
TimeStamp
to the underlying value. Unfortunately, this seems to be incompatible with packages such asencoding/json
. Here's a self-contained example (I omitted all the error handling to keep it simple):which outputs
{"TS":{}}
.However, if I try the same code using
github.com/godror/godror
like so:I get
{"TS":"2022-12-24T13:43:39.423782Z"}
because this code usestime.Time
as the underlying type.Note: I used
DYLD_LIBRARY_PATH=./instantclient_19_8
which I downloaded from here.I'm just speculating now, since I only have superficial knowledge of how various Golang database drivers are implemented, but maybe go-ora needs to do some extra conversions in
DataSet.Next()
, just like godror does inrows.Next
.I guess I can work around this by adding some go-ora custom type assertions when constructing
jObj
, but that's very inconvenient...PS: Thank you for writing and maintaining this amazing package! ❤️