github.com/dolthub/go-mysql-server@v0.18.0/enginetest/queries/json_table_queries.go (about)

     1  // Copyright 2022 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package queries
    16  
    17  import (
    18  	"github.com/dolthub/go-mysql-server/sql"
    19  	"github.com/dolthub/go-mysql-server/sql/types"
    20  )
    21  
    22  var JSONTableQueryTests = []QueryTest{
    23  	{
    24  		Query:    "SELECT * FROM JSON_TABLE(NULL,'$[*]' COLUMNS(x int path '$.a')) as t;",
    25  		Expected: []sql.Row{},
    26  	},
    27  	{
    28  		Query:    "SELECT * FROM JSON_TABLE('{}','$[*]' COLUMNS(x int path '$.a')) as t;",
    29  		Expected: []sql.Row{},
    30  	},
    31  	{
    32  		Query:    "SELECT * FROM JSON_TABLE('{\"a\":1}','$.b' COLUMNS(x varchar(100) path '$.a')) as tt;",
    33  		Expected: []sql.Row{},
    34  	},
    35  	{
    36  		Query: "SELECT * FROM JSON_TABLE('[{\"a\":1},{\"a\":2}]','$[*]' COLUMNS(x varchar(100) path '$.a')) as tt;",
    37  		Expected: []sql.Row{
    38  			{"1"},
    39  			{"2"},
    40  		},
    41  	},
    42  	{
    43  		Query: "SELECT * FROM JSON_TABLE('[{\"a\":1, \"b\":2},{\"a\":3, \"b\":4}]',\"$[*]\" COLUMNS(x int path '$.a', y int path '$.b')) as tt;",
    44  		Expected: []sql.Row{
    45  			{1, 2},
    46  			{3, 4},
    47  		},
    48  	},
    49  	{
    50  		Query: "SELECT * FROM JSON_TABLE('[{\"a\":1.5, \"b\":2.25},{\"a\":3.125, \"b\":4.0625}]','$[*]' COLUMNS(x float path '$.a', y float path '$.b')) as tt;",
    51  		Expected: []sql.Row{
    52  			{1.5, 2.25},
    53  			{3.125, 4.0625},
    54  		},
    55  	},
    56  	{
    57  		Query: "SELECT * FROM JSON_TABLE(concat('[{},','{}]'),'$[*]' COLUMNS(x varchar(100) path '$.a',y varchar(100) path '$.b')) as t;",
    58  		Expected: []sql.Row{
    59  			{nil, nil},
    60  			{nil, nil},
    61  		},
    62  	},
    63  	{
    64  		Query: "select * from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t1 join JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t2;",
    65  		Expected: []sql.Row{
    66  			{1, 1},
    67  			{1, 2},
    68  			{2, 1},
    69  			{2, 2},
    70  		},
    71  	},
    72  	{
    73  		Query: "select * from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t1 join one_pk order by x, pk;",
    74  		Expected: []sql.Row{
    75  			{1, 0, 0, 1, 2, 3, 4},
    76  			{1, 1, 10, 11, 12, 13, 14},
    77  			{1, 2, 20, 21, 22, 23, 24},
    78  			{1, 3, 30, 31, 32, 33, 34},
    79  			{2, 0, 0, 1, 2, 3, 4},
    80  			{2, 1, 10, 11, 12, 13, 14},
    81  			{2, 2, 20, 21, 22, 23, 24},
    82  			{2, 3, 30, 31, 32, 33, 34},
    83  		},
    84  	},
    85  	{
    86  		Query: "select * from one_pk join JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t1 order by x, pk;",
    87  		Expected: []sql.Row{
    88  			{0, 0, 1, 2, 3, 4, 1},
    89  			{1, 10, 11, 12, 13, 14, 1},
    90  			{2, 20, 21, 22, 23, 24, 1},
    91  			{3, 30, 31, 32, 33, 34, 1},
    92  			{0, 0, 1, 2, 3, 4, 2},
    93  			{1, 10, 11, 12, 13, 14, 2},
    94  			{2, 20, 21, 22, 23, 24, 2},
    95  			{3, 30, 31, 32, 33, 34, 2},
    96  		},
    97  	},
    98  	{
    99  		Query: "select * from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t1 union select * from JSON_TABLE('[{\"b\":3},{\"b\":4}]', '$[*]' COLUMNS(y int path '$.b')) as t2",
   100  		Expected: []sql.Row{
   101  			{1},
   102  			{2},
   103  			{3},
   104  			{4},
   105  		},
   106  	},
   107  	{
   108  		Query: "select * from one_pk where pk in (select x from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t)",
   109  		Expected: []sql.Row{
   110  			{1, 10, 11, 12, 13, 14},
   111  			{2, 20, 21, 22, 23, 24},
   112  		},
   113  	},
   114  	{
   115  		Query: "select * from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) t1 where x in (select y from JSON_TABLE('[{\"b\":1},{\"b\":100}]', '$[*]' COLUMNS(y int path '$.b')) as t2)",
   116  		Expected: []sql.Row{
   117  			{1},
   118  		},
   119  	},
   120  	{
   121  		Query: "with c as (select jt.a from json_table('[{\"a\":1,\"b\":2,\"c\":3},{\"a\":4,\"b\":5,\"c\":6},{\"a\":7,\"b\":8,\"c\":9}]', '$[*]' columns (a int path '$.a')) as jt) select * from c",
   122  		Expected: []sql.Row{
   123  			{1},
   124  			{4},
   125  			{7},
   126  		},
   127  	},
   128  	{
   129  		Query: "select * from json_table('[{\"a\":1,\"b\":2,\"c\":3},{\"a\":4,\"b\":5,\"c\":6},{\"a\":7,\"b\":8,\"c\":9}]', '$[*]' columns (a int path '$.a')) as jt\nunion\nselect * from json_table('[{\"a\":1,\"b\":2,\"c\":3},{\"a\":4,\"b\":5,\"c\":6},{\"a\":7,\"b\":8,\"c\":9}]', '$[*]' columns (b int path '$.b')) as jt\nunion\nselect * from json_table('[{\"a\":1,\"b\":2,\"c\":3},{\"a\":4,\"b\":5,\"c\":6},{\"a\":7,\"b\":8,\"c\":9}]', '$[*]' columns (c int path '$.c')) as jt;",
   130  		Expected: []sql.Row{
   131  			{1},
   132  			{4},
   133  			{7},
   134  			{2},
   135  			{5},
   136  			{8},
   137  			{3},
   138  			{6},
   139  			{9},
   140  		},
   141  	},
   142  }
   143  
   144  var JSONTableScriptTests = []ScriptTest{
   145  	{
   146  		Name: "create table from json column",
   147  		SetUpScript: []string{
   148  			"create table organizations (organization varchar(10), members json)",
   149  			`insert into organizations values("orgA", '["bob", "john"]'), ("orgB", '["alice", "mary"]'), ('orgC', '["kevin", "john"]'), ('orgD', '["alice", "alice"]')`,
   150  			"create table t1(json_col json);",
   151  			"insert into t1 values ('{ \"people\": [{\"name\":\"John Smith\", \"address\":\"780 Mission St, San Francisco, CA 94103\"}, { \"name\":\"Sally Brown\", \"address\":\"75 37th Ave S, St Cloud, MN 94103\"}, { \"name\":\"John Johnson\", \"address\":\"1262 Roosevelt Trail, Raymond, ME 04071\"}]}')",
   152  		},
   153  		Assertions: []ScriptTestAssertion{
   154  			{
   155  				Query: "select names from organizations, JSON_TABLE(members, '$[*]' columns (names varchar(100) path '$')) as jt;",
   156  				Expected: []sql.Row{
   157  					{"bob"},
   158  					{"john"},
   159  					{"alice"},
   160  					{"mary"},
   161  					{"kevin"},
   162  					{"john"},
   163  					{"alice"},
   164  					{"alice"},
   165  				},
   166  			},
   167  			{
   168  				Query: "SELECT names, COUNT(names) AS count FROM organizations, JSON_TABLE(members, '$[*]' COLUMNS (names varchar(100) path '$')) AS jt GROUP BY names ORDER BY names asc;",
   169  				Expected: []sql.Row{
   170  					{"alice", 3},
   171  					{"bob", 1},
   172  					{"john", 2},
   173  					{"kevin", 1},
   174  					{"mary", 1},
   175  				},
   176  			},
   177  			{
   178  				// qualified json column name
   179  				Query: "select names from organizations, JSON_TABLE(organizations.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
   180  				Expected: []sql.Row{
   181  					{"bob"},
   182  					{"john"},
   183  					{"alice"},
   184  					{"mary"},
   185  					{"kevin"},
   186  					{"john"},
   187  					{"alice"},
   188  					{"alice"},
   189  				},
   190  			},
   191  			{
   192  				// aliased without as keyword
   193  				Query: "select names from organizations o, JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
   194  				Expected: []sql.Row{
   195  					{"bob"},
   196  					{"john"},
   197  					{"alice"},
   198  					{"mary"},
   199  					{"kevin"},
   200  					{"john"},
   201  					{"alice"},
   202  					{"alice"},
   203  				},
   204  			},
   205  			{
   206  				// aliased table name
   207  				Query: "SELECT jt.names, COUNT(jt.names) AS count FROM organizations AS o, JSON_TABLE(o.members, '$[*]' COLUMNS (names varchar(100) path '$')) AS jt GROUP BY jt.names ORDER BY jt.names asc;",
   208  				Expected: []sql.Row{
   209  					{"alice", 3},
   210  					{"bob", 1},
   211  					{"john", 2},
   212  					{"kevin", 1},
   213  					{"mary", 1},
   214  				},
   215  			},
   216  			{
   217  				// aliased and qualified select
   218  				Query: "select o.organization, jt.names from organizations o, JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
   219  				Expected: []sql.Row{
   220  					{"orgA", "bob"},
   221  					{"orgA", "john"},
   222  					{"orgB", "alice"},
   223  					{"orgB", "mary"},
   224  					{"orgC", "kevin"},
   225  					{"orgC", "john"},
   226  					{"orgD", "alice"},
   227  					{"orgD", "alice"},
   228  				},
   229  			},
   230  			{
   231  				Query: "SELECT people.* FROM t1, JSON_TABLE(t1.json_col, '$.people[*]' COLUMNS (name VARCHAR(40) PATH '$.name', address VARCHAR(100) PATH '$.address')) people;",
   232  				Expected: []sql.Row{
   233  					{"John Smith", "780 Mission St, San Francisco, CA 94103"},
   234  					{"Sally Brown", "75 37th Ave S, St Cloud, MN 94103"},
   235  					{"John Johnson", "1262 Roosevelt Trail, Raymond, ME 04071"},
   236  				},
   237  			},
   238  		},
   239  	},
   240  	{
   241  		Name: "test other join types",
   242  		SetUpScript: []string{
   243  			"create table organizations (organization varchar(10), members json)",
   244  			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
   245  			`create table p (i int primary key)`,
   246  			`insert into p values (1),(2),(3)`,
   247  		},
   248  		Assertions: []ScriptTestAssertion{
   249  			{
   250  				Query: "select o.organization, jt.names from organizations o CROSS JOIN JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
   251  				Expected: []sql.Row{
   252  					{"orgA", "bob"},
   253  					{"orgA", "john"},
   254  					{"orgB", "alice"},
   255  					{"orgB", "mary"},
   256  				},
   257  			},
   258  			{
   259  				Query: "select o.organization, jt.names from organizations o NATURAL JOIN JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
   260  				Expected: []sql.Row{
   261  					{"orgA", "bob"},
   262  					{"orgA", "john"},
   263  					{"orgB", "alice"},
   264  					{"orgB", "mary"},
   265  				},
   266  			},
   267  			{
   268  				Query: "select o.organization, jt.names from organizations o INNER JOIN JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt on o.organization = 'orgA';",
   269  				Expected: []sql.Row{
   270  					{"orgA", "bob"},
   271  					{"orgA", "john"},
   272  				},
   273  			},
   274  			{
   275  				Query: `select (select jt.i from p inner join JSON_TABLE('[1,2,3]', '$[*]' columns (i int path '$')) as jt where p.i >= jt.i LIMIT 1);`,
   276  				Expected: []sql.Row{
   277  					{1},
   278  				},
   279  			},
   280  			{
   281  				Query: `select * from p left join JSON_TABLE('[1,2,3]', '$[*]' columns (i int path '$')) as jt on p.i > jt.i;`,
   282  				Expected: []sql.Row{
   283  					{1, nil},
   284  					{2, 1},
   285  					{3, 1},
   286  					{3, 2},
   287  				},
   288  			},
   289  			{
   290  				Query: `select * from p right join JSON_TABLE('[1,2,3]', '$[*]' columns (i int path '$')) as jt on p.i > jt.i;`,
   291  				Expected: []sql.Row{
   292  					{2, 1},
   293  					{3, 1},
   294  					{3, 2},
   295  					{nil, 3},
   296  				},
   297  			},
   298  		},
   299  	},
   300  	{
   301  		Name: "json table in subquery references parent data",
   302  		SetUpScript: []string{
   303  			"create table t (i int, j json)",
   304  			`insert into t values (1, '["test"]')`,
   305  		},
   306  		Assertions: []ScriptTestAssertion{
   307  			{
   308  				Query: "select i, (select names from JSON_Table(t.j, '$[*]' columns (names varchar(100) path '$')) jt) from t;",
   309  				Expected: []sql.Row{
   310  					{1, "test"},
   311  				},
   312  			},
   313  			{
   314  				Query: "select (select jt.a from t, json_table('[\"abc\"]', '$[*]' columns (a varchar(10) path '$')) as jt)",
   315  				Expected: []sql.Row{
   316  					{"abc"},
   317  				},
   318  			},
   319  			{
   320  				Query: "select (select a from t, json_table(t.j, '$[*]' columns (a varchar(10) path '$')) as jt)",
   321  				Expected: []sql.Row{
   322  					{"test"},
   323  				},
   324  			},
   325  		},
   326  	},
   327  	{
   328  		Name: "json table in cte",
   329  		SetUpScript: []string{
   330  			`create table tbl (i int primary key, j json)`,
   331  			`insert into tbl values (0, '[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]')`,
   332  			`create table t (i int primary key)`,
   333  			`insert into t values (1), (2)`,
   334  		},
   335  		Assertions: []ScriptTestAssertion{
   336  			{
   337  				Query: "with c as (select jt.a from tbl, json_table(tbl.j, '$[*]' columns (a int path '$.a')) as jt) select * from c",
   338  				Expected: []sql.Row{
   339  					{1},
   340  					{4},
   341  					{7},
   342  				},
   343  			},
   344  			{
   345  				Query: "with tt as (select * from t) select * from tt, json_table('[{\"a\":3}]', '$[*]' columns (a int path '$.a')) as jt",
   346  				Expected: []sql.Row{
   347  					{1, 3},
   348  					{2, 3},
   349  				},
   350  			},
   351  		},
   352  	},
   353  	{
   354  		Name: "table union cross join with json table",
   355  		SetUpScript: []string{
   356  			"create table t (i int, j json)",
   357  			`insert into t values (1, '["test"]')`,
   358  		},
   359  		Assertions: []ScriptTestAssertion{
   360  			{
   361  				Query: "select t.j from t union select a from t, json_table(t.j, '$[*]' columns (a varchar(10) path '$')) as jt;",
   362  				Expected: []sql.Row{
   363  					{"[\"test\"]"},
   364  					{"test"},
   365  				},
   366  			},
   367  		},
   368  	},
   369  	{
   370  		Name: "join table, json_table, json_table",
   371  		SetUpScript: []string{
   372  			`create table tbl (i int primary key, j json)`,
   373  			`insert into tbl values (0, '[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]')`,
   374  		},
   375  		Query: "select j1.a, j2.b, j3.c from tbl, json_table(tbl.j, '$[*]' columns (a int path '$.a')) as j1, json_table(tbl.j, '$[*]' columns (b int path '$.b')) as j2, json_table(tbl.j, '$[*]' columns (c int path '$.c')) as j3;",
   376  		Expected: []sql.Row{
   377  			{1, 2, 3},
   378  			{1, 2, 6},
   379  			{1, 2, 9},
   380  			{1, 5, 3},
   381  			{1, 5, 6},
   382  			{1, 5, 9},
   383  			{1, 8, 3},
   384  			{1, 8, 6},
   385  			{1, 8, 9},
   386  			{4, 2, 3},
   387  			{4, 2, 6},
   388  			{4, 2, 9},
   389  			{4, 5, 3},
   390  			{4, 5, 6},
   391  			{4, 5, 9},
   392  			{4, 8, 3},
   393  			{4, 8, 6},
   394  			{4, 8, 9},
   395  			{7, 2, 3},
   396  			{7, 2, 6},
   397  			{7, 2, 9},
   398  			{7, 5, 3},
   399  			{7, 5, 6},
   400  			{7, 5, 9},
   401  			{7, 8, 3},
   402  			{7, 8, 6},
   403  			{7, 8, 9},
   404  		},
   405  	},
   406  	{
   407  		Name: "join table, table, json_table",
   408  		SetUpScript: []string{
   409  			`create table t1 (x int primary key)`,
   410  			`insert into t1 values (1), (2)`,
   411  			`create table t2 (y int primary key)`,
   412  			`insert into t2 values (3), (4)`,
   413  			`create table tbl (j json)`,
   414  			`insert into tbl values ('[{"a":5},{"a":6}]')`,
   415  		},
   416  		Query: "select t1.x, t2.y, jt.a from t1, t2, tbl, json_table(tbl.j, '$[*]' columns (a int path '$.a')) as jt",
   417  		Expected: []sql.Row{
   418  			{1, 3, 5},
   419  			{1, 3, 6},
   420  			{1, 4, 5},
   421  			{1, 4, 6},
   422  			{2, 3, 5},
   423  			{2, 3, 6},
   424  			{2, 4, 5},
   425  			{2, 4, 6},
   426  		},
   427  	},
   428  	{
   429  		Name: "join table, table, json_table two references past one node",
   430  		SetUpScript: []string{
   431  			`create table t1 (i int, x json)`,
   432  			`insert into t1 values (1, '[{"a":5},{"a":6}]')`,
   433  			`create table t2 (y int primary key)`,
   434  			`insert into t2 values (3), (4)`,
   435  			`create table tbl (j json)`,
   436  			`insert into tbl values ('[{"a":5},{"a":6}]')`,
   437  		},
   438  		Query: "select t1.i, t2.y, jt.a from t1, t2, tbl, json_table(t1.x, '$[*]' columns (a int path '$.a')) as jt",
   439  		Expected: []sql.Row{
   440  			{1, 3, 5},
   441  			{1, 3, 6},
   442  			{1, 4, 5},
   443  			{1, 4, 6},
   444  		},
   445  	},
   446  
   447  	// Error tests
   448  	{
   449  		Name: "non existent unqualified column",
   450  		SetUpScript: []string{
   451  			"create table t (i int, j json)",
   452  		},
   453  		Query:       "select j.a from t, json_table(k, '$[*]' columns (a INT path '$.a')) AS j",
   454  		ExpectedErr: sql.ErrColumnNotFound,
   455  	},
   456  	{
   457  		Name: "non existent qualified column",
   458  		SetUpScript: []string{
   459  			"create table t (i int, j json)",
   460  		},
   461  		Query:       "select t.a from t, json_table(t.k, '$[*]' columns (a INT path '$.a')) AS j",
   462  		ExpectedErr: sql.ErrTableColumnNotFound,
   463  	},
   464  	{
   465  		Name: "select from non existent json table column",
   466  		SetUpScript: []string{
   467  			"create table t (i int, j json)",
   468  		},
   469  		Query:       "select j.b from t, json_table(t.j, '$[*]' columns (a INT path '$.a')) AS j",
   470  		ExpectedErr: sql.ErrTableColumnNotFound,
   471  	},
   472  	{
   473  		Name: "subquery argument to json_table not allowed",
   474  		SetUpScript: []string{
   475  			"create table t (i int, j json)",
   476  			`insert into t values (1, '["test"]')`,
   477  		},
   478  		Query:       "select * from json_table((select j from t), '$[*]' columns (a varchar(10) path '$')) as jt;",
   479  		ExpectedErr: sql.ErrInvalidArgument,
   480  	},
   481  
   482  	{
   483  		Name:        "test FOR ORDINALITY",
   484  		SetUpScript: []string{},
   485  		Assertions: []ScriptTestAssertion{
   486  			{
   487  				Query: "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS( pk FOR ORDINALITY, c1 INT PATH '$.c1')) as jt;",
   488  				Expected: []sql.Row{
   489  					{1, nil},
   490  				},
   491  			},
   492  			{
   493  				Query:    "SELECT * FROM JSON_TABLE('{}', '$[*]' COLUMNS( pk FOR ORDINALITY, c1 INT PATH '$.c1')) as jt;",
   494  				Expected: []sql.Row{},
   495  			},
   496  			{
   497  				Query: "SELECT * FROM JSON_TABLE('[{\"c1\": 333}, {\"c1\": 222}, {\"c1\": 111}]', '$[*]' COLUMNS( pk FOR ORDINALITY, c1 INT PATH '$.c1')) as jt;",
   498  				Expected: []sql.Row{
   499  					{1, 333},
   500  					{2, 222},
   501  					{3, 111},
   502  				},
   503  			},
   504  			{
   505  				Query: "SELECT * FROM JSON_TABLE('[{\"c1\": 333}, {\"c1\": 222}, {\"c1\": 111}]', '$[*]' COLUMNS( pk1 FOR ORDINALITY, pk2 FOR ORDINALITY, c1 INT PATH '$.c1')) as jt;",
   506  				Expected: []sql.Row{
   507  					{1, 1, 333},
   508  					{2, 2, 222},
   509  					{3, 3, 111},
   510  				},
   511  			},
   512  		},
   513  	},
   514  	{
   515  		Name:        "test EXISTS",
   516  		SetUpScript: []string{},
   517  		Assertions: []ScriptTestAssertion{
   518  			{
   519  				Query: "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(c1 INT EXISTS PATH '$.c1')) as jt;",
   520  				Expected: []sql.Row{
   521  					{0},
   522  				},
   523  			},
   524  			{
   525  				Query: "SELECT * FROM JSON_TABLE('{\"c1\": 123}', '$' COLUMNS(c1 INT EXISTS PATH '$.c1')) as jt;",
   526  				Expected: []sql.Row{
   527  					{1},
   528  				},
   529  			},
   530  			{
   531  				Query: "SELECT * FROM JSON_TABLE('[{\"c1\": 333}, {\"c1\": 222}, {\"c1\": 111}, {\"notc1\": 123}]', '$[*]' COLUMNS(c1 INT EXISTS PATH '$.c1')) as jt;",
   532  				Expected: []sql.Row{
   533  					{1},
   534  					{1},
   535  					{1},
   536  					{0},
   537  				},
   538  			},
   539  			{
   540  				Query: "SELECT * FROM JSON_TABLE('[{\"a\": 333}, {\"b\": 222}, {\"a\": 111}, {\"b\": 123}]', '$[*]' COLUMNS(a INT EXISTS PATH '$.a', b INT EXISTS PATH '$.b')) as jt;",
   541  				Expected: []sql.Row{
   542  					{1, 0},
   543  					{0, 1},
   544  					{1, 0},
   545  					{0, 1},
   546  				},
   547  			},
   548  		},
   549  	},
   550  	{
   551  		Name:        "test DEFAULT ON ERROR",
   552  		SetUpScript: []string{},
   553  		Assertions: []ScriptTestAssertion{
   554  			{
   555  				Query: "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(c1 INT PATH '$.c1' DEFAULT '123' ON ERROR)) as jt;",
   556  				Expected: []sql.Row{
   557  					{nil},
   558  				},
   559  			},
   560  			{
   561  				Query: "SELECT * FROM JSON_TABLE('{\"c1\":\"abc\"}', '$' COLUMNS(c1 INT PATH '$.c1' DEFAULT '123' ON ERROR)) as jt;",
   562  				Expected: []sql.Row{
   563  					{123},
   564  				},
   565  			},
   566  			{
   567  				Query:          "SELECT * FROM JSON_TABLE('{\"c1\":\"abc\"}', '$' COLUMNS(c1 INT PATH '$.c1' DEFAULT 'def' ON ERROR)) as jt;",
   568  				ExpectedErrStr: "error: 'def' is not a valid value for 'int'",
   569  			},
   570  		},
   571  	},
   572  	{
   573  		Name:        "test DEFAULT ON EMPTY",
   574  		SetUpScript: []string{},
   575  		Assertions: []ScriptTestAssertion{
   576  			{
   577  				Query: "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(c1 INT PATH '$.c1' DEFAULT '123' ON EMPTY)) as jt;",
   578  				Expected: []sql.Row{
   579  					{123},
   580  				},
   581  			},
   582  			{
   583  				Query: "SELECT * FROM JSON_TABLE('{\"notc1\": \"321321\"}', '$' COLUMNS(c1 INT PATH '$.c1' DEFAULT '123' ON EMPTY)) as jt;",
   584  				Expected: []sql.Row{
   585  					{123},
   586  				},
   587  			},
   588  			{
   589  				// MySQL only supports string type for DEFAULT
   590  				Query: "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(c1 INT PATH '$.c1' DEFAULT 123 ON EMPTY)) as jt;",
   591  				Expected: []sql.Row{
   592  					{123},
   593  				},
   594  			},
   595  		},
   596  	},
   597  	{
   598  		Name:        "test ERROR ON ERROR",
   599  		SetUpScript: []string{},
   600  		Assertions: []ScriptTestAssertion{
   601  			{
   602  				Query: "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(c1 INT PATH '$.c1' ERROR ON ERROR)) as jt;",
   603  				Expected: []sql.Row{
   604  					{nil},
   605  				},
   606  			},
   607  			{
   608  				Query:          "SELECT * FROM JSON_TABLE('{\"c1\":\"abc\"}', '$' COLUMNS(c1 INT PATH '$.c1' ERROR ON ERROR)) as jt;",
   609  				ExpectedErrStr: "error: 'abc' is not a valid value for 'int'",
   610  			},
   611  		},
   612  	},
   613  	{
   614  		Name:        "test ERROR ON EMPTY",
   615  		SetUpScript: []string{},
   616  		Assertions: []ScriptTestAssertion{
   617  			{
   618  				Query:          "SELECT * FROM JSON_TABLE('{}', '$' COLUMNS(c1 INT PATH '$.c1' ERROR ON EMPTY)) as jt;",
   619  				ExpectedErrStr: "missing value for JSON_TABLE column 'c1'",
   620  			},
   621  			{
   622  				Query:          "SELECT * FROM JSON_TABLE('{\"notc1\": \"321321\"}', '$' COLUMNS(c1 INT PATH '$.c1' ERROR ON EMPTY)) as jt;",
   623  				ExpectedErrStr: "missing value for JSON_TABLE column 'c1'",
   624  			},
   625  		},
   626  	},
   627  	{
   628  		Name:        "test NESTED simple",
   629  		SetUpScript: []string{},
   630  		Assertions: []ScriptTestAssertion{
   631  			{
   632  				Query: "SELECT * FROM JSON_TABLE('[{\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}]', '$[*]' COLUMNS(a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$'))) AS jt;",
   633  				Expected: []sql.Row{
   634  					{1, 11},
   635  					{1, 111},
   636  					{2, 22},
   637  					{2, 222},
   638  				},
   639  			},
   640  			{
   641  				Query: "SELECT * FROM  JSON_TABLE('[{\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}]', '$[*]' COLUMNS( a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$', b2 INT PATH '$'))) AS jt;",
   642  				Expected: []sql.Row{
   643  					{1, 11, 11},
   644  					{1, 111, 111},
   645  					{2, 22, 22},
   646  					{2, 222, 222},
   647  				},
   648  			},
   649  			// TODO: the path '$.b' and `$.b[*]` are equivalent, but somehow MySQL can differentiate this from the above test
   650  			{
   651  				Query: "SELECT * FROM  JSON_TABLE('[{\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}]', '$[*]' COLUMNS( a INT PATH '$.a', NESTED PATH '$.b' COLUMNS (b1 INT PATH '$[0]', b2 INT PATH '$[1]'))) AS jt;",
   652  				Skip:  true,
   653  				Expected: []sql.Row{
   654  					{1, 11, 111},
   655  					{2, 22, 222},
   656  				},
   657  			},
   658  		},
   659  	},
   660  	{
   661  		Name:        "test NESTED siblings",
   662  		SetUpScript: []string{},
   663  		Assertions: []ScriptTestAssertion{
   664  			{
   665  				Query: "SELECT * FROM  JSON_TABLE('[{\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}]', '$[*]' COLUMNS( a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b1 INT PATH '$'), NESTED PATH '$.b[*]' COLUMNS (b2 INT PATH '$'), NESTED PATH '$.b[*]' COLUMNS (b3 INT PATH '$'))) AS jt;",
   666  				Expected: []sql.Row{
   667  					{1, 11, nil, nil},
   668  					{1, 111, nil, nil},
   669  					{1, nil, 11, nil},
   670  					{1, nil, 111, nil},
   671  					{1, nil, nil, 11},
   672  					{1, nil, nil, 111},
   673  					{2, 22, nil, nil},
   674  					{2, 222, nil, nil},
   675  					{2, nil, 22, nil},
   676  					{2, nil, 222, nil},
   677  					{2, nil, nil, 22},
   678  					{2, nil, nil, 222},
   679  				},
   680  			},
   681  		},
   682  	},
   683  	{
   684  		Name:        "test NESTED NESTED",
   685  		SetUpScript: []string{},
   686  		Assertions: []ScriptTestAssertion{
   687  			// TODO: double check the for ordinal column
   688  			{
   689  				Query: `
   690  SELECT *
   691  FROM
   692  JSON_TABLE(
   693      '{"a": [123, 456]}',
   694      '$.a[*]' COLUMNS(
   695          id1 FOR ORDINALITY,
   696          a1 INT PATH '$',
   697          b1 INT PATH '$',
   698          c1 INT PATH '$',
   699          NESTED PATH '$' COLUMNS (
   700              id2 FOR ORDINALITY,
   701              i1 INT PATH '$',
   702              j1 INT PATH '$',
   703              k1 INT PATH '$',
   704              NESTED PATH '$' COLUMNS (
   705                  id4 FOR ORDINALITY,
   706                  x1 INT PATH '$',
   707                  y1 INT PATH '$',
   708                  z1 INT PATH '$'
   709              ),
   710              NESTED PATH '$' COLUMNS (
   711                  id5 FOR ORDINALITY,
   712                  x2 INT PATH '$',
   713                  y2 INT PATH '$',
   714                  z2 INT PATH '$'
   715              )
   716          ),
   717          NESTED PATH '$' COLUMNS (
   718              id6 FOR ORDINALITY,
   719              i2 INT PATH '$',
   720              j2 INT PATH '$',
   721              k2 INT PATH '$',
   722              NESTED PATH '$' COLUMNS (
   723                  id7 FOR ORDINALITY,
   724                  x3 INT PATH '$',
   725                  y3 INT PATH '$',
   726                  z3 INT PATH '$'
   727              ),
   728              NESTED PATH '$' COLUMNS (
   729                  id8 FOR ORDINALITY,
   730                  x4 INT PATH '$',
   731                  y4 INT PATH '$',
   732                  z4 INT PATH '$'
   733              )
   734          )
   735      )
   736  ) as jt;
   737  `,
   738  				Expected: []sql.Row{
   739  					{1, 123, 123, 123, 1, 123, 123, 123, 1, 123, 123, 123, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
   740  					{1, 123, 123, 123, 1, 123, 123, 123, nil, nil, nil, nil, 1, 123, 123, 123, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
   741  					{1, 123, 123, 123, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 1, 123, 123, 123, 1, 123, 123, 123, nil, nil, nil, nil},
   742  					{1, 123, 123, 123, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 1, 123, 123, 123, nil, nil, nil, nil, 1, 123, 123, 123},
   743  					{2, 456, 456, 456, 1, 456, 456, 456, 1, 456, 456, 456, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
   744  					{2, 456, 456, 456, 1, 456, 456, 456, nil, nil, nil, nil, 1, 456, 456, 456, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
   745  					{2, 456, 456, 456, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 1, 456, 456, 456, 1, 456, 456, 456, nil, nil, nil, nil},
   746  					{2, 456, 456, 456, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 1, 456, 456, 456, nil, nil, nil, nil, 1, 456, 456, 456},
   747  				},
   748  			},
   749  		},
   750  	},
   751  	{
   752  		Name:        "test combinations of options",
   753  		SetUpScript: []string{},
   754  		Assertions: []ScriptTestAssertion{
   755  			{
   756  				// From MySQL docs
   757  				Query: "SELECT * FROM JSON_TABLE('[{\"a\":\"3\"},{\"a\":2},{\"b\":1},{\"a\":0},{\"a\":[1,2]}]', \"$[*]\" COLUMNS (rowid FOR ORDINALITY, ac VARCHAR(100) PATH \"$.a\" DEFAULT '111' ON EMPTY DEFAULT '999' ON ERROR, aj JSON PATH \"$.a\" DEFAULT '{\"x\": 333}' ON EMPTY, bx INT EXISTS PATH \"$.b\")) AS tt;",
   758  				Expected: []sql.Row{
   759  					{1, "3", types.MustJSON("3"), 0},
   760  					{2, "2", types.MustJSON("2"), 0},
   761  					{3, "111", types.MustJSON("{\"x\": 333}"), 1},
   762  					{4, "0", types.MustJSON("0"), 0},
   763  					{5, "999", types.MustJSON("[1, 2]"), 0},
   764  				},
   765  			},
   766  			{
   767  				Query: "SELECT * FROM JSON_TABLE('[{\"x\":2,\"y\":\"8\"},{\"x\":\"3\",\"y\":\"7\"},{\"x\":\"4\",\"y\":6}]', \"$[*]\" COLUMNS (xval VARCHAR(100) PATH \"$.x\", yval VARCHAR(100) PATH \"$.y\")) AS  jt1;",
   768  				Expected: []sql.Row{
   769  					{"2", "8"},
   770  					{"3", "7"},
   771  					{"4", "6"},
   772  				},
   773  			},
   774  			{
   775  				Query: "SELECT * FROM JSON_TABLE('[{\"x\":2,\"y\":\"8\"},{\"x\":\"3\",\"y\":\"7\"},{\"x\":\"4\",\"y\":6}]', \"$[1]\" COLUMNS (xval VARCHAR(100) PATH \"$.x\", yval VARCHAR(100) PATH \"$.y\")) AS  jt1;",
   776  				Expected: []sql.Row{
   777  					{"3", "7"},
   778  				},
   779  			},
   780  		},
   781  	},
   782  }
   783  
   784  var BrokenJSONTableScriptTests = []ScriptTest{
   785  	{
   786  		// wrong error
   787  		Name: "json_table out of cte",
   788  		SetUpScript: []string{
   789  			"create table t (i int, j json)",
   790  			`insert into t values (1, '["test"]')`,
   791  		},
   792  		Assertions: []ScriptTestAssertion{
   793  			{
   794  				Query:       "with tt as (select * from t) select * from json_table(tt.j, '$[*]' columns (a varchar(10) path '$')) as jt;",
   795  				ExpectedErr: sql.ErrUnknownTable,
   796  			},
   797  			{
   798  				Query:       "with tt as (select * from t) select * from tt, json_table(tt.j, '$[*]' columns (a varchar(10) path '$')) as jt;",
   799  				ExpectedErr: sql.ErrInvalidArgument,
   800  			},
   801  		},
   802  	},
   803  	{
   804  		// Unsupported functionality
   805  		Name:        "json_table out of cte",
   806  		SetUpScript: []string{},
   807  		Assertions: []ScriptTestAssertion{
   808  			{
   809  				Query: "SELECT * FROM JSON_TABLE('[ {\"c1\": null} ]', '$[*]' COLUMNS( c1 INT PATH '$.c1' ERROR ON ERROR )) as jt;",
   810  				Expected: []sql.Row{
   811  					{nil},
   812  				},
   813  			},
   814  			{
   815  				Query: "SELECT * FROM JSON_TABLE('[{\"a\":\"3\"},{\"a\":2},{\"b\":1},{\"a\":0},{\"a\":[1,2]}]', \"$[*]\" COLUMNS(rowid FOR ORDINALITY, ac VARCHAR(100) PATH \"$.a\" DEFAULT '111' ON EMPTY DEFAULT '999' ON ERROR, aj JSON PATH \"$.a\" DEFAULT '{\"x\": 333}' ON EMPTY, bx INT EXISTS PATH \"$.b\")) AS tt;",
   816  				Expected: []sql.Row{
   817  					{1, 3, "3", 0},
   818  					{2, 2, 2, 0},
   819  					{3, 111, types.MustJSON("{\"x\": 333}"), 1},
   820  					{4, 0, 0, 0},
   821  					{5, 999, types.MustJSON("[1, 2]"), 0},
   822  				},
   823  			},
   824  			{
   825  				Query: "SELECT * FROM JSON_TABLE('[ {\"a\": 1, \"b\": [11,111]}, {\"a\": 2, \"b\": [22,222]}, {\"a\":3}]', '$[*]' COLUMNS(a INT PATH '$.a', NESTED PATH '$.b[*]' COLUMNS (b INT PATH '$'))) AS jt WHERE b IS NOT NULL;",
   826  				Expected: []sql.Row{
   827  					{1, 11},
   828  					{1, 111},
   829  					{2, 22},
   830  					{2, 222},
   831  				},
   832  			},
   833  		},
   834  	},
   835  }