From 5e16eb66fc9b8dc55491062fa03fc9fe6cdd7aa8 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Tue, 20 Aug 2024 21:47:34 +0530 Subject: [PATCH 1/3] fix: json type in bind variable Signed-off-by: Harshit Gangal --- .../vtgate/queries/dml/insert_test.go | 22 +++++++++++++++++++ .../vtgate/queries/dml/sharded_schema.sql | 7 ++++++ .../vtgate/queries/dml/unsharded_schema.sql | 9 +++++++- .../endtoend/vtgate/queries/dml/vschema.json | 8 +++++++ go/vt/sqlparser/normalizer_test.go | 14 ++++++++++++ go/vt/vtgate/engine/insert_select.go | 12 ++++++++-- 6 files changed, 69 insertions(+), 3 deletions(-) diff --git a/go/test/endtoend/vtgate/queries/dml/insert_test.go b/go/test/endtoend/vtgate/queries/dml/insert_test.go index 9e89f4f5f3e..c36ef9c90ec 100644 --- a/go/test/endtoend/vtgate/queries/dml/insert_test.go +++ b/go/test/endtoend/vtgate/queries/dml/insert_test.go @@ -491,3 +491,25 @@ 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.Exec(t, mcmp.VtConn, `select * from uks.j_utbl order by id`) +} 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..8cda3f1a6b3 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -230,6 +230,20 @@ 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("{\"k\", \"v\"}"), + }, }, { // 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) From 98f9c22451711c5145aeb24bff87ab7cd645a58f Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 21 Aug 2024 10:28:24 +0530 Subject: [PATCH 2/3] test: fix test expectation Signed-off-by: Harshit Gangal --- go/vt/sqlparser/normalizer_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/go/vt/sqlparser/normalizer_test.go b/go/vt/sqlparser/normalizer_test.go index 8cda3f1a6b3..60bc3f793e7 100644 --- a/go/vt/sqlparser/normalizer_test.go +++ b/go/vt/sqlparser/normalizer_test.go @@ -242,7 +242,10 @@ func TestNormalize(t *testing.T) { 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("{\"k\", \"v\"}"), + "bv1": sqltypes.StringBindVariable("_id"), + "bv2": sqltypes.Int64BindVariable(27), + "bv3": sqltypes.StringBindVariable("name"), + "bv4": sqltypes.StringBindVariable("carrot"), }, }, { // ORDER BY column_position From 068a651e75b61b52708c25ee9db118945987f2d7 Mon Sep 17 00:00:00 2001 From: Harshit Gangal Date: Wed, 21 Aug 2024 10:41:21 +0530 Subject: [PATCH 3/3] test: add test expectation Signed-off-by: Harshit Gangal --- go/test/endtoend/vtgate/queries/dml/insert_test.go | 3 ++- go/test/endtoend/vtgate/queries/dml/main_test.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go/test/endtoend/vtgate/queries/dml/insert_test.go b/go/test/endtoend/vtgate/queries/dml/insert_test.go index c36ef9c90ec..fc12d633316 100644 --- a/go/test/endtoend/vtgate/queries/dml/insert_test.go +++ b/go/test/endtoend/vtgate/queries/dml/insert_test.go @@ -511,5 +511,6 @@ func TestInsertJson(t *testing.T) { // insert unsharded select sharded utils.Exec(t, mcmp.VtConn, `insert into uks.j_utbl(id, jdoc) select * from sks.j_tbl`) - utils.Exec(t, mcmp.VtConn, `select * from uks.j_utbl order by id`) + 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