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

     1  // Copyright 2023 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/plan"
    20  	"github.com/dolthub/go-mysql-server/sql/types"
    21  )
    22  
    23  var GeneratedColumnTests = []ScriptTest{
    24  	{
    25  		Name: "stored generated column",
    26  		SetUpScript: []string{
    27  			"create table t1 (a int primary key, b int as (a + 1) stored)",
    28  		},
    29  		Assertions: []ScriptTestAssertion{
    30  			{
    31  				Query: "show create table t1",
    32  				// TODO: double parens here is a bug
    33  				Expected: []sql.Row{{"t1",
    34  					"CREATE TABLE `t1` (\n" +
    35  						"  `a` int NOT NULL,\n" +
    36  						"  `b` int GENERATED ALWAYS AS ((`a` + 1)) STORED,\n" +
    37  						"  PRIMARY KEY (`a`)\n" +
    38  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
    39  			},
    40  			{
    41  				Query:       "insert into t1 values (1,2)",
    42  				ExpectedErr: sql.ErrGeneratedColumnValue,
    43  			},
    44  			{
    45  				Query:       "insert into t1(a,b) values (1,2)",
    46  				ExpectedErr: sql.ErrGeneratedColumnValue,
    47  			},
    48  			{
    49  				Query:    "select * from t1 order by a",
    50  				Expected: []sql.Row{},
    51  			},
    52  			{
    53  				Query:    "insert into t1(a) values (1), (2), (3)",
    54  				Expected: []sql.Row{{types.NewOkResult(3)}},
    55  			},
    56  			{
    57  				Query:    "select * from t1 order by a",
    58  				Expected: []sql.Row{{1, 2}, {2, 3}, {3, 4}},
    59  			},
    60  			{
    61  				Query:    "insert into t1(a,b) values (4, DEFAULT)",
    62  				Expected: []sql.Row{{types.NewOkResult(1)}},
    63  			},
    64  			{
    65  				Query:    "select * from t1 where b = 5 order by a",
    66  				Expected: []sql.Row{{4, 5}},
    67  			},
    68  			{
    69  				Query:       "update t1 set b = b + 1",
    70  				ExpectedErr: sql.ErrGeneratedColumnValue,
    71  			},
    72  			{
    73  				Query:    "update t1 set a = 10 where a = 1",
    74  				Expected: []sql.Row{{newUpdateResult(1, 1)}},
    75  			},
    76  			{
    77  				Query:    "select * from t1 order by a",
    78  				Expected: []sql.Row{{2, 3}, {3, 4}, {4, 5}, {10, 11}},
    79  			},
    80  			{
    81  				Query:    "delete from t1 where b = 11",
    82  				Expected: []sql.Row{{types.NewOkResult(1)}},
    83  			},
    84  			{
    85  				Query:    "select * from t1 order by a",
    86  				Expected: []sql.Row{{2, 3}, {3, 4}, {4, 5}},
    87  			},
    88  		},
    89  	},
    90  	{
    91  		Name: "index on stored generated column",
    92  		SetUpScript: []string{
    93  			"create table t1 (a int primary key, b int as (a + 1) stored)",
    94  		},
    95  		Assertions: []ScriptTestAssertion{
    96  			{
    97  				Query:    "create index i1 on t1(b)",
    98  				Expected: []sql.Row{{types.NewOkResult(0)}},
    99  			},
   100  			{
   101  				Query: "show create table t1",
   102  				Expected: []sql.Row{{"t1",
   103  					"CREATE TABLE `t1` (\n" +
   104  						"  `a` int NOT NULL,\n" +
   105  						"  `b` int GENERATED ALWAYS AS ((`a` + 1)) STORED,\n" +
   106  						"  PRIMARY KEY (`a`),\n" +
   107  						"  KEY `i1` (`b`)\n" +
   108  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   109  			},
   110  			{
   111  				Query:    "insert into t1(a) values (1), (2)",
   112  				Expected: []sql.Row{{types.NewOkResult(2)}},
   113  			},
   114  			{
   115  				Query:    "select * from t1 where b = 2 order by a",
   116  				Expected: []sql.Row{{1, 2}},
   117  			},
   118  			{
   119  				Query:    "select * from t1 order by a",
   120  				Expected: []sql.Row{{1, 2}, {2, 3}},
   121  			},
   122  			{
   123  				Query:    "select * from t1 order by b",
   124  				Expected: []sql.Row{{1, 2}, {2, 3}},
   125  			},
   126  			{
   127  				Query:    "update t1 set a = 10 where a = 1",
   128  				Expected: []sql.Row{{newUpdateResult(1, 1)}},
   129  			},
   130  			{
   131  				Query:    "select * from t1 where b = 11 order by a",
   132  				Expected: []sql.Row{{10, 11}},
   133  			},
   134  			{
   135  				Query:    "delete from t1 where b = 11",
   136  				Expected: []sql.Row{{types.NewOkResult(1)}},
   137  			},
   138  			{
   139  				Query:    "select * from t1 where b = 3 order by a",
   140  				Expected: []sql.Row{{2, 3}},
   141  			},
   142  		},
   143  	},
   144  	{
   145  		Name: "creating index on stored generated column",
   146  		SetUpScript: []string{
   147  			"create table t1 (a int primary key, b int as (a + 1) stored)",
   148  			"insert into t1(a) values (1), (2)",
   149  		},
   150  		Assertions: []ScriptTestAssertion{
   151  			{
   152  				Query:    "create index i1 on t1(b)",
   153  				Expected: []sql.Row{{types.NewOkResult(0)}},
   154  			},
   155  			{
   156  				Query: "show create table t1",
   157  				Expected: []sql.Row{{"t1",
   158  					"CREATE TABLE `t1` (\n" +
   159  						"  `a` int NOT NULL,\n" +
   160  						"  `b` int GENERATED ALWAYS AS ((`a` + 1)) STORED,\n" +
   161  						"  PRIMARY KEY (`a`),\n" +
   162  						"  KEY `i1` (`b`)\n" +
   163  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   164  			},
   165  			{
   166  				Query:    "select * from t1 where b = 2 order by a",
   167  				Expected: []sql.Row{{1, 2}},
   168  			},
   169  			{
   170  				Query:    "select * from t1 order by a",
   171  				Expected: []sql.Row{{1, 2}, {2, 3}},
   172  			},
   173  			{
   174  				Query:    "select * from t1 order by b",
   175  				Expected: []sql.Row{{1, 2}, {2, 3}},
   176  			},
   177  		},
   178  	},
   179  	{
   180  		Name: "index on stored generated column and one non-generated column",
   181  		SetUpScript: []string{
   182  			"create table t1 (a int primary key, b int as (a + 1) stored, c int)",
   183  		},
   184  		Assertions: []ScriptTestAssertion{
   185  			{
   186  				Query:    "create index i1 on t1(b,c)",
   187  				Expected: []sql.Row{{types.NewOkResult(0)}},
   188  			},
   189  			{
   190  				Query: "show create table t1",
   191  				Expected: []sql.Row{{"t1",
   192  					"CREATE TABLE `t1` (\n" +
   193  						"  `a` int NOT NULL,\n" +
   194  						"  `b` int GENERATED ALWAYS AS ((`a` + 1)) STORED,\n" +
   195  						"  `c` int,\n" +
   196  						"  PRIMARY KEY (`a`),\n" +
   197  						"  KEY `i1` (`b`,`c`)\n" +
   198  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   199  			},
   200  			{
   201  				Query:    "insert into t1(a,c) values (1,3)",
   202  				Expected: []sql.Row{{types.NewOkResult(1)}},
   203  			},
   204  			{
   205  				Query:    "select * from t1 where b = 2 and c = 3 order by a",
   206  				Expected: []sql.Row{{1, 2, 3}},
   207  			},
   208  			{
   209  				Query:    "insert into t1(a,c) values (2,4)",
   210  				Expected: []sql.Row{{types.NewOkResult(1)}},
   211  			},
   212  			{
   213  				Query:    "delete from t1 where b = 3 and c = 4",
   214  				Expected: []sql.Row{{types.NewOkResult(1)}},
   215  			},
   216  			{
   217  				Query:    "select * from t1 order by a",
   218  				Expected: []sql.Row{{1, 2, 3}},
   219  			},
   220  			{
   221  				Query:    "update t1 set a = 5, c = 10 where b = 2 and c = 3",
   222  				Expected: []sql.Row{{newUpdateResult(1, 1)}},
   223  			},
   224  			{
   225  				Query:    "select * from t1 where b = 6 and c = 10 order by a",
   226  				Expected: []sql.Row{{5, 6, 10}},
   227  			},
   228  			{
   229  				Query:    "select * from t1 order by a",
   230  				Expected: []sql.Row{{5, 6, 10}},
   231  			},
   232  		},
   233  	},
   234  	{
   235  		Name: "add new generated column",
   236  		SetUpScript: []string{
   237  			"create table t1 (a int primary key, b int)",
   238  			"insert into t1 values (1,2), (2,3), (3,4)",
   239  		},
   240  		Assertions: []ScriptTestAssertion{
   241  			{
   242  				Query:    "alter table t1 add column c int as (a + b) stored",
   243  				Expected: []sql.Row{{types.NewOkResult(0)}},
   244  			},
   245  			{
   246  				Query:    "select * from t1 order by a",
   247  				Expected: []sql.Row{{1, 2, 3}, {2, 3, 5}, {3, 4, 7}},
   248  			},
   249  			{
   250  				Query: "show create table t1",
   251  				Expected: []sql.Row{{"t1",
   252  					"CREATE TABLE `t1` (\n" +
   253  						"  `a` int NOT NULL,\n" +
   254  						"  `b` int,\n" +
   255  						"  `c` int GENERATED ALWAYS AS ((`a` + `b`)) STORED,\n" +
   256  						"  PRIMARY KEY (`a`)\n" +
   257  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   258  			},
   259  		},
   260  	},
   261  	{
   262  		Name: "stored generated column with spaces",
   263  		SetUpScript: []string{
   264  			"create table tt (`col 1` int, `col 2` int);",
   265  		},
   266  		Assertions: []ScriptTestAssertion{
   267  			{
   268  				Query: "create table t (`col 1` int, `col 2` int, `col 3` int generated always as (`col 1` + `col 2` + pow(`col 1`, `col 2`)) stored);",
   269  				Expected: []sql.Row{
   270  					{types.NewOkResult(0)},
   271  				},
   272  			},
   273  			{
   274  				Query: "show create table t",
   275  				Expected: []sql.Row{
   276  					{"t", "CREATE TABLE `t` (\n" +
   277  						"  `col 1` int,\n" +
   278  						"  `col 2` int,\n" +
   279  						"  `col 3` int GENERATED ALWAYS AS (((`col 1` + `col 2`) + power(`col 1`, `col 2`))) STORED\n" +
   280  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
   281  				},
   282  			},
   283  			{
   284  				Query: "insert into t (`col 1`, `col 2`) values (1, 2);",
   285  				Expected: []sql.Row{
   286  					{types.NewOkResult(1)},
   287  				},
   288  			},
   289  			{
   290  				Query: "select * from t",
   291  				Expected: []sql.Row{
   292  					{1, 2, 4},
   293  				},
   294  			},
   295  			{
   296  				Query: "alter table tt add column `col 3` int generated always as (`col 1` + `col 2` + pow(`col 1`, `col 2`)) stored;",
   297  				Expected: []sql.Row{
   298  					{types.NewOkResult(0)},
   299  				},
   300  			},
   301  			{
   302  				Query: "show create table tt",
   303  				Expected: []sql.Row{
   304  					{"tt", "CREATE TABLE `tt` (\n" +
   305  						"  `col 1` int,\n" +
   306  						"  `col 2` int,\n" +
   307  						"  `col 3` int GENERATED ALWAYS AS (((`col 1` + `col 2`) + power(`col 1`, `col 2`))) STORED\n" +
   308  						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
   309  				},
   310  			},
   311  			{
   312  				Query: "insert into tt (`col 1`, `col 2`) values (1, 2);",
   313  				Expected: []sql.Row{
   314  					{types.NewOkResult(1)},
   315  				},
   316  			},
   317  			{
   318  				Query: "select * from tt",
   319  				Expected: []sql.Row{
   320  					{1, 2, 4},
   321  				},
   322  			},
   323  		},
   324  	},
   325  	{
   326  		Name: "virtual column inserts, updates, deletes",
   327  		SetUpScript: []string{
   328  			"create table t1 (a int primary key, b int generated always as (a + 1) virtual)",
   329  		},
   330  		Assertions: []ScriptTestAssertion{
   331  			{
   332  				Query:    "insert into t1 (a) values (1), (2), (3)",
   333  				Expected: []sql.Row{{types.NewOkResult(3)}},
   334  			},
   335  			{
   336  				Query:    "select * from t1 order by a",
   337  				Expected: []sql.Row{{1, 2}, {2, 3}, {3, 4}},
   338  			},
   339  			{
   340  				Query: "update t1 set a = 4 where a = 3",
   341  				Expected: []sql.Row{{types.OkResult{
   342  					RowsAffected: 1,
   343  					Info: plan.UpdateInfo{
   344  						Matched: 1,
   345  						Updated: 1,
   346  					}},
   347  				}},
   348  			},
   349  			{
   350  				Query:    "select * from t1 order by a",
   351  				Expected: []sql.Row{{1, 2}, {2, 3}, {4, 5}},
   352  			},
   353  			{
   354  				Query:    "delete from t1 where a = 2",
   355  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
   356  			},
   357  			{
   358  				Query:    "select * from t1 order by a",
   359  				Expected: []sql.Row{{1, 2}, {4, 5}},
   360  			},
   361  			{
   362  				Query:       "update t1 set b = b + 1",
   363  				ExpectedErr: sql.ErrGeneratedColumnValue,
   364  			},
   365  		},
   366  	},
   367  	{
   368  		Name: "virtual column selects",
   369  		SetUpScript: []string{
   370  			"create table t1 (a int primary key, b int generated always as (a + 1) virtual)",
   371  			"create table t2 (c int primary key, d int generated always as (c - 1) virtual)",
   372  		},
   373  		Assertions: []ScriptTestAssertion{
   374  			{
   375  				Query:    "insert into t1 (a) values (1), (2), (3)",
   376  				Expected: []sql.Row{{types.NewOkResult(3)}},
   377  			},
   378  			{
   379  				Query:    "select * from t1 order by a",
   380  				Expected: []sql.Row{{1, 2}, {2, 3}, {3, 4}},
   381  			},
   382  			{
   383  				Query:    "insert into t2 (c) values (1), (2), (3)",
   384  				Expected: []sql.Row{{types.NewOkResult(3)}},
   385  			},
   386  			{
   387  				Query:    "select * from t2 order by c",
   388  				Expected: []sql.Row{{1, 0}, {2, 1}, {3, 2}},
   389  			},
   390  			{
   391  				Query:    "select * from t1 where b = 2 order by a",
   392  				Expected: []sql.Row{{1, 2}},
   393  			},
   394  			{
   395  				Query:    "select * from t2 where d = 2 order by c",
   396  				Expected: []sql.Row{{3, 2}},
   397  			},
   398  			{
   399  				Query:    "select sum(b) from t1 where b > 2",
   400  				Expected: []sql.Row{{7.0}},
   401  			},
   402  			{
   403  				Query:    "select sum(d) from t2 where d >= 1",
   404  				Expected: []sql.Row{{3.0}},
   405  			},
   406  			{
   407  				Query:    "select a, (select b from t1 t1a where t1a.a = t1.a+1) from t1 order by a",
   408  				Expected: []sql.Row{{1, 3}, {2, 4}, {3, nil}},
   409  			},
   410  			{
   411  				Query:    "select c, (select d from t2 t2a where t2a.c = t2.c+1) from t2 order by c",
   412  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, nil}},
   413  			},
   414  			{
   415  				Query:    "select * from t1 join t2 on a = c order by a",
   416  				Expected: []sql.Row{{1, 2, 1, 0}, {2, 3, 2, 1}, {3, 4, 3, 2}},
   417  			},
   418  			{
   419  				Query:    "select * from t1 join t2 on a = d order by a",
   420  				Expected: []sql.Row{{1, 2, 2, 1}, {2, 3, 3, 2}},
   421  			},
   422  			{
   423  				Query:    "select * from t1 join t2 on b = d order by a",
   424  				Expected: []sql.Row{{1, 2, 3, 2}},
   425  			},
   426  			{
   427  				Query:    "select * from t1 join (select * from t2) as t3 on b = d order by a",
   428  				Expected: []sql.Row{{1, 2, 3, 2}},
   429  			},
   430  		},
   431  	},
   432  	{
   433  		Name: "virtual column in triggers",
   434  		SetUpScript: []string{
   435  			"create table t1 (a int primary key, b int generated always as (a + 1) virtual)",
   436  			"create table t2 (c int primary key, d int generated always as (c - 1) virtual)",
   437  		},
   438  		Assertions: []ScriptTestAssertion{
   439  			{
   440  				Query:    "insert into t1 (a) values (1), (2), (3)",
   441  				Expected: []sql.Row{{types.NewOkResult(3)}},
   442  			},
   443  			{
   444  				Query:    "insert into t2 (c) values (1), (2), (3)",
   445  				Expected: []sql.Row{{types.NewOkResult(3)}},
   446  			},
   447  			{
   448  				Query:    "create trigger t1insert before insert on t1 for each row insert into t2 (c) values (new.b + 1)",
   449  				Expected: []sql.Row{{types.NewOkResult(0)}},
   450  			},
   451  			{
   452  				Query:    "insert into t1 (a) values (4), (5)",
   453  				Expected: []sql.Row{{types.NewOkResult(2)}},
   454  			},
   455  			{
   456  				Query:    "select * from t1 order by a",
   457  				Expected: []sql.Row{{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}},
   458  			},
   459  			{
   460  				Query:    "select * from t2 order by c",
   461  				Expected: []sql.Row{{1, 0}, {2, 1}, {3, 2}, {6, 5}, {7, 6}},
   462  			},
   463  		},
   464  	},
   465  	{
   466  		Name: "virtual column json extract",
   467  		SetUpScript: []string{
   468  			"create table t1 (a int primary key, j json, b int generated always as (j->>'$.b') virtual)",
   469  		},
   470  		Assertions: []ScriptTestAssertion{
   471  			{
   472  				Query:    `insert into t1 (a, j) values (1, '{"a": 1, "b": 2}'), (2, '{"a": 1}'), (3, '{"b": "300"}')`,
   473  				Expected: []sql.Row{{types.NewOkResult(3)}},
   474  			},
   475  			{
   476  				Query: "select * from t1 order by a",
   477  				Expected: []sql.Row{
   478  					{1, types.MustJSON(`{"a": 1, "b": 2}`), 2},
   479  					{2, types.MustJSON(`{"a": 1}`), nil},
   480  					{3, types.MustJSON(`{"b": "300"}`), 300}},
   481  			},
   482  		},
   483  	},
   484  	{
   485  		Name: "virtual column with function",
   486  		SetUpScript: []string{
   487  			"create table t1 (a varchar(255) primary key, b varchar(255), c varchar(512) generated always as (concat(a,b)) virtual)",
   488  		},
   489  		Assertions: []ScriptTestAssertion{
   490  			{
   491  				Query:    `insert into t1 (a, b) values ('abc', '123'), ('def', null), ('ghi', '')`,
   492  				Expected: []sql.Row{{types.NewOkResult(3)}},
   493  			},
   494  			{
   495  				Query: "select * from t1 order by a",
   496  				Expected: []sql.Row{
   497  					{"abc", "123", "abc123"},
   498  					{"def", nil, nil},
   499  					{"ghi", "", "ghi"},
   500  				},
   501  			},
   502  		},
   503  	},
   504  	{
   505  		Name: "physical columns added after virtual one",
   506  		SetUpScript: []string{
   507  			"create table t (pk int primary key, col1 int as (pk + 1));",
   508  			"insert into t (pk) values (1), (3)",
   509  			"alter table t add index idx1 (col1, pk);",
   510  			"alter table t add index idx2 (col1);",
   511  			"alter table t add column col2 int;",
   512  			"alter table t add column col3 int;",
   513  			"insert into t (pk, col2, col3) values (2, 4, 5);",
   514  		},
   515  		Assertions: []ScriptTestAssertion{
   516  			{
   517  				Query: "select * from t order by pk",
   518  				Expected: []sql.Row{
   519  					{1, 2, nil, nil},
   520  					{2, 3, 4, 5},
   521  					{3, 4, nil, nil},
   522  				},
   523  			},
   524  			{
   525  				Query: "select * from t where col1 = 2",
   526  				Expected: []sql.Row{
   527  					{1, 2, nil, nil},
   528  				},
   529  			},
   530  			{
   531  				Query: "select * from t where col1 = 3 and pk = 2",
   532  				Expected: []sql.Row{
   533  					{2, 3, 4, 5},
   534  				},
   535  			},
   536  			{
   537  				Query: "select * from t where pk = 2",
   538  				Expected: []sql.Row{
   539  					{2, 3, 4, 5},
   540  				},
   541  			},
   542  		},
   543  	},
   544  	{
   545  		Name: "virtual column ordering",
   546  		SetUpScript: []string{
   547  			// virtual is the default for generated columns
   548  			"create table t1 (v1 int generated always as (2), a int, v2 int generated always as (a + v1), c int)",
   549  		},
   550  		Assertions: []ScriptTestAssertion{
   551  			{
   552  				Query:    "insert into t1 (a, c) values (1,5), (3,7)",
   553  				Expected: []sql.Row{{types.NewOkResult(2)}},
   554  			},
   555  			{
   556  				Query:    "insert into t1 (c, a) values (5,6), (7,8)",
   557  				Expected: []sql.Row{{types.NewOkResult(2)}},
   558  			},
   559  			{
   560  				Query: "select * from t1 order by a",
   561  				Expected: []sql.Row{
   562  					{2, 1, 3, 5},
   563  					{2, 3, 5, 7},
   564  					{2, 6, 8, 5},
   565  					{2, 8, 10, 7},
   566  				},
   567  			},
   568  			{
   569  				Query: "update t1 set a = 4 where a = 3",
   570  				Expected: []sql.Row{{types.OkResult{
   571  					RowsAffected: 1,
   572  					Info: plan.UpdateInfo{
   573  						Matched: 1,
   574  						Updated: 1,
   575  					}},
   576  				}},
   577  			},
   578  			{
   579  				Query: "select * from t1 order by a",
   580  				Expected: []sql.Row{
   581  					{2, 1, 3, 5},
   582  					{2, 4, 6, 7},
   583  					{2, 6, 8, 5},
   584  					{2, 8, 10, 7},
   585  				},
   586  			},
   587  			{
   588  				Query:    "delete from t1 where v2 = 6",
   589  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
   590  			},
   591  			{
   592  				Query: "select * from t1 order by a",
   593  				Expected: []sql.Row{
   594  					{2, 1, 3, 5},
   595  					{2, 6, 8, 5},
   596  					{2, 8, 10, 7},
   597  				},
   598  			},
   599  		},
   600  	},
   601  	{
   602  		Name: "adding a virtual column",
   603  		SetUpScript: []string{
   604  			"create table t1 (a int primary key, b int)",
   605  		},
   606  		Assertions: []ScriptTestAssertion{
   607  			{
   608  				Query:    "insert into t1 (a, b) values (1, 2), (3, 4)",
   609  				Expected: []sql.Row{{types.NewOkResult(2)}},
   610  			},
   611  			{
   612  				Query:    "alter table t1 add column c int generated always as (a + b) virtual",
   613  				Expected: []sql.Row{{types.NewOkResult(0)}},
   614  			},
   615  			{
   616  				Query:    "select * from t1 order by a",
   617  				Expected: []sql.Row{{1, 2, 3}, {3, 4, 7}},
   618  			},
   619  		},
   620  	},
   621  	{
   622  		Name: "virtual column index",
   623  		SetUpScript: []string{
   624  			"create table t1 (a int primary key, b int, c int generated always as (a + b) virtual, index idx_c (c))",
   625  			"insert into t1 (a, b) values (1, 2), (3, 4)",
   626  		},
   627  		Assertions: []ScriptTestAssertion{
   628  			{
   629  				Query:    "select * from t1 where c = 7",
   630  				Expected: []sql.Row{{3, 4, 7}},
   631  			},
   632  			{
   633  				Query:    "select * from t1 where c = 8",
   634  				Expected: []sql.Row{},
   635  			},
   636  			{
   637  				Query:    "update t1 set b = 5 where c = 3",
   638  				Expected: []sql.Row{{newUpdateResult(1, 1)}},
   639  			},
   640  			{
   641  				Query: "select * from t1 order by a",
   642  				Expected: []sql.Row{
   643  					{1, 5, 6},
   644  					{3, 4, 7},
   645  				},
   646  			},
   647  			{
   648  				Query: "select * from t1 where c = 6",
   649  				Expected: []sql.Row{
   650  					{1, 5, 6},
   651  				},
   652  			},
   653  			{
   654  				Query:    "delete from t1 where c = 6",
   655  				Expected: []sql.Row{{types.NewOkResult(1)}},
   656  			},
   657  			{
   658  				Query: "select * from t1 order by a",
   659  				Expected: []sql.Row{
   660  					{3, 4, 7},
   661  				},
   662  			},
   663  		},
   664  	},
   665  	{
   666  		Name: "virtual column index on a keyless table",
   667  		SetUpScript: []string{
   668  			"create table t1 (j json, v int generated always as (j->>'$.a') virtual, index idx_v (v))",
   669  			"insert into t1(j) values ('{\"a\": 1}'), ('{\"a\": 2}'), ('{\"b\": 3}')",
   670  		},
   671  		Assertions: []ScriptTestAssertion{
   672  			{
   673  				Query:    "select * from t1 where v = 2",
   674  				Expected: []sql.Row{{"{\"a\": 2}", 2}},
   675  			},
   676  			{
   677  				Query:    "update t1 set j = '{\"a\": 5}' where v = 2",
   678  				Expected: []sql.Row{{newUpdateResult(1, 1)}},
   679  			},
   680  			{
   681  				Query: "select * from t1 order by v",
   682  				Expected: []sql.Row{
   683  					{"{\"b\": 3}", nil},
   684  					{"{\"a\": 1}", 1},
   685  					{"{\"a\": 5}", 5}},
   686  			},
   687  			{
   688  				Query:    "delete from t1 where v = 5",
   689  				Expected: []sql.Row{{types.NewOkResult(1)}},
   690  			},
   691  			{
   692  				Query: "select * from t1 order by v",
   693  				Expected: []sql.Row{
   694  					{"{\"b\": 3}", nil},
   695  					{"{\"a\": 1}", 1},
   696  				},
   697  			},
   698  		},
   699  	},
   700  	{
   701  		Name: "illegal table definitions",
   702  		SetUpScript: []string{
   703  			"create table t2 (a int generated always as (2), b int)",
   704  		},
   705  		Assertions: []ScriptTestAssertion{
   706  			{
   707  				Query:       "create table t1 (a int generated always as (2), b int, primary key (a))",
   708  				ExpectedErr: sql.ErrVirtualColumnPrimaryKey,
   709  			},
   710  			{
   711  				Query:       "create table t1 (a int generated always as (2), b int, primary key (a, b))",
   712  				ExpectedErr: sql.ErrVirtualColumnPrimaryKey,
   713  			},
   714  			{
   715  				Query:       "alter table t2 add primary key (a)",
   716  				ExpectedErr: sql.ErrVirtualColumnPrimaryKey,
   717  			},
   718  			{
   719  				Query:       "alter table t2 add primary key (a, b)",
   720  				ExpectedErr: sql.ErrVirtualColumnPrimaryKey,
   721  			},
   722  		},
   723  	},
   724  	{
   725  		Name: "generated columns in primary key",
   726  		SetUpScript: []string{
   727  			"create table t2 (a int, b int generated always as (a + 2) stored, primary key (b))",
   728  			"create table t3 (a int, b int generated always as (a + 2) stored, primary key (a, b))",
   729  		},
   730  		Assertions: []ScriptTestAssertion{
   731  			{
   732  				Query:    "insert into t2 (a) values (1), (2)",
   733  				Expected: []sql.Row{{types.NewOkResult(2)}},
   734  			},
   735  			{
   736  				Query: "select * from t2 order by a",
   737  				Expected: []sql.Row{
   738  					{1, 3},
   739  					{2, 4},
   740  				},
   741  			},
   742  			{
   743  				Query: "select * from t2 where b = 4",
   744  				Expected: []sql.Row{
   745  					{2, 4},
   746  				},
   747  			},
   748  			{
   749  				Query:    "insert into t3 (a) values (1), (2)",
   750  				Expected: []sql.Row{{types.NewOkResult(2)}},
   751  			},
   752  			{
   753  				Query: "select * from t3 order by a",
   754  				Expected: []sql.Row{
   755  					{1, 3},
   756  					{2, 4},
   757  				},
   758  			},
   759  			{
   760  				Query: "select * from t3 where a = 2 and b = 4",
   761  				Expected: []sql.Row{
   762  					{2, 4},
   763  				},
   764  			},
   765  		},
   766  	},
   767  }
   768  
   769  var BrokenGeneratedColumnTests = []ScriptTest{
   770  	{
   771  		Name: "update a virtual column with a trigger",
   772  		SetUpScript: []string{
   773  			"create table t1 (a int primary key, b int, c int generated always as (a + b) virtual)",
   774  			"create table t2 (a int primary key)",
   775  			"create trigger t1insert before update on t1 for each row set new.c = 2",
   776  		},
   777  		Assertions: []ScriptTestAssertion{
   778  			{
   779  				// Not sure if this should be an error at trigger creation time or execution time
   780  				Query:       "insert into t1 (a, b) values (1, 2), (3, 4)",
   781  				ExpectedErr: sql.ErrGeneratedColumnValue,
   782  			},
   783  		},
   784  	},
   785  }