diff --git a/go/test/endtoend/vtgate/queries/dml/insert_test.go b/go/test/endtoend/vtgate/queries/dml/insert_test.go index 9e89f4f5f3e..fc12d633316 100644 --- a/go/test/endtoend/vtgate/queries/dml/insert_test.go +++ b/go/test/endtoend/vtgate/queries/dml/insert_test.go @@ -491,3 +491,26 @@ func TestInsertAlias(t *testing.T) { // this validates the record. mcmp.Exec("select id, region_id, name from user_tbl order by id") } + +// TestInsertJson test insert of json data. +func TestInsertJson(t *testing.T) { + mcmp, closer := start(t) + defer closer() + + // simple insert + mcmp.Exec(`insert into j_tbl(id, jdoc) values (1, '{}'), (2, '{"a": 1, "b": 2}')`) + mcmp.Exec(`select * from j_tbl order by id`) + + // insert select sharded + mcmp.Exec(`insert into j_tbl(id, jdoc) select id * 10, jdoc from j_tbl`) + mcmp.Exec(`select * from j_tbl order by id`) + + // insert select dual + mcmp.Exec(`insert into j_tbl(id, jdoc) select 3, json_object("k", "a")`) + mcmp.Exec(`select * from j_tbl order by id`) + + // insert unsharded select sharded + utils.Exec(t, mcmp.VtConn, `insert into uks.j_utbl(id, jdoc) select * from sks.j_tbl`) + utils.AssertMatches(t, mcmp.VtConn, `select * from uks.j_utbl order by id`, + `[[INT64(1) JSON("{}")] [INT64(2) JSON("{\"a\": 1, \"b\": 2}")] [INT64(3) JSON("{\"k\": \"a\"}")] [INT64(10) JSON("{}")] [INT64(20) JSON("{\"a\": 1, \"b\": 2}")]]`) +} diff --git a/go/test/endtoend/vtgate/queries/dml/main_test.go b/go/test/endtoend/vtgate/queries/dml/main_test.go index c00e27fe3a0..0c4d58aa614 100644 --- a/go/test/endtoend/vtgate/queries/dml/main_test.go +++ b/go/test/endtoend/vtgate/queries/dml/main_test.go @@ -133,7 +133,7 @@ func start(t *testing.T) (utils.MySQLCompare, func()) { tables := []string{ "s_tbl", "num_vdx_tbl", "user_tbl", "order_tbl", "oevent_tbl", "oextra_tbl", - "auto_tbl", "oid_vdx_tbl", "unq_idx", "nonunq_idx", "u_tbl", "mixed_tbl", "lkp_map_idx", + "auto_tbl", "oid_vdx_tbl", "unq_idx", "nonunq_idx", "u_tbl", "mixed_tbl", "lkp_map_idx", "j_tbl", "j_utbl", } for _, table := range tables { // TODO (@frouioui): following assertions produce different results between MySQL and Vitess diff --git a/go/test/endtoend/vtgate/queries/dml/sharded_schema.sql b/go/test/endtoend/vtgate/queries/dml/sharded_schema.sql index 8ddf9250e45..cd129bd779a 100644 --- a/go/test/endtoend/vtgate/queries/dml/sharded_schema.sql +++ b/go/test/endtoend/vtgate/queries/dml/sharded_schema.sql @@ -87,3 +87,10 @@ create table lkp_mixed_idx keyspace_id varbinary(20), primary key (lkp_key) ) Engine = InnoDB; + +create table j_tbl +( + id bigint, + jdoc json, + primary key (id) +) Engine = InnoDB; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/dml/unsharded_schema.sql b/go/test/endtoend/vtgate/queries/dml/unsharded_schema.sql index 4d2ad06618a..cd64605ad20 100644 --- a/go/test/endtoend/vtgate/queries/dml/unsharded_schema.sql +++ b/go/test/endtoend/vtgate/queries/dml/unsharded_schema.sql @@ -34,4 +34,11 @@ values (0, 1, 1000); insert into auto_seq(id, next_id, cache) values (0, 666, 1000); insert into mixed_seq(id, next_id, cache) -values (0, 1, 1000); \ No newline at end of file +values (0, 1, 1000); + +create table j_utbl +( + id bigint, + jdoc json, + primary key (id) +) Engine = InnoDB; \ No newline at end of file diff --git a/go/test/endtoend/vtgate/queries/dml/vschema.json b/go/test/endtoend/vtgate/queries/dml/vschema.json index a42a93d7403..72a949a49e4 100644 --- a/go/test/endtoend/vtgate/queries/dml/vschema.json +++ b/go/test/endtoend/vtgate/queries/dml/vschema.json @@ -188,6 +188,14 @@ "name": "hash" } ] + }, + "j_tbl": { + "column_vindexes": [ + { + "column": "id", + "name": "hash" + } + ] } } } \ No newline at end of file diff --git a/go/vt/sqlparser/normalizer_test.go b/go/vt/sqlparser/normalizer_test.go index c574b00832d..60bc3f793e7 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -230,6 +230,23 @@ func TestNormalize(t *testing.T) { outbv: map[string]*querypb.BindVariable{ "v1": sqltypes.BitNumBindVariable([]byte("0b11")), }, + }, { + // json value in insert + in: "insert into t values ('{\"k\", \"v\"}')", + outstmt: "insert into t values (:bv1 /* VARCHAR */)", + outbv: map[string]*querypb.BindVariable{ + "bv1": sqltypes.StringBindVariable("{\"k\", \"v\"}"), + }, + }, { + // json function in insert + in: "insert into t values (JSON_OBJECT('_id', 27, 'name', 'carrot'))", + outstmt: "insert into t values (json_object(:bv1 /* VARCHAR */, :bv2 /* INT64 */, :bv3 /* VARCHAR */, :bv4 /* VARCHAR */))", + outbv: map[string]*querypb.BindVariable{ + "bv1": sqltypes.StringBindVariable("_id"), + "bv2": sqltypes.Int64BindVariable(27), + "bv3": sqltypes.StringBindVariable("name"), + "bv4": sqltypes.StringBindVariable("carrot"), + }, }, { // ORDER BY column_position in: "select a, b from t order by 1 asc", diff --git a/go/vt/vtgate/engine/insert_select.go b/go/vt/vtgate/engine/insert_select.go index 88767420508..cae9dbebc9b 100644 --- a/go/vt/vtgate/engine/insert_select.go +++ b/go/vt/vtgate/engine/insert_select.go @@ -167,7 +167,11 @@ func (ins *InsertSelect) getInsertUnshardedQuery(rows []sqltypes.Row, bindVars m row := sqlparser.ValTuple{} for c, value := range inputRow { bvName := insertVarOffset(r, c) - bindVars[bvName] = sqltypes.ValueBindVariable(value) + if value.Type() == querypb.Type_JSON { + bindVars[bvName] = sqltypes.StringBindVariable(value.RawStr()) + } else { + bindVars[bvName] = sqltypes.ValueBindVariable(value) + } row = append(row, sqlparser.NewArgument(bvName)) } mids = append(mids, row) @@ -264,7 +268,11 @@ func (ins *InsertSelect) getInsertShardedQueries( row := sqlparser.ValTuple{} for colOffset, value := range rows[index] { bvName := insertVarOffset(index, colOffset) - bvs[bvName] = sqltypes.ValueBindVariable(value) + if value.Type() == querypb.Type_JSON { + bvs[bvName] = sqltypes.StringBindVariable(value.RawStr()) + } else { + bvs[bvName] = sqltypes.ValueBindVariable(value) + } row = append(row, sqlparser.NewArgument(bvName)) } mids = append(mids, row)