Skip to content

Any way to support JSON values inserted using []byte rather than string #819

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dterei opened this issue Jun 13, 2018 · 8 comments
Closed

Comments

@dterei
Copy link

dterei commented Jun 13, 2018

Issue description

Golang uses []byte as the underlying type for JSON values. However, if you try to insert a value into MySQL for a JSON column using []byte and interpolateParams=true then it will fail with:

unable to upsert for t: Error 3144: Cannot create a
JSON value from a string with CHARACTER SET 'binary'

This appears to be becuase MySQL doesn't support inserting binary values into JSON columns, it wants an explicit character set to be specified (see bug).

While using string is a workaround of sorts, or disabling interpolateParams, hoping you may have better advice on how to solve this?

This problem causes issues when using ORM libraries like SQLBoiler that map a JSON field in a struct to []byte before invoking the SQL interface (see bug raised with SQLBoiler). SQLBoiler folks don't want to change their mapping from string to []byte for JSON just for MySQL.

Arguably the Go SQL interface should support JSON as a valid type rather than forcing it to be mapped to []byte or string, then go-sql-driver can decide on the mapping itself.

Configuration

Driver version (or git SHA): v1.4.0

Go version: 1.10.1

Server version: MySQL 5.7.21

Server OS: Arch Linux

@methane
Copy link
Member

methane commented Jun 13, 2018

This is limitation of MySQL text protocol. How about stop using interpolateParams?

@methane
Copy link
Member

methane commented Jun 13, 2018

BTW, can hex decimal literal be used for JSON?
#381

@dterei
Copy link
Author

dterei commented Jun 13, 2018

@methane I could stop using interpolateParams, just trying to understand the issue better and see if there is a solution that would allow me to keep it on.

@methane
Copy link
Member

methane commented Jun 13, 2018

I think best solution is using string type.
There are no other way to distinguish text and binary value from driver's side.

@dterei
Copy link
Author

dterei commented Jun 17, 2018

@methane One question, how much performance is gained or not with interpolateParams? Are we waiting for two RTT for each statement? Or are we using the X-protoocol and pipelining the PREPARE/EXECUTE so really not much difference?

@dterei
Copy link
Author

dterei commented Jun 17, 2018

OK, nvm, seems we aren't using XAPI, so forced into 2-RTT by the protocol.

@renthraysk
Copy link

Think this fudge works...

js, err := json.Marshal(&o)
...
_, err = db.ExecContext(context.Background(), "INSERT json(json) VALUES(CAST(CONVERT(? USING utf8) AS JSON))", js)

@methane
Copy link
Member

methane commented Jun 18, 2018

I don't know about SQLBoiler and I don't want to pay my time to learn it only for this issue.
But generally speaking, you can avoid interpolateParams selectively by using explicit
DB.Prepare() instead of DB.Exec() or DB.Query().

Additionally, you can skip 2-RTT by reusing explicitly prepared statement.

alexsn added a commit to alexsn/mysql that referenced this issue Feb 8, 2020
json encoded data is represented as bytes however it should be
interpolated as a string.

Signed-off-by: Alex Snast <[email protected]>
alexsn added a commit to alexsn/mysql that referenced this issue Feb 8, 2020
json encoded data is represented as bytes however it should be
interpolated as a string.

Signed-off-by: Alex Snast <[email protected]>
tz70s pushed a commit to tz70s/mysql that referenced this issue Sep 5, 2020
json encoded data is represented as bytes however it should be interpolated as a string

Fixes go-sql-driver#819
tz70s pushed a commit to tz70s/mysql that referenced this issue Sep 5, 2020
json encoded data is represented as bytes however it should be interpolated as a string

Fixes go-sql-driver#819
tdeebswihart added a commit to temporalio/temporal that referenced this issue Feb 16, 2024
You can't interpolate a []byte into a JSON field: go-sql-driver/mysql#819
tdeebswihart added a commit to temporalio/temporal that referenced this issue Feb 16, 2024
You can't interpolate a []byte into a JSON field: go-sql-driver/mysql#819
tdeebswihart added a commit to temporalio/temporal that referenced this issue Feb 20, 2024
You can't interpolate a []byte into a JSON field: go-sql-driver/mysql#819
tdeebswihart added a commit to temporalio/temporal that referenced this issue Feb 20, 2024
You can't interpolate a []byte into a JSON field: go-sql-driver/mysql#819
tdeebswihart added a commit to temporalio/temporal that referenced this issue Mar 6, 2024
You can't interpolate a []byte into a JSON field: go-sql-driver/mysql#819
tdeebswihart added a commit to temporalio/temporal that referenced this issue Mar 8, 2024
You can't interpolate a []byte into a JSON field: go-sql-driver/mysql#819
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants