Skip to content

fix MySQL JSON append args for MariaDB#4495

Open
errdefer wants to merge 1 commit intoent:masterfrom
errdefer:master
Open

fix MySQL JSON append args for MariaDB#4495
errdefer wants to merge 1 commit intoent:masterfrom
errdefer:master

Conversation

@errdefer
Copy link
Copy Markdown

Summary

Replace CAST(? AS JSON) with JSON_EXTRACT(?, '$') when appending marshaled JSON values in the MySQL sqljson dialect.

MariaDB treats JSON as an alias for LONGTEXT and does not support CAST(... AS JSON). As a result, sqljson.Append fails on MariaDB when appending non-primitive values such as objects, maps, structs, or arrays.

Using JSON_EXTRACT(?, '$') parses the argument as JSON and returns the root JSON value, preserving the intended append semantics for marshaled values while working on both MySQL and MariaDB.

Problem

Given a schema field that stores a slice of objects:

field.JSON("metadata", []map[string]string{}).
    Default([]map[string]string{}).
    StructTag(`json:"metadata"`)

Appending a non-primitive element on MariaDB:

_, err := client.Entity.UpdateOneID(id).
    AppendMetadata([]map[string]string{
        {
            "key":  "value",
            "time": time.Now().Format(time.RFC3339),
        },
    }).
    Save(ctx)

can generate an update containing CAST(? AS JSON) and fail with:

Error 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use near
'JSON)) END WHERE `id` = ?' at line 1

The failing SQL is generated by the MySQL sqljson dialect for non-primitive append arguments:

JSON_ARRAY_APPEND(`metadata`, '$', CAST(? AS JSON))

This works for MySQL, but not for MariaDB.

Fix

In dialect/sql/sqljson/dialect.go, update the non-primitive branch of (*mysql).appendArg to emit:

JSON_EXTRACT(?, '$')

instead of:

CAST(? AS JSON)

resulting in:

Before:

JSON_ARRAY_APPEND(`metadata`, '$', CAST(? AS JSON))

After:

JSON_ARRAY_APPEND(`metadata`, '$', JSON_EXTRACT(?, '$'))

Replace CAST(? AS JSON) with JSON_EXTRACT(?, '$') when appending marshaled JSON values in the MySQL sqljson dialect. MariaDB treats JSON as an alias for LONGTEXT and does not support CAST(... AS JSON), causing sqljson.Append on non-primitive values to fail with a syntax error. JSON_EXTRACT(?, '$') parses and returns the root JSON value, preserving the existing object/array append semantics while working on both MySQL and MariaDB.
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

Successfully merging this pull request may close these issues.

1 participant