queries

package
v0.14.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 21, 2023 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BlobErrors = []QueryErrorTest{
	{
		Query:       "alter table mytable modify s blob",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "alter table mytable modify s text",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "alter table blobt add index bidx (b)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "alter table blobt add index tidx (i, b)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "alter table blobt add index bidx (b(3073))",
		ExpectedErr: sql.ErrKeyTooLong,
	},
	{
		Query:       "alter table blobt add column b2 blob default '1'",
		ExpectedErr: sql.ErrInvalidTextBlobColumnDefault,
	},
	{
		Query:       "alter table textt add index tidx (t)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "alter table textt add index tidx (t(769))",
		ExpectedErr: sql.ErrKeyTooLong,
	},
	{
		Query:       "alter table textt add column t2 text default '1'",
		ExpectedErr: sql.ErrInvalidTextBlobColumnDefault,
	},
	{
		Query:       "alter table textt add index tidx (i, t)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table b (b blob primary key)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table b (b tinyblob primary key)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table t (t text primary key)",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table t (t text, primary key (t))",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table b (b blob, primary key (b))",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table b (b blob, primary key (b(3073)))",
		ExpectedErr: sql.ErrKeyTooLong,
	},
	{
		Query:       "create table t (t text, primary key (t(769)))",
		ExpectedErr: sql.ErrKeyTooLong,
	},
	{
		Query:       "create table b (i int primary key, b blob, index bidx(b))",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "create table b (i int primary key, b blob, index bidx(b(3073)))",
		ExpectedErr: sql.ErrKeyTooLong,
	},
	{
		Query:       "CREATE TABLE b (pk BIGINT PRIMARY KEY, v1 TEXT, INDEX (v1));",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
	{
		Query:       "CREATE TABLE b (pk BIGINT PRIMARY KEY, v1 TINYTEXT, INDEX (v1));",
		ExpectedErr: sql.ErrInvalidBlobTextKey,
	},
}
View Source
var BlobQueries = []QueryTest{
	{
		Query: "select i, hex(b) from blobt",
		Expected: []sql.Row{
			{1, "666972737420726F77"},
			{2, "7365636F6E6420726F77"},
			{3, "746869726420726F77"},
		},
	},
	{
		Query: "select * from blobt where i = 1",
		Expected: []sql.Row{
			{1, []byte("first row")},
		},
	},
	{
		Query: "select * from blobt order by b desc",
		Expected: []sql.Row{
			{3, []byte("third row")},
			{2, []byte("second row")},
			{1, []byte("first row")},
		},
	},
	{
		Query: "select * from blobt where b <= 'second row'",
		Expected: []sql.Row{
			{2, []byte("second row")},
			{1, []byte("first row")},
		},
	},
	{
		Query: "select i, hex(t) from textt",
		Expected: []sql.Row{
			{1, "666972737420726F77"},
			{2, "7365636F6E6420726F77"},
			{3, "746869726420726F77"},
		},
	},
	{
		Query: "select * from textt where i = 1",
		Expected: []sql.Row{
			{1, "first row"},
		},
	},
	{
		Query: "select * from textt order by t desc",
		Expected: []sql.Row{
			{3, "third row"},
			{2, "second row"},
			{1, "first row"},
		},
	},
	{
		Query: "select * from textt where t <= 'second row'",
		Expected: []sql.Row{
			{1, "first row"},
			{2, "second row"},
		},
	},
}
View Source
var BlobUnsupported = []QueryTest{
	{
		Query: "select convert(`b` using utf8) from blobt",
		Expected: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
		},
	},
}
View Source
var BlobWriteQueries = []WriteQueryTest{
	{
		WriteQuery:          "insert into blobt values (4, '100000000')",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "select * from blobt where i = 4",
		ExpectedSelect:      []sql.Row{{4, []byte("100000000")}},
	},
	{
		WriteQuery:          "update blobt set b = '100000000' where i = 1",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "select * from blobt where i = 1",
		ExpectedSelect:      []sql.Row{{1, []byte("100000000")}},
	},
	{
		WriteQuery:          "delete from blobt where i = 1",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "select * from blobt",
		ExpectedSelect: []sql.Row{
			{2, []byte("second row")},
			{3, []byte("third row")},
		},
	},
	{
		WriteQuery:          "alter table blobt rename column b to v, add v1 int",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "select * from blobt",
		ExpectedSelect: []sql.Row{
			{1, []byte("first row"), nil},
			{2, []byte("second row"), nil},
			{3, []byte("third row"), nil},
		},
	},
	{
		WriteQuery:          "ALTER TABLE blobt ADD COLUMN v2 BIGINT DEFAULT (i + 2) AFTER b",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "select * from blobt",
		ExpectedSelect: []sql.Row{
			{1, []byte("first row"), 3},
			{2, []byte("second row"), 4},
			{3, []byte("third row"), 5},
		},
	},
	{
		WriteQuery:          "insert into textt values (4, '100000000')",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "select * from textt where i = 4",
		ExpectedSelect:      []sql.Row{{4, "100000000"}},
	},
	{
		WriteQuery:          "update textt set t = '100000000' where i = 1",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "select * from textt where i = 1",
		ExpectedSelect:      []sql.Row{{1, "100000000"}},
	},
	{
		WriteQuery:          "delete from textt where i = 1",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "select * from textt",
		ExpectedSelect: []sql.Row{
			{2, "second row"},
			{3, "third row"},
		},
	},
	{
		WriteQuery:          "alter table textt rename column t to v, add v1 int",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "select * from textt",
		ExpectedSelect: []sql.Row{
			{1, "first row", nil},
			{2, "second row", nil},
			{3, "third row", nil},
		},
	},
	{
		WriteQuery:          "ALTER TABLE textt ADD COLUMN v2 BIGINT DEFAULT (i + 2) AFTER t",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "select * from textt",
		ExpectedSelect: []sql.Row{
			{1, "first row", 3},
			{2, "second row", 4},
			{3, "third row", 5},
		},
	},
}
View Source
var BrokenCreateTableQueries = []WriteQueryTest{
	{
		WriteQuery:          `create table t1 (b blob, primary key(b(1)))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `b` blob NOT NULL,\n  PRIMARY KEY (`b`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `create table t1 (b1 blob, b2 blob, primary key(b1(123), b2(456)))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `b1` blob NOT NULL,\n  `b2` blob NOT NULL,\n  PRIMARY KEY (`b1`(123),`b2`(456))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `create table t1 (i int, b1 blob, b2 blob, primary key(b1(123), b2(456), i))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `b1` blob NOT NULL,\n  `b2` blob NOT NULL,\n  PRIMARY KEY (`b1`(123),`b2`(456),`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
}
View Source
var BrokenErrorQueries = []QueryErrorTest{
	{
		Query:          "with a as (select * from c), b as (select * from a), c as (select * from b) select * from a",
		ExpectedErrStr: "table not found: c",
	},
	{
		Query:       "WITH Numbers AS ( SELECT n = 1 UNION ALL SELECT n + 1 FROM Numbers WHERE n+1 <= 10) SELECT n FROM Numbers;",
		ExpectedErr: sql.ErrTableNotFound,
	},
}
View Source
var BrokenJSONTableScriptTests = []ScriptTest{
	{

		Name: "json table in cross join in subquery",
		SetUpScript: []string{
			"create table t (j json)",
		},
		Query: "select (select jt.a from t, json_table('[\"abc\"]', '$[*]' columns (a varchar(10) path '$')) as jt)",
		Expected: []sql.Row{
			{"abc"},
		},
	},
	{

		Name: "json table in cross join in subquery with reference to left",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query: "select (select a from t, json_table(t.j, '$[*]' columns (a varchar(10) path '$')) as jt)",
		Expected: []sql.Row{
			{1},
		},
	},
	{

		Name: "json_table out of cte",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query:       "with tt as (select * from t) select * from json_table(tt.j, '$[*]' columns (a varchar(10) path '$')) as jt;",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{

		Name: "json_table out of cte with join",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query:       "with tt as (select * from t) select * from tt, json_table(tt.j, '$[*]' columns (a varchar(10) path '$')) as jt;",
		ExpectedErr: sql.ErrInvalidArgument,
	},
}
View Source
var BrokenQueries = []QueryTest{
	{

		Query: "select t2.* from mytable t1 natural join mytable t2 join othertable t3 on t2.i = t3.i2;",
		Expected: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
		},
	},
	{

		Query: "select t1.*, t2.*, i from mytable t1 natural join mytable t2 join othertable t3 on t2.i = t3.i2;",
		Expected: []sql.Row{
			{1, "first row", 1, "first row", 1},
			{2, "second row", 2, "second row", 2},
			{3, "third row", 3, "third row", 3},
		},
	},
	{

		Query: "select * from mytable t1 natural join mytable t2 join othertable t3 on t2.i = t3.i2;",
		Expected: []sql.Row{
			{1, "first row", "third", 1},
			{2, "second row", "second", 2},
			{3, "third row", "first", 3},
		},
	},
	{

		Query:    "with recursive MYTABLE(j) as (select 2 union select MYTABLE.j from MYTABLE join mytable on MYTABLE.j = mytable.i) select j from MYTABLE",
		Expected: []sql.Row{{2}},
	},
	{

		Query:    "with recursive MYTABLE(j) as (select 2 union select MYTABLE.j from MYTABLE join mytable on MYTABLE.j = mytable.i) select i from mytable;",
		Expected: []sql.Row{{1}, {2}, {3}},
	},
	{

		Query:    "with a(j) as (select 1), b(i) as (select 2) (select j from a union select i from b order by 1 desc) union select j from a;",
		Expected: []sql.Row{{2}, {1}},
	},
	{

		Query:    "with a(j) as (select 1 union select 2 union select 3), b(i) as (select 2 union select 3) select (3,4) in (select a.j, b.i+1 from a, b where a.j = b.i) as k group by k having k = 1;",
		Expected: []sql.Row{{1}},
	},
	{

		Query:    "With recursive a(x) as (select 1 union select 2 union select x in (select t1.i from mytable t1) from a) select x from a;",
		Expected: []sql.Row{{1}, {2}},
	},
	{

		Query:    "with a(j) as (select 1) ( with c(k) as (select 3) select k from c union select 6) union select k from c;",
		Expected: []sql.Row{{3}, {6}},
	},
	{
		Query:    "SELECT pk1, SUM(c1) FROM two_pk",
		Expected: []sql.Row{{0, 60.0}},
	},

	{
		Query: `SELECT pk, (SELECT max(pk) FROM one_pk WHERE pk < opk.pk) AS x 
						FROM one_pk opk WHERE x > 0 ORDER BY x`,
		Expected: []sql.Row{
			{2, 1},
			{3, 2},
		},
	},
	{
		Query: `SELECT pk,
					(SELECT max(pk) FROM one_pk WHERE pk < opk.pk) AS min,
					(SELECT min(pk) FROM one_pk WHERE pk > opk.pk) AS max
					FROM one_pk opk
					WHERE max > 1
					ORDER BY max;`,
		Expected: []sql.Row{
			{1, 0, 2},
			{2, 1, 3},
		},
	},

	{
		Query: `SELECT pk,
						(SELECT sum(c1) FROM two_pk WHERE c1 IN (SELECT c4 FROM two_pk WHERE c3 > opk.c5)) AS sum,
						(SELECT avg(c1) FROM two_pk WHERE pk2 IN (SELECT pk2 FROM two_pk WHERE c1 < opk.c2)) AS avg
					FROM one_pk opk ORDER BY pk`,
		Expected: []sql.Row{
			{0, 60.0, nil},
			{1, 50.0, 10.0},
			{2, 30.0, 15.0},
			{3, nil, 15.0},
		},
	},

	{
		Query: `SELECT column_0, sum(column_1) FROM 
			(values row(1,1), row(1,3), row(2,2), row(2,5), row(3,9)) a 
			group by 1 having avg(column_1) > 2 order by 1`,
		Expected: []sql.Row{
			{2, 7.0},
			{3, 9.0},
		},
	},

	{
		Query: `WITH t AS (SELECT 1) SELECT * FROM t UNION (WITH t AS (SELECT 2) SELECT * FROM t)`,
		Expected: []sql.Row{
			{1},
			{2},
		},
	},
	{
		Query: "SELECT json_array() FROM dual;",
	},
	{
		Query: "SELECT json_array_append() FROM dual;",
	},
	{
		Query: "SELECT json_array_insert() FROM dual;",
	},
	{
		Query: "SELECT json_contains() FROM dual;",
	},
	{
		Query: "SELECT json_contains_path() FROM dual;",
	},
	{
		Query: "SELECT json_depth() FROM dual;",
	},
	{
		Query: "SELECT json_insert() FROM dual;",
	},
	{
		Query: "SELECT json_keys() FROM dual;",
	},
	{
		Query: "SELECT json_length() FROM dual;",
	},
	{
		Query: "SELECT json_merge_patch() FROM dual;",
	},
	{
		Query: "SELECT json_merge_preserve() FROM dual;",
	},
	{
		Query: "SELECT json_object() FROM dual;",
	},
	{
		Query: "SELECT json_overlaps() FROM dual;",
	},
	{
		Query: "SELECT json_pretty() FROM dual;",
	},
	{
		Query: "SELECT json_quote() FROM dual;",
	},
	{
		Query: "SELECT json_remove() FROM dual;",
	},
	{
		Query: "SELECT json_replace() FROM dual;",
	},
	{
		Query: "SELECT json_schema_valid() FROM dual;",
	},
	{
		Query: "SELECT json_schema_validation_report() FROM dual;",
	},
	{
		Query: "SELECT json_set() FROM dual;",
	},
	{
		Query: "SELECT json_search() FROM dual;",
	},
	{
		Query: "SELECT json_storage_free() FROM dual;",
	},
	{
		Query: "SELECT json_storage_size() FROM dual;",
	},
	{
		Query: "SELECT json_type() FROM dual;",
	},
	{
		Query: "SELECT json_table() FROM dual;",
	},
	{
		Query: "SELECT json_valid() FROM dual;",
	},
	{
		Query: "SELECT json_value() FROM dual;",
	},

	{
		Query: `SELECT s as i, i as i from mytable order by i`,
	},

	{
		Query: "SELECT i, I, s, S FROM mytable;",
		Expected: []sql.Row{
			{1, 1, "first row", "first row"},
			{2, 2, "second row", "second row"},
			{3, 3, "third row", "third row"},
		},
		ExpectedColumns: sql.Schema{
			{
				Name: "i",
				Type: types.Int64,
			},
			{
				Name: "I",
				Type: types.Int64,
			},
			{
				Name: "s",
				Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
			},
			{
				Name: "S",
				Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
			},
		},
	},
	{
		Query: "SELECT `i`, `I`, `s`, `S` FROM mytable;",
		Expected: []sql.Row{
			{1, 1, "first row", "first row"},
			{2, 2, "second row", "second row"},
			{3, 3, "third row", "third row"},
		},
		ExpectedColumns: sql.Schema{
			{
				Name: "i",
				Type: types.Int64,
			},
			{
				Name: "I",
				Type: types.Int64,
			},
			{
				Name: "s",
				Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
			},
			{
				Name: "S",
				Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
			},
		},
	},
	{
		Query: "SELECT `mytable`.`i`, `mytable`.`I`, `mytable`.`s`, `mytable`.`S` FROM mytable;",
		Expected: []sql.Row{
			{1, 1, "first row", "first row"},
			{2, 2, "second row", "second row"},
			{3, 3, "third row", "third row"},
		},
		ExpectedColumns: sql.Schema{
			{
				Name: "i",
				Type: types.Int64,
			},
			{
				Name: "I",
				Type: types.Int64,
			},
			{
				Name: "s",
				Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
			},
			{
				Name: "S",
				Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
			},
		},
	},

	{
		Query:    `SELECT json_unquote(json_extract('{"hi":"there"}', '$.nope'))`,
		Expected: []sql.Row{{nil}},
	},

	{
		Query:    "SELECT 1 FROM DUAL WHERE (1, null) in ((1, null))",
		Expected: []sql.Row{},
	},
	{
		Query:    "SELECT 1 FROM DUAL WHERE (1, null) != (0, null)",
		Expected: []sql.Row{},
	},
	{
		Query:    "SELECT 1 FROM DUAL WHERE (0, null) = (0, null)",
		Expected: []sql.Row{},
	},
	{
		Query:    "SELECT 1 FROM DUAL WHERE ('0', 0) = (0, '0')",
		Expected: []sql.Row{{1}},
	},
	{
		Query:    "SELECT 1 FROM DUAL WHERE (null, null) = (select null, null from dual)",
		Expected: []sql.Row{},
	},

	{
		Query: "SELECT c AS i_do_not_conflict, COUNT(*), MIN((SELECT COUNT(*) FROM (SELECT 1 AS d) b WHERE b.d = a.c)) FROM (SELECT 1 AS c) a GROUP BY i_do_not_conflict;",
	},
	{
		Query: "SELECT c AS c, COUNT(*), MIN((SELECT COUNT(*) FROM (SELECT 1 AS d) b WHERE b.d = a.c)) FROM (SELECT 1 AS c) a GROUP BY a.c;",
	},

	{
		Query: `
			with recursive t1 (sub_part, part, quantity) as (
				with recursive t2 (sub_part, part, quantity) as (
					SELECT p2.sub_part, p2.part, p2.quantity FROM parts as p2
					UNION
					SELECT p1.sub_part, p1.part, p1.quantity FROM parts as p1
					JOIN t2
					ON
						p1.sub_part = t2.sub_part
					WHERE p1.part = 'pie' and t2.part = 'crust'
				) select * from t2
				UNION
				SELECT t1.sub_part, t1.part, t1.quantity
				FROM t1
				JOIN parts AS p
				ON p.part = p.part
			) SELECT t1.sub_part, sum(t1.quantity) as total_quantity FROM t1 GROUP BY t1.sub_part;`,
		Expected: []sql.Row{
			{"crust", float64(1)},
			{"filling", float64(2)},
			{"flour", float64(20)},
			{"butter", float64(18)},
			{"salt", float64(18)},
			{"sugar", float64(7)},
			{"fruit", float64(9)},
		},
	},
	{

		Query:    "select i, date_col from datetime_table",
		Expected: []sql.Row{{1, "2019-12-31"}},
	},

	{
		Query:    "SELECT X'0a'",
		Expected: []sql.Row{{"0x0A"}},
	},

	{
		Query:    "STR_TO_DATE('2013 32 Tuesday', '%X %V %W')",
		Expected: []sql.Row{{"2013-08-13"}},
	},
	{

		Query:    "select 2000.0 / 250000000.0 * (24.0 * 6.0 * 6.25 * 10.0);",
		Expected: []sql.Row{{"0.0720000000"}},
	},
}

BrokenQueries are queries that are known to be broken in the engine.

View Source
var BrokenScriptTests = []ScriptTest{
	{
		Name: "ALTER TABLE MODIFY column with multiple UNIQUE KEYS",
		SetUpScript: []string{
			"CREATE table test (pk int primary key, uk1 int, uk2 int, unique(uk1, uk2))",
			"ALTER TABLE `test` MODIFY column uk1 int auto_increment",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "", ""},
					{"uk1", "int", "YES", "UNI", "", "auto_increment"},
					{"uk1", "int", "YES", "UNI", "", "auto_increment"},
				},
			},
		},
	},
	{
		Name: "ALTER TABLE MODIFY column with multiple KEYS",
		SetUpScript: []string{
			"CREATE table test (pk int primary key, mk1 int, mk2 int, index(uk1, uk2))",
			"ALTER TABLE `test` MODIFY column mk1 int auto_increment",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "", ""},
					{"mk1", "int", "YES", "MUL", "", "auto_increment"},
					{"mk1", "int", "YES", "MUL", "", "auto_increment"},
				},
			},
		},
	},
	{
		Name:        "ALTER TABLE RENAME on a column when another column has a default dependency on it",
		SetUpScript: []string{"CREATE TABLE `test` (`pk` bigint NOT NULL,`v2` int NOT NULL DEFAULT '100',`v3` int DEFAULT ((`v2` + 1)),PRIMARY KEY (`pk`));"},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table test rename column v2 to mycol",
				ExpectedErr: sql.ErrAlterTableNotSupported,
			},
		},
	},

	{
		Name: "Keyless Table with Unique Index",
		SetUpScript: []string{
			"create table a (x int, val int unique)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO a VALUES (1, 1)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "INSERT INTO a VALUES (1, 1)",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
		},
	},
	{
		Name: "Multialter DDL with ADD/DROP Primary Key",
		SetUpScript: []string{
			"CREATE TABLE t(pk int primary key, v1 int)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE t ADD COLUMN (v2 int), drop primary key, add primary key (v2)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "", "", ""},
					{"v1", "int", "YES", "", "", ""},
					{"v2", "int", "NO", "PRI", "", ""},
				},
			},
			{
				Query:       "ALTER TABLE t ADD COLUMN (v3 int), drop primary key, add primary key (notacolumn)",
				ExpectedErr: sql.ErrKeyColumnDoesNotExist,
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "", "", ""},
					{"v1", "int", "YES", "", "", ""},
					{"v2", "int", "NO", "PRI", "", ""},
				},
			},
			{
				Query:    "ALTER TABLE t ADD column `v4` int NOT NULL, ADD column `v5` int NOT NULL, DROP COLUMN `v1`, ADD COLUMN `v6` int NOT NULL, DROP COLUMN `v2`, ADD COLUMN v7 int NOT NULL",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "", "", ""},
					{"v4", "int", "NO", "", "", ""},
					{"v5", "int", "NO", "", "", ""},
					{"v6", "int", "NO", "", "", ""},
					{"v7", "int", "NO", "", "", ""},
				},
			},
		},
	},
	{
		Name: "REGEXP operator",
		SetUpScript: []string{
			"CREATE TABLE IF NOT EXISTS `person` (`id` INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` VARCHAR(255) NOT NULL);",
			"INSERT INTO `person` (`name`) VALUES ('n1'), ('n2'), ('n3')",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT `t1`.`id`, `t1`.`name` FROM `person` AS `t1` WHERE (`t1`.`name` REGEXP 'N[1,3]') ORDER BY `t1`.`name`;",
				Expected: []sql.Row{{1, "n1"}, {3, "n3"}},
			},
		},
	},
	{
		Name: "non-existent procedure in trigger body",
		SetUpScript: []string{
			"CREATE TABLE XA(YW VARCHAR(24) NOT NULL, XB VARCHAR(100), XC VARCHAR(2500),\n  XD VARCHAR(2500), XE VARCHAR(100), XF VARCHAR(100), XG VARCHAR(100),\n  XI VARCHAR(100), XJ VARCHAR(100), XK VARCHAR(100), XL VARCHAR(100),\n  XM VARCHAR(1000), XN TEXT, XO TEXT, PRIMARY KEY (YW));",
			"CREATE TABLE XP(YW VARCHAR(24) NOT NULL, XQ VARCHAR(100) NOT NULL,\n  XR VARCHAR(1000), PRIMARY KEY (YW));",
			"CREATE TABLE XS(YW VARCHAR(24) NOT NULL, XT VARCHAR(24) NOT NULL,\n  XU VARCHAR(24), XV VARCHAR(100) NOT NULL, XW DOUBLE NOT NULL,\n  XX DOUBLE NOT NULL, XY VARCHAR(100), XC VARCHAR(100), XZ VARCHAR(100) NOT NULL,\n  YA DOUBLE, YB VARCHAR(24) NOT NULL, YC VARCHAR(1000), XO VARCHAR(1000),\n  YD DOUBLE NOT NULL, YE DOUBLE NOT NULL, PRIMARY KEY (YW));",
			"CREATE TABLE YF(YW VARCHAR(24) NOT NULL, XB VARCHAR(100) NOT NULL, YG VARCHAR(100),\n  YH VARCHAR(100), XO TEXT, PRIMARY KEY (YW));",
			"CREATE TABLE yp(YW VARCHAR(24) NOT NULL, XJ VARCHAR(100) NOT NULL, XL VARCHAR(100),\n  XT VARCHAR(24) NOT NULL, YI INT NOT NULL, XO VARCHAR(1000), PRIMARY KEY (YW),\n  FOREIGN KEY (XT) REFERENCES XP (YW));",
			"INSERT INTO XS VALUES ('', '', NULL, 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC', 0, 0,\n  NULL, NULL, '', NULL, '', NULL, NULL, 0, 0);",
			"INSERT INTO YF VALUES ('', '', NULL, NULL, NULL);",
			"INSERT INTO XA VALUES ('', '', '', '', '', 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC',\n  '', '', '', '', '', '', '', '');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT DISTINCT YM.YW AS YW,\n  (SELECT YW FROM YF WHERE YF.XB = YM.XB) AS YF_YW,\n  (\n    SELECT YW\n    FROM yp\n    WHERE\n      yp.XJ = YM.XJ AND\n      (yp.XL = YM.XL OR (yp.XL IS NULL AND YM.XL IS NULL)) AND\n      yp.XT = nd.XT\n    ) AS YJ,\n  XE AS XE,\n  XI AS YO,\n  XK AS XK,\n  XM AS XM,\n  CASE\n    WHEN YM.XO <> 'Z'\n  THEN YM.XO\n  ELSE NULL\n  END AS XO\n  FROM (\n    SELECT YW, XB, XC, XE, XF, XI, XJ, XK,\n      CASE WHEN XL = 'Z' OR XL = 'Z' THEN NULL ELSE XL END AS XL,\n      XM, XO\n    FROM XA\n  ) YM\n  INNER JOIN XS nd\n    ON nd.XV = XF\n  WHERE\n    XB IN (SELECT XB FROM YF) AND\n    (XF IS NOT NULL AND XF <> 'Z')\n  UNION\n  SELECT DISTINCT YL.YW AS YW,\n    (\n      SELECT YW\n      FROM YF\n      WHERE YF.XB = YL.XB\n    ) AS YF_YW,\n    (\n      SELECT YW FROM yp\n      WHERE\n        yp.XJ = YL.XJ AND\n        (yp.XL = YL.XL OR (yp.XL IS NULL AND YL.XL IS NULL)) AND\n        yp.XT = YN.XT\n    ) AS YJ,\n    XE AS XE,\n    XI AS YO,\n    XK AS XK,\n    XM AS XM,\n    CASE WHEN YL.XO <> 'Z' THEN YL.XO ELSE NULL END AS XO\n  FROM (\n    SELECT YW, XB, XC, XE, XF, XI, XJ, XK,\n      CASE WHEN XL = 'Z' OR XL = 'Z' THEN NULL ELSE XL END AS XL,\n      XM, XO\n      FROM XA\n  ) YL\n  INNER JOIN XS YN\n    ON YN.XC = YL.XC\n  WHERE\n    XB IN (SELECT XB FROM YF) AND \n    (XF IS NULL OR XF = 'Z');",
				Expected: []sql.Row{{"", "", "", "", "", "", "", ""}},
			},
		},
	},
}
View Source
var BrokenTriggerQueries = []ScriptTest{
	{
		Name: "update common table multiple times in single insert",
		SetUpScript: []string{
			"create table mytable (id integer PRIMARY KEY DEFAULT 0, sometext text);",
			"create table sequence_table (max_id integer PRIMARY KEY);",
			"create trigger update_position_id before insert on mytable for each row begin set new.id = (select coalesce(max(max_id),1) from sequence_table); update sequence_table set max_id = max_id + 1; end;",
			"insert into sequence_table values (1);",
		},
		Assertions: []ScriptTestAssertion{

			{
				Query:    "insert into mytable () values (), ();",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query: "select * from mytable order by id",
				Expected: []sql.Row{
					{1, nil},
					{2, nil},
					{3, nil},
				},
			},
		},
	},
	{
		Name: "insert into table multiple times",
		SetUpScript: []string{
			"CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"CREATE TABLE test2(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"INSERT INTO test VALUES (0,2),(1,3)",
			`CREATE TRIGGER tt BEFORE INSERT ON test FOR EACH ROW 
				BEGIN 
					insert into test2 values (new.pk * 3, new.v1);
					insert into test2 values (new.pk * 5, new.v1);
				END;`,

			"INSERT INTO test VALUES (2,4), (6,8);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM test ORDER BY 1",
				Expected: []sql.Row{
					{0, 2}, {1, 3}, {2, -440},
				},
			},
			{
				Query: "SELECT * FROM test2 ORDER BY 1",
				Expected: []sql.Row{
					{2, -440},
				},
			},
		},
	},

	{
		Name: "trigger after update, delete from other table",
		SetUpScript: []string{
			"create table foo.a (x int primary key)",
			"create table foo.b (y int primary key)",
			"insert into foo.a values (0), (2), (4), (6), (8)",
			"insert into foo.b values (1), (3), (5), (7), (9)",
			"use foo",
			"create trigger insert_into_b after update on a for each row insert into b values (old.x + new.x + 1)",
			"use mydb",
			"update foo.a set x = x + 1 where x in (2,4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from foo.a order by 1",
				Expected: []sql.Row{
					{0}, {3}, {5}, {6}, {8},
				},
			},
			{
				Query: "select y from foo.b order by 1",
				Expected: []sql.Row{
					{1}, {3}, {7},
				},
			},
		},
	},

	{
		Name: "trigger before update, begin block with references to other table",
		SetUpScript: []string{
			"CREATE TABLE a (i int primary key, j int)",
			"INSERT INTO a VALUES (0,1),(2,3),(4,5)",
			"CREATE TABLE b (x int)",
			"INSERT INTO b VALUES (1)",
			"CREATE TRIGGER trig BEFORE UPDATE ON a FOR EACH ROW BEGIN SET NEW.i = (SELECT x FROM b); SET NEW.j = OLD.j + NEW.j; UPDATE b SET x = x + 1; END;",
			"UPDATE a SET j = 10;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM a ORDER BY 1",
				Expected: []sql.Row{
					{1, 11}, {2, 13}, {3, 15},
				},
			},
			{
				Query: "SELECT * FROM b ORDER BY x",
				Expected: []sql.Row{
					{4},
				},
			},
		},
	},
	{
		Name: "trigger after inserts, use updated self reference",
		SetUpScript: []string{
			"create table a (i int primary key, j int)",
			"create table b (x int primary key)",
			"insert into b values (1)",
			"create trigger trig after insert on a for each row begin update b set x = (select count(*) from a); end;",
			"insert into a values (1,0), (2,0), (3,0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from a order by i",
				Expected: []sql.Row{
					{1, 0}, {2, 0}, {3, 0},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{3},
				},
			},
			{
				Query: "insert into a values (4,0), (5,0)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
}

BrokenTriggerQueries contains trigger queries that should work but do not yet

View Source
var CharsetCollationEngineTests = []CharsetCollationEngineTest{
	{
		Name: "Insert multiple character sets",
		SetUpScript: []string{
			"CREATE TABLE test (v1 VARCHAR(255) COLLATE utf16_unicode_ci);",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query:    "INSERT INTO test VALUES ('hey');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO test VALUES (_utf16'\x00h\x00i');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO test VALUES (_utf8mb4'\x68\x65\x6c\x6c\x6f');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM test ORDER BY 1;",
				Expected: []sql.Row{{"hello"}, {"hey"}, {"hi"}},
			},
		},
	},
	{
		Name: "Sorting differences",
		SetUpScript: []string{
			"CREATE TABLE test1 (v1 VARCHAR(255) COLLATE utf8mb4_0900_bin);",
			"CREATE TABLE test2 (v1 VARCHAR(255) COLLATE utf16_unicode_ci);",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query:    "INSERT INTO test1 VALUES ('HEY2'), ('hey1');",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO test2 VALUES ('HEY2'), ('hey1');",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "SELECT * FROM test1 ORDER BY 1;",
				Expected: []sql.Row{{"HEY2"}, {"hey1"}},
			},
			{
				Query:    "SELECT * FROM test2 ORDER BY 1;",
				Expected: []sql.Row{{"hey1"}, {"HEY2"}},
			},
		},
	},
	{
		Name: "Character set introducer with invalid collate",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT _utf16'\x00a' COLLATE utf8mb4_0900_bin;",
				Error: true,
			},
			{
				Query: "SELECT _utf16'\x00a' COLLATE binary;",
				Error: true,
			},
		},
	},
	{
		Name: "Properly block using not-yet-implemented character sets/collations",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query:   "CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) CHARACTER SET utf16le);",
				ErrKind: sql.ErrCharSetNotYetImplementedTemp,
			},
			{
				Query:   "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf16le_general_ci);",
				ErrKind: sql.ErrCharSetNotYetImplementedTemp,
			},
			{
				Query:    "CREATE TABLE test3 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) CHARACTER SET utf16);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:   "ALTER TABLE test3 MODIFY COLUMN v1 VARCHAR(255) COLLATE utf16_croatian_ci;",
				ErrKind: sql.ErrCollationNotYetImplementedTemp,
			},
			{
				Query:   "CREATE TABLE test4 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf16_croatian_ci);",
				ErrKind: sql.ErrCollationNotYetImplementedTemp,
			},
		},
	},
	{
		Name: "Order by behaves differently according to case-sensitivity",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf16_unicode_ci, INDEX(v1));",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf8mb4_0900_bin, INDEX(v1));",
			"INSERT INTO test1 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"INSERT INTO test2 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT v1, pk FROM test1 ORDER BY pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 ORDER BY pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", int64(2)}, {"AbC", int64(4)}, {"aBc", int64(3)}, {"abc", int64(1)},
				},
			},
		},
	},
	{
		Name: "Proper index access",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf16_unicode_ci, INDEX(v1));",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf8mb4_0900_bin, INDEX(v1));",
			"INSERT INTO test1 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"INSERT INTO test2 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query:    "SELECT v1, pk FROM test1 WHERE v1 > 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row(nil),
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 >= 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 = 'ABC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 BETWEEN 'ABC' AND 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 IN ('abc') ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 > 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"aBc", int64(3)}, {"abc", int64(1)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 >= 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"AbC", int64(4)}, {"aBc", int64(3)}, {"abc", int64(1)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", int64(2)}, {"AbC", int64(4)}, {"aBc", int64(3)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 = 'ABC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", int64(2)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 BETWEEN 'ABC' AND 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", int64(2)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 IN ('abc') ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)},
				},
			},
		},
	},
	{
		Name: "Table collation is respected",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255)) COLLATE utf16_unicode_ci;",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255)) COLLATE utf8mb4_unicode_ci;",
			"CREATE TABLE test3 LIKE test2;",
			"INSERT INTO test1 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"INSERT INTO test2 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"INSERT INTO test3 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"CREATE TABLE test4 AS SELECT * FROM test2;",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "ALTER TABLE test2 MODIFY COLUMN v1 VARCHAR(100);",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test3 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SELECT v1, pk FROM test4 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", int64(1)}, {"ABC", int64(2)}, {"aBc", int64(3)}, {"AbC", int64(4)},
				},
			},
			{
				Query: "SHOW CREATE TABLE test1;",
				Expected: []sql.Row{
					{"test1", "CREATE TABLE `test1` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(255) CHARACTER SET utf16 COLLATE utf16_unicode_ci,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci"},
				},
			},
			{
				Query: "SHOW CREATE TABLE test2;",
				Expected: []sql.Row{
					{"test2", "CREATE TABLE `test2` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(100) COLLATE utf8mb4_unicode_ci,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"},
				},
			},
			{
				Query: "SHOW CREATE TABLE test3;",
				Expected: []sql.Row{
					{"test3", "CREATE TABLE `test3` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(255) COLLATE utf8mb4_unicode_ci,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"},
				},
			},
			{
				Query: "SHOW CREATE TABLE test4;",
				Expected: []sql.Row{
					{"test4", "CREATE TABLE `test4` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(255) COLLATE utf8mb4_unicode_ci\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "ALTER TABLE test3 ADD COLUMN v2 VARCHAR(255);",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "SHOW CREATE TABLE test3;",
				Expected: []sql.Row{
					{"test3", "CREATE TABLE `test3` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(255) COLLATE utf8mb4_unicode_ci,\n  `v2` varchar(255) COLLATE utf8mb4_unicode_ci,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"},
				},
			},
			{
				Query: "ALTER TABLE test2 CHANGE COLUMN v1 v1 VARCHAR(220);",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "SHOW CREATE TABLE test2;",
				Expected: []sql.Row{
					{"test2", "CREATE TABLE `test2` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(220) COLLATE utf8mb4_unicode_ci,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"},
				},
			},
		},
	},
	{
		Name: "SET NAMES does not interfere with column charset",
		SetUpScript: []string{
			"SET NAMES utf8mb3;",
			"CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 VARCHAR(100) COLLATE utf8mb4_0900_bin);",
			"INSERT INTO test VALUES (1, 'a'), (2, 'b');",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query:    "SELECT * FROM test ORDER BY v1 COLLATE utf8mb4_bin ASC;",
				Expected: []sql.Row{{int64(1), "a"}, {int64(2), "b"}},
			},
			{
				Query:   "SELECT * FROM test ORDER BY v1 COLLATE utf8mb3_bin ASC;",
				ErrKind: sql.ErrCollationInvalidForCharSet,
			},
			{
				Query:    "SELECT 'a' COLLATE utf8mb3_bin;",
				Expected: []sql.Row{{"a"}},
			},
			{
				Query:   "SELECT 'a' COLLATE utf8mb4_bin;",
				ErrKind: sql.ErrCollationInvalidForCharSet,
			},
		},
	},
	{
		Name: "ENUM collation handling",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 ENUM('abc','def','ghi') COLLATE utf16_unicode_ci);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 ENUM('abc','def','ghi') COLLATE utf8mb4_0900_bin);",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "INSERT INTO test1 VALUES (1, 'ABC');",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (1, 'ABC');",
				Error: true,
			},
			{
				Query: "INSERT INTO test1 VALUES (2, _utf16'\x00d\x00e\x00f' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (2, _utf16'\x00d\x00e\x00f' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "SELECT * FROM test1 ORDER BY pk;",
				Expected: []sql.Row{
					{int64(1), uint16(1)}, {int64(2), uint16(2)},
				},
			},
			{
				Query: "SELECT * FROM test2 ORDER BY pk;",
				Expected: []sql.Row{
					{int64(2), uint16(2)},
				},
			},
		},
	},
	{
		Name: "SET collation handling",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 SET('a','b','c') COLLATE utf16_unicode_ci);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 SET('a','b','c') COLLATE utf8mb4_0900_bin);",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "INSERT INTO test1 VALUES (1, 'A');",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (1, 'A');",
				Error: true,
			},
			{
				Query: "INSERT INTO test1 VALUES (2, _utf16'\x00b\x00,\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (2, _utf16'\x00b\x00,\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "SELECT * FROM test1 ORDER BY pk;",
				Expected: []sql.Row{
					{int64(1), uint64(1)}, {int64(2), uint64(6)},
				},
			},
			{
				Query: "SELECT * FROM test2 ORDER BY pk;",
				Expected: []sql.Row{
					{int64(2), uint64(6)},
				},
			},
		},
	},
	{
		Name: "LIKE respects table collations",
		SetUpScript: []string{
			"SET NAMES utf8mb4;",
			"CREATE TABLE test(v1 VARCHAR(100) COLLATE utf8mb4_0900_bin, v2 VARCHAR(100) COLLATE utf8mb4_0900_ai_ci);",
			"INSERT INTO test VALUES ('abc', 'abc'), ('ABC', 'ABC');",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'ABC';",
				Expected: []sql.Row{
					{int64(1)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE 'ABC';",
				Expected: []sql.Row{
					{int64(2)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'A%';",
				Expected: []sql.Row{
					{int64(1)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE 'A%';",
				Expected: []sql.Row{
					{int64(2)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE '%C';",
				Expected: []sql.Row{
					{int64(1)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE '%C';",
				Expected: []sql.Row{
					{int64(2)},
				},
			},
			{
				Query:    "SET collation_connection = 'utf8mb4_0900_bin';",
				Expected: []sql.Row{{}},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'ABC';",
				Expected: []sql.Row{
					{int64(1)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE 'ABC';",
				Expected: []sql.Row{
					{int64(2)},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'ABC' COLLATE utf8mb4_0900_ai_ci;",
				Expected: []sql.Row{
					{int64(2)},
				},
			},
		},
	},
	{
		Name: "LIKE respects connection collation",
		SetUpScript: []string{
			"SET NAMES utf8mb4;",
		},
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT 'abc' LIKE 'ABC';",
				Expected: []sql.Row{
					{true},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_bin LIKE 'ABC';",
				Expected: []sql.Row{
					{false},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_bin;",
				Expected: []sql.Row{
					{false},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_ai_ci LIKE 'ABC';",
				Expected: []sql.Row{
					{true},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_ai_ci;",
				Expected: []sql.Row{
					{true},
				},
			},
			{
				Query:    "SET collation_connection = 'utf8mb4_0900_bin';",
				Expected: []sql.Row{{}},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC';",
				Expected: []sql.Row{
					{false},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_ai_ci LIKE 'ABC';",
				Expected: []sql.Row{
					{true},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_ai_ci;",
				Expected: []sql.Row{
					{true},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_bin LIKE 'ABC';",
				Expected: []sql.Row{
					{false},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_bin;",
				Expected: []sql.Row{
					{false},
				},
			},
			{
				Query: "SELECT _utf8mb4'abc' LIKE 'ABC';",
				Expected: []sql.Row{
					{false},
				},
			},
			{
				Query: "SELECT 'abc' LIKE _utf8mb4'ABC';",
				Expected: []sql.Row{
					{false},
				},
			},
		},
	},
	{
		Name: "STRCMP() function",
		Queries: []CharsetCollationEngineTestQuery{

			{

				Query: "SELECT STRCMP(_utf8mb4'A' COLLATE utf8mb4_0900_ai_ci, _latin1'b' COLLATE latin1_general_cs)",
				Expected: []sql.Row{
					{int(-1)},
				},
			},
		},
	},
	{
		Name: "LENGTH() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT LENGTH(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{int32(6)},
				},
			},
			{
				Query: "SELECT LENGTH(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{int32(3)},
				},
			},
			{
				Query: "SELECT LENGTH(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{int32(6)},
				},
			},
		},
	},
	{
		Name: "CHAR_LENGTH() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT CHAR_LENGTH(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{int32(3)},
				},
			},
			{
				Query: "SELECT CHAR_LENGTH(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{int32(3)},
				},
			},
			{
				Query: "SELECT CHAR_LENGTH(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{int32(6)},
				},
			},
		},
	},
	{
		Name: "UPPER() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT UPPER(_utf16'\x00a\x00B\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"ABC"},
				},
			},
			{
				Query: "SELECT UPPER(_utf8mb4'aBc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"ABC"},
				},
			},
			{
				Query: "SELECT UPPER(_utf8mb4'\x00a\x00B\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00A\x00B\x00C"},
				},
			},
		},
	},
	{
		Name: "LOWER() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT LOWER(_utf16'\x00A\x00b\x00C' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT LOWER(_utf8mb4'AbC' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT LOWER(_utf8mb4'\x00A\x00b\x00C' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
		},
	},
	{
		Name: "RPAD() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT RPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, 'z');",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 9, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00czzz"},
				},
			},
		},
	},
	{
		Name: "LPAD() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT LPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, 'z');",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 9, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"zzz\x00a\x00b\x00c"},
				},
			},
		},
	},
	{
		Name: "HEX() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT HEX(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"006100620063"},
				},
			},
			{
				Query: "SELECT HEX(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"616263"},
				},
			},
			{
				Query: "SELECT HEX(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"006100620063"},
				},
			},
		},
	},
	{
		Name: "UNHEX() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT UNHEX(_utf16'\x006\x001\x006\x002\x006\x003' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{[]byte("abc")},
				},
			},
			{
				Query: "SELECT UNHEX(_utf8mb4'616263' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{[]byte("abc")},
				},
			},
		},
	},
	{
		Name: "SUBSTRING() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT SUBSTRING(_utf16'\x00a\x00b\x00c\x00d' COLLATE utf16_unicode_ci, 2, 2);",
				Expected: []sql.Row{
					{"bc"},
				},
			},
			{
				Query: "SELECT SUBSTRING(_utf8mb4'abcd' COLLATE utf8mb4_0900_bin, 2, 2);",
				Expected: []sql.Row{
					{"bc"},
				},
			},
			{
				Query: "SELECT SUBSTRING(_utf8mb4'\x00a\x00b\x00c\x00d' COLLATE utf8mb4_0900_bin, 2, 2);",
				Expected: []sql.Row{
					{"a\x00"},
				},
			},
		},
	},
	{
		Name: "TO_BASE64() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT TO_BASE64(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"AGEAYgBj"},
				},
			},
			{
				Query: "SELECT TO_BASE64(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"YWJj"},
				},
			},
			{
				Query: "SELECT TO_BASE64(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"AGEAYgBj"},
				},
			},
		},
	},
	{
		Name: "FROM_BASE64() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT FROM_BASE64(_utf16'\x00Y\x00W\x00J\x00j' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{[]byte("abc")},
				},
			},
			{
				Query: "SELECT FROM_BASE64(_utf8mb4'YWJj' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{[]byte("abc")},
				},
			},
		},
	},
	{
		Name: "TRIM() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT TRIM(_utf16'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT TRIM(_utf8mb4' abc ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT TRIM(_utf8mb4'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c\x00"},
				},
			},
		},
	},
	{
		Name: "RTRIM() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT RTRIM(_utf16'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{" abc"},
				},
			},
			{
				Query: "SELECT RTRIM(_utf8mb4' abc ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{" abc"},
				},
			},
			{
				Query: "SELECT RTRIM(_utf8mb4'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c\x00"},
				},
			},
		},
	},
	{
		Name: "LTRIM() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT LTRIM(_utf16'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abc "},
				},
			},
			{
				Query: "SELECT LTRIM(_utf8mb4' abc ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc "},
				},
			},
			{
				Query: "SELECT LTRIM(_utf8mb4'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c\x00 "},
				},
			},
		},
	},
	{
		Name: "BINARY() function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT BINARY(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{[]byte("\x00a\x00b\x00c")},
				},
			},
			{
				Query: "SELECT BINARY(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{[]byte("abc")},
				},
			},
			{
				Query: "SELECT BINARY(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{[]byte("\x00a\x00b\x00c")},
				},
			},
		},
	},
	{
		Name: "CAST(... AS BINARY) function",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: "SELECT CAST(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci AS BINARY);",
				Expected: []sql.Row{
					{[]byte("\x00a\x00b\x00c")},
				},
			},
			{
				Query: "SELECT CAST(_utf8mb4'abc' COLLATE utf8mb4_0900_bin AS BINARY);",
				Expected: []sql.Row{
					{[]byte("abc")},
				},
			},
			{
				Query: "SELECT CAST(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin AS BINARY);",
				Expected: []sql.Row{
					{[]byte("\x00a\x00b\x00c")},
				},
			},
		},
	},
	{
		Name: "Issue #5482",
		Queries: []CharsetCollationEngineTestQuery{
			{
				Query: `SELECT T.TABLE_NAME AS label, 'connection.table' as type, T.TABLE_SCHEMA AS 'schema',
T.TABLE_SCHEMA AS 'database', T.TABLE_CATALOG AS 'catalog',
0 AS isView FROM INFORMATION_SCHEMA.TABLES AS T WHERE T.TABLE_CATALOG = 'def' AND
                                                      UPPER(T.TABLE_TYPE) = 'BASE TABLE' ORDER BY T.TABLE_NAME;`,
				Expected: []sql.Row(nil),
			},
		},
	},
}

CharsetCollationEngineTests are used to ensure that character sets and collations have the correct behavior over the engine. Return values should all have the `utf8mb4` encoding, as it's returning the internal encoding type.

View Source
var CharsetCollationWireTests = []CharsetCollationWireTest{
	{
		Name: "Insert multiple character sets",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test (v1 VARCHAR(255) COLLATE utf16_unicode_ci);",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "INSERT INTO test VALUES ('hey');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO test VALUES (_utf16'\x00h\x00i');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO test VALUES (_utf8mb4'\x68\x65\x6c\x6c\x6f');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM test ORDER BY 1;",
				Expected: []sql.Row{{"\x00h\x00e\x00l\x00l\x00o"}, {"\x00h\x00e\x00y"}, {"\x00h\x00i"}},
			},
		},
	},
	{
		Name: "Sorting differences",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test1 (v1 VARCHAR(255) COLLATE utf8mb4_0900_bin);",
			"CREATE TABLE test2 (v1 VARCHAR(255) COLLATE utf16_unicode_ci);",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "INSERT INTO test1 VALUES ('HEY2'), ('hey1');",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO test2 VALUES ('HEY2'), ('hey1');",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "SELECT * FROM test1 ORDER BY 1;",
				Expected: []sql.Row{{"HEY2"}, {"hey1"}},
			},
			{
				Query:    "SELECT * FROM test2 ORDER BY 1;",
				Expected: []sql.Row{{"\x00h\x00e\x00y\x001"}, {"\x00H\x00E\x00Y\x002"}},
			},
		},
	},
	{
		Name: "Order by behaves differently according to case-sensitivity",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf16_unicode_ci, INDEX(v1));",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf8mb4_0900_bin, INDEX(v1));",
			"INSERT INTO test1 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"INSERT INTO test2 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT v1, pk FROM test1 ORDER BY pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 ORDER BY pk;",
				Expected: []sql.Row{
					{"abc", "1"}, {"ABC", "2"}, {"aBc", "3"}, {"AbC", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", "2"}, {"AbC", "4"}, {"aBc", "3"}, {"abc", "1"},
				},
			},
		},
	},
	{
		Name: "Proper index access",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf16_unicode_ci, INDEX(v1));",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf8mb4_0900_bin, INDEX(v1));",
			"INSERT INTO test1 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
			"INSERT INTO test2 VALUES (1, 'abc'), (2, 'ABC'), (3, 'aBc'), (4, 'AbC');",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "SELECT v1, pk FROM test1 WHERE v1 > 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row(nil),
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 >= 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 = 'ABC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 BETWEEN 'ABC' AND 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test1 WHERE v1 IN ('abc') ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c", "1"}, {"\x00A\x00B\x00C", "2"}, {"\x00a\x00B\x00c", "3"}, {"\x00A\x00b\x00C", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 > 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"aBc", "3"}, {"abc", "1"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 >= 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"AbC", "4"}, {"aBc", "3"}, {"abc", "1"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 <= 'aBc' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", "2"}, {"AbC", "4"}, {"aBc", "3"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 = 'ABC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", "2"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 BETWEEN 'ABC' AND 'AbC' ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"ABC", "2"}, {"AbC", "4"},
				},
			},
			{
				Query: "SELECT v1, pk FROM test2 WHERE v1 IN ('abc') ORDER BY v1, pk;",
				Expected: []sql.Row{
					{"abc", "1"},
				},
			},
		},
	},
	{
		Name: "SET NAMES does not interfere with column charset",
		SetUpScript: []string{
			"SET NAMES utf8mb3;",
			"CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 VARCHAR(100) COLLATE utf8mb4_0900_bin);",
			"INSERT INTO test VALUES (1, 'a'), (2, 'b');",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "SELECT * FROM test ORDER BY v1 COLLATE utf8mb4_bin ASC;",
				Expected: []sql.Row{{"1", "a"}, {"2", "b"}},
			},
			{
				Query: "SELECT * FROM test ORDER BY v1 COLLATE utf8mb3_bin ASC;",
				Error: true,
			},
			{
				Query:    "SELECT 'a' COLLATE utf8mb3_bin;",
				Expected: []sql.Row{{"a"}},
			},
			{
				Query: "SELECT 'a' COLLATE utf8mb4_bin;",
				Error: true,
			},
		},
	},
	{
		Name: "Coercibility test using HEX",
		SetUpScript: []string{
			"SET NAMES utf8mb4;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "SELECT HEX(UNHEX('c0a80000')) = 'c0a80000'",
				Expected: []sql.Row{{"1"}},
			},
			{
				Query:    "SET collation_connection = 'utf8mb4_0900_bin';",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SELECT HEX(UNHEX('c0a80000')) = 'c0a80000'",
				Expected: []sql.Row{{"0"}},
			},
		},
	},
	{
		Name: "ENUM collation handling",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 ENUM('abc','def','ghi') COLLATE utf16_unicode_ci);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 ENUM('abc','def','ghi') COLLATE utf8mb4_0900_bin);",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "INSERT INTO test1 VALUES (1, 'ABC');",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (1, 'ABC');",
				Error: true,
			},
			{
				Query: "INSERT INTO test1 VALUES (2, _utf16'\x00d\x00e\x00f' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (2, _utf16'\x00d\x00e\x00f' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "SELECT * FROM test1 ORDER BY pk;",
				Expected: []sql.Row{
					{"1", "\x00a\x00b\x00c"}, {"2", "\x00d\x00e\x00f"},
				},
			},
			{
				Query: "SELECT * FROM test2 ORDER BY pk;",
				Expected: []sql.Row{
					{"2", "def"},
				},
			},
		},
	},
	{
		Name: "SET collation handling",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 SET('a','b','c') COLLATE utf16_unicode_ci);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 SET('a','b','c') COLLATE utf8mb4_0900_bin);",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "INSERT INTO test1 VALUES (1, 'A');",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (1, 'A');",
				Error: true,
			},
			{
				Query: "INSERT INTO test1 VALUES (2, _utf16'\x00b\x00,\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "INSERT INTO test2 VALUES (2, _utf16'\x00b\x00,\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "SELECT * FROM test1 ORDER BY pk;",
				Expected: []sql.Row{
					{"1", "\x00a"}, {"2", "\x00b\x00,\x00c"},
				},
			},
			{
				Query: "SELECT * FROM test2 ORDER BY pk;",
				Expected: []sql.Row{
					{"2", "b,c"},
				},
			},
		},
	},
	{
		Name: "Correct behavior with `character_set_results`",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
			"CREATE TABLE test (v1 VARCHAR(255) COLLATE utf16_unicode_ci);",
			"INSERT INTO test VALUES (_utf8mb4'hey');",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{"\x00h\x00e\x00y"}},
			},
			{
				Query:    "SET character_set_results = 'utf8mb4';",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{"hey"}},
			},
			{
				Query:    "SET character_set_results = 'utf32';",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{"\x00\x00\x00h\x00\x00\x00e\x00\x00\x00y"}},
			},
		},
	},
	{
		Name: "LIKE respects table collations",
		SetUpScript: []string{
			"SET NAMES utf8mb4;",
			"CREATE TABLE test(v1 VARCHAR(100) COLLATE utf8mb4_0900_bin, v2 VARCHAR(100) COLLATE utf8mb4_0900_ai_ci);",
			"INSERT INTO test VALUES ('abc', 'abc'), ('ABC', 'ABC');",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'ABC';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE 'ABC';",
				Expected: []sql.Row{
					{"2"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'A%';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE 'A%';",
				Expected: []sql.Row{
					{"2"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE '%C';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE '%C';",
				Expected: []sql.Row{
					{"2"},
				},
			},
			{
				Query:    "SET collation_connection = 'utf8mb4_0900_bin';",
				Expected: []sql.Row{{}},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'ABC';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v2 LIKE 'ABC';",
				Expected: []sql.Row{
					{"2"},
				},
			},
			{
				Query: "SELECT COUNT(*) FROM test WHERE v1 LIKE 'ABC' COLLATE utf8mb4_0900_ai_ci;",
				Expected: []sql.Row{
					{"2"},
				},
			},
		},
	},
	{
		Name: "LIKE respects connection collation",
		SetUpScript: []string{
			"SET NAMES utf8mb4;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT 'abc' LIKE 'ABC';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_bin LIKE 'ABC';",
				Expected: []sql.Row{
					{"0"},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_bin;",
				Expected: []sql.Row{
					{"0"},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_ai_ci LIKE 'ABC';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_ai_ci;",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query:    "SET collation_connection = 'utf8mb4_0900_bin';",
				Expected: []sql.Row{{}},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC';",
				Expected: []sql.Row{
					{"0"},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_ai_ci LIKE 'ABC';",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_ai_ci;",
				Expected: []sql.Row{
					{"1"},
				},
			},
			{
				Query: "SELECT 'abc' COLLATE utf8mb4_0900_bin LIKE 'ABC';",
				Expected: []sql.Row{
					{"0"},
				},
			},
			{
				Query: "SELECT 'abc' LIKE 'ABC' COLLATE utf8mb4_0900_bin;",
				Expected: []sql.Row{
					{"0"},
				},
			},
			{
				Query: "SELECT _utf8mb4'abc' LIKE 'ABC';",
				Expected: []sql.Row{
					{"0"},
				},
			},
			{
				Query: "SELECT 'abc' LIKE _utf8mb4'ABC';",
				Expected: []sql.Row{
					{"0"},
				},
			},
		},
	},
	{
		Name: "STRCMP() function",
		Queries: []CharsetCollationWireTestQuery{

			{

				Query: "SELECT STRCMP(_utf8mb4'A' COLLATE utf8mb4_0900_ai_ci, _latin1'b' COLLATE latin1_general_cs)",
				Expected: []sql.Row{
					{"-1"},
				},
			},
		},
	},
	{
		Name: "LENGTH() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT LENGTH(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"6"},
				},
			},
			{
				Query: "SELECT LENGTH(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"3"},
				},
			},
			{
				Query: "SELECT LENGTH(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"6"},
				},
			},
		},
	},
	{
		Name: "CHAR_LENGTH() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT CHAR_LENGTH(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"3"},
				},
			},
			{
				Query: "SELECT CHAR_LENGTH(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"3"},
				},
			},
			{
				Query: "SELECT CHAR_LENGTH(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"6"},
				},
			},
		},
	},
	{
		Name: "UPPER() function",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT UPPER(_utf16'\x00a\x00B\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00A\x00B\x00C"},
				},
			},
			{
				Query: "SELECT UPPER(_utf8mb4'aBc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"ABC"},
				},
			},
			{
				Query: "SELECT UPPER(_utf8mb4'\x00a\x00B\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00A\x00B\x00C"},
				},
			},
		},
	},
	{
		Name: "LOWER() function",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT LOWER(_utf16'\x00A\x00b\x00C' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT LOWER(_utf8mb4'AbC' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT LOWER(_utf8mb4'\x00A\x00b\x00C' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
		},
	},
	{
		Name: "RPAD() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT RPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, 'z');",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abczzz"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT RPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 9, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00czzz"},
				},
			},
		},
	},
	{
		Name: "LPAD() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT LPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, 'z');",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf8mb4'z' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'abc' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"zzzabc"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 6, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT LPAD(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin, 9, _utf16'\x00z' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"zzz\x00a\x00b\x00c"},
				},
			},
		},
	},
	{
		Name: "HEX() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT HEX(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"006100620063"},
				},
			},
			{
				Query: "SELECT HEX(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"616263"},
				},
			},
			{
				Query: "SELECT HEX(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"006100620063"},
				},
			},
		},
	},
	{
		Name: "UNHEX() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT UNHEX(_utf16'\x006\x001\x006\x002\x006\x003' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT UNHEX(_utf8mb4'616263' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
		},
	},
	{
		Name: "SUBSTRING() function",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT SUBSTRING(_utf16'\x00a\x00b\x00c\x00d' COLLATE utf16_unicode_ci, 2, 2);",
				Expected: []sql.Row{
					{"\x00b\x00c"},
				},
			},
			{
				Query: "SELECT SUBSTRING(_utf8mb4'abcd' COLLATE utf8mb4_0900_bin, 2, 2);",
				Expected: []sql.Row{
					{"bc"},
				},
			},
			{
				Query: "SELECT SUBSTRING(_utf8mb4'\x00a\x00b\x00c\x00d' COLLATE utf8mb4_0900_bin, 2, 2);",
				Expected: []sql.Row{
					{"a\x00"},
				},
			},
		},
	},
	{
		Name: "TO_BASE64() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT TO_BASE64(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"AGEAYgBj"},
				},
			},
			{
				Query: "SELECT TO_BASE64(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"YWJj"},
				},
			},
			{
				Query: "SELECT TO_BASE64(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"AGEAYgBj"},
				},
			},
		},
	},
	{
		Name: "FROM_BASE64() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT FROM_BASE64(_utf16'\x00Y\x00W\x00J\x00j' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT FROM_BASE64(_utf8mb4'YWJj' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
		},
	},
	{
		Name: "TRIM() function",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT TRIM(_utf16'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT TRIM(_utf8mb4' abc ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT TRIM(_utf8mb4'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c\x00"},
				},
			},
		},
	},
	{
		Name: "RTRIM() function",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT RTRIM(_utf16'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT RTRIM(_utf8mb4' abc ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{" abc"},
				},
			},
			{
				Query: "SELECT RTRIM(_utf8mb4'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c\x00"},
				},
			},
		},
	},
	{
		Name: "LTRIM() function",
		SetUpScript: []string{
			"SET character_set_results = 'binary';",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT LTRIM(_utf16'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c\x00 "},
				},
			},
			{
				Query: "SELECT LTRIM(_utf8mb4' abc ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc "},
				},
			},
			{
				Query: "SELECT LTRIM(_utf8mb4'\x00 \x00a\x00b\x00c\x00 ' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00 \x00a\x00b\x00c\x00 "},
				},
			},
		},
	},
	{
		Name: "BINARY() function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT BINARY(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT BINARY(_utf8mb4'abc' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT BINARY(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
		},
	},
	{
		Name: "CAST(... AS BINARY) function",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "SELECT CAST(_utf16'\x00a\x00b\x00c' COLLATE utf16_unicode_ci AS BINARY);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
			{
				Query: "SELECT CAST(_utf8mb4'abc' COLLATE utf8mb4_0900_bin AS BINARY);",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "SELECT CAST(_utf8mb4'\x00a\x00b\x00c' COLLATE utf8mb4_0900_bin AS BINARY);",
				Expected: []sql.Row{
					{"\x00a\x00b\x00c"},
				},
			},
		},
	},
}

CharsetCollationWireTests are used to ensure that character sets and collations have the correct behavior over the wire. Return values should all have the table encoding, as it's returning the table's encoding type.

View Source
var ChecksOnUpdateScriptTests = []ScriptTest{
	{
		Name: "Single table updates",
		SetUpScript: []string{
			"CREATE TABLE t1 (a INTEGER PRIMARY KEY, b INTEGER)",
			"ALTER TABLE t1 ADD CONSTRAINT chk1 CHECK (b > 10) NOT ENFORCED",
			"ALTER TABLE t1 ADD CONSTRAINT chk2 CHECK (b > 0)",
			"ALTER TABLE t1 ADD CONSTRAINT chk3 CHECK ((a + b) / 2 >= 1) ENFORCED",
			"INSERT INTO t1 VALUES (1,1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM t1;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:       "UPDATE t1 set b = 0;",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
			{
				Query:       "UPDATE t1 set a = 0, b = 1;",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
			{
				Query:       "UPDATE t1 set b = 0 WHERE b = 1;",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
			{
				Query:       "UPDATE t1 set a = 0, b = 1 WHERE b = 1;",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
		},
	},
	{
		Name: "Update join updates",
		SetUpScript: []string{
			"CREATE TABLE sales (year_built int primary key, CONSTRAINT `valid_year_built` CHECK (year_built <= 2022));",
			"INSERT INTO sales VALUES (1981);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "UPDATE sales JOIN (SELECT year_built FROM sales) AS t ON sales.year_built = t.year_built SET sales.year_built = 1901;",
				Expected: []sql.Row{{types.OkResult{1, 0, plan.UpdateInfo{1, 1, 0}}}},
			},
			{
				Query:    "select * from sales;",
				Expected: []sql.Row{{1901}},
			},
			{
				Query:    "UPDATE sales as s1 JOIN (SELECT year_built FROM sales) AS t SET S1.year_built = 1902;",
				Expected: []sql.Row{{types.OkResult{1, 0, plan.UpdateInfo{1, 1, 0}}}},
			},
			{
				Query:    "select * from sales;",
				Expected: []sql.Row{{1902}},
			},
			{
				Query:       "UPDATE sales as s1 JOIN (SELECT year_built FROM sales) AS t SET t.year_built = 1903;",
				ExpectedErr: plan.ErrUpdateForTableNotSupported,
			},
			{
				Query:       "UPDATE sales JOIN (SELECT year_built FROM sales) AS t SET sales.year_built = 2030;",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
			{
				Query:       "UPDATE sales as s1 JOIN (SELECT year_built FROM sales) AS t SET s1.year_built = 2030;",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
			{
				Query:       "UPDATE sales as s1 JOIN (SELECT year_built FROM sales) AS t SET t.year_built = 2030;",
				ExpectedErr: plan.ErrUpdateForTableNotSupported,
			},
		},
	},
}
View Source
var ColumnAliasQueries = []ScriptTest{
	{
		Name: "column aliases in a single scope",
		SetUpScript: []string{
			"create table xy (x int primary key, y int);",
			"create table uv (u int primary key, v int);",
			"insert into xy values (0,0),(1,1),(2,2),(3,3);",
			"insert into uv values (0,3),(3,0),(2,1),(1,2);",
		},
		Assertions: []ScriptTestAssertion{
			{

				Query: `SELECT i AS cOl FROM mytable`,
				ExpectedColumns: sql.Schema{
					{
						Name: "cOl",
						Type: types.Int64,
					},
				},
				Expected: []sql.Row{{int64(1)}, {int64(2)}, {int64(3)}},
			},
			{
				Query: `SELECT i AS cOl, s as COL FROM mytable`,
				ExpectedColumns: sql.Schema{
					{
						Name: "cOl",
						Type: types.Int64,
					},
					{
						Name: "COL",
						Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
					},
				},
				Expected: []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
			},
			{

				Query:       `SELECT i AS new1, new1 as new2 FROM mytable`,
				ExpectedErr: sql.ErrMisusedAlias,
			},
			{

				Query:       `SELECT i AS cOl, s as COL FROM mytable where cOl = 1`,
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{

				Query:       "select t1.i as a, t1.s as b from mytable as t1 left join mytable as t2 on a = t2.i;",
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{

				Query:    "select 1 as a order by a desc;",
				Expected: []sql.Row{{1}},
			},
			{

				Query:    "select v as u from uv order by u;",
				Expected: []sql.Row{{0}, {1}, {2}, {3}},
			},
			{

				Query:       "select u as u, v as u from uv order by u;",
				ExpectedErr: sql.ErrAmbiguousColumnOrAliasName,
			},
			{

				Query: `SELECT s as COL1, SUM(i) COL2 FROM mytable group by col1 order by col2`,
				ExpectedColumns: sql.Schema{
					{
						Name: "COL1",
						Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
					},
					{
						Name: "COL2",
						Type: types.Int64,
					},
				},
				Expected: []sql.Row{
					{"first row", float64(1)},
					{"second row", float64(2)},
					{"third row", float64(3)},
				},
			},
			{

				Query:    "select t1.u as a from uv as t1 having a > 0 order by a;",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{

				Query:    "select t1.u as a from uv as t1 having a = t1.u order by a;",
				Expected: []sql.Row{{0}, {1}, {2}, {3}},
			},
			{

				Query: `SELECT s as coL1, SUM(i) coL2 FROM mytable group by 1 order by 2`,
				ExpectedColumns: sql.Schema{
					{
						Name: "coL1",
						Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
					},
					{
						Name: "coL2",
						Type: types.Int64,
					},
				},
				Expected: []sql.Row{
					{"first row", float64(1)},
					{"second row", float64(2)},
					{"third row", float64(3)},
				},
			},
			{

				Query: `SELECT s as Date, SUM(i) TimeStamp FROM mytable group by 1 order by 2`,
				ExpectedColumns: sql.Schema{
					{
						Name: "Date",
						Type: types.MustCreateStringWithDefaults(sqltypes.VarChar, 20),
					},
					{
						Name: "TimeStamp",
						Type: types.Int64,
					},
				},
				Expected: []sql.Row{
					{"first row", float64(1)},
					{"second row", float64(2)},
					{"third row", float64(3)},
				},
			},
			{
				Query:    "select t1.i as a from mytable as t1 having a = t1.i;",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
		},
	},
	{
		Name: "column aliases in two scopes",
		SetUpScript: []string{
			"create table xy (x int primary key, y int);",
			"create table uv (u int primary key, v int);",
			"insert into xy values (0,0),(1,1),(2,2),(3,3);",
			"insert into uv values (0,3),(3,0),(2,1),(1,2);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    `select "foo" as dummy, (select dummy)`,
				Expected: []sql.Row{{"foo", "foo"}},
			},
			{

				Query:    "select x as v, (select u from uv where v = y) as u from xy;",
				Expected: []sql.Row{{0, 3}, {1, 2}, {2, 1}, {3, 0}},
			},
			{

				Skip: true,

				Query:    "select 0 as a, 1 as a, (SELECT x from xy where x = a);",
				Expected: []sql.Row{{0, 1, 0}},
			},
			{
				Query:    "SELECT 1 as a, (select a) as a;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:    "SELECT 1 as a, (select a) as b;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:    "SELECT 1 as a, (select a) as b from dual;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:    "SELECT 1 as a, (select a) as b from xy;",
				Expected: []sql.Row{{1, 1}, {1, 1}, {1, 1}, {1, 1}},
			},
			{
				Query:    "select x, (select 1) as y from xy;",
				Expected: []sql.Row{{0, 1}, {1, 1}, {2, 1}, {3, 1}},
			},
			{
				Query:    "SELECT 1 as a, (select a) from xy;",
				Expected: []sql.Row{{1, 1}, {1, 1}, {1, 1}, {1, 1}},
			},
		},
	},
	{
		Name: "column aliases in three scopes",
		SetUpScript: []string{
			"create table xy (x int primary key, y int);",
			"create table uv (u int primary key, v int);",
			"insert into xy values (0,0),(1,1),(2,2),(3,3);",
			"insert into uv values (0,3),(3,0),(2,1),(1,2);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select x, (select 1) as y, (select (select y as q)) as z from (select * from xy) as xy;",
				Expected: []sql.Row{{0, 1, 0}, {1, 1, 1}, {2, 1, 2}, {3, 1, 3}},
			},
		},
	},
	{
		Name: "various broken alias queries",
		Assertions: []ScriptTestAssertion{
			{

				Skip:     true,
				Query:    `SELECT *, (select i union select i) as a from mytable;`,
				Expected: []sql.Row{{1, "first row", 1}, {2, "second row", 2}, {3, "third row", 3}},
			},
			{

				Skip:     true,
				Query:    `SELECT 1 as a, (select a union select a) as b;`,
				Expected: []sql.Row{{1, 1}},
			},
			{

				Skip:        true,
				Query:       `select 1 as a, (select b), 0 as b;`,
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{

				Skip:  true,
				Query: "select 1 as a, one + 1 as mod1, dt.* from mytable as t1, (select 1, 2 from mytable) as dt (one, two) where dt.one > 0 group by one;",

				Expected: []sql.Row{{1, 2, 1, 2}},
			},
			{

				Skip:     true,
				Query:    "select 1 as b, (select b group by b order by b) order by 1;",
				Expected: []sql.Row{{1, 1}},
			},
		},
	},
}
View Source
var ComplexIndexQueries = []QueryTest{}/* 703 elements not displayed */
View Source
var CreateCheckConstraintsScripts = []ScriptTest{
	{
		Name: "Run SHOW CREATE TABLE with different types of check constraints",
		SetUpScript: []string{
			"CREATE TABLE mytable1(pk int PRIMARY KEY, CONSTRAINT check1 CHECK (pk = 5))",
			"ALTER TABLE mytable1 ADD CONSTRAINT check11 CHECK (pk < 6)",
			"CREATE TABLE mytable2(pk int PRIMARY KEY, v int, CONSTRAINT check2 CHECK (v < 5))",
			"ALTER TABLE mytable2 ADD CONSTRAINT check12 CHECK (pk  + v = 6)",
			"CREATE TABLE mytable3(pk int PRIMARY KEY, v int, CONSTRAINT check3 CHECK (pk > 2 AND v < 5))",
			"ALTER TABLE mytable3 ADD CONSTRAINT check13 CHECK (pk BETWEEN 2 AND 100)",
			"CREATE TABLE mytable4(pk int PRIMARY KEY, v int, CONSTRAINT check4 CHECK (pk > 2 AND v < 5 AND pk < 9))",
			"CREATE TABLE mytable5(pk int PRIMARY KEY, v int, CONSTRAINT check5 CHECK (pk > 2 OR (v < 5 AND pk < 9)))",
			"CREATE TABLE mytable6(pk int PRIMARY KEY, v int, CONSTRAINT check6 CHECK (NOT pk))",
			"CREATE TABLE mytable7(pk int PRIMARY KEY, v int, CONSTRAINT check7 CHECK (pk != v))",
			"CREATE TABLE mytable8(pk int PRIMARY KEY, v int, CONSTRAINT check8 CHECK (pk > 2 OR v < 5 OR pk < 10))",
			"CREATE TABLE mytable9(pk int PRIMARY KEY, v int, CONSTRAINT check9 CHECK ((pk + v) / 2 >= 1))",
			"CREATE TABLE mytable10(pk int PRIMARY KEY, v int, CONSTRAINT check10 CHECK (v < 5) NOT ENFORCED)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SHOW CREATE TABLE mytable1",
				Expected: []sql.Row{
					{
						"mytable1",
						"CREATE TABLE `mytable1` (\n  `pk` int NOT NULL,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check1` CHECK ((`pk` = 5)),\n" +
							"  CONSTRAINT `check11` CHECK ((`pk` < 6))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable2",
				Expected: []sql.Row{
					{
						"mytable2",
						"CREATE TABLE `mytable2` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check2` CHECK ((`v` < 5)),\n" +
							"  CONSTRAINT `check12` CHECK (((`pk` + `v`) = 6))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable3",
				Expected: []sql.Row{
					{
						"mytable3",
						"CREATE TABLE `mytable3` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check3` CHECK (((`pk` > 2) AND (`v` < 5))),\n" +
							"  CONSTRAINT `check13` CHECK ((`pk` BETWEEN 2 AND 100))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable4",
				Expected: []sql.Row{
					{
						"mytable4",
						"CREATE TABLE `mytable4` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check4` CHECK ((((`pk` > 2) AND (`v` < 5)) AND (`pk` < 9)))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable5",
				Expected: []sql.Row{
					{
						"mytable5",
						"CREATE TABLE `mytable5` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check5` CHECK (((`pk` > 2) OR ((`v` < 5) AND (`pk` < 9))))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable6",
				Expected: []sql.Row{
					{
						"mytable6",
						"CREATE TABLE `mytable6` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check6` CHECK ((NOT(`pk`)))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable7",
				Expected: []sql.Row{
					{
						"mytable7",
						"CREATE TABLE `mytable7` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check7` CHECK ((NOT((`pk` = `v`))))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable8",
				Expected: []sql.Row{
					{
						"mytable8",
						"CREATE TABLE `mytable8` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check8` CHECK ((((`pk` > 2) OR (`v` < 5)) OR (`pk` < 10)))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable9",
				Expected: []sql.Row{
					{
						"mytable9",
						"CREATE TABLE `mytable9` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check9` CHECK ((((`pk` + `v`) / 2) >= 1))\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE TABLE mytable10",
				Expected: []sql.Row{
					{
						"mytable10",
						"CREATE TABLE `mytable10` (\n  `pk` int NOT NULL,\n" +
							"  `v` int,\n" +
							"  PRIMARY KEY (`pk`),\n" +
							"  CONSTRAINT `check10` CHECK ((`v` < 5)) /*!80016 NOT ENFORCED */\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
		},
	},
	{
		Name: "Create a table with a check and validate that it appears in check_constraints and table_constraints",
		SetUpScript: []string{
			"CREATE TABLE mytable (pk int primary key, test_score int, height int, CONSTRAINT mycheck CHECK (test_score >= 50), CONSTRAINT hcheck CHECK (height < 10), CONSTRAINT vcheck CHECK (height > 0))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * from information_schema.check_constraints where constraint_name IN ('mycheck', 'hcheck') ORDER BY constraint_name",
				Expected: []sql.Row{
					{"def", "mydb", "hcheck", "(height < 10)"},
					{"def", "mydb", "mycheck", "(test_score >= 50)"},
				},
			},
			{
				Query: "SELECT * FROM information_schema.table_constraints where table_name='mytable' ORDER BY constraint_type,constraint_name",
				Expected: []sql.Row{
					{"def", "mydb", "hcheck", "mydb", "mytable", "CHECK", "YES"},
					{"def", "mydb", "mycheck", "mydb", "mytable", "CHECK", "YES"},
					{"def", "mydb", "vcheck", "mydb", "mytable", "CHECK", "YES"},
					{"def", "mydb", "PRIMARY", "mydb", "mytable", "PRIMARY KEY", "YES"},
				},
			},
		},
	},
	{
		Name: "multi column index, lower()",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 varchar(100), v2 varchar(100), INDEX (v1,v2));",
			"INSERT INTO test VALUES (1,'happy','birthday'), (2,'HAPPY','BIRTHDAY'), (3,'hello','sailor');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT pk FROM test where lower(v1) = 'happy' and lower(v2) = 'birthday' order by 1",
				Expected: []sql.Row{{1}, {2}},
			},
		},
	},
	{
		Name: "adding check constraint to a table that violates said constraint correctly throws an error",
		SetUpScript: []string{
			"CREATE TABLE test (pk int)",
			"INSERT INTO test VALUES (1),(2),(300)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE test ADD CONSTRAINT bad_check CHECK (pk < 5)",
				ExpectedErr: plan.ErrCheckViolated,
			},
		},
	},
	{
		Name: "duplicate indexes still returns correct results",
		SetUpScript: []string{
			"CREATE TABLE test (i int)",
			"CREATE INDEX test_idx1 on test (i)",
			"CREATE INDEX test_idx2 on test (i)",
			"INSERT INTO test values (1), (2), (3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM test ORDER BY i",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query: "SELECT * FROM test where i = 2",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
}
View Source
var CreateTableQueries = []WriteQueryTest{
	{
		WriteQuery:          `create table floattypedefs (a float(10), b float(10, 2), c double(10, 2))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE floattypedefs",
		ExpectedSelect:      []sql.Row{sql.Row{"floattypedefs", "CREATE TABLE `floattypedefs` (\n  `a` float,\n  `b` float,\n  `c` double\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (a INTEGER, b TEXT, c DATE, d TIMESTAMP, e VARCHAR(20), f BLOB NOT NULL, b1 BOOL, b2 BOOLEAN NOT NULL, g DATETIME, h CHAR(40))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int,\n  `b` text,\n  `c` date,\n  `d` timestamp,\n  `e` varchar(20),\n  `f` blob NOT NULL,\n  `b1` tinyint,\n  `b2` tinyint NOT NULL,\n  `g` datetime,\n  `h` char(40)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (a INTEGER NOT NULL PRIMARY KEY, b VARCHAR(10) NOT NULL)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int NOT NULL,\n  `b` varchar(10) NOT NULL,\n  PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (a INTEGER, b TEXT NOT NULL COMMENT 'comment', c bool, primary key (a))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int NOT NULL,\n  `b` text NOT NULL COMMENT 'comment',\n  `c` tinyint,\n  PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (a INTEGER, create_time timestamp(6) NOT NULL DEFAULT NOW(6), primary key (a))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int NOT NULL,\n  `create_time` timestamp NOT NULL DEFAULT (NOW(6)),\n  PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 LIKE mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `i` bigint NOT NULL,\n  `s` varchar(20) NOT NULL COMMENT 'column s',\n  PRIMARY KEY (`i`),\n  KEY `idx_si` (`s`,`i`),\n  KEY `mytable_i_s` (`i`,`s`),\n  UNIQUE KEY `mytable_s` (`s`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery: `CREATE TABLE t1 (
			pk bigint primary key,
			v1 bigint default (2) comment 'hi there',
			index idx_v1 (v1) comment 'index here'
			)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `pk` bigint NOT NULL,\n  `v1` bigint DEFAULT (2) COMMENT 'hi there',\n  PRIMARY KEY (`pk`),\n  KEY `idx_v1` (`v1`) COMMENT 'index here'\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `create table t1 like foo.other_table`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `text` varchar(20) NOT NULL,\n  `number` mediumint,\n  PRIMARY KEY (`text`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (a INTEGER NOT NULL PRIMARY KEY, b VARCHAR(10) UNIQUE)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int NOT NULL,\n  `b` varchar(10),\n  PRIMARY KEY (`a`),\n  UNIQUE KEY `b` (`b`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (a INTEGER NOT NULL PRIMARY KEY, b VARCHAR(10) UNIQUE KEY)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int NOT NULL,\n  `b` varchar(10),\n  PRIMARY KEY (`a`),\n  UNIQUE KEY `b` (`b`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 SELECT * from mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `i` bigint NOT NULL,\n  `s` varchar(20) NOT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE mydb.t1 (a INTEGER NOT NULL PRIMARY KEY, b VARCHAR(10) NOT NULL)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE mydb.t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `a` int NOT NULL,\n  `b` varchar(10) NOT NULL,\n  PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (i int primary key, j int auto_increment unique)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `j` int AUTO_INCREMENT,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `j` (`j`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (i int primary key, j int auto_increment, index (j))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `j` int AUTO_INCREMENT,\n  PRIMARY KEY (`i`),\n  KEY `j` (`j`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (i int primary key, j int auto_increment, k int, unique(j,k))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `j` int AUTO_INCREMENT,\n  `k` int,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `jk` (`j`,`k`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (i int primary key, j int auto_increment, k int, index (j,k))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `j` int AUTO_INCREMENT,\n  `k` int,\n  PRIMARY KEY (`i`),\n  KEY `jk` (`j`,`k`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery: `CREATE TABLE t1 (
		  pk int NOT NULL,
		  col1 blob DEFAULT (_utf8mb4'abc'),
		  col2 json DEFAULT (json_object(_utf8mb4'a',1)),
		  col3 text DEFAULT (_utf8mb4'abc'),
		  PRIMARY KEY (pk)
		)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE t1",
		ExpectedSelect:      []sql.Row{sql.Row{"t1", "CREATE TABLE `t1` (\n  `pk` int NOT NULL,\n  `col1` blob DEFAULT ('abc'),\n  `col2` json DEFAULT (json_object('a',1)),\n  `col3` text DEFAULT ('abc'),\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery: `CREATE TABLE td (
		  pk int PRIMARY KEY,
		  col2 int NOT NULL DEFAULT 2,
 		  col3 double NOT NULL DEFAULT (round(-(1.58),0)),
		  col4 varchar(10) DEFAULT 'new row',
          col5 float DEFAULT 33.33,
          col6 int DEFAULT NULL,
		  col7 timestamp DEFAULT NOW(),
		  col8 bigint DEFAULT (NOW())
		)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SHOW CREATE TABLE td",
		ExpectedSelect:      []sql.Row{sql.Row{"td", "CREATE TABLE `td` (\n  `pk` int NOT NULL,\n  `col2` int NOT NULL DEFAULT '2',\n  `col3` double NOT NULL DEFAULT (round(-1.58,0)),\n  `col4` varchar(10) DEFAULT 'new row',\n  `col5` float DEFAULT '33.33',\n  `col6` int DEFAULT NULL,\n  `col7` timestamp DEFAULT (NOW()),\n  `col8` bigint DEFAULT (NOW()),\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 (i int PRIMARY KEY, j varchar(MAX))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `SHOW CREATE TABLE t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `j` varchar(16383),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `create table t1 (i int primary key, b1 blob, b2 blob, index(b1(123), b2(456)))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `b1` blob,\n  `b2` blob,\n  PRIMARY KEY (`i`),\n  KEY `b1b2` (`b1`(123),`b2`(456))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `create table t1 (i int primary key, b1 blob, b2 blob, unique index(b1(123), b2(456)))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `b1` blob,\n  `b2` blob,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `b1b2` (`b1`(123),`b2`(456))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `create table t1 (i int primary key, b1 blob, b2 blob, index(b1(10)), index(b2(20)), index(b1(123), b2(456)))`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `i` int NOT NULL,\n  `b1` blob,\n  `b2` blob,\n  PRIMARY KEY (`i`),\n  KEY `b1` (`b1`(10)),\n  KEY `b1b2` (`b1`(123),`b2`(456)),\n  KEY `b2` (`b2`(20))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select * from mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `select * from t1 order by i`,
		ExpectedSelect:      []sql.Row{{1, "first row"}, {2, "second row"}, {3, "third row"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select * from mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `show create table t1`,
		ExpectedSelect:      []sql.Row{{"t1", "CREATE TABLE `t1` (\n  `i` bigint NOT NULL,\n  `s` varchar(20) NOT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select s, i from mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `select * from t1 order by i`,
		ExpectedSelect:      []sql.Row{{"first row", 1}, {"second row", 2}, {"third row", 3}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select distinct s, i from mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `select * from t1 order by i`,
		ExpectedSelect:      []sql.Row{{"first row", 1}, {"second row", 2}, {"third row", 3}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select s, i from mytable order by s`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `select * from t1 order by i`,
		ExpectedSelect:      []sql.Row{{"first row", 1}, {"second row", 2}, {"third row", 3}},
	},

	{
		WriteQuery:          `CREATE TABLE t1 as select s, sum(i) from mytable group by s`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `select * from t1 order by s`,
		ExpectedSelect:      []sql.Row{{"first row", 1}, {"second row", 2}, {"third row", 3}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select s, sum(i) from mytable group by s having sum(i) > 2`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "select * from t1",
		ExpectedSelect:      []sql.Row{{"third row", 3}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select s, i from mytable order by s limit 1`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         `select * from t1 order by i`,
		ExpectedSelect:      []sql.Row{{"first row", 1}},
	},
	{
		WriteQuery:          `CREATE TABLE t1 as select concat("new", s), i from mytable`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         `select * from t1 order by i`,
		ExpectedSelect:      []sql.Row{{"newfirst row", 1}, {"newsecond row", 2}, {"newthird row", 3}},
	},
}
View Source
var DatabaseCollationWireTests = []CharsetCollationWireTest{
	{
		Name: "CREATE DATABASE default collation",
		SetUpScript: []string{
			"CREATE DATABASE test_db;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb4", "utf8mb4_0900_bin"},
				},
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "CREATE DATABASE set character set only",
		SetUpScript: []string{
			"CREATE DATABASE test_db CHARACTER SET utf8mb3;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_general_ci"},
				},
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "CREATE DATABASE set collation only",
		SetUpScript: []string{
			"CREATE DATABASE test_db_a COLLATE latin1_general_ci;",
			"CREATE DATABASE test_db_b COLLATE latin1_general_cs;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"latin1", "latin1_general_ci"},
				},
			},
			{
				Query:    "USE test_db_b;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"latin1", "latin1_general_cs"},
				},
			},
			{
				Query:    "DROP DATABASE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query:    "DROP DATABASE test_db_b;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "CREATE DATABASE set character set and collation",
		SetUpScript: []string{
			"CREATE DATABASE test_db CHARACTER SET utf8mb3 COLLATE utf8mb3_bin;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_bin"},
				},
			},
			{
				Query: "CREATE DATABASE invalid_db CHARACTER SET utf8mb4 COLLATE ascii_bin;",
				Error: true,
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "ALTER DATABASE requires character set or collation",
		SetUpScript: []string{
			"CREATE DATABASE test_db;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: "ALTER DATABASE test_db;",
				Error: true,
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "ALTER DATABASE set character set only",
		SetUpScript: []string{
			"CREATE DATABASE test_db;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb4", "utf8mb4_0900_bin"},
				},
			},
			{
				Query:    "ALTER DATABASE test_db CHARACTER SET utf8mb3;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_general_ci"},
				},
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "ALTER DATABASE set collation only",
		SetUpScript: []string{
			"CREATE DATABASE test_db_a COLLATE latin1_general_ci;",
			"CREATE DATABASE test_db_b COLLATE latin1_general_cs;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"latin1", "latin1_general_ci"},
				},
			},
			{
				Query:    "USE test_db_b;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"latin1", "latin1_general_cs"},
				},
			},
			{
				Query:    "ALTER DATABASE test_db_a COLLATE utf8mb3_bin;",
				Expected: []sql.Row{},
			},
			{
				Query:    "ALTER DATABASE test_db_b COLLATE utf8mb3_general_ci;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_general_ci"},
				},
			},
			{
				Query:    "USE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_bin"},
				},
			},
			{
				Query:    "DROP DATABASE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query:    "DROP DATABASE test_db_b;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "ALTER DATABASE set character set and collation",
		SetUpScript: []string{
			"CREATE DATABASE test_db CHARACTER SET utf8mb3 COLLATE utf8mb3_bin;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_bin"},
				},
			},
			{
				Query:    "ALTER DATABASE test_db CHARACTER SET ascii COLLATE ascii_bin;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT @@character_set_database, @@collation_database;",
				Expected: []sql.Row{
					{"ascii", "ascii_bin"},
				},
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Tables inherit database collation",
		SetUpScript: []string{
			"CREATE DATABASE test_db COLLATE utf8mb3_bin;",
			"CREATE TABLE test_db.other (pk VARCHAR(20) PRIMARY KEY) COLLATE utf8mb3_unicode_ci;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db;",
				Expected: []sql.Row{},
			},
			{
				Query: "CREATE TABLE test_a (pk VARCHAR(20) PRIMARY KEY);",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "CREATE TABLE test_b LIKE other;",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "CREATE TABLE test_c AS SELECT * FROM other;",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "SHOW CREATE TABLE test_a;",
				Expected: []sql.Row{
					{"test_a", "CREATE TABLE `test_a` (\n  `pk` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_bin NOT NULL,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin"},
				},
			},
			{
				Query: "SHOW CREATE TABLE test_b;",
				Expected: []sql.Row{
					{"test_b", "CREATE TABLE `test_b` (\n  `pk` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci"},
				},
			},
			{
				Query: "SHOW CREATE TABLE test_c;",
				Expected: []sql.Row{
					{"test_c", "CREATE TABLE `test_c` (\n  `pk` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin"},
				},
			},
			{
				Query:    "ALTER DATABASE test_db COLLATE utf8mb3_general_ci;",
				Expected: []sql.Row{},
			},
			{
				Query: "CREATE TABLE test_d (pk VARCHAR(20) PRIMARY KEY);",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "SHOW CREATE TABLE test_d;",
				Expected: []sql.Row{
					{"test_d", "CREATE TABLE `test_d` (\n  `pk` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci"},
				},
			},
			{
				Query:    "DROP DATABASE test_db;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "INFORMATION_SCHEMA shows character set and collation",
		SetUpScript: []string{
			"CREATE DATABASE test_db_a COLLATE latin1_general_ci;",
			"CREATE DATABASE test_db_b COLLATE latin1_general_cs;",
		},
		Queries: []CharsetCollationWireTestQuery{
			{
				Query:    "USE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'test_db_a';",
				Expected: []sql.Row{
					{"latin1", "latin1_general_ci"},
				},
			},
			{
				Query: "SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'test_db_b';",
				Expected: []sql.Row{
					{"latin1", "latin1_general_cs"},
				},
			},
			{
				Query:    "ALTER DATABASE test_db_a COLLATE utf8mb3_general_ci;",
				Expected: []sql.Row{},
			},
			{
				Query: "SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'test_db_a';",
				Expected: []sql.Row{
					{"utf8mb3", "utf8mb3_general_ci"},
				},
			},
			{
				Query:    "DROP DATABASE test_db_a;",
				Expected: []sql.Row{},
			},
			{
				Query:    "DROP DATABASE test_db_b;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Issue #5482",
		Queries: []CharsetCollationWireTestQuery{
			{
				Query: `SELECT T.TABLE_NAME AS label, 'connection.table' as type, T.TABLE_SCHEMA AS 'schema',
T.TABLE_SCHEMA AS 'database', T.TABLE_CATALOG AS 'catalog',
0 AS isView FROM INFORMATION_SCHEMA.TABLES AS T WHERE T.TABLE_CATALOG = 'def' AND
                                                      UPPER(T.TABLE_TYPE) = 'BASE TABLE' ORDER BY T.TABLE_NAME;`,
				Expected: []sql.Row(nil),
			},
		},
	},
}

DatabaseCollationWireTests are used to validate that CREATE DATABASE and ALTER DATABASE correctly handle having their character set and collations modified.

View Source
var DateParseQueries = []QueryTest{
	{
		Query:    "SELECT STR_TO_DATE('Jan 3, 2000', '%b %e, %Y')",
		Expected: []sql.Row{{"2000-01-03"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('01,5,2013', '%d,%m,%Y')",
		Expected: []sql.Row{{"2013-05-01"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('May 1, 2013','%M %d,%Y')",
		Expected: []sql.Row{{"2013-05-01"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('a09:30:17','a%h:%i:%s')",
		Expected: []sql.Row{{"09:30:17"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('a09:30:17','%h:%i:%s')",
		Expected: []sql.Row{{nil}},
	},
	{
		Query:    "SELECT STR_TO_DATE('09:30:17a','%h:%i:%s')",
		Expected: []sql.Row{{"09:30:17"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('09:30:17 pm','%h:%i:%s %p')",
		Expected: []sql.Row{{"21:30:17"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('9','%m')",
		Expected: []sql.Row{{"0000-09-00"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('9','%s')",
		Expected: []sql.Row{{"00:00:09"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('01/02/99 314', '%m/%e/%y %f')",
		Expected: []sql.Row{{"1999-01-02 00:00:00.314000"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('01/02/99 0', '%m/%e/%y %f')",
		Expected: []sql.Row{{"1999-01-02 00:00:00.000000"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('01/02/99 05:14:12 PM', '%m/%e/%y %r')",
		Expected: []sql.Row{{"1999-01-02 17:14:12"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('May 3, 10:23:00 2000', '%b %e, %H:%i:%s %Y')",
		Expected: []sql.Row{{"2000-05-03 10:23:00"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('May 3, 10:23:00 PM 2000', '%b %e, %h:%i:%s %p %Y')",
		Expected: []sql.Row{{"2000-05-03 22:23:00"}},
	},
	{
		Query:    "SELECT STR_TO_DATE('May 3, 10:23:00 PM 2000', '%b %e, %H:%i:%s %p %Y')",
		Expected: []sql.Row{{nil}},
	},
	{
		Query:    "SELECT STR_TO_DATE('abc','abc')",
		Expected: []sql.Row{{nil}},
	},
	{
		Query:    "SELECT STR_TO_DATE('invalid', 'notvalid')",
		Expected: []sql.Row{{nil}},
	},
}
View Source
var DeleteErrorTests = []ScriptTest{
	{
		Name: "DELETE FROM error cases",
		Assertions: []ScriptTestAssertion{
			{

				Query:          "DELETE FROM invalidtable WHERE x < 1;",
				ExpectedErrStr: "table not found: invalidtable",
			},
			{

				Query:          "DELETE FROM mytable WHERE z = 'dne';",
				ExpectedErrStr: "column \"z\" could not be found in any table in scope",
			},
			{

				Query:          "DELETE FROM mytable WHERE i = ?;",
				ExpectedErrStr: "unbound variable \"v1\" in query",
			},
			{

				Query:          "DELETE FROM mytable LIMIT -1;",
				ExpectedErrStr: "syntax error at position 28 near 'LIMIT'",
			},
			{

				Query:          "DELETE FROM mytable LIMIT 1 OFFSET -1;",
				ExpectedErrStr: "syntax error at position 37 near 'OFFSET'",
			},
			{

				Query:          "DELETE mytable WHERE i = 1;",
				ExpectedErrStr: "syntax error at position 21 near 'WHERE'",
			},
			{

				Query:          "DELETE FROM (SELECT * FROM mytable) mytable WHERE i = 1;",
				ExpectedErrStr: "syntax error at position 14 near 'FROM'",
			},
		},
	},
	{
		Name: "DELETE FROM JOIN error cases",
		Assertions: []ScriptTestAssertion{
			{

				Query:          "DELETE mydb.mytable, test.other FROM mydb.mytable inner join test.other on mydb.mytable.i=test.other.pk;",
				ExpectedErrStr: "multiple databases specified as delete from targets",
			},
			{

				Query:          "DELETE unknowntable FROM mytable WHERE i < 1;",
				ExpectedErrStr: "table not found: unknowntable",
			},
			{

				Query:          "DELETE tabletest FROM mytable WHERE i < 1;",
				ExpectedErrStr: "table \"tabletest\" not found in DELETE FROM sources",
			},
			{

				Query:          "DELETE mytable, mytable FROM mytable WHERE i < 1;",
				ExpectedErrStr: "duplicate tables specified as delete from targets",
			},
			{

				Query:          "DELETE FROM mytable one, mytable two WHERE one.i = 1;",
				ExpectedErrStr: "syntax error at position 24 near 'one'",
			},
			{

				Query:          "DELETE jt FROM mytable join tabletest on mytable.i=tabletest.i join JSON_TABLE('[{\"x\": 1},{\"x\": 2}]', '$[*]' COLUMNS (x INT PATH '$.x')) as jt on jt.x=mytable.i;",
				ExpectedErrStr: "table not found: jt",
			},
			{

				Query:          "DELETE mytable, jt FROM mytable join tabletest on mytable.i=tabletest.i join JSON_TABLE('[{\"x\": 1},{\"x\": 2}]', '$[*]' COLUMNS (x INT PATH '$.x')) as jt on jt.x=mytable.i;",
				ExpectedErrStr: "table not found: jt",
			},
		},
	},
}
View Source
var DeleteJoinTests = []WriteQueryTest{
	{
		WriteQuery:          "DELETE mytable FROM mytable join tabletest where mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 3}},
	},
	{
		WriteQuery:          "DELETE MYTABLE FROM mytAble join tAbletest where mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 3}},
	},
	{
		WriteQuery:          "DELETE tabletest FROM mytable join tabletest where mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{3, 0}},
	},
	{
		WriteQuery:          "DELETE t1 FROM mytable as t1 join tabletest where t1.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 3}},
	},
	{
		WriteQuery:          "DELETE mytable, tabletest FROM mytable join tabletest where mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 0}},
	},
	{
		WriteQuery:          "DELETE MYTABLE, TABLETEST FROM mytable join tabletest where mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 0}},
	},
	{
		WriteQuery:          "DELETE mytable FROM mytable;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT count(*) FROM mytable;",
		ExpectedSelect:      []sql.Row{{0}},
	},
	{
		WriteQuery:          "DELETE mytable FROM mytable WHERE i > 9999;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SELECT count(*) FROM mytable;",
		ExpectedSelect:      []sql.Row{{3}},
	},
	{
		WriteQuery:          "DELETE FROM mytable USING mytable inner join tabletest on mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 3}},
	},
	{
		WriteQuery:          "DELETE FROM tabletest USING mytable inner join tabletest on mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{3, 0}},
	},
	{
		WriteQuery:          "DELETE FROM mytable, tabletest USING mytable inner join tabletest on mytable.i=tabletest.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{0, 0}},
	},
	{
		WriteQuery:          "DELETE mytable FROM mytable join tabletest where mytable.i=tabletest.i and mytable.i = 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{2, 3}},
	},
	{
		WriteQuery:          "DELETE mytable, tabletest FROM mytable join tabletest where mytable.i=tabletest.i and mytable.i = 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{2, 2}},
	},
	{
		WriteQuery:          "DELETE tabletest, mytable FROM mytable join tabletest where mytable.i=tabletest.i and mytable.i = 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{2, 2}},
	},
	{
		WriteQuery:          "DELETE mytable FROM mytable join (select 1 as i union all select 2 as i) dt where mytable.i=dt.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{1, 3}},
	},
	{
		WriteQuery:          "with t (n) as (select (1) from dual) delete mytable from mytable join tabletest where mytable.i=tabletest.i and mytable.i in (select n from t)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1}}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{2, 3}},
	},
	{
		WriteQuery:          "with t (n) as (select (1) from dual) delete mytable, tabletest from mytable join tabletest where mytable.i=tabletest.i and mytable.i in (select n from t)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1}}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{2, 2}},
	},
	{

		WriteQuery:          "DELETE mytable FROM mytable join tabletest on mytable.i=tabletest.i join JSON_TABLE('[{\"x\": 1},{\"x\": 2}]', '$[*]' COLUMNS (x INT PATH '$.x')) as jt on jt.x=mytable.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{1, 3}},
	},
	{

		WriteQuery:          "DELETE mytable, tabletest FROM mytable join tabletest on mytable.i=tabletest.i join JSON_TABLE('[{\"x\": 1},{\"x\": 2}]', '$[*]' COLUMNS (x INT PATH '$.x')) as jt on jt.x=mytable.i;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT (select count(*) FROM mytable), (SELECT count(*) from tabletest);",
		ExpectedSelect:      []sql.Row{{1, 1}},
	},
}

DeleteJoinTests contains tests for deletes that explicitly list the table from which to delete, and whose source may contain joined table relations.

View Source
var DeleteTests = []WriteQueryTest{
	{
		WriteQuery:          "DELETE FROM mytable;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      nil,
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i = 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE I = 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i < 3;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i > 1;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i <= 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i >= 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE s = 'first row';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE s <> 'dne';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      nil,
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i in (2,3);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE s LIKE '%row';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      nil,
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE s = 'dne';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE i = 'invalid';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(0)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable ORDER BY i ASC LIMIT 2;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable ORDER BY i DESC LIMIT 1;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable ORDER BY i DESC LIMIT 1 OFFSET 1;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "DELETE FROM mytable WHERE (i,s) = (1, 'first row');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          `DELETE FROM tabletest where 's' = 'something'`,
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 0}}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "with t (n) as (select (1) from dual) delete from mytable where i in (select n from t)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1}}},
		SelectQuery:         "select * from mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
		},
	},
	{
		WriteQuery:          "with recursive t (n) as (select (1) from dual union all select n + 1 from t where n < 2) delete from mytable where i in (select n from t)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 2}}},
		SelectQuery:         "select * from mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(3, "third row"),
		},
	},
}

DeleteTests contains tests for deletes that implicitly target the single table mentioned in the from clause.

View Source
var DerivedTableOuterScopeVisibilityQueries = []ScriptTest{
	{
		Name: "outer scope visibility for derived tables",
		SetUpScript: []string{
			"create table t1 (a int primary key, b int, c int, d int, e int);",
			"create table t2 (a int primary key, b int, c int, d int, e int);",
			"insert into t1 values (1, 1, 1, 100, 100), (2, 2, 2, 200, 200);",
			"insert into t2 values (2, 2, 2, 2, 2);",
			"create table numbers (val int);",
			"insert into numbers values (1), (1), (2), (3), (3), (3), (4), (5), (6), (6), (6);",
		},
		Assertions: []ScriptTestAssertion{
			{

				Query:    "SELECT * FROM t1 WHERE t1.d > (SELECT dt.a FROM (SELECT t2.a AS a FROM t2 WHERE t2.b = t1.b) dt);",
				Expected: []sql.Row{{2, 2, 2, 200, 200}},
			},
			{

				Query:    "SELECT * FROM t1 HAVING t1.d > (SELECT dt.a FROM (SELECT t2.a AS a FROM t2 WHERE t2.b = t1.b) dt);",
				Expected: []sql.Row{{2, 2, 2, 200, 200}},
			},
			{
				Query:    "SELECT (SELECT dt.z FROM (SELECT t2.a AS z FROM t2 WHERE t2.b = t1.b) dt) FROM t1;",
				Expected: []sql.Row{{nil}, {2}},
			},
			{
				Query:    "SELECT (SELECT max(dt.z) FROM (SELECT t2.a AS z FROM t2 WHERE t2.b = t1.b) dt) FROM t1;",
				Expected: []sql.Row{{nil}, {2}},
			},
			{

				Query:    "SELECT t1.*, (SELECT max(dt.a) FROM (SELECT t2.a AS a FROM t2 WHERE t2.b = t1.b) dt) FROM t1;",
				Expected: []sql.Row{{1, 1, 1, 100, 100, nil}, {2, 2, 2, 200, 200, 2}},
			},
			{

				Query:    "SELECT t1.a, t1.b, (SELECT max(dt.a) FROM (SELECT t2.a AS a FROM t2 WHERE t2.b = t1.b) dt) FROM t1 GROUP BY 1, 2, 3;",
				Expected: []sql.Row{{1, 1, nil}, {2, 2, 2}},
			},
			{

				Query:    "SELECT val, row_number() over (partition by val) as 'row_number', (SELECT two from (SELECT val*2, val*3) as dt(one, two)) as a1 from numbers having a1 > 10;",
				Expected: []sql.Row{{4, 1, 12}, {5, 1, 15}, {6, 1, 18}, {6, 2, 18}, {6, 3, 18}},
			},
			{

				Query:    "SELECT max(val), (select max(dt.a) from (SELECT val as a) as dt(a)) as a1 from numbers group by a1;",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}},
			},
			{

				Query:    "SELECT DISTINCT numbers.val, (WITH cte1 AS (SELECT val * 2 as val2 from numbers) SELECT count(*) from cte1 where numbers.val = cte1.val2) as count from numbers having count > 0;",
				Expected: []sql.Row{{2, 2}, {4, 1}, {6, 3}},
			},
			{

				Query:    "select distinct n1.val, (with recursive cte1(n) as (select (n1.val) from dual union all select n + 1 from cte1 where n < 10) select sum(n) from cte1) from numbers n1 where n1.val > 4;",
				Expected: []sql.Row{{5, 45.0}, {6, 40.0}},
			},
		},
	},
	{
		Name: "outer scope visibility for derived tables – error cases",
		SetUpScript: []string{
			"create table numbers (val int);",
			"insert into numbers values (1), (1), (2), (3), (3), (3), (4), (5), (6), (6), (6);",
		},
		Assertions: []ScriptTestAssertion{
			{

				Query:       "select 'foo' as foo, (select dt.b from (select 1 as a, foo as b) dt);",
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{

				Query:       "SELECT n1.val as a1 from numbers n1, (select n1.val, n2.val * -1 from numbers n2 where n1.val = n2.val) as dt;",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{

				Query:       "SELECT 1 as a1, dt.* from (select * from (select a1 from numbers group by val having val = a1) as dt2(val)) as dt(val);",
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{

				Skip: true,

				Query:       "with cte1 as (SELECT c3 FROM one_pk WHERE c4 < opk.c2 ORDER BY 1 DESC LIMIT 1)  SELECT pk, (select c3 from cte1) FROM one_pk opk ORDER BY 1",
				ExpectedErr: sql.ErrTableNotFound,
			},
		},
	},
	{
		Name: "https://github.com/gabereiser/go-mysql-server/issues/1282",
		SetUpScript: []string{
			"CREATE TABLE `dcim_rackgroup` (`id` char(32) NOT NULL, `lft` int unsigned NOT NULL, `rght` int unsigned NOT NULL, `tree_id` int unsigned NOT NULL, `level` int unsigned NOT NULL, `parent_id` char(32), PRIMARY KEY (`id`), KEY `dcim_rackgroup_tree_id_9c2ad6f4` (`tree_id`), CONSTRAINT `dcim_rackgroup_parent_id_cc315105_fk_dcim_rackgroup_id` FOREIGN KEY (`parent_id`) REFERENCES `dcim_rackgroup` (`id`));",
			"CREATE TABLE `dcim_rack` (`id` char(32) NOT NULL, `group_id` char(32), PRIMARY KEY (`id`), KEY `dcim_rack_group_id_44e90ea9` (`group_id`), CONSTRAINT `dcim_rack_group_id_44e90ea9_fk_dcim_rackgroup_id` FOREIGN KEY (`group_id`) REFERENCES `dcim_rackgroup` (`id`));",
			"INSERT INTO dcim_rackgroup VALUES ('rackgroup-parent', 100, 200, 1000, 1, NULL), ('rackgroup1', 101, 201, 1000, 1, 'rackgroup-parent'), ('rackgroup2', 102, 202, 1000, 1, 'rackgroup-parent');",
			"INSERT INTO dcim_rack VALUES ('rack1', 'rackgroup1'), ('rack2', 'rackgroup1'), ('rack3', 'rackgroup1'), ('rack4', 'rackgroup2');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `
SELECT (
  SELECT count(*) FROM (
    SELECT U0.id
    FROM dcim_rack U0
    INNER JOIN dcim_rackgroup U1 ON (U0.group_id = U1.id)
    WHERE 
      U1.lft >= dcim_rackgroup.lft AND
      U1.lft <= dcim_rackgroup.rght AND
      U1.tree_id = dcim_rackgroup.tree_id
  ) _count
) AS rack_count
FROM dcim_rackgroup
WHERE dcim_rackgroup.id IN ('rackgroup1', 'rackgroup2')`,
				Expected: []sql.Row{{4}, {1}},
			},
			{
				Query:    "SELECT COUNT(*) FROM (SELECT (SELECT count(*) FROM (SELECT U0.`id` FROM `dcim_rack` U0 INNER JOIN `dcim_rackgroup` U1 ON (U0.`group_id` = U1.`id`) WHERE (U1.`lft` >= `dcim_rackgroup`.`lft` AND U1.`lft` <= `dcim_rackgroup`.`rght` AND U1.`tree_id` = `dcim_rackgroup`.`tree_id`)) _count) AS `rack_count` FROM `dcim_rackgroup` WHERE `dcim_rackgroup`.`id` IN ('rackgroup1', 'rackgroup2')) subquery;",
				Expected: []sql.Row{{2}},
			},
		},
	},
}
View Source
var ErrorQueries = []QueryErrorTest{
	{
		Query:       "with a(j) as (select 1), b(i) as (select 2) (select j from a union select i from b order by 1 desc) union select j from a order by 1 asc;",
		ExpectedErr: sql.ErrConflictingExternalQuery,
	},
	{

		Query:       "select * from dual where foo() and true;",
		ExpectedErr: sql.ErrFunctionNotFound,
	},
	{
		Query:       "select * from mytable where (i = 1, i = 0 or i = 2) and (i > -1)",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select * from mytable where (i = 1, i = 0 or i = 2) or (i > -1)",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select * from mytable where ((i = 1, i = 0 or i = 2) or (i > -1)) and (i < 6)",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select * from mytable where ((i = 1, i = 0 or i = 2) is true or (i > -1)) and (i < 6)",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select foo.i from mytable as a",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "select foo.i from mytable",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "select foo.* from mytable",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "select foo.* from mytable as a",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "select x from mytable",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       "select mytable.x from mytable",
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Query:       "select a.x from mytable as a",
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Query:       "select a from notable",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "select myTable.i from mytable as mt",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "select myTable.* from mytable as mt",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT one_pk.c5,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON one_pk.pk=two_pk.pk1 ORDER BY 1,2,3",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT pk,pk1,pk2 FROM one_pk opk JOIN two_pk tpk ON one_pk.pk=two_pk.pk1 AND opk.pk=tpk.pk2 ORDER BY 1,2,3",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT t.i, myview1.s FROM myview AS t ORDER BY i",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT * FROM mytable AS t, othertable as t",
		ExpectedErr: sql.ErrDuplicateAliasOrTable,
	},
	{

		Query:       "select * from mytable a join mytable A on a.i = A.i;",
		ExpectedErr: sql.ErrDuplicateAliasOrTable,
	},
	{
		Query:       "SELECT * FROM mytable AS t UNION SELECT * FROM mytable AS t, othertable AS t",
		ExpectedErr: sql.ErrDuplicateAliasOrTable,
	},
	{
		Query:       "SELECT * FROM mytable AS OTHERTABLE, othertable",
		ExpectedErr: sql.ErrDuplicateAliasOrTable,
	},
	{
		Query:       `SELECT * FROM mytable WHERE s REGEXP("*main.go")`,
		ExpectedErr: expression.ErrInvalidRegexp,
	},
	{
		Query:       `SELECT SUBSTRING(s, 1, 10) AS sub_s, SUBSTRING(SUB_S, 2, 3) AS sub_sub_s FROM mytable`,
		ExpectedErr: sql.ErrMisusedAlias,
	},
	{
		Query:       "SELECT pk, (SELECT max(pk) FROM one_pk b WHERE b.pk <= one_pk.pk) FROM one_pk opk ORDER BY 1",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT pk, (SELECT max(pk) FROM one_pk WHERE b.pk <= one_pk.pk) FROM one_pk opk ORDER BY 1",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT pk, (SELECT max(pk) FROM one_pk WHERE b.pk <= one_pk.pk) FROM one_pk opk ORDER BY 1",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT pk, (SELECT max(pk) FROM two_pk WHERE pk <= one_pk.pk3) FROM one_pk ORDER BY 1",
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Query:       "SELECT pk, (SELECT max(pk) FROM dne WHERE pk <= one_pk.pk3) FROM one_pk ORDER BY 1",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:       "SELECT pk, (SELECT max(pk) FROM two_pk WHERE pk <= c6) FROM one_pk ORDER BY 1",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       "SELECT i FROM myhistorytable AS OF MAX(abc)",
		ExpectedErr: sql.ErrInvalidAsOfExpression,
	},
	{
		Query:       "SELECT pk FROM one_pk WHERE pk > ?",
		ExpectedErr: sql.ErrUnboundPreparedStatementVariable,
	},
	{
		Query:       "SELECT pk FROM one_pk WHERE pk > :pk",
		ExpectedErr: sql.ErrUnboundPreparedStatementVariable,
	},
	{
		Query: `WITH mt1 (x,y) as (select i,s FROM mytable)
			SELECT mt1.i, mt1.s FROM mt1`,
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Query: `WITH mt1 (x,y) as (select i,s FROM mytable)
			SELECT i, s FROM mt1`,
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query: `WITH mt1 (x,y,z) as (select i,s FROM mytable)
			SELECT i, s FROM mt1`,
		ExpectedErr: sql.ErrColumnCountMismatch,
	},

	{
		Query: `WITH mt1 as (select i,s FROM mytable), mt2 as (select i+1, concat(s, '!') from mytable)
			SELECT mt1.i, mt2.s FROM mt1 join mt2 on mt1.i = mt2.i;`,
		ExpectedErr: sql.ErrTableColumnNotFound,
	},

	{
		Query:       `SHOW TABLE STATUS FROM baddb`,
		ExpectedErr: sql.ErrDatabaseNotFound,
	},
	{
		Query:       `SELECT s as i, i as i from mytable order by 1`,
		ExpectedErr: sql.ErrAmbiguousColumnInOrderBy,
	},
	{
		Query: `SELECT pk as pk, nt.i  as i, nt2.i as i FROM one_pk
						RIGHT JOIN niltable nt ON pk=nt.i
						RIGHT JOIN niltable nt2 ON pk=nt2.i - 1
						ORDER BY 3`,
		ExpectedErr: sql.ErrAmbiguousColumnInOrderBy,
	},
	{
		Query:       "SELECT C FROM (select i,s FROM mytable) mt (a,b) order by a desc;",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       "SELECT i FROM (select i,s FROM mytable) mt (a,b) order by a desc;",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       "SELECT mt.i FROM (select i,s FROM mytable) mt (a,b) order by a desc;",
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Query:       "SELECT a FROM (select i,s FROM mytable) mt (a) order by a desc;",
		ExpectedErr: sql.ErrColumnCountMismatch,
	},
	{
		Query:       "SELECT a FROM (select i,s FROM mytable) mt (a,b,c) order by a desc;",
		ExpectedErr: sql.ErrColumnCountMismatch,
	},
	{
		Query:       `SELECT name FROM specialtable t WHERE t.name LIKE '$%' ESCAPE 'abc'`,
		ExpectedErr: sql.ErrInvalidArgument,
	},
	{
		Query:       `SELECT name FROM specialtable t WHERE t.name LIKE '$%' ESCAPE '$$'`,
		ExpectedErr: sql.ErrInvalidArgument,
	},
	{
		Query:       `SELECT JSON_OBJECT("a","b","c") FROM dual`,
		ExpectedErr: sql.ErrInvalidArgumentNumber,
	},
	{
		Query:       `alter table mytable add primary key (s)`,
		ExpectedErr: sql.ErrMultiplePrimaryKeysDefined,
	},

	{
		Query:       "SELECT SUM(i), i FROM mytable GROUP BY i ORDER BY 1+SUM(i) ASC",
		ExpectedErr: analyzer.ErrAggregationUnsupported,
	},
	{
		Query:       "SELECT SUM(i) as sum, i FROM mytable GROUP BY i ORDER BY 1+SUM(i) ASC",
		ExpectedErr: analyzer.ErrAggregationUnsupported,
	},
	{
		Query:       "select ((1, 2)) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (select 1, 2 from dual) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select concat((1, 2)) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (1, 2) = (1) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (1) in (select 1, 2 from dual) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (1, 2) in (select 1, 2, 3 from dual) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (select 1 from dual) in ((1, 2)) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (((1,2),3)) = (((1,2))) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (((1,2),3)) = (((1),2)) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (((1,2),3)) = (((1))) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select (((1,2),3)) = (((1,2),3),(4,5)) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "select ((4,5),((1,2),3)) = ((1,2),(4,5)) from dual",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       "SELECT (2, 2)=1 FROM dual where exists (SELECT 1 FROM dual)",
		ExpectedErr: sql.ErrInvalidOperandColumns,
	},
	{
		Query:       `SELECT pk, (SELECT concat(pk, pk) FROM one_pk WHERE pk < opk.pk ORDER BY 1 DESC LIMIT 1) as strpk FROM one_pk opk where strpk > "0" ORDER BY 2`,
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       `CREATE TABLE test (pk int, primary key(pk, noexist))`,
		ExpectedErr: sql.ErrUnknownIndexColumn,
	},
	{
		Query:       `CREATE TABLE test (pk int auto_increment, pk2 int auto_increment, primary key (pk))`,
		ExpectedErr: sql.ErrInvalidAutoIncCols,
	},
	{
		Query:       `CREATE TABLE test (pk int auto_increment)`,
		ExpectedErr: sql.ErrInvalidAutoIncCols,
	},
	{
		Query:       `CREATE TABLE test (pk int primary key auto_increment default 100, col int)`,
		ExpectedErr: sql.ErrInvalidAutoIncCols,
	},
	{
		Query:       "with recursive t (n) as (select (1) from dual union all select n from t where n < 2) select sum(n) from t",
		ExpectedErr: sql.ErrCteRecursionLimitExceeded,
	},
	{
		Query:       "with recursive t (n) as (select (1) from dual union all select n + 1 from t where n < 1002) select sum(n) from t",
		ExpectedErr: sql.ErrCteRecursionLimitExceeded,
	},
	{
		Query:       `alter table a add fulltext index idx (id)`,
		ExpectedErr: sql.ErrUnsupportedFeature,
	},
	{
		Query:       `CREATE TABLE test (pk int primary key, body text, FULLTEXT KEY idx_body (body))`,
		ExpectedErr: sql.ErrUnsupportedFeature,
	},
	{
		Query:       `CREATE FULLTEXT INDEX idx ON opening_lines(opening_line)`,
		ExpectedErr: sql.ErrUnsupportedFeature,
	},
	{
		Query:       `SELECT * FROM datetime_table where date_col >= 'not a valid date'`,
		ExpectedErr: types.ErrConvertingToTime,
	},
	{
		Query:       `SELECT * FROM datetime_table where datetime_col >= 'not a valid datetime'`,
		ExpectedErr: types.ErrConvertingToTime,
	},

	{
		Query:       `CREATE PROCEDURE proc1 (OUT out_count INT) READS SQL DATA SELECT COUNT(*) FROM mytable WHERE i = 1 AND s = 'first row' AND func1(i);`,
		ExpectedErr: sql.ErrFunctionNotFound,
	},
	{
		Query:       "CREATE TABLE table_test (id int PRIMARY KEY, c float DEFAULT rand())",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       "CREATE TABLE table_test (id int PRIMARY KEY, c float DEFAULT rand)",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       "CREATE TABLE table_test (id int PRIMARY KEY, c float DEFAULT (select 1))",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       "CREATE TABLE table_test (id int PRIMARY KEY, b int DEFAULT '2', c int DEFAULT `b`)",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       "CREATE TABLE t0 (id INT PRIMARY KEY, v1 POINT DEFAULT POINT(1,2));",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       "CREATE TABLE t0 (id INT PRIMARY KEY, v1 JSON DEFAULT JSON_ARRAY(1,2));",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       "CREATE TABLE t0 (id INT PRIMARY KEY, j JSON DEFAULT '{}');",
		ExpectedErr: sql.ErrInvalidTextBlobColumnDefault,
	},
	{
		Query:       "CREATE TABLE t0 (id INT PRIMARY KEY, g GEOMETRY DEFAULT '');",
		ExpectedErr: sql.ErrInvalidTextBlobColumnDefault,
	},
	{
		Query:       "CREATE TABLE t0 (id INT PRIMARY KEY, t TEXT DEFAULT '');",
		ExpectedErr: sql.ErrInvalidTextBlobColumnDefault,
	},
	{
		Query:       "CREATE TABLE t0 (id INT PRIMARY KEY, b BLOB DEFAULT '');",
		ExpectedErr: sql.ErrInvalidTextBlobColumnDefault,
	},
	{
		Query:       "with a as (select * from a) select * from a",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Query:          "with a as (select * from c), b as (select * from a), c as (select * from b) select * from a",
		ExpectedErrStr: "table not found: a",
	},
	{
		Query:       "WITH Numbers AS ( SELECT n = 1 UNION ALL SELECT n + 1 FROM Numbers WHERE n+1 <= 10) SELECT n FROM Numbers;",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       "WITH recursive Numbers AS ( SELECT n = 1 UNION ALL SELECT n + 1 FROM Numbers WHERE n+1 <= 10) SELECT n FROM Numbers;",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:          "CREATE TABLE invalid_decimal (number DECIMAL(65,31));",
		ExpectedErrStr: "Too big scale 31 specified. Maximum is 30.",
	},
	{
		Query:          "CREATE TABLE invalid_decimal (number DECIMAL(66,30));",
		ExpectedErrStr: "Too big precision 66 specified. Maximum is 65.",
	},
	{
		Query:          "CREATE TABLE invalid_decimal (number DECIMAL(66,31));",
		ExpectedErrStr: "Too big scale 31 specified. Maximum is 30.",
	},
	{
		Query:       "select 18446744073709551615 div 0.1;",
		ExpectedErr: expression.ErrIntDivDataOutOfRange,
	},
	{
		Query:       "select -9223372036854775807 div 0.1;",
		ExpectedErr: expression.ErrIntDivDataOutOfRange,
	},
	{
		Query:       "select -9223372036854775808 div 0.1;",
		ExpectedErr: expression.ErrIntDivDataOutOfRange,
	},
	{
		Query:       "drop table myview;",
		ExpectedErr: sql.ErrUnknownTable,
	},
}
View Source
var ExternalProcedureTests = []ScriptTest{
	{
		Name: "Call external stored procedure that does not exist",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL procedure_does_not_exist('foo');",
				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
			},
		},
	},
	{
		Name: "INOUT on first param, IN on second param",
		SetUpScript: []string{
			"SET @outparam = 5;",
			"CALL memory_inout_add(@outparam, 11);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @outparam;",
				Expected: []sql.Row{{16}},
			},
		},
	},
	{
		Name: "Handle setting uninitialized user variables",
		SetUpScript: []string{
			"CALL memory_inout_set_unitialized(@uservar12, @uservar13, @uservar14, @uservar15);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @uservar12;",
				Expected: []sql.Row{{5}},
			},
			{
				Query:    "SELECT @uservar13;",
				Expected: []sql.Row{{uint(5)}},
			},
			{
				Query:    "SELECT @uservar14;",
				Expected: []sql.Row{{"5"}},
			},
			{
				Query:    "SELECT @uservar15;",
				Expected: []sql.Row{{0}},
			},
		},
	},
	{
		Name: "Called from standard stored procedure",
		SetUpScript: []string{
			"CREATE PROCEDURE p1(x BIGINT) BEGIN CALL memory_inout_add(x, x); SELECT x; END;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL p1(11);",
				Expected: []sql.Row{{22}},
			},
		},
	},
	{
		Name: "Overloaded Name",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL memory_overloaded_mult(1);",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "CALL memory_overloaded_mult(2, 3);",
				Expected: []sql.Row{{6}},
			},
			{
				Query:    "CALL memory_overloaded_mult(4, 5, 6);",
				Expected: []sql.Row{{120}},
			},
		},
	},
	{
		Name: "Passing in all supported types",
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL memory_overloaded_type_test(1, 100, 10000, 1000000, 100000000, 3, 300," +
					"10, 1000, 100000, 10000000, 1000000000, 30, 3000);",
				Expected: []sql.Row{{1111114444}},
			},
			{
				Query: "CALL memory_overloaded_type_test(false, 'hi', 'A', '2020-02-20 12:00:00', 123.456," +
					"true, 'bye', 'B', '2022-02-02 12:00:00', 654.32);",
				Expected: []sql.Row{{`aa:false,ba:true,ab:"hi",bb:"bye",ac:[65],bc:[66],ad:2020-02-20,bd:2022-02-02,ae:123.456,be:654.32`}},
			},
			{
				Query: "CALL memory_type_test3(1, 100, 10000, 1000000, 100000000, 3, 300," +
					"10, 1000, 100000, 10000000, 1000000000, 30, 3000);",
				Expected: []sql.Row{{uint64(1111114444)}},
			},
		},
	},
	{
		Name: "BOOL and []BYTE INOUT conversions",
		SetUpScript: []string{
			"SET @outparam1 = 1;",
			"SET @outparam2 = 0;",
			"SET @outparam3 = 'A';",
			"SET @outparam4 = 'B';",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @outparam1, @outparam2, @outparam3, @outparam4;",
				Expected: []sql.Row{{1, 0, "A", "B"}},
			},
			{
				Query:    "CALL memory_inout_bool_byte(@outparam1, @outparam2, @outparam3, @outparam4);",
				Expected: []sql.Row{},
			},
			{
				Query:    "SELECT @outparam1, @outparam2, @outparam3, @outparam4;",
				Expected: []sql.Row{{1, 1, "A", []byte("C")}},
			},
			{
				Query:    "CALL memory_inout_bool_byte(@outparam1, @outparam2, @outparam3, @outparam4);",
				Expected: []sql.Row{},
			},
			{
				Query:    "SELECT @outparam1, @outparam2, @outparam3, @outparam4;",
				Expected: []sql.Row{{1, 0, "A", []byte("D")}},
			},
		},
	},
	{
		Name: "Errors returned",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL memory_error_table_not_found();",
				ExpectedErr: sql.ErrTableNotFound,
			},
		},
	},
	{
		Name: "Variadic parameter",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL memory_variadic_add();",
				Expected: []sql.Row{{0}},
			},
			{
				Query:    "CALL memory_variadic_add(1);",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "CALL memory_variadic_add(1, 2);",
				Expected: []sql.Row{{3}},
			},
			{
				Query:    "CALL memory_variadic_add(1, 2, 3);",
				Expected: []sql.Row{{6}},
			},
			{
				Query:    "CALL memory_variadic_add(1, 2, 3, 4);",
				Expected: []sql.Row{{10}},
			},
		},
	},
	{
		Name: "Variadic byte slices",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL memory_variadic_byte_slice();",
				Expected: []sql.Row{{""}},
			},
			{
				Query:    "CALL memory_variadic_byte_slice('A');",
				Expected: []sql.Row{{"A"}},
			},
			{
				Query:    "CALL memory_variadic_byte_slice('A', 'B');",
				Expected: []sql.Row{{"AB"}},
			},
		},
	},
	{
		Name: "Variadic overloading",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL memory_variadic_overload();",
				ExpectedErr: sql.ErrCallIncorrectParameterCount,
			},
			{
				Query:       "CALL memory_variadic_overload('A');",
				ExpectedErr: sql.ErrCallIncorrectParameterCount,
			},
			{
				Query:    "CALL memory_variadic_overload('A', 'B');",
				Expected: []sql.Row{{"A-B"}},
			},
			{
				Query:       "CALL memory_variadic_overload('A', 'B', 'C');",
				ExpectedErr: sql.ErrInvalidValue,
			},
			{
				Query:    "CALL memory_variadic_overload('A', 'B', 5);",
				Expected: []sql.Row{{"A,B,[5]"}},
			},
		},
	},
	{
		Name: "show create procedure for external stored procedures",
		Assertions: []ScriptTestAssertion{
			{
				Query: "show create procedure memory_variadic_overload;",
				Expected: []sql.Row{{
					"memory_variadic_overload",
					"",
					"CREATE PROCEDURE memory_variadic_overload() SELECT 'External stored procedure';",
					"utf8mb4",
					"utf8mb4_0900_bin",
					"utf8mb4_0900_bin",
				}},
			},
		},
	},
}
View Source
var ForeignKeyTests = []ScriptTest{
	{
		Name: "ALTER TABLE Single Named FOREIGN KEY",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_named FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE child;",
				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n  `id` int NOT NULL,\n  `v1` int,\n  `v2` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_named` FOREIGN KEY (`v1`) REFERENCES `parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "CREATE TABLE Single Named FOREIGN KEY",
		SetUpScript: []string{
			"CREATE TABLE sibling (id int PRIMARY KEY, v1 int, CONSTRAINT fk_named FOREIGN KEY (v1) REFERENCES parent(v1));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE sibling;",
				Expected: []sql.Row{{"sibling", "CREATE TABLE `sibling` (\n  `id` int NOT NULL,\n  `v1` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_named` FOREIGN KEY (`v1`) REFERENCES `parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "Parent table index required",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1,v2) REFERENCES parent(v1,v2);",
				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
			},
			{
				Query:    "ALTER TABLE child ADD CONSTRAINT fk_id FOREIGN KEY (v1) REFERENCES parent(id);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "indexes with prefix lengths are ignored for foreign keys",
		SetUpScript: []string{
			"create table prefixParent(v varchar(100), index(v(1)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "create table prefixChild(v varchar(100), foreign key (v) references prefixParent(v))",
				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
			},
		},
	},
	{
		Name: "CREATE TABLE Name Collision",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CREATE TABLE child2 (id INT PRIMARY KEY, v1 INT, CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1), CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1));",
				ExpectedErr: sql.ErrForeignKeyDuplicateName,
			},
		},
	},
	{
		Name: "CREATE TABLE Type Mismatch",
		SetUpScript: []string{
			"CREATE TABLE sibling (pk INT PRIMARY KEY, v1 TIME);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE sibling ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1);",
				ExpectedErr: sql.ErrForeignKeyColumnTypeMismatch,
			},
		},
	},
	{
		Name: "CREATE TABLE Type Mismatch special case for strings",
		SetUpScript: []string{
			"CREATE TABLE parent1 (pk BIGINT PRIMARY KEY, v1 CHAR(20), INDEX (v1));",
			"CREATE TABLE parent2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(20), INDEX (v1));",
			"CREATE TABLE parent3 (pk BIGINT PRIMARY KEY, v1 BINARY(20), INDEX (v1));",
			"CREATE TABLE parent4 (pk BIGINT PRIMARY KEY, v1 VARBINARY(20), INDEX (v1));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CREATE TABLE child1 (pk BIGINT PRIMARY KEY, v1 CHAR(30), CONSTRAINT fk_child1 FOREIGN KEY (v1) REFERENCES parent1 (v1));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "CREATE TABLE child2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(30), CONSTRAINT fk_child2 FOREIGN KEY (v1) REFERENCES parent2 (v1));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "CREATE TABLE child3 (pk BIGINT PRIMARY KEY, v1 BINARY(30), CONSTRAINT fk_child3 FOREIGN KEY (v1) REFERENCES parent3 (v1));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			}, {
				Query:    "CREATE TABLE child4 (pk BIGINT PRIMARY KEY, v1 VARBINARY(30), CONSTRAINT fk_child4 FOREIGN KEY (v1) REFERENCES parent4 (v1));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "CREATE TABLE Key Count Mismatch",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1, v2);",
				ExpectedErr: sql.ErrForeignKeyColumnCountMismatch,
			},
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1, v2) REFERENCES parent(v1);",
				ExpectedErr: sql.ErrForeignKeyColumnCountMismatch,
			},
		},
	},
	{
		Name: "SET DEFAULT not supported",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1) ON DELETE SET DEFAULT;",
				ExpectedErr: sql.ErrForeignKeySetDefault,
			},
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1) ON UPDATE SET DEFAULT;",
				ExpectedErr: sql.ErrForeignKeySetDefault,
			},
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1) ON UPDATE SET DEFAULT ON DELETE SET DEFAULT;",
				ExpectedErr: sql.ErrForeignKeySetDefault,
			},
		},
	},
	{
		Name: "CREATE TABLE Disallow TEXT/BLOB",
		SetUpScript: []string{
			"CREATE TABLE parent1 (id INT PRIMARY KEY, v1 TINYTEXT, v2 TEXT, v3 MEDIUMTEXT, v4 LONGTEXT);",
			"CREATE TABLE parent2 (id INT PRIMARY KEY, v1 TINYBLOB, v2 BLOB, v3 MEDIUMBLOB, v4 LONGBLOB);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CREATE TABLE child11 (id INT PRIMARY KEY, parent_v1 TINYTEXT, FOREIGN KEY (parent_v1) REFERENCES parent1(v1));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child12 (id INT PRIMARY KEY, parent_v2 TEXT, FOREIGN KEY (parent_v2) REFERENCES parent1(v2));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child13 (id INT PRIMARY KEY, parent_v3 MEDIUMTEXT, FOREIGN KEY (parent_v3) REFERENCES parent1(v3));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child14 (id INT PRIMARY KEY, parent_v4 LONGTEXT, FOREIGN KEY (parent_v4) REFERENCES parent1(v4));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child21 (id INT PRIMARY KEY, parent_v1 TINYBLOB, FOREIGN KEY (parent_v1) REFERENCES parent2(v1));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child22 (id INT PRIMARY KEY, parent_v2 BLOB, FOREIGN KEY (parent_v2) REFERENCES parent2(v2));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child23 (id INT PRIMARY KEY, parent_v3 MEDIUMBLOB, FOREIGN KEY (parent_v3) REFERENCES parent2(v3));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
			{
				Query:       "CREATE TABLE child24 (id INT PRIMARY KEY, parent_v4 LONGBLOB, FOREIGN KEY (parent_v4) REFERENCES parent2(v4));",
				ExpectedErr: sql.ErrForeignKeyTextBlob,
			},
		},
	},
	{
		Name: "CREATE TABLE Non-existent Table",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES father(v1);",
				ExpectedErr: sql.ErrTableNotFound,
			},
		},
	},
	{
		Name: "CREATE TABLE Non-existent Columns",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (random) REFERENCES parent(v1);",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(random);",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
		},
	},
	{
		Name: "ALTER TABLE Foreign Key Name Collision",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
				ExpectedErr: sql.ErrForeignKeyDuplicateName,
			},
		},
	},
	{
		Name: "ALTER TABLE DROP FOREIGN KEY",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE child;",
				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n  `id` int NOT NULL,\n  `v1` int,\n  `v2` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_name` FOREIGN KEY (`v1`) REFERENCES `parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "ALTER TABLE child DROP FOREIGN KEY fk_name;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SHOW CREATE TABLE child;",
				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n  `id` int NOT NULL,\n  `v1` int,\n  `v2` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "ALTER TABLE child DROP FOREIGN KEY fk_name;",
				ExpectedErr: sql.ErrForeignKeyNotFound,
			},
		},
	},
	{
		Name: "ALTER TABLE SET NULL on non-nullable column",
		SetUpScript: []string{
			"ALTER TABLE child MODIFY v1 int NOT NULL;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1) ON DELETE SET NULL;",
				ExpectedErr: sql.ErrForeignKeySetNullNonNullable,
			},
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1) ON UPDATE SET NULL;",
				ExpectedErr: sql.ErrForeignKeySetNullNonNullable,
			},
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1) ON DELETE SET NULL ON UPDATE SET NULL;",
				ExpectedErr: sql.ErrForeignKeySetNullNonNullable,
			},
		},
	},
	{
		Name: "ADD FOREIGN KEY fails on existing table when data would cause violation",
		SetUpScript: []string{
			"INSERT INTO parent VALUES (1, 1, 1), (2, 2, 2);",
			"INSERT INTO child VALUES (1, 1, 1), (2, 3, 2);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1)",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
		},
	},
	{
		Name: "RENAME TABLE",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
			"RENAME TABLE parent TO new_parent;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE child;",
				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n  `id` int NOT NULL,\n  `v1` int,\n  `v2` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_name` FOREIGN KEY (`v1`) REFERENCES `new_parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "RENAME TABLE child TO new_child;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SHOW CREATE TABLE new_child;",
				Expected: []sql.Row{{"new_child", "CREATE TABLE `new_child` (\n  `id` int NOT NULL,\n  `v1` int,\n  `v2` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_name` FOREIGN KEY (`v1`) REFERENCES `new_parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "RENAME TABLE with primary key indexes",
		SetUpScript: []string{
			"CREATE TABLE parent1 (pk BIGINT PRIMARY KEY);",
			"CREATE TABLE child1 (pk BIGINT PRIMARY KEY, CONSTRAINT `fk` FOREIGN KEY (pk) REFERENCES parent1(pk))",
			"RENAME TABLE parent1 TO new_parent1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE child1;",
				Expected: []sql.Row{{"child1", "CREATE TABLE `child1` (\n  `pk` bigint NOT NULL,\n  PRIMARY KEY (`pk`),\n  CONSTRAINT `fk` FOREIGN KEY (`pk`) REFERENCES `new_parent1` (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "RENAME TABLE child1 TO new_child1;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SHOW CREATE TABLE new_child1;",
				Expected: []sql.Row{{"new_child1", "CREATE TABLE `new_child1` (\n  `pk` bigint NOT NULL,\n  PRIMARY KEY (`pk`),\n  CONSTRAINT `fk` FOREIGN KEY (`pk`) REFERENCES `new_parent1` (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "DROP TABLE",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DROP TABLE parent;",
				ExpectedErr: sql.ErrForeignKeyDropTable,
			},
			{
				Query:    "DROP TABLE child;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "DROP TABLE parent;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Indexes used by foreign keys can't be dropped",
		SetUpScript: []string{
			"ALTER TABLE child ADD INDEX v1 (v1);",
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child DROP INDEX v1;",
				ExpectedErr: sql.ErrForeignKeyDropIndex,
			},
			{
				Query:       "ALTER TABLE parent DROP INDEX v1;",
				ExpectedErr: sql.ErrForeignKeyDropIndex,
			},
			{
				Query:    "ALTER TABLE child DROP FOREIGN KEY fk_name;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child DROP INDEX v1;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE parent DROP INDEX v1;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "ALTER TABLE RENAME COLUMN",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1);",
			"ALTER TABLE parent RENAME COLUMN v1 TO v1_new;",
			"ALTER TABLE child RENAME COLUMN v1 TO v1_new;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE child;",
				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n  `id` int NOT NULL,\n  `v1_new` int,\n  `v2` int,\n  PRIMARY KEY (`id`),\n  KEY `v1` (`v1_new`),\n  CONSTRAINT `fk1` FOREIGN KEY (`v1_new`) REFERENCES `parent` (`v1_new`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "ALTER TABLE MODIFY COLUMN type change not allowed",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE parent MODIFY v1 MEDIUMINT;",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE child MODIFY v1 MEDIUMINT;",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
		},
	},
	{
		Name: "ALTER TABLE MODIFY COLUMN type change allowed when lengthening string",
		SetUpScript: []string{
			"CREATE TABLE parent1 (pk BIGINT PRIMARY KEY, v1 CHAR(20), INDEX (v1));",
			"CREATE TABLE parent2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(20), INDEX (v1));",
			"CREATE TABLE parent3 (pk BIGINT PRIMARY KEY, v1 BINARY(20), INDEX (v1));",
			"CREATE TABLE parent4 (pk BIGINT PRIMARY KEY, v1 VARBINARY(20), INDEX (v1));",
			"CREATE TABLE child1 (pk BIGINT PRIMARY KEY, v1 CHAR(20), CONSTRAINT fk_child1 FOREIGN KEY (v1) REFERENCES parent1 (v1));",
			"CREATE TABLE child2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(20), CONSTRAINT fk_child2 FOREIGN KEY (v1) REFERENCES parent2 (v1));",
			"CREATE TABLE child3 (pk BIGINT PRIMARY KEY, v1 BINARY(20), CONSTRAINT fk_child3 FOREIGN KEY (v1) REFERENCES parent3 (v1));",
			"CREATE TABLE child4 (pk BIGINT PRIMARY KEY, v1 VARBINARY(20), CONSTRAINT fk_child4 FOREIGN KEY (v1) REFERENCES parent4 (v1));",
			"INSERT INTO parent2 VALUES (1, 'aa'), (2, 'bb');",
			"INSERT INTO child2 VALUES (1, 'aa');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE parent1 MODIFY v1 CHAR(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE child1 MODIFY v1 CHAR(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE parent2 MODIFY v1 VARCHAR(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE child2 MODIFY v1 VARCHAR(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE parent3 MODIFY v1 BINARY(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE child3 MODIFY v1 BINARY(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE parent4 MODIFY v1 VARBINARY(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE child4 MODIFY v1 VARBINARY(10);",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:    "ALTER TABLE parent1 MODIFY v1 CHAR(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child1 MODIFY v1 CHAR(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE parent2 MODIFY v1 VARCHAR(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child2 MODIFY v1 VARCHAR(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE parent3 MODIFY v1 BINARY(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child3 MODIFY v1 BINARY(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE parent4 MODIFY v1 VARBINARY(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child4 MODIFY v1 VARBINARY(30);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO child2 VALUES (2, 'bb');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "INSERT INTO child2 VALUES (3, 'cc');",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
		},
	},
	{
		Name: "ALTER TABLE MODIFY COLUMN type change only cares about foreign key columns",
		SetUpScript: []string{
			"CREATE TABLE parent1 (pk INT PRIMARY KEY, v1 INT UNSIGNED, v2 INT UNSIGNED, INDEX (v1));",
			"CREATE TABLE child1 (pk INT PRIMARY KEY, v1 INT UNSIGNED, v2 INT UNSIGNED, CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent1(v1));",
			"INSERT INTO parent1 VALUES (1, 2, 3), (4, 5, 6);",
			"INSERT INTO child1 VALUES (7, 2, 9);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE parent1 MODIFY v1 BIGINT;",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:       "ALTER TABLE child1 MODIFY v1 BIGINT;",
				ExpectedErr: sql.ErrForeignKeyTypeChange,
			},
			{
				Query:    "ALTER TABLE parent1 MODIFY v2 BIGINT;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child1 MODIFY v2 BIGINT;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "DROP COLUMN parent",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE parent DROP COLUMN v1;",
				ExpectedErr: sql.ErrForeignKeyDropColumn,
			},
			{
				Query:    "ALTER TABLE child DROP FOREIGN KEY fk_name;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE parent DROP COLUMN v1;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "DROP COLUMN child",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child DROP COLUMN v1;",
				ExpectedErr: sql.ErrForeignKeyDropColumn,
			},
			{
				Query:    "ALTER TABLE child DROP FOREIGN KEY fk_name;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child DROP COLUMN v1;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Disallow change column to nullable with ON UPDATE SET NULL",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1) ON UPDATE SET NULL",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child CHANGE COLUMN v1 v1 INT NOT NULL;",
				ExpectedErr: sql.ErrForeignKeyTypeChangeSetNull,
			},
		},
	},
	{
		Name: "Disallow change column to nullable with ON DELETE SET NULL",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_name FOREIGN KEY (v1) REFERENCES parent(v1) ON DELETE SET NULL",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child CHANGE COLUMN v1 v1 INT NOT NULL;",
				ExpectedErr: sql.ErrForeignKeyTypeChangeSetNull,
			},
		},
	},
	{
		Name: "SQL CASCADE",
		SetUpScript: []string{
			"CREATE TABLE one (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1 (v1));",
			"CREATE TABLE two (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1v2 (v1, v2), CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1) ON DELETE CASCADE ON UPDATE CASCADE);",
			"CREATE TABLE three (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_name_2 FOREIGN KEY (v1, v2) REFERENCES two(v1, v2) ON DELETE CASCADE ON UPDATE CASCADE);",
			"INSERT INTO one VALUES (1, 1, 4), (2, 2, 5), (3, 3, 6), (4, 4, 5);",
			"INSERT INTO two VALUES (2, 1, 1), (3, 2, 2), (4, 3, 3), (5, 4, 4);",
			"INSERT INTO three VALUES (3, 1, 1), (4, 2, 2), (5, 3, 3), (6, 4, 4);",
			"UPDATE one SET v1 = v1 + v2;",
			"DELETE one FROM one WHERE pk = 3;",
			"UPDATE two SET v2 = v1 - 2;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM one;",
				Expected: []sql.Row{{1, 5, 4}, {2, 7, 5}, {4, 9, 5}},
			},
			{
				Query:    "SELECT * FROM two;",
				Expected: []sql.Row{{2, 5, 3}, {3, 7, 5}},
			},
			{
				Query:    "SELECT * FROM three;",
				Expected: []sql.Row{{3, 5, 3}, {4, 7, 5}},
			},
		},
	},
	{
		Name: "SQL SET NULL",
		SetUpScript: []string{
			"CREATE TABLE one (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1 (v1));",
			"CREATE TABLE two (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1) ON DELETE SET NULL ON UPDATE SET NULL);",
			"INSERT INTO one VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
			"INSERT INTO two VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
			"UPDATE one SET v1 = v1 * v2;",
			"INSERT INTO one VALUES (4, 4, 4);",
			"INSERT INTO two VALUES (4, 4, 4);",
			"UPDATE one SET v2 = v1 * v2;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM one;",
				Expected: []sql.Row{{1, 1, 1}, {2, 4, 8}, {3, 9, 27}, {4, 4, 16}},
			},
			{
				Query:    "SELECT * FROM two;",
				Expected: []sql.Row{{1, 1, 1}, {2, nil, 2}, {3, nil, 3}, {4, 4, 4}},
			},
			{
				Query:    "DELETE one FROM one inner join two on one.pk=two.pk;",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:    "select * from two;",
				Expected: []sql.Row{{1, nil, 1}, {2, nil, 2}, {3, nil, 3}, {4, nil, 4}},
			},
		},
	},
	{
		Name: "SQL RESTRICT",
		SetUpScript: []string{
			"CREATE TABLE one (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1 (v1));",
			"CREATE TABLE two (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1) ON DELETE RESTRICT ON UPDATE RESTRICT);",
			"INSERT INTO one VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
			"INSERT INTO two VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "UPDATE one SET v1 = v1 + v2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "UPDATE one SET v1 = v1;",
				Expected: []sql.Row{{types.OkResult{Info: plan.UpdateInfo{Matched: 3}}}},
			},
			{
				Query:       "DELETE FROM one;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "DELETE one FROM one inner join two on one.pk=two.pk;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "DELETE one, two FROM one inner join two on one.pk=two.pk;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
		},
	},
	{
		Name: "Multi-table DELETE FROM JOIN with multiple foreign keys",
		SetUpScript: []string{
			"CREATE TABLE one (pk int PRIMARY KEY);",
			"CREATE TABLE two (pk int PRIMARY KEY);",
			"CREATE TABLE three (pk int PRIMARY KEY, fk3 int, CONSTRAINT fk_3 FOREIGN KEY (fk3) REFERENCES one(pk) ON DELETE CASCADE);",
			"CREATE TABLE four (pk int PRIMARY KEY, fk4 int, CONSTRAINT fk_4 FOREIGN KEY (fk4) REFERENCES two(pk) ON DELETE CASCADE);",
			"INSERT INTO one VALUES (1), (2), (3);",
			"INSERT INTO two VALUES (1), (2), (3);",
			"INSERT INTO three VALUES (1, 1), (2, 2), (3, 3);",
			"INSERT INTO four VALUES (1, 1), (2, 2), (3, 3);",
			"DELETE one, two FROM one inner join two on one.pk=two.pk",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * from three union all select * from four;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Single-table DELETE FROM JOIN with multiple foreign keys",
		SetUpScript: []string{
			"CREATE TABLE one (pk int PRIMARY KEY);",
			"CREATE TABLE two (pk int PRIMARY KEY);",
			"CREATE TABLE three (pk int PRIMARY KEY, fk3 int, CONSTRAINT fk_3 FOREIGN KEY (fk3) REFERENCES one(pk) ON DELETE CASCADE);",
			"CREATE TABLE four (pk int PRIMARY KEY, fk4 int, CONSTRAINT fk_4 FOREIGN KEY (fk4) REFERENCES two(pk) ON DELETE CASCADE);",
			"INSERT INTO one VALUES (1), (2), (3);",
			"INSERT INTO two VALUES (1), (2), (3);",
			"INSERT INTO three VALUES (1, 1), (2, 2), (3, 3);",
			"INSERT INTO four VALUES (1, 1), (2, 2), (3, 3);",
			"DELETE t1 FROM one t1 inner join two t2 on t1.pk=t2.pk",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * from three;",
				Expected: []sql.Row{},
			},
			{
				Query:    "select * from four;",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
		},
	},
	{
		Name: "SQL no reference options",
		SetUpScript: []string{
			"CREATE TABLE one (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1 (v1));",
			"CREATE TABLE two (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1));",
			"INSERT INTO one VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
			"INSERT INTO two VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "UPDATE one SET v1 = v1 + v2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "UPDATE one SET v1 = v1;",
				Expected: []sql.Row{{types.OkResult{Info: plan.UpdateInfo{Matched: 3}}}},
			},
			{
				Query:       "DELETE FROM one;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
		},
	},
	{
		Name: "SQL INSERT multiple keys violates only one",
		SetUpScript: []string{
			"CREATE TABLE one (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1 (v1), INDEX v2 (v2));",
			"CREATE TABLE two (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1), CONSTRAINT fk_name_2 FOREIGN KEY (v2) REFERENCES one(v2));",
			"INSERT INTO one VALUES (1, 1, 1), (2, 2, 2), (3, 3, 3);",
			"INSERT INTO two VALUES (1, NULL, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "INSERT INTO two VALUES (2, NULL, 4);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
			{
				Query:       "INSERT INTO two VALUES (3, 4, NULL);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
			{
				Query:    "INSERT INTO two VALUES (4, NULL, NULL);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{

		Name: "Self-referential same column(s)",
		SetUpScript: []string{
			"CREATE INDEX v1v2 ON parent(v1, v2);",
			"CREATE TABLE parent2 (id INT PRIMARY KEY, v1 INT, v2 INT, INDEX v1v2 (v1, v2));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE parent ADD CONSTRAINT fk_name1 FOREIGN KEY (v1) REFERENCES parent(v1);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE parent ADD CONSTRAINT fk_name2 FOREIGN KEY (v1, v2) REFERENCES parent(v1, v2);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Self-referential child column follows parent RESTRICT",
		SetUpScript: []string{
			"ALTER TABLE parent ADD CONSTRAINT fk_named FOREIGN KEY (v2) REFERENCES parent(v1);",
			"INSERT INTO parent VALUES (1, 1, 1), (2, 2, 1), (3, 3, NULL);",
			"UPDATE parent SET v1 = 1 WHERE id = 1;",
			"UPDATE parent SET v1 = 4 WHERE id = 3;",
			"DELETE FROM parent WHERE id = 3;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 1, 1}, {2, 2, 1}},
			},
			{
				Query:       "DELETE FROM parent WHERE v1 = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "REPLACE INTO parent VALUES (1, 1, 1);",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
		},
	},
	{
		Name: "Self-referential child column follows parent CASCADE",
		SetUpScript: []string{
			"ALTER TABLE parent ADD CONSTRAINT fk_named FOREIGN KEY (v2) REFERENCES parent(v1) ON UPDATE CASCADE ON DELETE CASCADE;",
			"INSERT INTO parent VALUES (1, 1, 1), (2, 2, 1), (3, 3, NULL);",
			"UPDATE parent SET v1 = 1 WHERE id = 1;",
			"UPDATE parent SET v1 = 4 WHERE id = 3;",
			"DELETE FROM parent WHERE id = 3;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "REPLACE INTO parent VALUES (1, 1, 1), (2, 2, 2);",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 1, 1}, {2, 2, 2}},
			},
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "UPDATE parent SET v1 = 2 WHERE id = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "REPLACE INTO parent VALUES (1, 1, 2), (2, 2, 1);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
			{
				Query:    "UPDATE parent SET v2 = 2 WHERE id = 1;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "UPDATE parent SET v2 = 1 WHERE id = 2;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 1, 2}, {2, 2, 1}},
			},
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "UPDATE parent SET v1 = 2 WHERE id = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "DELETE FROM parent WHERE v1 = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Self-referential child column follows parent SET NULL",
		SetUpScript: []string{
			"ALTER TABLE parent ADD CONSTRAINT fk_named FOREIGN KEY (v2) REFERENCES parent(v1) ON UPDATE SET NULL ON DELETE SET NULL;",
			"INSERT INTO parent VALUES (1,1,1), (2, 2, 1), (3, 3, NULL);",
			"UPDATE parent SET v1 = 1 WHERE id = 1;",
			"UPDATE parent SET v1 = 4 WHERE id = 3;",
			"DELETE FROM parent WHERE id = 3;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "REPLACE INTO parent VALUES (1, 1, 1), (2, 2, 2);",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 1, 1}, {2, 2, 2}},
			},
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "UPDATE parent SET v1 = 2 WHERE id = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "REPLACE INTO parent VALUES (1,1,2), (2,2,1);",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 1, nil}, {2, 2, 1}},
			},
			{
				Query:    "UPDATE parent SET v2 = 2 WHERE id = 1;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "UPDATE parent SET v2 = 1 WHERE id = 2;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, Info: plan.UpdateInfo{Matched: 1}}}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 1, 2}, {2, 2, 1}},
			},
			{
				Query:       "UPDATE parent SET v1 = 2;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:       "UPDATE parent SET v1 = 2 WHERE id = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "DELETE FROM parent WHERE v1 = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{2, 2, nil}},
			},
		},
	},
	{

		Name: "Multiple self-referential foreign keys without data",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE, v2 BIGINT UNIQUE, v3 BIGINT UNIQUE, v4 BIGINT UNIQUE," +
				"v5 BIGINT UNIQUE, v6 BIGINT UNIQUE, v7 BIGINT UNIQUE," +
				"CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES test (pk)," +
				"CONSTRAINT fk2 FOREIGN KEY (v2) REFERENCES test (pk)," +
				"CONSTRAINT fk3 FOREIGN KEY (v3) REFERENCES test (pk)," +
				"CONSTRAINT fk4 FOREIGN KEY (v4) REFERENCES test (pk)," +
				"CONSTRAINT fk5 FOREIGN KEY (v5) REFERENCES test (pk)," +
				"CONSTRAINT fk6 FOREIGN KEY (v6) REFERENCES test (pk)," +
				"CONSTRAINT fk7 FOREIGN KEY (v7) REFERENCES test (pk));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `UPDATE test SET v1 = NULL, v2 = NULL WHERE test.pk = 0;`,
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 0,
					InsertID:     0,
					Info: plan.UpdateInfo{
						Matched:  0,
						Updated:  0,
						Warnings: 0,
					},
				}}},
			},
		},
	},
	{
		Name: "Self-referential delete cascade depth limit",
		SetUpScript: []string{
			"CREATE TABLE under_limit(pk BIGINT PRIMARY KEY, v1 BIGINT, INDEX idx_v1(v1));",
			"CREATE TABLE over_limit(pk BIGINT PRIMARY KEY, v1 BIGINT, INDEX idx_v1(v1));",
			"INSERT INTO under_limit VALUES (1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10),(10,11),(11,12),(12,13),(13,14),(14,1);",
			"INSERT INTO over_limit VALUES (1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,9),(9,10),(10,11),(11,12),(12,13),(13,14),(14,15),(15,1);",
			"ALTER TABLE under_limit ADD CONSTRAINT fk_under FOREIGN KEY (v1) REFERENCES under_limit(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE over_limit ADD CONSTRAINT fk_over FOREIGN KEY (v1) REFERENCES over_limit(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE FROM under_limit WHERE pk = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "DELETE FROM over_limit WHERE pk = 1;",
				ExpectedErr: sql.ErrForeignKeyDepthLimit,
			},
			{
				Query:    "DELETE FROM over_limit WHERE pk = 0;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "UPDATE over_limit SET pk = 1 WHERE pk = 1;",
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 0,
					InsertID:     0,
					Info: plan.UpdateInfo{
						Matched:  1,
						Updated:  0,
						Warnings: 0,
					},
				}}},
			},
			{
				Query:       "UPDATE over_limit SET pk = 2 WHERE pk = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
		},
	},
	{
		Name: "Cyclic 2-table delete cascade depth limit",
		SetUpScript: []string{
			"CREATE TABLE under_cycle1(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"CREATE TABLE under_cycle2(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"INSERT INTO under_cycle1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7);",
			"INSERT INTO under_cycle2 VALUES (1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,1);",
			"ALTER TABLE under_cycle1 ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES under_cycle2(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE under_cycle2 ADD CONSTRAINT fk2 FOREIGN KEY (v1) REFERENCES under_cycle1(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"CREATE TABLE over_cycle1(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"CREATE TABLE over_cycle2(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"INSERT INTO over_cycle1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);",
			"INSERT INTO over_cycle2 VALUES (1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(7,8),(8,1);",
			"ALTER TABLE over_cycle1 ADD CONSTRAINT fk3 FOREIGN KEY (v1) REFERENCES over_cycle2(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE over_cycle2 ADD CONSTRAINT fk4 FOREIGN KEY (v1) REFERENCES over_cycle1(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE FROM under_cycle1 WHERE pk = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "DELETE FROM over_cycle1 WHERE pk = 1;",
				ExpectedErr: sql.ErrForeignKeyDepthLimit,
			},
		},
	},
	{
		Name: "Cyclic 3-table delete cascade depth limit",
		SetUpScript: []string{
			"CREATE TABLE under_cycle1(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"CREATE TABLE under_cycle2(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"CREATE TABLE under_cycle3(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"INSERT INTO under_cycle1 VALUES (1,1),(2,2),(3,3),(4,4);",
			"INSERT INTO under_cycle2 VALUES (1,1),(2,2),(3,3),(4,4);",
			"INSERT INTO under_cycle3 VALUES (1,2),(2,3),(3,4),(4,1);",
			"ALTER TABLE under_cycle1 ADD CONSTRAINT fk1 FOREIGN KEY (v1) REFERENCES under_cycle2(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE under_cycle2 ADD CONSTRAINT fk2 FOREIGN KEY (v1) REFERENCES under_cycle3(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE under_cycle3 ADD CONSTRAINT fk3 FOREIGN KEY (v1) REFERENCES under_cycle1(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"CREATE TABLE over_cycle1(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"CREATE TABLE over_cycle2(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"CREATE TABLE over_cycle3(pk BIGINT PRIMARY KEY, v1 BIGINT UNIQUE);",
			"INSERT INTO over_cycle1 VALUES (1,1),(2,2),(3,3),(4,4),(5,5);",
			"INSERT INTO over_cycle2 VALUES (1,1),(2,2),(3,3),(4,4),(5,5);",
			"INSERT INTO over_cycle3 VALUES (1,2),(2,3),(3,4),(4,5),(5,1);",
			"ALTER TABLE over_cycle1 ADD CONSTRAINT fk4 FOREIGN KEY (v1) REFERENCES over_cycle2(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE over_cycle2 ADD CONSTRAINT fk5 FOREIGN KEY (v1) REFERENCES over_cycle3(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
			"ALTER TABLE over_cycle3 ADD CONSTRAINT fk6 FOREIGN KEY (v1) REFERENCES over_cycle1(pk) ON UPDATE CASCADE ON DELETE CASCADE;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE FROM under_cycle1 WHERE pk = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "DELETE FROM over_cycle1 WHERE pk = 1;",
				ExpectedErr: sql.ErrForeignKeyDepthLimit,
			},
		},
	},
	{
		Name: "Acyclic delete cascade depth limit",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY);",
			"CREATE TABLE t2(pk BIGINT PRIMARY KEY, CONSTRAINT fk1 FOREIGN KEY (pk) REFERENCES t1(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t3(pk BIGINT PRIMARY KEY, CONSTRAINT fk2 FOREIGN KEY (pk) REFERENCES t2(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t4(pk BIGINT PRIMARY KEY, CONSTRAINT fk3 FOREIGN KEY (pk) REFERENCES t3(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t5(pk BIGINT PRIMARY KEY, CONSTRAINT fk4 FOREIGN KEY (pk) REFERENCES t4(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t6(pk BIGINT PRIMARY KEY, CONSTRAINT fk5 FOREIGN KEY (pk) REFERENCES t5(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t7(pk BIGINT PRIMARY KEY, CONSTRAINT fk6 FOREIGN KEY (pk) REFERENCES t6(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t8(pk BIGINT PRIMARY KEY, CONSTRAINT fk7 FOREIGN KEY (pk) REFERENCES t7(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t9(pk BIGINT PRIMARY KEY, CONSTRAINT fk8 FOREIGN KEY (pk) REFERENCES t8(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t10(pk BIGINT PRIMARY KEY, CONSTRAINT fk9 FOREIGN KEY (pk) REFERENCES t9(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t11(pk BIGINT PRIMARY KEY, CONSTRAINT fk10 FOREIGN KEY (pk) REFERENCES t10(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t12(pk BIGINT PRIMARY KEY, CONSTRAINT fk11 FOREIGN KEY (pk) REFERENCES t11(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t13(pk BIGINT PRIMARY KEY, CONSTRAINT fk12 FOREIGN KEY (pk) REFERENCES t12(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t14(pk BIGINT PRIMARY KEY, CONSTRAINT fk13 FOREIGN KEY (pk) REFERENCES t13(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t15(pk BIGINT PRIMARY KEY, CONSTRAINT fk14 FOREIGN KEY (pk) REFERENCES t14(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t16(pk BIGINT PRIMARY KEY, CONSTRAINT fk15 FOREIGN KEY (pk) REFERENCES t15(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"INSERT INTO t1 VALUES (1);",
			"INSERT INTO t2 VALUES (1);",
			"INSERT INTO t3 VALUES (1);",
			"INSERT INTO t4 VALUES (1);",
			"INSERT INTO t5 VALUES (1);",
			"INSERT INTO t6 VALUES (1);",
			"INSERT INTO t7 VALUES (1);",
			"INSERT INTO t8 VALUES (1);",
			"INSERT INTO t9 VALUES (1);",
			"INSERT INTO t10 VALUES (1);",
			"INSERT INTO t11 VALUES (1);",
			"INSERT INTO t12 VALUES (1);",
			"INSERT INTO t13 VALUES (1);",
			"INSERT INTO t14 VALUES (1);",
			"INSERT INTO t15 VALUES (1);",
			"INSERT INTO t16 VALUES (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DELETE FROM t1;",
				ExpectedErr: sql.ErrForeignKeyDepthLimit,
			},
			{
				Query:    "DELETE FROM t16;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "DELETE FROM t1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "Acyclic update cascade depth limit",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY);",
			"CREATE TABLE t2(pk BIGINT PRIMARY KEY, CONSTRAINT fk1 FOREIGN KEY (pk) REFERENCES t1(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t3(pk BIGINT PRIMARY KEY, CONSTRAINT fk2 FOREIGN KEY (pk) REFERENCES t2(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t4(pk BIGINT PRIMARY KEY, CONSTRAINT fk3 FOREIGN KEY (pk) REFERENCES t3(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t5(pk BIGINT PRIMARY KEY, CONSTRAINT fk4 FOREIGN KEY (pk) REFERENCES t4(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t6(pk BIGINT PRIMARY KEY, CONSTRAINT fk5 FOREIGN KEY (pk) REFERENCES t5(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t7(pk BIGINT PRIMARY KEY, CONSTRAINT fk6 FOREIGN KEY (pk) REFERENCES t6(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t8(pk BIGINT PRIMARY KEY, CONSTRAINT fk7 FOREIGN KEY (pk) REFERENCES t7(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t9(pk BIGINT PRIMARY KEY, CONSTRAINT fk8 FOREIGN KEY (pk) REFERENCES t8(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t10(pk BIGINT PRIMARY KEY, CONSTRAINT fk9 FOREIGN KEY (pk) REFERENCES t9(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t11(pk BIGINT PRIMARY KEY, CONSTRAINT fk10 FOREIGN KEY (pk) REFERENCES t10(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t12(pk BIGINT PRIMARY KEY, CONSTRAINT fk11 FOREIGN KEY (pk) REFERENCES t11(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t13(pk BIGINT PRIMARY KEY, CONSTRAINT fk12 FOREIGN KEY (pk) REFERENCES t12(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t14(pk BIGINT PRIMARY KEY, CONSTRAINT fk13 FOREIGN KEY (pk) REFERENCES t13(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t15(pk BIGINT PRIMARY KEY, CONSTRAINT fk14 FOREIGN KEY (pk) REFERENCES t14(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"CREATE TABLE t16(pk BIGINT PRIMARY KEY, CONSTRAINT fk15 FOREIGN KEY (pk) REFERENCES t15(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"INSERT INTO t1 VALUES (1);",
			"INSERT INTO t2 VALUES (1);",
			"INSERT INTO t3 VALUES (1);",
			"INSERT INTO t4 VALUES (1);",
			"INSERT INTO t5 VALUES (1);",
			"INSERT INTO t6 VALUES (1);",
			"INSERT INTO t7 VALUES (1);",
			"INSERT INTO t8 VALUES (1);",
			"INSERT INTO t9 VALUES (1);",
			"INSERT INTO t10 VALUES (1);",
			"INSERT INTO t11 VALUES (1);",
			"INSERT INTO t12 VALUES (1);",
			"INSERT INTO t13 VALUES (1);",
			"INSERT INTO t14 VALUES (1);",
			"INSERT INTO t15 VALUES (1);",
			"INSERT INTO t16 VALUES (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "UPDATE t1 SET pk = 2;",
				ExpectedErr: sql.ErrForeignKeyDepthLimit,
			},
			{
				Query:    "DELETE FROM t16;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query: "UPDATE t1 SET pk = 2;",
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 1,
					InsertID:     0,
					Info: plan.UpdateInfo{
						Matched:  1,
						Updated:  1,
						Warnings: 0,
					},
				}}},
			},
		},
	},
	{
		Name: "VARCHAR child violation detection",
		SetUpScript: []string{
			"CREATE TABLE colors (id INT NOT NULL, color VARCHAR(32) NOT NULL, PRIMARY KEY (id), INDEX color_index(color));",
			"CREATE TABLE objects (id INT NOT NULL, name VARCHAR(64) NOT NULL, color VARCHAR(32), PRIMARY KEY(id), CONSTRAINT color_fk FOREIGN KEY (color) REFERENCES colors(color));",
			"INSERT INTO colors (id, color) VALUES (1, 'red'), (2, 'green'), (3, 'blue'), (4, 'purple');",
			"INSERT INTO objects (id, name, color) VALUES (1, 'truck', 'red'), (2, 'ball', 'green'), (3, 'shoe', 'blue');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DELETE FROM colors where color='green';",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "SELECT * FROM colors;",
				Expected: []sql.Row{{1, "red"}, {2, "green"}, {3, "blue"}, {4, "purple"}},
			},
		},
	},
	{
		Name: "INSERT IGNORE INTO works correctly with foreign key violations",
		SetUpScript: []string{
			"CREATE TABLE colors (id INT NOT NULL, color VARCHAR(32) NOT NULL, PRIMARY KEY (id), INDEX color_index(color));",
			"CREATE TABLE objects (id INT NOT NULL, name VARCHAR(64) NOT NULL, color VARCHAR(32), PRIMARY KEY(id), CONSTRAINT color_fk FOREIGN KEY (color) REFERENCES colors(color));",
			"INSERT INTO colors (id, color) VALUES (1, 'red'), (2, 'green'), (3, 'blue'), (4, 'purple');",
			"INSERT INTO objects (id, name, color) VALUES (1, 'truck', 'red'), (2, 'ball', 'green'), (3, 'shoe', 'blue');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT IGNORE INTO objects (id, name, color) VALUES (5, 'hi', 'yellow');",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SELECT * FROM objects;",
				Expected: []sql.Row{{1, "truck", "red"}, {2, "ball", "green"}, {3, "shoe", "blue"}},
			},
		},
	},
	{
		Name: "Delayed foreign key resolution",
		SetUpScript: []string{
			"SET FOREIGN_KEY_CHECKS=0;",
			"CREATE TABLE delayed_child (pk INT PRIMARY KEY, v1 INT, CONSTRAINT fk_delayed FOREIGN KEY (v1) REFERENCES delayed_parent(v1));",
			"CREATE TABLE delayed_parent (pk INT PRIMARY KEY, v1 INT, INDEX (v1));",
			"INSERT INTO delayed_child VALUES (1, 2);",
			"SET FOREIGN_KEY_CHECKS=1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE delayed_child;",
				Expected: []sql.Row{{"delayed_child", "CREATE TABLE `delayed_child` (\n  `pk` int NOT NULL,\n  `v1` int,\n  PRIMARY KEY (`pk`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_delayed` FOREIGN KEY (`v1`) REFERENCES `delayed_parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "SELECT * FROM delayed_parent;",
				Expected: []sql.Row{},
			},
			{
				Query:    "SELECT * FROM delayed_child;",
				Expected: []sql.Row{{1, 2}},
			},
			{
				Query:       "INSERT INTO delayed_child VALUES (2, 3);",
				ExpectedErr: sql.ErrForeignKeyNotResolved,
			},
			{
				Query:    "INSERT INTO delayed_parent VALUES (1, 2), (2, 3);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO delayed_child VALUES (2, 3);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM delayed_child;",
				Expected: []sql.Row{{1, 2}, {2, 3}},
			},
		},
	},
	{
		Name: "Delayed foreign key still does some validation",
		SetUpScript: []string{
			"SET FOREIGN_KEY_CHECKS=0;",
			"CREATE TABLE valid_delayed_child (i INT, CONSTRAINT valid_fk FOREIGN KEY (i) REFERENCES delayed_parent(i))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CREATE TABLE delayed_child1(i int, CONSTRAINT fk_delayed1 FOREIGN KEY (badcolumn) REFERENCES delayed_parent(i));",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query:       "CREATE TABLE delayed_child2(i int, CONSTRAINT fk_delayed2 FOREIGN KEY (i) REFERENCES delayed_parent(c1, c2, c3));",
				ExpectedErr: sql.ErrForeignKeyColumnCountMismatch,
			},
			{
				Query:       "CREATE TABLE delayed_child3(i int, j int, CONSTRAINT fk_i FOREIGN KEY (i) REFERENCES delayed_parent(i), CONSTRAINT fk_i FOREIGN KEY (j) REFERENCES delayed_parent(j));",
				ExpectedErr: sql.ErrForeignKeyDuplicateName,
			},
			{
				Query:       "CREATE TABLE delayed_child4(i int, CONSTRAINT fk_delayed4 FOREIGN KEY (i,i,i) REFERENCES delayed_parent(c1, c2, c3));",
				ExpectedErr: sql.ErrAddForeignKeyDuplicateColumn,
			},
			{
				Query:       "ALTER TABLE valid_delayed_child drop index i",
				ExpectedErr: sql.ErrForeignKeyDropIndex,
			},
		},
	},
	{
		Name: "Delayed foreign key resolution resetting FOREIGN_KEY_CHECKS",
		SetUpScript: []string{
			"SET FOREIGN_KEY_CHECKS=0;",
			"CREATE TABLE delayed_child (pk INT PRIMARY KEY, v1 INT, CONSTRAINT fk_delayed FOREIGN KEY (v1) REFERENCES delayed_parent(v1));",
			"INSERT INTO delayed_child VALUES (1, 2);",
			"SET FOREIGN_KEY_CHECKS=1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE delayed_child;",
				Expected: []sql.Row{{"delayed_child", "CREATE TABLE `delayed_child` (\n  `pk` int NOT NULL,\n  `v1` int,\n  PRIMARY KEY (`pk`),\n  KEY `v1` (`v1`),\n  CONSTRAINT `fk_delayed` FOREIGN KEY (`v1`) REFERENCES `delayed_parent` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "SELECT * FROM delayed_child;",
				Expected: []sql.Row{{1, 2}},
			},
			{
				Query:       "INSERT INTO delayed_child VALUES (2, 3);",
				ExpectedErr: sql.ErrForeignKeyNotResolved,
			},
			{
				Query:    "CREATE TABLE delayed_parent (pk INT PRIMARY KEY, v1 INT, INDEX (v1));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO delayed_parent VALUES (1, 2), (2, 3);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO delayed_child VALUES (2, 3);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM delayed_child;",
				Expected: []sql.Row{{1, 2}, {2, 3}},
			},
		},
	},
	{
		Name: "DROP TABLE with FOREIGN_KEY_CHECKS=0",
		SetUpScript: []string{
			"ALTER TABLE child ADD CONSTRAINT fk_dropped FOREIGN KEY (v1) REFERENCES parent(v1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "TRUNCATE parent;",
				ExpectedErr: sql.ErrTruncateReferencedFromForeignKey,
			},
			{
				Query:       "DROP TABLE parent;",
				ExpectedErr: sql.ErrForeignKeyDropTable,
			},
			{
				Query:    "SET FOREIGN_KEY_CHECKS=0;",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "TRUNCATE parent;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "DROP TABLE parent;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SET FOREIGN_KEY_CHECKS=1;",
				Expected: []sql.Row{{}},
			},
			{
				Query:       "INSERT INTO child VALUES (4, 5, 6);",
				ExpectedErr: sql.ErrForeignKeyNotResolved,
			},
			{
				Query:    "CREATE TABLE parent (pk INT PRIMARY KEY, v1 INT, INDEX (v1));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO parent VALUES (1, 5);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO child VALUES (4, 5, 6);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{1, 5}},
			},
			{
				Query:    "SELECT * FROM child;",
				Expected: []sql.Row{{4, 5, 6}},
			},
		},
	},
	{
		Name: "ALTER TABLE ADD CONSTRAINT for different database",
		SetUpScript: []string{
			"CREATE DATABASE public;",
			"CREATE TABLE public.cities (pk INT PRIMARY KEY, city VARCHAR(255), state VARCHAR(2));",
			"CREATE TABLE public.states (state_id INT PRIMARY KEY, state VARCHAR(2));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE public.cities ADD CONSTRAINT foreign_key1 FOREIGN KEY (state) REFERENCES public.states(state);",
				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
			},
			{
				Query:    "CREATE INDEX foreign_key1 ON public.states(state);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE public.cities ADD CONSTRAINT foreign_key1 FOREIGN KEY (state) REFERENCES public.states(state);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Creating a foreign key on a table with an unsupported type works",
		SetUpScript: []string{
			"CREATE TABLE IF NOT EXISTS restaurants (id INT PRIMARY KEY, coordinate POINT);",
			"CREATE TABLE IF NOT EXISTS hours (restaurant_id INT PRIMARY KEY AUTO_INCREMENT, CONSTRAINT fk_name FOREIGN KEY (restaurant_id) REFERENCES restaurants(id));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE hours;",
				Expected: []sql.Row{{"hours", "CREATE TABLE `hours` (\n  `restaurant_id` int NOT NULL AUTO_INCREMENT,\n  PRIMARY KEY (`restaurant_id`),\n  CONSTRAINT `fk_name` FOREIGN KEY (`restaurant_id`) REFERENCES `restaurants` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "Create foreign key onto primary key",
		SetUpScript: []string{
			"DROP TABLE child;",
			"DROP TABLE parent;",
			"CREATE TABLE parent (a INT, b INT, c INT, PRIMARY KEY (b, a));",
			"CREATE TABLE child (a INT PRIMARY KEY, b INT);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE child ADD CONSTRAINT fk1 FOREIGN KEY (b) REFERENCES parent (b);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child ADD CONSTRAINT fk2 FOREIGN KEY (a) REFERENCES parent (b);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child ADD CONSTRAINT fk3 FOREIGN KEY (a, b) REFERENCES parent (a, b);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE child ADD CONSTRAINT fk4 FOREIGN KEY (b, a) REFERENCES parent (b, a);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Reordered foreign key columns match an index's prefix, INSERT values",
		SetUpScript: []string{
			"DROP TABLE child;",
			"DROP TABLE parent;",
			"CREATE TABLE parent(pk DOUBLE PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX(v1, v2, pk));",
			"INSERT INTO parent VALUES (1, 1, 1), (2, 1, 2);",
			"CREATE TABLE child(pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_child FOREIGN KEY (v2, v1) REFERENCES parent(v2, v1));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO child VALUES (1, 1, 1);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "INSERT INTO child VALUES (2, 2, 2);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
			{
				Query:       "INSERT INTO child VALUES (3, 2, 1);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
			{
				Query:    "INSERT INTO child VALUES (4, 1, 2);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "Reordered foreign key columns match an index's prefix, ALTER TABLE ADD FOREIGN KEY fails check",
		SetUpScript: []string{
			"DROP TABLE child;",
			"DROP TABLE parent;",
			"CREATE TABLE parent(pk DOUBLE PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX(v1, v2, pk));",
			"INSERT INTO parent VALUES (1, 1, 1), (2, 1, 2);",
			"CREATE TABLE child(pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT);",
			"INSERT INTO child VALUES (1, 2, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE child ADD CONSTRAINT fk_child FOREIGN KEY (v2, v1) REFERENCES parent(v2, v1);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
		},
	},
	{
		Name: "Self-referential deletion with ON UPDATE CASCADE",
		SetUpScript: []string{
			"CREATE TABLE self(pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX(v1), CONSTRAINT fk_self FOREIGN KEY(v2) REFERENCES self(v1) ON UPDATE CASCADE);",
			"INSERT INTO self VALUES (0, 1, 1), (1, 2, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DELETE FROM self WHERE v1 = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "DELETE FROM self WHERE v1 = 2;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "Self-referential deletion with ON DELETE CASCADE",
		SetUpScript: []string{
			"CREATE TABLE self(pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX(v1), CONSTRAINT fk_self FOREIGN KEY(v2) REFERENCES self(v1) ON DELETE CASCADE);",
			"INSERT INTO self VALUES (0, 1, 1), (1, 2, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE FROM self WHERE v1 = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM self;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Cascaded DELETE becomes cascading UPDATE after first child, using ON DELETE for second child",
		SetUpScript: []string{
			"DROP TABLE child;",
			"DROP TABLE parent;",
			"CREATE TABLE parent (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX (v1), INDEX (v2), INDEX (v1, v2));",
			"CREATE TABLE child (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_child FOREIGN KEY (v1, v2) REFERENCES parent (v1, v2) ON DELETE SET NULL);",
			"CREATE TABLE child2 (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_child2 FOREIGN KEY (v1, v2) REFERENCES child (v1, v2) ON DELETE SET NULL);",
			"INSERT INTO parent VALUES (1,1,1), (2,2,2), (3,3,3);",
			"INSERT INTO child VALUES (1,1,1), (2,2,2), (3,3,3);",
			"INSERT INTO child2 VALUES (1,1,1), (2,2,2), (3,3,3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DELETE FROM parent WHERE pk = 1;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
		},
	},
	{
		Name: "Cascaded DELETE becomes cascading UPDATE after first child, using ON UPDATE for second child",
		SetUpScript: []string{
			"DROP TABLE child;",
			"DROP TABLE parent;",
			"CREATE TABLE parent (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX (v1), INDEX (v2), INDEX (v1, v2));",
			"CREATE TABLE child (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_child FOREIGN KEY (v1, v2) REFERENCES parent (v1, v2) ON DELETE SET NULL);",
			"CREATE TABLE child2 (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, CONSTRAINT fk_child2 FOREIGN KEY (v1, v2) REFERENCES child (v1, v2) ON UPDATE CASCADE);",
			"INSERT INTO parent VALUES (1,1,1), (2,2,2), (3,3,3);",
			"INSERT INTO child VALUES (1,1,1), (2,2,2), (3,3,3);",
			"INSERT INTO child2 VALUES (1,1,1), (2,2,2), (3,3,3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE FROM parent WHERE pk = 1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM parent;",
				Expected: []sql.Row{{2, 2, 2}, {3, 3, 3}},
			},
			{
				Query:    "SELECT * FROM child;",
				Expected: []sql.Row{{1, nil, nil}, {2, 2, 2}, {3, 3, 3}},
			},
			{
				Query:    "SELECT * FROM child2;",
				Expected: []sql.Row{{1, nil, nil}, {2, 2, 2}, {3, 3, 3}},
			},
		},
	},
	{
		Name: "INSERT on DUPLICATE correctly works with FKs",
		SetUpScript: []string{
			"INSERT INTO parent values (1,1,1),(2,2,2),(3,3,3)",
			"ALTER TABLE child ADD CONSTRAINT fk_named FOREIGN KEY (v1) REFERENCES parent(v1);",
			"INSERT into child values (1, 1, 1)",
			"CREATE TABLE one (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1 (v1));",
			"CREATE TABLE two (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, INDEX v1v2 (v1, v2), CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1) ON DELETE CASCADE ON UPDATE CASCADE);",
			"INSERT INTO one VALUES (1, 1, 4), (2, 2, 5), (3, 3, 6), (4, 4, 5);",
			"INSERT INTO two VALUES (2, 1, 1), (3, 2, 2), (4, 3, 3), (5, 4, 4);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "INSERT INTO parent VALUES (1,200,1) ON DUPLICATE KEY UPDATE v1 = values(v1)",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "INSERT INTO one VALUES (1, 2, 4) on duplicate key update v1 = VALUES(v1)",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "SELECT * FROM two where pk = 2",
				Expected: []sql.Row{{2, 2, 1}},
			},
		},
	},
	{
		Name: "Referencing Primary Key",
		SetUpScript: []string{
			"CREATE table parent1 (pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"CREATE table child1 (pk BIGINT PRIMARY KEY, v1 BIGINT, FOREIGN KEY (v1) REFERENCES parent1(pk) ON UPDATE CASCADE ON DELETE CASCADE);",
			"INSERT INTO parent1 VALUES (1, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO child1 VALUES (1, 1);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM child1;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:    "UPDATE parent1 SET pk = 2;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "SELECT * FROM child1;",
				Expected: []sql.Row{{1, 2}},
			},
		},
	},
	{
		Name: "Referencing Composite Primary Key",
		SetUpScript: []string{
			"CREATE table parent1 (pk1 BIGINT, pk2 BIGINT, v1 BIGINT, PRIMARY KEY(pk1, pk2));",
			"CREATE table child1 (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, FOREIGN KEY (v1, v2) REFERENCES parent1(pk1, pk2) ON UPDATE CASCADE ON DELETE CASCADE);",
			"INSERT INTO parent1 VALUES (1, 2, 3), (4, 5, 6);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO child1 VALUES (1, 1, 2), (2, 4, 5);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "SELECT * FROM child1;",
				Expected: []sql.Row{{1, 1, 2}, {2, 4, 5}},
			},
			{
				Query:    "UPDATE parent1 SET pk2 = pk1 + pk2;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2, Info: plan.UpdateInfo{Matched: 2, Updated: 2}}}},
			},
			{
				Query:    "SELECT * FROM child1;",
				Expected: []sql.Row{{1, 1, 3}, {2, 4, 9}},
			},
		},
	},
	{
		Name: "Keyless CASCADE deleting all rows",
		SetUpScript: []string{
			"CREATE TABLE one (v0 BIGINT, v1 BIGINT, INDEX one_v0 (v0), INDEX one_v1 (v1));",
			"CREATE TABLE two (v1 BIGINT, CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1) ON DELETE CASCADE ON UPDATE CASCADE);",
			"INSERT INTO one VALUES (1, 2);",
			"INSERT INTO two VALUES (2);",
			"UPDATE one SET v1 = v0 + v1;",
			"DELETE FROM one WHERE v0 = 1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM one;",
				Expected: []sql.Row{},
			},
			{
				Query:    "SELECT * FROM two;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Keyless CASCADE over three tables",
		SetUpScript: []string{
			"CREATE TABLE one (v0 BIGINT, v1 BIGINT, v2 BIGINT, INDEX idx (v0));",
			"ALTER TABLE one ADD INDEX v1 (v1);",
			"CREATE TABLE two (v0 BIGINT, v1 BIGINT, v2 BIGINT, INDEX idx (v0), CONSTRAINT fk_name_1 FOREIGN KEY (v1) REFERENCES one(v1) ON DELETE CASCADE ON UPDATE CASCADE);",
			"ALTER TABLE two ADD INDEX v1v2 (v1, v2);",
			"CREATE TABLE three (v0 BIGINT, v1 BIGINT, v2 BIGINT, INDEX idx (v0), CONSTRAINT fk_name_2 FOREIGN KEY (v1, v2) REFERENCES two(v1, v2) ON DELETE CASCADE ON UPDATE CASCADE);",
			"INSERT INTO one VALUES (1, 1, 4), (2, 2, 5), (3, 3, 6), (4, 4, 5);",
			"INSERT INTO two VALUES (2, 1, 1), (3, 2, 2), (4, 3, 3), (5, 4, 4);",
			"INSERT INTO three VALUES (3, 1, 1), (4, 2, 2), (5, 3, 3), (6, 4, 4);",
			"UPDATE one SET v1 = v1 + v2;",
			"DELETE FROM one WHERE v0 = 3;",
			"UPDATE two SET v2 = v1 - 2;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM one;",
				Expected: []sql.Row{{1, 5, 4}, {2, 7, 5}, {4, 9, 5}},
			},
			{
				Query:    "SELECT * FROM two;",
				Expected: []sql.Row{{2, 5, 3}, {3, 7, 5}},
			},
			{
				Query:    "SELECT * FROM three;",
				Expected: []sql.Row{{3, 5, 3}, {4, 7, 5}},
			},
		},
	},
	{
		Name: "Table with inverted primary key referencing another table can insert rows",
		SetUpScript: []string{
			"create table a (x int, y int, primary key (x,y), INDEX `a_y_idx` (y));",
			"create table b (x int, y int, primary key (y,x), foreign key (y) references a(y) on update cascade on delete cascade);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT into a (x, y) VALUES (1, 3);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT into b (x, y) VALUES (2, 3);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT x, y from a;",
				Expected: []sql.Row{{1, 3}},
			},
			{
				Query:    "SELECT x, y  from b;",
				Expected: []sql.Row{{2, 3}},
			},
			{
				Query:       "INSERT into b (x, y) VALUES (3, 5);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
		},
	},
	{
		Name: "Table with inverted primary key referencing another table with inverted primary keys can be inserted",
		SetUpScript: []string{
			"create table a (x int, y int, primary key (y,x));",
			"create table b (x int, y int, primary key (y,x), foreign key (y) references a(y) on update cascade on delete cascade);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT into a (x, y) VALUES (1, 3);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT into b (x, y) VALUES (2, 3);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT x, y from a;",
				Expected: []sql.Row{{1, 3}},
			},
			{
				Query:    "SELECT x, y from b;",
				Expected: []sql.Row{{2, 3}},
			},
			{
				Query:       "INSERT into b (x, y) VALUES (3, 5);",
				ExpectedErr: sql.ErrForeignKeyChildViolation,
			},
		},
	},
	{
		Name: "Table with inverted primary key referencing another table can be updated",
		SetUpScript: []string{
			"create table a (x int, y int, primary key (x,y), INDEX `a_y_idx` (y));",
			"create table b (x int, y int, primary key (y,x), foreign key (y) references a(y) on update cascade on delete cascade);",
			"INSERT into a VALUES (1, 3);",
			"INSERT into b VALUES (2, 3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "UPDATE a SET y = 4 where y = 3;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "SELECT x, y from a;",
				Expected: []sql.Row{{1, 4}},
			},
			{
				Query:    "SELECT x, y from b;",
				Expected: []sql.Row{{2, 4}},
			},
		},
	},
	{
		Name: "Table with inverted primary key referencing another table with inverted primary keys can be updated",
		SetUpScript: []string{
			"create table a (x int, y int, primary key (y,x));",
			"create table b (x int, y int, primary key (y,x), foreign key (y) references a(y) on update cascade on delete cascade);",
			"INSERT into a VALUES (1, 3)",
			"INSERT into b VALUES (2, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "UPDATE a SET y = 4 where y = 3;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "SELECT x, y from a;",
				Expected: []sql.Row{{1, 4}},
			},
			{
				Query:    "SELECT x, y from b;",
				Expected: []sql.Row{{2, 4}},
			},
		},
	},
	{
		Name: "Table with inverted primary key referencing another table can be deleted",
		SetUpScript: []string{
			"create table a (x int, y int, primary key (x,y), INDEX `a_y_idx` (y));",
			"create table b (x int, y int, primary key (y,x), foreign key (y) references a(y) on update cascade on delete cascade);",
			"INSERT into a VALUES (1, 3);",
			"INSERT into b VALUES (2, 3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE from a where x = 1 AND y = 3;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * from a;",
				Expected: []sql.Row{},
			},
			{
				Query:    "SELECT * from b;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Table with inverted primary key referencing another table with inverted primary keys can be deleted",
		SetUpScript: []string{
			"create table a (x int, y int, primary key (y,x));",
			"create table b (x int, y int, primary key (y,x), foreign key (y) references a(y) on update cascade on delete cascade);",
			"INSERT into a VALUES (1, 3)",
			"INSERT into b VALUES (2, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE from a where x = 1 AND y = 3;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * from a;",
				Expected: []sql.Row{},
			},
			{
				Query:    "SELECT * from b;",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "May use different collations as long as the character sets are equivalent",
		SetUpScript: []string{
			"CREATE TABLE t1 (pk char(32) COLLATE utf8mb4_0900_ai_ci PRIMARY KEY);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CREATE TABLE t2 (pk char(32) COLLATE utf8mb4_0900_bin PRIMARY KEY, CONSTRAINT fk_1 FOREIGN KEY (pk) REFERENCES t1 (pk));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
}

ForeignKeyTests will run the following statements BEFORE the SetUpScript: CREATE TABLE parent (id INT PRIMARY KEY, v1 INT, v2 INT, INDEX v1 (v1), INDEX v2 (v2)); CREATE TABLE child (id INT PRIMARY KEY, v1 INT, v2 INT);

View Source
var GenericUpdateErrorTests = []GenericErrorQueryTest{
	{
		Name:  "invalid table",
		Query: "UPDATE doesnotexist SET i = 0;",
	},
	{
		Name:  "missing binding",
		Query: "UPDATE mytable SET i = ?;",
	},
	{
		Name:  "wrong number of columns",
		Query: `UPDATE mytable SET i = ("one", "two");`,
	},
	{
		Name:  "type mismatch: string -> int",
		Query: `UPDATE mytable SET i = "one"`,
	},
	{
		Name:  "type mismatch: string -> float",
		Query: `UPDATE floattable SET f64 = "one"`,
	},
	{
		Name:  "type mismatch: string -> uint",
		Query: `UPDATE typestable SET f64 = "one"`,
	},
	{
		Name:  "invalid column set",
		Query: "UPDATE mytable SET z = 0;",
	},
	{
		Name:  "invalid column set value",
		Query: "UPDATE mytable SET i = z;",
	},
	{
		Name:  "invalid column where",
		Query: "UPDATE mytable SET s = 'hi' WHERE z = 1;",
	},
	{
		Name:  "invalid column order by",
		Query: "UPDATE mytable SET s = 'hi' ORDER BY z;",
	},
	{
		Name:  "negative limit",
		Query: "UPDATE mytable SET s = 'hi' LIMIT -1;",
	},
	{
		Name:  "negative offset",
		Query: "UPDATE mytable SET s = 'hi' LIMIT 1 OFFSET -1;",
	},
	{
		Name:  "set null on non-nullable",
		Query: "UPDATE mytable SET s = NULL;",
	},
	{
		Name:  "targets join",
		Query: "UPDATE mytable one, mytable two SET s = NULL;",
	},
	{
		Name:  "targets subquery alias",
		Query: "UPDATE (SELECT * FROM mytable) mytable SET s = NULL;",
	},
}
View Source
var IgnoreWithDuplicateUniqueKeyKeylessScripts = []ScriptTest{
	{
		Name: "Test that INSERT IGNORE INTO works with unique keys on a keyless table",
		SetUpScript: []string{
			"CREATE TABLE one_uniq(not_pk int, value int UNIQUE)",
			"CREATE TABLE two_uniq(not_pk int, col1 int, col2 int, UNIQUE KEY col1_col2_uniq (col1, col2));",
			"INSERT INTO one_uniq values (1, 1)",
			"INSERT INTO two_uniq values (1, 1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "INSERT IGNORE INTO one_uniq VALUES (3, 2), (2, 1), (4, null), (5, null)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 3}},
				},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query: "SELECT * from one_uniq;",
				Expected: []sql.Row{
					{1, 1}, {3, 2}, {4, nil}, {5, nil},
				},
			},
			{
				Query: "INSERT IGNORE INTO two_uniq VALUES (4, 1, 2), (5, 2, 1), (6, null, 1), (7, null, 1), (12, 1, 1), (8, 1, null), (9, 1, null), (10, null, null), (11, null, null)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 8}},
				},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query: "SELECT * from two_uniq;",
				Expected: []sql.Row{
					{1, 1, 1}, {4, 1, 2}, {5, 2, 1}, {6, nil, 1}, {7, nil, 1}, {8, 1, nil}, {9, 1, nil}, {10, nil, nil}, {11, nil, nil},
				},
			},
		},
	},
	{
		Name: "INSERT IGNORE INTO multiple violations of a unique secondary index",
		SetUpScript: []string{
			"CREATE TABLE keyless(pk int, val int)",
			"INSERT INTO keyless values (1, 1), (2, 2), (3, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT IGNORE INTO keyless VALUES (1, 2);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "ALTER TABLE keyless ADD CONSTRAINT c UNIQUE(val)",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "DELETE FROM keyless where pk = 1 and val = 2",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "ALTER TABLE keyless ADD CONSTRAINT c UNIQUE(val)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:           "INSERT IGNORE INTO keyless VALUES (1, 3)",
				Expected:        []sql.Row{{types.NewOkResult(0)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
		},
	},
	{
		Name: "UPDATE IGNORE keyless tables and secondary indexes",
		SetUpScript: []string{
			"CREATE TABLE keyless(pk int, val int)",
			"INSERT INTO keyless VALUES (1, 1), (2, 2), (3, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "UPDATE IGNORE keyless SET val = 2 where pk = 1",
				Expected: []sql.Row{{newUpdateResult(1, 1)}},
			},
			{
				Query:    "SELECT * FROM keyless ORDER BY pk",
				Expected: []sql.Row{{1, 2}, {2, 2}, {3, 3}},
			},
			{
				Query:       "ALTER TABLE keyless ADD CONSTRAINT c UNIQUE(val)",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:           "UPDATE IGNORE keyless SET val = 1 where pk = 1",
				Expected:        []sql.Row{{newUpdateResult(1, 1)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query:    "ALTER TABLE keyless ADD CONSTRAINT c UNIQUE(val)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:           "UPDATE IGNORE keyless SET val = 3 where pk = 1",
				Expected:        []sql.Row{{newUpdateResult(1, 0)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query:    "SELECT * FROM keyless ORDER BY pk",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:           "UPDATE IGNORE keyless SET val = val + 1 ORDER BY pk",
				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query:    "SELECT * FROM keyless ORDER BY pk",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 4}},
			},
		},
	},
}
View Source
var IndexPlanTests = []QueryPlanTest{}/* 732 elements not displayed */
View Source
var IndexPrefixQueries = []ScriptTest{
	{
		Name: "int prefix",
		SetUpScript: []string{
			"create table t (i int)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (i(10))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "alter table t add index (i(10))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table c_tbl (i int, primary key (i(10)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table c_tbl (i int primary key, j int, index (j(10)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
		},
	},
	{
		Name: "float prefix",
		SetUpScript: []string{
			"create table t (f float)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (f(10))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "alter table t add index (f(10))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table c_tbl (f float, primary key (f(10)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table c_tbl (i int primary key, f float, index (f(10)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
		},
	},
	{
		Name: "string index prefix errors",
		SetUpScript: []string{
			"create table v_tbl (v varchar(10))",
			"create table c_tbl (c char(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table v_tbl add primary key (v(0))",
				ExpectedErr: sql.ErrKeyZero,
			},
			{
				Query:       "alter table v_tbl add primary key (v(11))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "alter table v_tbl add index (v(0))",
				ExpectedErr: sql.ErrKeyZero,
			},
			{
				Query:       "alter table v_tbl add index (v(11))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "alter table c_tbl add primary key (c(11))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "alter table c_tbl add index (c(11))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table t (v varchar(10), primary key(v(0)))",
				ExpectedErr: sql.ErrKeyZero,
			},
			{
				Query:       "create table t (v varchar(10), primary key(v(11)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table t (v varchar(10), index(v(11)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table t (c char(10), primary key(c(11)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
			{
				Query:       "create table t (c char(10), index(c(11)))",
				ExpectedErr: sql.ErrInvalidIndexPrefix,
			},
		},
	},
	{
		Name: "varchar primary key prefix",
		SetUpScript: []string{
			"create table t (v varchar(100))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (v(10))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
			{
				Query:       "create table v_tbl (v varchar(100), primary key (v(10)))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
		},
	},
	{
		Name: "varchar keyed secondary index prefix",
		SetUpScript: []string{
			"create table t (i int primary key, v varchar(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (v(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `v` varchar(10),\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `v` (`v`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values (0, 'aa'), (1, 'ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "insert into t values (0, 'aa'), (1, 'bb'), (2, 'cc')",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
			{
				Query:    "select * from t where v = 'a'",
				Expected: []sql.Row{},
			},
			{
				Query: "select * from t where v = 'aa'",
				Expected: []sql.Row{
					{0, "aa"},
				},
			},
			{
				Query:    "create table v_tbl (i int primary key, v varchar(100), index (v(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table v_tbl",
				Expected: []sql.Row{{"v_tbl", "CREATE TABLE `v_tbl` (\n  `i` int NOT NULL,\n  `v` varchar(100),\n  PRIMARY KEY (`i`),\n  KEY `v` (`v`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "varchar keyless secondary index prefix",
		SetUpScript: []string{
			"create table t (v varchar(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (v(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `v` varchar(10),\n  UNIQUE KEY `v` (`v`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values ('aa'), ('ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table v_tbl (v varchar(100), index (v(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table v_tbl",
				Expected: []sql.Row{{"v_tbl", "CREATE TABLE `v_tbl` (\n  `v` varchar(100),\n  KEY `v` (`v`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "char primary key prefix",
		SetUpScript: []string{
			"create table t (c char(100))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (c(10))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
			{
				Query:       "create table c_tbl (c char(100), primary key (c(10)))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
		},
	},
	{
		Name: "char keyed secondary index prefix",
		SetUpScript: []string{
			"create table t (i int primary key, c char(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (c(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `c` char(10),\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `c` (`c`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values (0, 'aa'), (1, 'ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table c_tbl (i int primary key, c varchar(100), index (c(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table c_tbl",
				Expected: []sql.Row{{"c_tbl", "CREATE TABLE `c_tbl` (\n  `i` int NOT NULL,\n  `c` varchar(100),\n  PRIMARY KEY (`i`),\n  KEY `c` (`c`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "char keyless secondary index prefix",
		SetUpScript: []string{
			"create table t (c char(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (c(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `c` char(10),\n  UNIQUE KEY `c` (`c`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values ('aa'), ('ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table c_tbl (c char(100), index (c(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table c_tbl",
				Expected: []sql.Row{{"c_tbl", "CREATE TABLE `c_tbl` (\n  `c` char(100),\n  KEY `c` (`c`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "varbinary primary key prefix",
		SetUpScript: []string{
			"create table t (v varbinary(100))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (v(10))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
			{
				Query:       "create table v_tbl (v varbinary(100), primary key (v(10)))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
		},
	},
	{
		Name: "varbinary keyed secondary index prefix",
		SetUpScript: []string{
			"create table t (i int primary key, v varbinary(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (v(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `v` varbinary(10),\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `v` (`v`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values (0, 'aa'), (1, 'ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table v_tbl (i int primary key, v varbinary(100), index (v(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table v_tbl",
				Expected: []sql.Row{{"v_tbl", "CREATE TABLE `v_tbl` (\n  `i` int NOT NULL,\n  `v` varbinary(100),\n  PRIMARY KEY (`i`),\n  KEY `v` (`v`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "varbinary keyless secondary index prefix",
		SetUpScript: []string{
			"create table t (v varbinary(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (v(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `v` varbinary(10),\n  UNIQUE KEY `v` (`v`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values ('aa'), ('ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table v_tbl (v varbinary(100), index (v(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table v_tbl",
				Expected: []sql.Row{{"v_tbl", "CREATE TABLE `v_tbl` (\n  `v` varbinary(100),\n  KEY `v` (`v`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "binary primary key prefix",
		SetUpScript: []string{
			"create table t (b binary(100))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (b(10))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
			{
				Query:       "create table b_tbl (b binary(100), primary key (b(10)))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
		},
	},
	{
		Name: "binary keyed secondary index prefix",
		SetUpScript: []string{
			"create table t (i int primary key, b binary(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (b(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `b` binary(10),\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `b` (`b`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values (0, 'aa'), (1, 'ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table b_tbl (i int primary key, b binary(100), index (b(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table b_tbl",
				Expected: []sql.Row{{"b_tbl", "CREATE TABLE `b_tbl` (\n  `i` int NOT NULL,\n  `b` binary(100),\n  PRIMARY KEY (`i`),\n  KEY `b` (`b`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "binary keyless secondary index prefix",
		SetUpScript: []string{
			"create table t (b binary(10))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (b(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `b` binary(10),\n  UNIQUE KEY `b` (`b`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values ('aa'), ('ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table b_tbl (b binary(100), index (b(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table b_tbl",
				Expected: []sql.Row{{"b_tbl", "CREATE TABLE `b_tbl` (\n  `b` binary(100),\n  KEY `b` (`b`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "blob primary key prefix",
		SetUpScript: []string{
			"create table t (b blob)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (b(10))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
			{
				Query:       "create table b_tbl (b blob, primary key (b(10)))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
		},
	},
	{
		Name: "blob keyed secondary index prefix",
		SetUpScript: []string{
			"create table t (i int primary key, b blob)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (b(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `b` blob,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `b` (`b`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values (0, 'aa'), (1, 'ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table b_tbl (i int primary key, b blob, index (b(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table b_tbl",
				Expected: []sql.Row{{"b_tbl", "CREATE TABLE `b_tbl` (\n  `i` int NOT NULL,\n  `b` blob,\n  PRIMARY KEY (`i`),\n  KEY `b` (`b`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "blob keyless secondary index prefix",
		SetUpScript: []string{
			"create table t (b blob)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (b(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `b` blob,\n  UNIQUE KEY `b` (`b`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values ('aa'), ('ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table b_tbl (b blob, index (b(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table b_tbl",
				Expected: []sql.Row{{"b_tbl", "CREATE TABLE `b_tbl` (\n  `b` blob,\n  KEY `b` (`b`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "text primary key prefix",
		SetUpScript: []string{
			"create table t (t text)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table t add primary key (t(10))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
			{
				Query:       "create table b_tbl (t text, primary key (t(10)))",
				ExpectedErr: sql.ErrUnsupportedIndexPrefix,
			},
		},
	},
	{
		Name: "text keyed secondary index prefix",
		SetUpScript: []string{
			"create table t (i int primary key, t text)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (t(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `t` text,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `t` (`t`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values (0, 'aa'), (1, 'ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table t_tbl (i int primary key, t text, index (t(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t_tbl",
				Expected: []sql.Row{{"t_tbl", "CREATE TABLE `t_tbl` (\n  `i` int NOT NULL,\n  `t` text,\n  PRIMARY KEY (`i`),\n  KEY `t` (`t`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "text keyless secondary index prefix",
		SetUpScript: []string{
			"create table t (t text)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table t add unique index (t(1))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `t` text,\n  UNIQUE KEY `t` (`t`(1))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:       "insert into t values ('aa'), ('ab')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "create table t_tbl (t text, index (t(10)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table t_tbl",
				Expected: []sql.Row{{"t_tbl", "CREATE TABLE `t_tbl` (\n  `t` text,\n  KEY `t` (`t`(10))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "inline secondary indexes",
		SetUpScript: []string{
			"create table t (i int primary key, v1 varchar(10), v2 varchar(10), unique index (v1(3),v2(5)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `v1` varchar(10),\n  `v2` varchar(10),\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `v1v2` (`v1`(3),`v2`(5))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "insert into t values (0, 'a', 'a'), (1, 'ab','ab'), (2, 'abc', 'abc'), (3, 'abcde', 'abcde')",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:       "insert into t values (99, 'abc', 'abcde')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:       "insert into t values (99, 'abc123', 'abcde123')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query: "select * from t where v1 = 'a'",
				Expected: []sql.Row{
					{0, "a", "a"},
				},
			},
			{
				Query: "select * from t where v1 = 'abc'",
				Expected: []sql.Row{
					{2, "abc", "abc"},
				},
			},
			{
				Query:    "select * from t where v1 = 'abcd'",
				Expected: []sql.Row{},
			},
			{
				Query: "select * from t where v1 > 'a' and v1 < 'abcde'",
				Expected: []sql.Row{
					{1, "ab", "ab"},
					{2, "abc", "abc"},
				},
			},
			{
				Query: "select * from t where v1 > 'a' and v2 < 'abcde'",
				Expected: []sql.Row{
					{1, "ab", "ab"},
					{2, "abc", "abc"},
				},
			},
			{
				Query: "update t set v1 = concat(v1, 'z') where v1 >= 'a'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4, InsertID: 0, Info: plan.UpdateInfo{Matched: 4, Updated: 4}}},
				},
			},
			{
				Query: "select * from t",
				Expected: []sql.Row{
					{0, "az", "a"},
					{1, "abz", "ab"},
					{2, "abcz", "abc"},
					{3, "abcdez", "abcde"},
				},
			},
			{
				Query: "delete from t where v1 >= 'a'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query:    "select * from t",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "inline secondary indexes keyless",
		SetUpScript: []string{
			"create table t (v1 varchar(10), v2 varchar(10), unique index (v1(3),v2(5)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `v1` varchar(10),\n  `v2` varchar(10),\n  UNIQUE KEY `v1v2` (`v1`(3),`v2`(5))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "insert into t values ('a', 'a'), ('ab','ab'), ('abc', 'abc'), ('abcde', 'abcde')",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:       "insert into t values ('abc', 'abcde')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:       "insert into t values ('abc123', 'abcde123')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query: "select * from t where v1 = 'a'",
				Expected: []sql.Row{
					{"a", "a"},
				},
			},
			{
				Query: "select * from t where v1 = 'abc'",
				Expected: []sql.Row{
					{"abc", "abc"},
				},
			},
			{
				Query:    "select * from t where v1 = 'abcd'",
				Expected: []sql.Row{},
			},
			{
				Query: "select * from t where v1 > 'a' and v1 < 'abcde'",
				Expected: []sql.Row{
					{"ab", "ab"},
					{"abc", "abc"},
				},
			},
			{
				Query: "select * from t where v1 > 'a' and v2 < 'abcde'",
				Expected: []sql.Row{
					{"ab", "ab"},
					{"abc", "abc"},
				},
			},
			{
				Query: "update t set v1 = concat(v1, 'z') where v1 >= 'a'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4, InsertID: 0, Info: plan.UpdateInfo{Matched: 4, Updated: 4}}},
				},
			},
			{
				Query: "select * from t",
				Expected: []sql.Row{
					{"az", "a"},
					{"abz", "ab"},
					{"abcz", "abc"},
					{"abcdez", "abcde"},
				},
			},
			{
				Query: "delete from t where v1 >= 'a'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query:    "select * from t",
				Expected: []sql.Row{},
			},
		},
	},

	{
		Name: "inline secondary indexes with collation",
		SetUpScript: []string{
			"create table t (i int primary key, v1 varchar(10), v2 varchar(10), unique index (v1(3),v2(5))) collate utf8mb4_0900_ai_ci",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `v1` varchar(10) COLLATE utf8mb4_0900_ai_ci,\n  `v2` varchar(10) COLLATE utf8mb4_0900_ai_ci,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `v1v2` (`v1`(3),`v2`(5))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci"}},
			},
			{
				Query:    "insert into t values (0, 'a', 'a'), (1, 'ab','ab'), (2, 'abc', 'abc'), (3, 'abcde', 'abcde')",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Skip:        true,
				Query:       "insert into t values (99, 'ABC', 'ABCDE')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Skip:        true,
				Query:       "insert into t values (99, 'ABC123', 'ABCDE123')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Skip:  true,
				Query: "select * from t where v1 = 'A'",
				Expected: []sql.Row{
					{0, "a", "a"},
				},
			},
			{
				Skip:  true,
				Query: "select * from t where v1 = 'ABC'",
				Expected: []sql.Row{
					{2, "abc", "abc"},
				},
			},
			{
				Query:    "select * from t where v1 = 'ABCD'",
				Expected: []sql.Row{},
			},
			{
				Skip:  true,
				Query: "select * from t where v1 > 'A' and v1 < 'ABCDE'",
				Expected: []sql.Row{
					{1, "ab", "ab"},
				},
			},
			{
				Query: "select * from t where v1 > 'A' and v2 < 'ABCDE'",
				Expected: []sql.Row{
					{1, "ab", "ab"},
					{2, "abc", "abc"},
				},
			},
			{
				Skip:  true,
				Query: "update t set v1 = concat(v1, 'Z') where v1 >= 'A'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4, InsertID: 0, Info: plan.UpdateInfo{Matched: 4, Updated: 4}}},
				},
			},
			{
				Skip:  true,
				Query: "select * from t",
				Expected: []sql.Row{
					{0, "aZ", "a"},
					{1, "abZ", "ab"},
					{2, "abcZ", "abc"},
					{3, "abcdeZ", "abcde"},
				},
			},
			{
				Skip:  true,
				Query: "delete from t where v1 >= 'A'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Skip:     true,
				Query:    "select * from t",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "referenced secondary indexes",
		SetUpScript: []string{
			"create table t (i int primary key, v1 text, v2 text, unique index (v1(3),v2(5)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table t",
				Expected: []sql.Row{{"t", "CREATE TABLE `t` (\n  `i` int NOT NULL,\n  `v1` text,\n  `v2` text,\n  PRIMARY KEY (`i`),\n  UNIQUE KEY `v1v2` (`v1`(3),`v2`(5))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "insert into t values (0, 'a', 'a'), (1, 'ab','ab'), (2, 'abc', 'abc'), (3, 'abcde', 'abcde')",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:       "insert into t values (99, 'abc', 'abcde')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:       "insert into t values (99, 'abc123', 'abcde123')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query: "select * from t where v1 = 'a'",
				Expected: []sql.Row{
					{0, "a", "a"},
				},
			},
			{
				Query: "select * from t where v1 = 'abc'",
				Expected: []sql.Row{
					{2, "abc", "abc"},
				},
			},
			{
				Query:    "select * from t where v1 = 'abcd'",
				Expected: []sql.Row{},
			},
			{
				Query: "select * from t where v1 > 'a' and v1 < 'abcde'",
				Expected: []sql.Row{
					{1, "ab", "ab"},
					{2, "abc", "abc"},
				},
			},
			{
				Query: "select * from t where v1 > 'a' and v2 < 'abcde'",
				Expected: []sql.Row{
					{1, "ab", "ab"},
					{2, "abc", "abc"},
				},
			},
			{
				Query: "update t set v1 = concat(v1, 'z') where v1 >= 'a'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4, InsertID: 0, Info: plan.UpdateInfo{Matched: 4, Updated: 4}}},
				},
			},
			{
				Query: "select * from t",
				Expected: []sql.Row{
					{0, "az", "a"},
					{1, "abz", "ab"},
					{2, "abcz", "abc"},
					{3, "abcdez", "abcde"},
				},
			},
			{
				Query: "delete from t where v1 >= 'a'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query:    "select * from t",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name:        "test prefix limits",
		SetUpScript: []string{},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "create table varchar_limit(c varchar(10000), index (c(768)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "create table text_limit(c text, index (c(768)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "create table varbinary_limit(c varbinary(10000), index (c(3072)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "create table blob_limit(c blob, index (c(3072)))",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:       "create table bad(c varchar(10000), index (c(769)))",
				ExpectedErr: sql.ErrKeyTooLong,
			},
			{
				Query:       "create table bad(c text, index (c(769)))",
				ExpectedErr: sql.ErrKeyTooLong,
			},
			{
				Query:       "create table bad(c varbinary(10000), index (c(3073)))",
				ExpectedErr: sql.ErrKeyTooLong,
			},
			{
				Query:       "create table bad(c blob, index (c(3073)))",
				ExpectedErr: sql.ErrKeyTooLong,
			},
		},
	},
}
View Source
var IndexQueries = []ScriptTest{
	{
		Name: "unique key violation prevents insert",
		SetUpScript: []string{
			"create table users (id varchar(26) primary key, namespace varchar(50), name varchar(50));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "create unique index namespace__name on users (namespace, name)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 0}},
				},
			},
			{
				Query: "show create table users",
				Expected: []sql.Row{
					{"users", "CREATE TABLE `users` (\n  `id` varchar(26) NOT NULL,\n  `namespace` varchar(50),\n  `name` varchar(50),\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `namespace__name` (`namespace`,`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "insert into users values ('user1', 'namespace1', 'name1')",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query:       "insert into users values ('user2', 'namespace1', 'name1')",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
		},
	},
	{
		Name: "unique key duplicate key update",
		SetUpScript: []string{
			"CREATE TABLE auniquetable (pk int primary key, uk int unique key, i int);",
			"INSERT INTO auniquetable VALUES(0,0,0);",
			"INSERT INTO auniquetable (pk,uk) VALUES(1,0) on duplicate key update i = 99;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT pk, uk, i from auniquetable",
				Expected: []sql.Row{
					{0, 0, 99},
				},
			},
		},
	},
	{
		Name: "non-unique indexes on keyless tables",
		SetUpScript: []string{
			"create table t (i int, j int, index(i))",
			"insert into t values (0, 100), (0, 200), (1, 100), (1, 200), (2, 100), (2, 200)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select i, j from t where i = 0 order by i, j",
				Expected: []sql.Row{
					{0, 100},
					{0, 200},
				},
			},
			{
				Query: "select i, j from t where i = 1 order by i, j",
				Expected: []sql.Row{
					{1, 100},
					{1, 200},
				},
			},
			{
				Query: "select i, j from t where i > 0 order by i, j",
				Expected: []sql.Row{
					{1, 100},
					{1, 200},
					{2, 100},
					{2, 200},
				},
			},
			{
				Query: "select i, j from t where i > 0 and i < 2 order by i, j",
				Expected: []sql.Row{
					{1, 100},
					{1, 200},
				},
			},
		},
	},
	{
		Name: "more non-unique indexes on keyless tables",
		SetUpScript: []string{
			"create table t (i int, j int, k int, index(i, j))",
			"insert into t values (0, 0, 123), (0, 1, 456), (1, 0, 123), (1, 1, 456), (2, 0, 123), (2, 1, 456)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select i, j, k from t where i = 0 order by i, j, k",
				Expected: []sql.Row{
					{0, 0, 123},
					{0, 1, 456},
				},
			},
			{
				Query: "select i, j, k from t where i = 0 and j = 0 order by i, j, k",
				Expected: []sql.Row{
					{0, 0, 123},
				},
			},
			{
				Query: "select i, j, k from t where i = 1 and (j = 0 or j = 1) order by i, j, k",
				Expected: []sql.Row{
					{1, 0, 123},
					{1, 1, 456},
				},
			},
			{
				Query: "select i, j, k from t where i > 0 and j > 0 order by i, j, k",
				Expected: []sql.Row{
					{1, 1, 456},
					{2, 1, 456},
				},
			},
			{
				Query: "select i, j, k from t where i > 0 and i < 2 order by i, j, k",
				Expected: []sql.Row{
					{1, 0, 123},
					{1, 1, 456},
				},
			},
		},
	},
}
View Source
var InfoSchemaQueries = []QueryTest{
	{
		Query: `select table_name from information_schema.tables where table_schema = 'information_schema' order by table_name;`,
		Expected: []sql.Row{
			{"administrable_role_authorizations"},
			{"applicable_roles"},
			{"character_sets"},
			{"check_constraints"},
			{"collations"},
			{"collation_character_set_applicability"},
			{"columns"},
			{"columns_extensions"},
			{"column_privileges"},
			{"column_statistics"},
			{"enabled_roles"},
			{"engines"},
			{"events"},
			{"files"},
			{"innodb_buffer_page"},
			{"innodb_buffer_page_lru"},
			{"innodb_buffer_pool_stats"},
			{"innodb_cached_indexes"},
			{"innodb_cmp"},
			{"innodb_cmpmem"},
			{"innodb_cmpmem_reset"},
			{"innodb_cmp_per_index"},
			{"innodb_cmp_per_index_reset"},
			{"innodb_cmp_reset"},
			{"innodb_columns"},
			{"innodb_datafiles"},
			{"innodb_fields"},
			{"innodb_foreign"},
			{"innodb_foreign_cols"},
			{"innodb_ft_being_deleted"},
			{"innodb_ft_config"},
			{"innodb_ft_default_stopword"},
			{"innodb_ft_deleted"},
			{"innodb_ft_index_cache"},
			{"innodb_ft_index_table"},
			{"innodb_indexes"},
			{"innodb_metrics"},
			{"innodb_session_temp_tablespaces"},
			{"innodb_tables"},
			{"innodb_tablespaces"},
			{"innodb_tablespaces_brief"},
			{"innodb_tablestats"},
			{"innodb_temp_table_info"},
			{"innodb_trx"},
			{"innodb_virtual"},
			{"keywords"},
			{"key_column_usage"},
			{"optimizer_trace"},
			{"parameters"},
			{"partitions"},
			{"plugins"},
			{"processlist"},
			{"profiling"},
			{"referential_constraints"},
			{"resource_groups"},
			{"role_column_grants"},
			{"role_routine_grants"},
			{"role_table_grants"},
			{"routines"},
			{"schemata"},
			{"schemata_extensions"},
			{"schema_privileges"},
			{"statistics"},
			{"st_geometry_columns"},
			{"st_spatial_reference_systems"},
			{"st_units_of_measure"},
			{"tables"},
			{"tablespaces"},
			{"tablespaces_extensions"},
			{"tables_extensions"},
			{"table_constraints"},
			{"table_constraints_extensions"},
			{"table_privileges"},
			{"triggers"},
			{"user_attributes"},
			{"user_privileges"},
			{"views"},
			{"view_routine_usage"},
			{"view_table_usage"},
		},
	},
	{
		Query: "SHOW TABLES",
		Expected: []sql.Row{
			{"myview"},
			{"fk_tbl"},
			{"mytable"},
		},
	},
	{
		Query: "SHOW FULL TABLES",
		Expected: []sql.Row{
			{"fk_tbl", "BASE TABLE"},
			{"myview", "VIEW"},
			{"mytable", "BASE TABLE"},
		},
	},
	{
		Query: "SHOW TABLES FROM foo",
		Expected: []sql.Row{
			{"other_table"},
		},
	},
	{
		Query: "SHOW TABLES LIKE '%table'",
		Expected: []sql.Row{
			{"mytable"},
		},
	},
	{
		Query: `SHOW COLUMNS FROM mytable`,
		Expected: []sql.Row{
			{"i", "bigint", "NO", "PRI", "NULL", ""},
			{"s", "varchar(20)", "NO", "UNI", "NULL", ""},
		},
	},
	{
		Query: `DESCRIBE mytable`,
		Expected: []sql.Row{
			{"i", "bigint", "NO", "PRI", "NULL", ""},
			{"s", "varchar(20)", "NO", "UNI", "NULL", ""},
		},
	},
	{
		Query: `DESC mytable`,
		Expected: []sql.Row{
			{"i", "bigint", "NO", "PRI", "NULL", ""},
			{"s", "varchar(20)", "NO", "UNI", "NULL", ""},
		},
	},
	{
		Query: `SHOW COLUMNS FROM mytable WHERE Field = 'i'`,
		Expected: []sql.Row{
			{"i", "bigint", "NO", "PRI", "NULL", ""},
		},
	},
	{
		Query: `SHOW COLUMNS FROM mytable LIKE 'i'`,
		Expected: []sql.Row{
			{"i", "bigint", "NO", "PRI", "NULL", ""},
		},
	},
	{
		Query: `SHOW FULL COLUMNS FROM mytable`,
		Expected: []sql.Row{
			{"i", "bigint", nil, "NO", "PRI", "NULL", "", "", ""},
			{"s", "varchar(20)", "utf8mb4_0900_bin", "NO", "UNI", "NULL", "", "", "column s"},
		},
	},
	{
		Query: "SHOW TABLES WHERE `Tables_in_mydb` = 'mytable'",
		Expected: []sql.Row{
			{"mytable"},
		},
	},
	{
		Query: `
		SELECT
			LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA
		FROM INFORMATION_SCHEMA.FILES
		WHERE FILE_TYPE = 'UNDO LOG'
			AND FILE_NAME IS NOT NULL
			AND LOGFILE_GROUP_NAME IS NOT NULL
		GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE, TOTAL_EXTENTS, INITIAL_SIZE
		ORDER BY LOGFILE_GROUP_NAME
		`,
		Expected: nil,
	},
	{
		Query: `
		SELECT DISTINCT
			TABLESPACE_NAME, FILE_NAME, LOGFILE_GROUP_NAME, EXTENT_SIZE, INITIAL_SIZE, ENGINE
		FROM INFORMATION_SCHEMA.FILES
		WHERE FILE_TYPE = 'DATAFILE'
		ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME
		`,
		Expected: nil,
	},
	{
		Query: `
		SELECT TABLE_NAME FROM information_schema.TABLES
		WHERE TABLE_SCHEMA='mydb' AND (TABLE_TYPE='BASE TABLE' OR TABLE_TYPE='VIEW')
		ORDER BY 1
		`,
		Expected: []sql.Row{
			{"fk_tbl"},
			{"mytable"},
			{"myview"},
		},
	},
	{
		Query: `
		SELECT COLUMN_NAME, DATA_TYPE FROM information_schema.COLUMNS
		WHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='mytable'
		`,
		Expected: []sql.Row{
			{"s", "varchar"},
			{"i", "bigint"},
		},
	},
	{
		Query: `
		SELECT COLUMN_NAME FROM information_schema.COLUMNS
		WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME LIKE '%table'
		GROUP BY COLUMN_NAME
		`,
		Expected: []sql.Row{
			{"s"},
			{"i"},
		},
	},
	{
		Query: `
		SELECT COLUMN_NAME FROM information_schema.COLUMNS
		WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME LIKE '%table'
		GROUP BY 1
		`,
		Expected: []sql.Row{
			{"s"},
			{"i"},
		},
	},
	{
		Query: `
		SELECT COLUMN_NAME AS COLUMN_NAME FROM information_schema.COLUMNS
		WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME LIKE '%table'
		GROUP BY 1
		`,
		Expected: []sql.Row{
			{"s"},
			{"i"},
		},
	},
	{
		Query: `SHOW INDEXES FROM mytaBLE`,
		Expected: []sql.Row{
			{"mytable", 0, "PRIMARY", 1, "i", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 0, "mytable_s", 1, "s", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "mytable_i_s", 1, "i", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "mytable_i_s", 2, "s", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "idx_si", 1, "s", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "idx_si", 2, "i", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		Query: `SHOW KEYS FROM mytaBLE`,
		Expected: []sql.Row{
			{"mytable", 0, "PRIMARY", 1, "i", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 0, "mytable_s", 1, "s", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "mytable_i_s", 1, "i", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "mytable_i_s", 2, "s", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "idx_si", 1, "s", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"mytable", 1, "idx_si", 2, "i", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		Query: `SHOW CREATE TABLE mytaBLE`,
		Expected: []sql.Row{
			{"mytable", "CREATE TABLE `mytable` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `s` varchar(20) NOT NULL COMMENT 'column s',\n" +
				"  PRIMARY KEY (`i`),\n" +
				"  KEY `idx_si` (`s`,`i`),\n" +
				"  KEY `mytable_i_s` (`i`,`s`),\n" +
				"  UNIQUE KEY `mytable_s` (`s`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
		},
	},
	{
		Query: `SHOW CREATE TABLE fk_TBL`,
		Expected: []sql.Row{
			{"fk_tbl", "CREATE TABLE `fk_tbl` (\n" +
				"  `pk` bigint NOT NULL,\n" +
				"  `a` bigint,\n" +
				"  `b` varchar(20),\n" +
				"  PRIMARY KEY (`pk`),\n" +
				"  KEY `ab` (`a`,`b`),\n" +
				"  CONSTRAINT `fk1` FOREIGN KEY (`a`,`b`) REFERENCES `mytable` (`i`,`s`) ON DELETE CASCADE\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
		},
	},
	{

		Query: "SELECT table_name, `auto_increment` FROM information_schema.tables " +
			"WHERE TABLE_SCHEMA='mydb' AND TABLE_TYPE='BASE TABLE' ORDER BY 1",
		Expected: []sql.Row{
			{"fk_tbl", nil},
			{"mytable", nil},
		},
	},
	{
		Query: "SHOW ENGINES",
		Expected: []sql.Row{
			{"InnoDB", "DEFAULT", "Supports transactions, row-level locking, and foreign keys", "YES", "YES", "YES"},
		},
	},
	{
		Query: "SELECT * FROM information_schema.table_constraints ORDER BY table_name, constraint_type;",
		Expected: []sql.Row{
			{"def", "mydb", "fk1", "mydb", "fk_tbl", "FOREIGN KEY", "YES"},
			{"def", "mydb", "PRIMARY", "mydb", "fk_tbl", "PRIMARY KEY", "YES"},
			{"def", "mydb", "PRIMARY", "mydb", "mytable", "PRIMARY KEY", "YES"},
			{"def", "mydb", "mytable_s", "mydb", "mytable", "UNIQUE", "YES"},
			{"def", "foo", "PRIMARY", "foo", "other_table", "PRIMARY KEY", "YES"},
		},
	},
	{
		Query:    "SELECT * FROM information_schema.check_constraints ORDER BY constraint_schema, constraint_name, check_clause ",
		Expected: []sql.Row{},
	},
	{
		Query: "SELECT * FROM information_schema.key_column_usage ORDER BY constraint_schema, table_name",
		Expected: []sql.Row{
			{"def", "foo", "PRIMARY", "def", "foo", "other_table", "text", 1, nil, nil, nil, nil},
			{"def", "mydb", "PRIMARY", "def", "mydb", "fk_tbl", "pk", 1, nil, nil, nil, nil},
			{"def", "mydb", "fk1", "def", "mydb", "fk_tbl", "a", 1, 1, "mydb", "mytable", "i"},
			{"def", "mydb", "fk1", "def", "mydb", "fk_tbl", "b", 2, 2, "mydb", "mytable", "s"},
			{"def", "mydb", "PRIMARY", "def", "mydb", "mytable", "i", 1, nil, nil, nil, nil},
			{"def", "mydb", "mytable_s", "def", "mydb", "mytable", "s", 1, nil, nil, nil, nil},
		},
	},
	{
		Query: `
				select CONCAT(tbl.table_schema, '.', tbl.table_name) as the_table,
				       col.column_name, GROUP_CONCAT(kcu.column_name SEPARATOR ',') as pk
				from information_schema.tables as tbl
				join information_schema.columns as col
				  on tbl.table_name = col.table_name
				join information_schema.key_column_usage as kcu
				  on tbl.table_name = kcu.table_name
				join information_schema.table_constraints as tc
				  on kcu.constraint_name = tc.constraint_name
				where tbl.table_schema = 'mydb' and
					  tbl.table_name = kcu.table_name and
					  tc.constraint_type = 'PRIMARY KEY' and
					  col.column_name like 'pk%'
				group by the_table, col.column_name
				`,
		Expected: []sql.Row{
			{"mydb.fk_tbl", "pk", "pk,pk,pk"},
		},
	},
	{
		Query:    `SELECT count(*) FROM information_schema.COLLATIONS`,
		Expected: []sql.Row{{286}},
	},
	{
		Query: `SELECT * FROM information_schema.COLLATIONS ORDER BY collation_name LIMIT 4`,
		Expected: []sql.Row{
			{"armscii8_bin", "armscii8", uint64(64), "", "Yes", uint32(1), "PAD SPACE"},
			{"armscii8_general_ci", "armscii8", uint64(32), "Yes", "Yes", uint32(1), "PAD SPACE"},
			{"ascii_bin", "ascii", uint64(65), "", "Yes", uint32(1), "PAD SPACE"},
			{"ascii_general_ci", "ascii", uint64(11), "Yes", "Yes", uint32(1), "PAD SPACE"},
		},
	},
	{
		Query: `SELECT * FROM information_schema.COLLATION_CHARACTER_SET_APPLICABILITY ORDER BY collation_name LIMIT 4 `,
		Expected: []sql.Row{
			{"armscii8_bin", "armscii8"},
			{"armscii8_general_ci", "armscii8"},
			{"ascii_bin", "ascii"},
			{"ascii_general_ci", "ascii"},
		},
	},
	{
		Query: `SELECT * FROM information_schema.ENGINES ORDER BY engine`,
		Expected: []sql.Row{
			{"InnoDB", "DEFAULT", "Supports transactions, row-level locking, and foreign keys", "YES", "YES", "YES"},
		},
	},
	{
		Query:    `SELECT * from information_schema.administrable_role_authorizations`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.applicable_roles`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.column_privileges`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.optimizer_trace`,
		Expected: []sql.Row{},
	},
	{
		Query:    "SELECT * FROM information_schema.partitions",
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.plugins`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.profiling`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.resource_groups`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.role_column_grants`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.role_routine_grants`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.tablespaces`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.tablespaces_extensions`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.view_routine_usage`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * FROM information_schema.view_table_usage`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_buffer_page`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_buffer_page_lru`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_buffer_pool_stats`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cached_indexes`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cmp`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cmp_reset`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cmpmem`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cmpmem_reset`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cmp_per_index`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_cmp_per_index_reset`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_columns`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_datafiles`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_fields`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_foreign`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_foreign_cols`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_ft_being_deleted`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_ft_config`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_ft_default_stopword`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_ft_deleted`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_ft_index_cache`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_ft_index_table`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_indexes`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_metrics`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_session_temp_tablespaces`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_tables`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_tablespaces`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_tablespaces_brief`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_tablestats`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_temp_table_info`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_trx`,
		Expected: []sql.Row{},
	},
	{
		Query:    `SELECT * from information_schema.innodb_virtual`,
		Expected: []sql.Row{},
	},
	{
		Query: `SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, SEQ_IN_INDEX, 'PRIMARY' AS PK_NAME 
FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA = 'mydb' AND INDEX_NAME='PRIMARY' ORDER BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, SEQ_IN_INDEX;`,
		Expected: []sql.Row{
			{"mydb", "fk_tbl", "pk", 1, "PRIMARY"},
			{"mydb", "mytable", "i", 1, "PRIMARY"},
		},
	},
	{
		Query:    "select * from information_schema.character_sets;",
		Expected: []sql.Row{{"utf8mb4", "utf8mb4_0900_ai_ci", "UTF-8 Unicode", uint32(4)}},
	},
	{
		Query: `show columns from fk_tbl from mydb`,
		Expected: []sql.Row{
			{"pk", "bigint", "NO", "PRI", "NULL", ""},
			{"a", "bigint", "YES", "MUL", "NULL", ""},
			{"b", "varchar(20)", "YES", "", "NULL", ""},
		},
	},
	{
		Query: "SELECT * FROM information_schema.referential_constraints where CONSTRAINT_SCHEMA = 'mydb'",
		Expected: []sql.Row{
			{"def", "mydb", "fk1", "def", "mydb", nil, "NONE", "NO ACTION", "CASCADE", "fk_tbl", "mytable"},
		},
	},
	{
		Query:    "SELECT count(*) FROM information_schema.keywords",
		Expected: []sql.Row{{747}},
	},
	{
		Query: "SELECT * FROM information_schema.st_spatial_reference_systems order by srs_id",
		Expected: []sql.Row{
			{"", uint32(0), nil, nil, "", nil},
			{"WGS 84", uint32(4326), "EPSG", uint32(4326), "GEOGCS[\"WGS 84\",DATUM[\"World Geodetic System 1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.017453292519943278,AUTHORITY[\"EPSG\",\"9122\"]],AXIS[\"Lat\",NORTH],AXIS[\"Lon\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]", nil},
		},
	},
	{
		Query:    "SELECT count(*) FROM information_schema.st_units_of_measure",
		Expected: []sql.Row{{47}},
	},
	{
		Query:    "SELECT * FROM information_schema.schemata_extensions",
		Expected: []sql.Row{{"def", "information_schema", ""}, {"def", "foo", ""}, {"def", "mydb", ""}},
	},
	{
		Query:    `SELECT * FROM information_schema.columns_extensions where table_name = 'mytable'`,
		Expected: []sql.Row{{"def", "mydb", "mytable", "i", nil, nil}, {"def", "mydb", "mytable", "s", nil, nil}},
	},
	{
		Query:    `SELECT * FROM information_schema.table_constraints_extensions where table_name = 'fk_tbl'`,
		Expected: []sql.Row{{"def", "mydb", "PRIMARY", "fk_tbl", nil, nil}, {"def", "mydb", "ab", "fk_tbl", nil, nil}},
	},
	{
		Query:    `SELECT * FROM information_schema.tables_extensions where table_name = 'mytable'`,
		Expected: []sql.Row{{"def", "mydb", "mytable", nil, nil}},
	},
	{
		Query:    "SELECT table_rows FROM INFORMATION_SCHEMA.TABLES where table_name='mytable'",
		Expected: []sql.Row{{uint64(3)}},
	},
	{
		Query:    "select table_name from information_schema.tables where table_schema collate utf8_general_ci = 'information_schema' and table_name collate utf8_general_ci = 'parameters'",
		Expected: []sql.Row{{"parameters"}},
	},
}
View Source
var InfoSchemaScripts = []ScriptTest{
	{
		Name: "query does not use optimization rule on LIKE clause because info_schema db charset is utf8mb3",
		SetUpScript: []string{
			"CREATE TABLE t1 (a int, condition_choose varchar(10));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select column_name from information_schema.columns where column_name like 'condition%';",
				Expected: []sql.Row{{"condition_choose"}},
			},
			{
				Query:    "select column_name from information_schema.columns where column_name like '%condition%';",
				Expected: []sql.Row{{"ACTION_CONDITION"}, {"condition_choose"}},
			},
		},
	},
	{
		Name: "test databases created with non default collation and charset",
		SetUpScript: []string{
			"CREATE DATABASE test_db CHARACTER SET utf8mb3 COLLATE utf8mb3_bin;",
			"USE test_db",
			"CREATE TABLE small_table (a binary, b VARCHAR(50));",
			"CREATE TABLE test_table (id INT PRIMARY KEY, col1 TEXT, col2 CHAR(20) CHARACTER SET latin1 COLLATE latin1_german1_ci) CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT table_schema, table_name, column_name, character_set_name, collation_name, column_type FROM information_schema.columns where table_schema = 'test_db' order by column_name",
				Expected: []sql.Row{
					{"test_db", "small_table", "a", nil, nil, "binary(1)"},
					{"test_db", "small_table", "b", "utf8mb3", "utf8mb3_bin", "varchar(50)"},
					{"test_db", "test_table", "col1", "utf8mb4", "utf8mb4_0900_bin", "text"},
					{"test_db", "test_table", "col2", "latin1", "latin1_german1_ci", "char(20)"},
					{"test_db", "test_table", "id", nil, nil, "int"},
				},
			},
		},
	},
	{
		Name: "information_schema.table_constraints ignores non-unique indexes",
		SetUpScript: []string{
			"CREATE TABLE t (pk int primary key, test_score int, height int)",
			"CREATE INDEX myindex on t(test_score)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.table_constraints where table_name='t' ORDER BY constraint_type,constraint_name",
				Expected: []sql.Row{
					{"def", "mydb", "PRIMARY", "mydb", "t", "PRIMARY KEY", "YES"},
				},
			},
		},
	},
	{
		Name: "information_schema.key_column_usage ignores non-unique indexes",
		SetUpScript: []string{
			"CREATE TABLE t (pk int primary key, test_score int, height int)",
			"CREATE INDEX myindex on t(test_score)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.key_column_usage where table_name='t'",
				Expected: []sql.Row{
					{"def", "mydb", "PRIMARY", "def", "mydb", "t", "pk", 1, nil, nil, nil, nil},
				},
			},
		},
	},
	{
		Name: "information_schema.key_column_usage works with composite foreign and primary keys",
		SetUpScript: []string{
			"CREATE TABLE ptable (pk int primary key, test_score int, height int)",
			"CREATE INDEX myindex on ptable(test_score, height)",
			"CREATE TABLE ptable2 (pk int primary key, test_score2 int, height2 int, CONSTRAINT fkr FOREIGN KEY (test_score2, height2) REFERENCES ptable(test_score,height));",

			"CREATE TABLE atable (pk int, test_score int, height int, PRIMARY KEY (pk, test_score))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.key_column_usage where table_name='ptable2' ORDER BY constraint_name",
				Expected: []sql.Row{
					{"def", "mydb", "fkr", "def", "mydb", "ptable2", "test_score2", 1, 1, "mydb", "ptable", "test_score"},
					{"def", "mydb", "fkr", "def", "mydb", "ptable2", "height2", 2, 2, "mydb", "ptable", "height"},
					{"def", "mydb", "PRIMARY", "def", "mydb", "ptable2", "pk", 1, nil, nil, nil, nil},
				},
			},
			{
				Query: "SELECT * FROM information_schema.key_column_usage where table_name='atable' ORDER BY constraint_name",
				Expected: []sql.Row{
					{"def", "mydb", "PRIMARY", "def", "mydb", "atable", "pk", 1, nil, nil, nil, nil},
					{"def", "mydb", "PRIMARY", "def", "mydb", "atable", "test_score", 2, nil, nil, nil, nil},
				},
			},
		},
	},
	{
		Name: "information_schema.referential_constraints works with primary, non-unique and unique keys",
		SetUpScript: []string{
			"CREATE TABLE my_table (i int primary key, height int, weight int)",
			"CREATE INDEX h on my_TABLE(height)",
			"CREATE UNIQUE INDEX w on my_TABLE(weight)",
			"CREATE TABLE ref_table (a int primary key, height int, weight int)",
			"alter table ref_table add constraint fk_across_dbs_ref_pk foreign key (a) references my_table(i)",
			"alter table ref_table add constraint fk_across_dbs_key foreign key (a) references my_table(height)",
			"alter table ref_table add constraint fk_across_dbs_unique foreign key (a) references my_table(weight)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.referential_constraints where constraint_schema = 'mydb' and table_name = 'ref_table'",
				Expected: []sql.Row{
					{"def", "mydb", "fk_across_dbs_ref_pk", "def", "mydb", "PRIMARY", "NONE", "NO ACTION", "NO ACTION", "ref_table", "my_table"},
					{"def", "mydb", "fk_across_dbs_key", "def", "mydb", nil, "NONE", "NO ACTION", "NO ACTION", "ref_table", "my_table"},
					{"def", "mydb", "fk_across_dbs_unique", "def", "mydb", "w", "NONE", "NO ACTION", "NO ACTION", "ref_table", "my_table"},
				},
			},
		},
	},
	{
		Name: "information_schema.triggers create trigger definer defined",
		SetUpScript: []string{
			"CREATE TABLE aa (x INT PRIMARY KEY, y INT)",
			"CREATE DEFINER=`dolt`@`localhost` TRIGGER trigger1 BEFORE INSERT ON aa FOR EACH ROW SET NEW.x = NEW.x + 1",
			"CREATE TRIGGER trigger2 BEFORE INSERT ON aa FOR EACH ROW SET NEW.y = NEW.y + 2",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT trigger_name, event_object_table, definer FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_name = 'trigger1'",
				Expected: []sql.Row{
					{"trigger1", "aa", "dolt@localhost"},
				},
			},
			{
				Query: `SELECT trigger_catalog, trigger_schema, trigger_name, event_manipulation, event_object_catalog,
event_object_schema, event_object_table, action_order, action_condition, action_statement, action_orientation, action_timing,
action_reference_old_table, action_reference_new_table, action_reference_old_row, action_reference_new_row, sql_mode, definer,
character_set_client, collation_connection, database_collation
FROM INFORMATION_SCHEMA.TRIGGERS WHERE trigger_schema = 'mydb'`,
				Expected: []sql.Row{
					{"def", "mydb", "trigger1", "INSERT", "def", "mydb", "aa", 1, nil, "SET NEW.x = NEW.x + 1", "ROW", "BEFORE", nil, nil, "OLD", "NEW",
						"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY", "dolt@localhost", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
					{"def", "mydb", "trigger2", "INSERT", "def", "mydb", "aa", 2, nil, "SET NEW.y = NEW.y + 2", "ROW", "BEFORE", nil, nil, "OLD", "NEW",
						"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY", "root@localhost", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
				},
			},
		},
	},
	{
		Name: "information_schema.statistics shows non unique index",
		SetUpScript: []string{
			"CREATE TABLE t (pk int primary key, test_score int, height int)",
			"CREATE INDEX myindex on t(test_score)",
			"INSERT INTO t VALUES (2,23,25), (3,24,26)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.statistics where table_name='t'",
				Expected: []sql.Row{
					{"def", "mydb", "t", 1, "mydb", "myindex", 1, "test_score", "A", 0, nil, nil, "YES", "BTREE", "", "", "YES", nil},
					{"def", "mydb", "t", 0, "mydb", "PRIMARY", 1, "pk", "A", 0, nil, nil, "", "BTREE", "", "", "YES", nil},
				},
			},
		},
	},
	{
		Name: "information_schema.columns shows default value",
		SetUpScript: []string{
			"CREATE TABLE t (pk int primary key, fname varchar(20), lname varchar(20), height int)",
			"ALTER TABLE t CHANGE fname fname varchar(20) NOT NULL DEFAULT ''",
			"ALTER TABLE t CHANGE lname lname varchar(20) NOT NULL DEFAULT 'ln'",
			"ALTER TABLE t CHANGE height h int DEFAULT NULL",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT table_name, column_name, column_default, is_nullable FROM information_schema.columns where table_name='t' order by 1,2",
				Expected: []sql.Row{
					{"t", "fname", "", "NO"},
					{"t", "h", nil, "YES"},
					{"t", "lname", "ln", "NO"},
					{"t", "pk", nil, "NO"},
				},
			},
		},
	},
	{
		Name: "information_schema.columns shows default value with more types",
		SetUpScript: []string{
			"CREATE TABLE test_table (pk int primary key, col2 float NOT NULL DEFAULT 4.5, col3 double NOT NULL DEFAULT 3.14159, col4 datetime NULL DEFAULT '2008-04-22 16:16:16', col5 boolean NULL DEFAULT FALSE)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT table_name, column_name, column_default, is_nullable FROM information_schema.CoLuMnS where table_name='test_table'",
				Expected: []sql.Row{
					{"test_table", "pk", nil, "NO"},
					{"test_table", "col2", "4.5", "NO"},
					{"test_table", "col3", "3.14159", "NO"},
					{"test_table", "col4", "2008-04-22 16:16:16", "YES"},
					{"test_table", "col5", "0", "YES"},
				},
			},
		},
	},
	{
		Name: "information_schema.columns shows default value with more types",
		SetUpScript: []string{
			"CREATE TABLE test_table (pk int primary key, col2 float DEFAULT (length('he`Llo')), col3 int DEFAULT (greatest(`pk`, 2)), col4 int DEFAULT (5 + 5), col5 datetime default NOW(), create_time timestamp(6) NOT NULL DEFAULT NOW(6));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT table_name, column_name, column_default, is_nullable FROM information_schema.columns where table_name='test_table'",
				Expected: []sql.Row{
					{"test_table", "pk", nil, "NO"},
					{"test_table", "col2", "length('he`Llo')", "YES"},
					{"test_table", "col3", "greatest(pk,2)", "YES"},
					{"test_table", "col4", "(5 + 5)", "YES"},
					{"test_table", "col5", "CURRENT_TIMESTAMP", "YES"},
					{"test_table", "create_time", "CURRENT_TIMESTAMP(6)", "NO"},
				},
			},
		},
	},
	{
		Name: "information_schema.columns correctly shows numeric precision and scale for a wide variety of types",
		SetUpScript: []string{
			"CREATE TABLE `digits` (`c0` tinyint,`c1` tinyint unsigned,`c2` smallint,`c3` smallint unsigned,`c4` mediumint,`c5` mediumint unsigned,`c6` int,`c7` int unsigned,`c8` bigint,`c9` bigint unsigned,`c10` float,`c11` dec(5,2),`st` varchar(100))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select column_name, numeric_precision, numeric_scale from information_schema.columns where table_name='digits' order by ordinal_position;",
				Expected: []sql.Row{
					{"c0", 3, 0},
					{"c1", 3, 0},
					{"c2", 5, 0},
					{"c3", 5, 0},
					{"c4", 7, 0},
					{"c5", 7, 0},
					{"c6", 10, 0},
					{"c7", 10, 0},
					{"c8", 19, 0},
					{"c9", 20, 0},
					{"c10", 12, nil},
					{"c11", 5, 2},
					{"st", nil, nil},
				},
			},
		},
	},
	{
		Name: "information_schema.routines",
		SetUpScript: []string{
			"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6",
			"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7",
			"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8",
			"USE foo",
			"CREATE PROCEDURE p12() COMMENT 'hello' DETERMINISTIC SELECT 6",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT specific_name, routine_catalog, routine_schema, routine_name, routine_type, " +
					"data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, " +
					"datetime_precision, character_set_name, collation_name, dtd_identifier, " +
					"routine_body, external_name, external_language, parameter_style, is_deterministic, " +
					"sql_data_access, sql_path, security_type, sql_mode, routine_comment, definer, " +
					"character_set_client, collation_connection, database_collation FROM information_schema.routines",
				Expected: []sql.Row{
					{"p1", "def", "mydb", "p1", "PROCEDURE", "", nil, nil, nil, nil, nil, nil, nil, nil, "SQL",
						nil, "SQL", "SQL", "YES", "CONTAINS SQL", nil, "DEFINER", "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY",
						"hi", "", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
					{"p2", "def", "mydb", "p2", "PROCEDURE", "", nil, nil, nil, nil, nil, nil, nil, nil, "SQL",
						nil, "SQL", "SQL", "NO", "CONTAINS SQL", nil, "INVOKER", "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY",
						"", "user@%", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
					{"p12", "def", "foo", "p12", "PROCEDURE", "", nil, nil, nil, nil, nil, nil, nil, nil, "SQL",
						nil, "SQL", "SQL", "YES", "CONTAINS SQL", nil, "DEFINER", "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY",
						"hello", "", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
					{"p21", "def", "mydb", "p21", "PROCEDURE", "", nil, nil, nil, nil, nil, nil, nil, nil, "SQL",
						nil, "SQL", "SQL", "NO", "CONTAINS SQL", nil, "DEFINER", "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY",
						"", "", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
				},
			},
		},
	},
	{
		Name: "information_schema.columns for view",
		SetUpScript: []string{
			"USE foo",
			"drop table other_table",
			"CREATE TABLE t (i int)",
			"CREATE VIEW v as select * from t",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = 'foo'",
				Expected: []sql.Row{
					{"def", "foo", "t", "i", uint32(1), nil, "YES", "int", nil, nil, int64(10), int64(0), nil, nil, nil, "int", "", "", "insert,references,select,update", "", "", nil},
					{"def", "foo", "v", "", uint32(0), nil, "", nil, nil, nil, nil, nil, nil, "", "", "", "", "", "select", "", "", nil},
				},
			},
		},
	},
	{
		Name: "information_schema.columns with column key check for PRI and UNI",
		SetUpScript: []string{
			"CREATE TABLE about (id int unsigned NOT NULL AUTO_INCREMENT, uuid char(36) NOT NULL, " +
				"status varchar(255) NOT NULL DEFAULT 'draft', date_created timestamp DEFAULT NULL, date_updated timestamp DEFAULT NULL, " +
				"url_key varchar(255) NOT NULL, PRIMARY KEY (uuid), UNIQUE KEY about_url_key_unique (url_key), UNIQUE KEY id (id))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, COLUMN_TYPE, COLUMN_KEY, CHARACTER_MAXIMUM_LENGTH, EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'about'",
				Expected: []sql.Row{
					{"about", "id", nil, "NO", "int unsigned", "UNI", nil, "auto_increment"},
					{"about", "uuid", nil, "NO", "char(36)", "PRI", 36, ""},
					{"about", "status", "draft", "NO", "varchar(255)", "", 255, ""},
					{"about", "date_created", nil, "YES", "timestamp", "", nil, ""},
					{"about", "date_updated", nil, "YES", "timestamp", "", nil, ""},
					{"about", "url_key", nil, "NO", "varchar(255)", "UNI", 255, ""},
				},
			},
		},
	},
	{
		Name: "information_schema.columns with column key check for MUL",
		SetUpScript: []string{
			"create table new_table (id int, name varchar(30), cname varbinary(100));",
			"alter table new_table modify column id int NOT NULL, add key(id);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT TABLE_NAME, COLUMN_NAME, IS_NULLABLE, DATA_TYPE, COLUMN_TYPE, COLUMN_KEY, CHARACTER_MAXIMUM_LENGTH, EXTRA FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'new_table'",
				Expected: []sql.Row{
					{"new_table", "id", "NO", "int", "int", "MUL", nil, ""},
					{"new_table", "name", "YES", "varchar", "varchar(30)", "", 30, ""},
					{"new_table", "cname", "YES", "varbinary", "varbinary(100)", "", 100, ""},
				},
			},
		},
	},
	{
		Name: "information_schema.columns with column key check for MUL for only the first column of composite unique key",
		SetUpScript: []string{
			"create table comp_uni (pk int not null, c0 int, c1 int, primary key (pk), unique key c0c1 (c0, c1));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT TABLE_NAME, COLUMN_NAME, IS_NULLABLE, COLUMN_TYPE, COLUMN_KEY FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'comp_uni'",
				Expected: []sql.Row{
					{"comp_uni", "pk", "NO", "int", "PRI"},
					{"comp_uni", "c0", "YES", "int", "MUL"},
					{"comp_uni", "c1", "YES", "int", ""},
				},
			},
		},
	},
	{
		Name: "information_schema.columns with column key UNI is displayed as PRI if it cannot contain NULL values and there is no PRIMARY KEY in the table",
		SetUpScript: []string{
			"create table ptable (id int not null, id2 int not null, col1 bool, UNIQUE KEY unique_key (id), UNIQUE KEY unique_key2 (id2));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT TABLE_NAME, COLUMN_NAME, IS_NULLABLE, DATA_TYPE, COLUMN_TYPE, COLUMN_KEY FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'ptable'",
				Expected: []sql.Row{
					{"ptable", "id", "NO", "int", "int", "PRI"},
					{"ptable", "id2", "NO", "int", "int", "UNI"},
					{"ptable", "col1", "YES", "tinyint", "tinyint", ""},
				},
			},
		},
	},
	{
		Name: "information_schema.columns with srs_id defined in spatial columns",
		SetUpScript: []string{
			"CREATE TABLE stable (geo GEOMETRY NOT NULL DEFAULT (POINT(2, 5)), line LINESTRING NOT NULL, pnt POINT SRID 4326, pol POLYGON NOT NULL SRID 0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, COLUMN_TYPE, COLUMN_KEY, SRS_ID FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'stable'",
				Expected: []sql.Row{
					{"stable", "geo", "point(2,5)", "NO", "geometry", "geometry", "", nil},
					{"stable", "line", nil, "NO", "linestring", "linestring", "", nil},
					{"stable", "pnt", nil, "YES", "point", "point", "", uint32(4326)},
					{"stable", "pol", nil, "NO", "polygon", "polygon", "", uint32(0)},
				},
			},
		},
	},
	{
		Name: "column specific tests information_schema.statistics table",
		SetUpScript: []string{
			`create table ptable (i int primary key, b blob, c char(10))`,
			`alter table ptable add unique index (c(3))`,
			`alter table ptable add unique index (b(4))`,
			`create index b_and_c on ptable (b(5), c(6))`,
			`insert into ptable values (0 , ('abc'), 'abc'), (1 , ('bcd'), 'bcdefg'), (2 , null, 'bceff')`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `select index_name, seq_in_index, column_name, sub_part from information_schema.statistics where table_schema = 'mydb' and table_name = 'ptable' ORDER BY INDEX_NAME`,
				Expected: []sql.Row{
					{"b", 1, "b", 4},
					{"b_and_c", 1, "b", 5},
					{"b_and_c", 2, "c", 6},
					{"c", 1, "c", 3},
					{"PRIMARY", 1, "i", nil},
				},
			},
			{

				Skip:     true,
				Query:    `select index_name, seq_in_index, column_name, cardinality, sub_part from information_schema.statistics where table_schema = 'mydb' and table_name = 'ptable' ORDER BY INDEX_NAME`,
				Expected: []sql.Row{{2}, {2}, {2}, {2}, {2}},
			},
			{
				Query: `SELECT seq_in_index, sub_part, index_name, index_type, CASE non_unique WHEN 0 THEN 'TRUE' ELSE 'FALSE' END AS is_unique, column_name
	FROM information_schema.statistics WHERE table_schema='mydb' AND table_name='ptable' ORDER BY index_name, seq_in_index;`,
				Expected: []sql.Row{
					{1, 4, "b", "BTREE", "TRUE", "b"},
					{1, 5, "b_and_c", "BTREE", "FALSE", "b"},
					{2, 6, "b_and_c", "BTREE", "FALSE", "c"},
					{1, 3, "c", "BTREE", "TRUE", "c"},
					{1, nil, "PRIMARY", "BTREE", "TRUE", "i"},
				},
			},
		},
	},
	{
		Name: "column specific tests on information_schema.columns table",
		SetUpScript: []string{
			`CREATE TABLE all_types (
pk int NOT NULL,
binary_1 binary(1) DEFAULT "1",
big_int bigint DEFAULT "1",
bit_2 bit(2) DEFAULT 2,
some_blob blob DEFAULT ("abc"),
char_1 char(1) DEFAULT "A",
some_date date DEFAULT "2022-02-22",
date_time datetime DEFAULT "2022-02-22 22:22:21",
decimal_52 decimal(5,2) DEFAULT "994.45",
some_double double DEFAULT "1.1",
some_enum enum('s','m','l') DEFAULT "s",
some_float float DEFAULT "4.4",
some_geometry geometry srid 4326 DEFAULT (POINT(1, 2)),
some_int int DEFAULT "3",
some_json json DEFAULT (JSON_OBJECT("a", 1)),
line_string linestring DEFAULT (LINESTRING(POINT(0, 0),POINT(1, 2))),
long_blob longblob DEFAULT ("abc"),
long_text longtext DEFAULT ("abc"),
medium_blob mediumblob DEFAULT ("abc"),
medium_int mediumint DEFAULT "7",
medium_text mediumtext DEFAULT ("abc"),
some_point point DEFAULT (POINT(2, 2)),
some_polygon polygon DEFAULT NULL,
some_set set('one','two') DEFAULT "one,two",
small_int smallint DEFAULT "5",
some_text text DEFAULT ("abc"),
time_6 time(6) DEFAULT "11:59:59.000010",
time_stamp timestamp DEFAULT (CURRENT_TIMESTAMP()),
tiny_blob tinyblob DEFAULT ("abc"),
tiny_int tinyint DEFAULT "4",
tiny_text tinytext DEFAULT ("abc"),
var_char varchar(255) DEFAULT "varchar value",
var_binary varbinary(255) DEFAULT "11111",
some_year year DEFAULT "2023",
PRIMARY KEY (pk)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT table_catalog, table_schema, table_name, column_name, ordinal_position
FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='all_types' ORDER BY ORDINAL_POSITION`,
				Expected: []sql.Row{
					{"def", "mydb", "all_types", "pk", uint32(1)},
					{"def", "mydb", "all_types", "binary_1", uint32(2)},
					{"def", "mydb", "all_types", "big_int", uint32(3)},
					{"def", "mydb", "all_types", "bit_2", uint32(4)},
					{"def", "mydb", "all_types", "some_blob", uint32(5)},
					{"def", "mydb", "all_types", "char_1", uint32(6)},
					{"def", "mydb", "all_types", "some_date", uint32(7)},
					{"def", "mydb", "all_types", "date_time", uint32(8)},
					{"def", "mydb", "all_types", "decimal_52", uint32(9)},
					{"def", "mydb", "all_types", "some_double", uint32(10)},
					{"def", "mydb", "all_types", "some_enum", uint32(11)},
					{"def", "mydb", "all_types", "some_float", uint32(12)},
					{"def", "mydb", "all_types", "some_geometry", uint32(13)},
					{"def", "mydb", "all_types", "some_int", uint32(14)},
					{"def", "mydb", "all_types", "some_json", uint32(15)},
					{"def", "mydb", "all_types", "line_string", uint32(16)},
					{"def", "mydb", "all_types", "long_blob", uint32(17)},
					{"def", "mydb", "all_types", "long_text", uint32(18)},
					{"def", "mydb", "all_types", "medium_blob", uint32(19)},
					{"def", "mydb", "all_types", "medium_int", uint32(20)},
					{"def", "mydb", "all_types", "medium_text", uint32(21)},
					{"def", "mydb", "all_types", "some_point", uint32(22)},
					{"def", "mydb", "all_types", "some_polygon", uint32(23)},
					{"def", "mydb", "all_types", "some_set", uint32(24)},
					{"def", "mydb", "all_types", "small_int", uint32(25)},
					{"def", "mydb", "all_types", "some_text", uint32(26)},
					{"def", "mydb", "all_types", "time_6", uint32(27)},
					{"def", "mydb", "all_types", "time_stamp", uint32(28)},
					{"def", "mydb", "all_types", "tiny_blob", uint32(29)},
					{"def", "mydb", "all_types", "tiny_int", uint32(30)},
					{"def", "mydb", "all_types", "tiny_text", uint32(31)},
					{"def", "mydb", "all_types", "var_char", uint32(32)},
					{"def", "mydb", "all_types", "var_binary", uint32(33)},
					{"def", "mydb", "all_types", "some_year", uint32(34)},
				},
			},
			{
				Query: `SELECT column_name, column_default, is_nullable, data_type, column_type, character_maximum_length, character_octet_length
FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='all_types' ORDER BY ORDINAL_POSITION`,
				Expected: []sql.Row{
					{"pk", nil, "NO", "int", "int", nil, nil},
					{"binary_1", "0x31", "YES", "binary", "binary(1)", 1, 1},
					{"big_int", "1", "YES", "bigint", "bigint", nil, nil},
					{"bit_2", "b'10'", "YES", "bit", "bit(2)", nil, nil},
					{"some_blob", "'abc'", "YES", "blob", "blob", 65535, 65535},
					{"char_1", "A", "YES", "char", "char(1)", 1, 4},
					{"some_date", "2022-02-22 00:00:00", "YES", "date", "date", nil, nil},
					{"date_time", "2022-02-22 22:22:21", "YES", "datetime", "datetime", nil, nil},
					{"decimal_52", "994.45", "YES", "decimal", "decimal(5,2)", nil, nil},
					{"some_double", "1.1", "YES", "double", "double", nil, nil},
					{"some_enum", "s", "YES", "enum", "enum('s','m','l')", 1, 4},
					{"some_float", "4.4", "YES", "float", "float", nil, nil},
					{"some_geometry", "point(1,2)", "YES", "geometry", "geometry", nil, nil},
					{"some_int", "3", "YES", "int", "int", nil, nil},
					{"some_json", "json_object('a',1)", "YES", "json", "json", nil, nil},
					{"line_string", "linestring(point(0,0),point(1,2))", "YES", "linestring", "linestring", nil, nil},
					{"long_blob", "'abc'", "YES", "longblob", "longblob", 4294967295, 4294967295},
					{"long_text", "'abc'", "YES", "longtext", "longtext", 1073741823, 4294967295},
					{"medium_blob", "'abc'", "YES", "mediumblob", "mediumblob", 16777215, 16777215},
					{"medium_int", "7", "YES", "mediumint", "mediumint", nil, nil},
					{"medium_text", "'abc'", "YES", "mediumtext", "mediumtext", 4194303, 16777215},
					{"some_point", "point(2,2)", "YES", "point", "point", nil, nil},
					{"some_polygon", nil, "YES", "polygon", "polygon", nil, nil},
					{"some_set", "one,two", "YES", "set", "set('one','two')", 7, 28},
					{"small_int", "5", "YES", "smallint", "smallint", nil, nil},
					{"some_text", "'abc'", "YES", "text", "text", 16383, 65535},
					{"time_6", "11:59:59.000010", "YES", "time", "time(6)", nil, nil},
					{"time_stamp", "CURRENT_TIMESTAMP", "YES", "timestamp", "timestamp", nil, nil},
					{"tiny_blob", "'abc'", "YES", "tinyblob", "tinyblob", 255, 255},
					{"tiny_int", "4", "YES", "tinyint", "tinyint", nil, nil},
					{"tiny_text", "'abc'", "YES", "tinytext", "tinytext", 63, 255},
					{"var_char", "varchar value", "YES", "varchar", "varchar(255)", 255, 1020},
					{"var_binary", "0x3131313131", "YES", "varbinary", "varbinary(255)", 255, 255},
					{"some_year", "2023", "YES", "year", "year", nil, nil},
				},
			},
			{
				Query: `SELECT column_name, column_type, numeric_precision, numeric_scale, datetime_precision, character_set_name, collation_name, column_key, extra, column_comment, generation_expression, srs_id
FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='all_types' ORDER BY ORDINAL_POSITION`,
				Expected: []sql.Row{
					{"pk", "int", 10, 0, nil, nil, nil, "PRI", "", "", "", nil},
					{"binary_1", "binary(1)", nil, nil, nil, nil, nil, "", "", "", "", nil},
					{"big_int", "bigint", 19, 0, nil, nil, nil, "", "", "", "", nil},
					{"bit_2", "bit(2)", 2, nil, nil, nil, nil, "", "", "", "", nil},
					{"some_blob", "blob", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"char_1", "char(1)", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "", "", "", nil},
					{"some_date", "date", nil, nil, nil, nil, nil, "", "", "", "", nil},
					{"date_time", "datetime", nil, nil, 0, nil, nil, "", "", "", "", nil},
					{"decimal_52", "decimal(5,2)", 5, 2, nil, nil, nil, "", "", "", "", nil},
					{"some_double", "double", 22, nil, nil, nil, nil, "", "", "", "", nil},
					{"some_enum", "enum('s','m','l')", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "", "", "", nil},
					{"some_float", "float", 12, nil, nil, nil, nil, "", "", "", "", nil},
					{"some_geometry", "geometry", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", uint32(4326)},
					{"some_int", "int", 10, 0, nil, nil, nil, "", "", "", "", nil},
					{"some_json", "json", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"line_string", "linestring", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"long_blob", "longblob", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"long_text", "longtext", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "DEFAULT_GENERATED", "", "", nil},
					{"medium_blob", "mediumblob", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"medium_int", "mediumint", 7, 0, nil, nil, nil, "", "", "", "", nil},
					{"medium_text", "mediumtext", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "DEFAULT_GENERATED", "", "", nil},
					{"some_point", "point", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"some_polygon", "polygon", nil, nil, nil, nil, nil, "", "", "", "", nil},
					{"some_set", "set('one','two')", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "", "", "", nil},
					{"small_int", "smallint", 5, 0, nil, nil, nil, "", "", "", "", nil},
					{"some_text", "text", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "DEFAULT_GENERATED", "", "", nil},
					{"time_6", "time(6)", nil, nil, 6, nil, nil, "", "", "", "", nil},
					{"time_stamp", "timestamp", nil, nil, 0, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"tiny_blob", "tinyblob", nil, nil, nil, nil, nil, "", "DEFAULT_GENERATED", "", "", nil},
					{"tiny_int", "tinyint", 3, 0, nil, nil, nil, "", "", "", "", nil},
					{"tiny_text", "tinytext", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "DEFAULT_GENERATED", "", "", nil},
					{"var_char", "varchar(255)", nil, nil, nil, "utf8mb4", "utf8mb4_0900_bin", "", "", "", "", nil},
					{"var_binary", "varbinary(255)", nil, nil, nil, nil, nil, "", "", "", "", nil},
					{"some_year", "year", nil, nil, nil, nil, nil, "", "", "", "", nil},
				},
			},
		},
	},
	{
		Name: "column specific tests on information_schema.tables table",
		SetUpScript: []string{
			`create table bigtable (text varchar(20) primary key, number mediumint, pt point default (POINT(1,1)))`,
			`insert into bigtable values ('a',4,POINT(1,4)),('b',2,null),('c',0,null),('d',2,POINT(1, 2)),('e',2,POINT(1, 2))`,
			`create index bigtable_number on bigtable (number)`,
			`CREATE VIEW myview1 AS SELECT * FROM mytable`,
			`CREATE VIEW myview2 AS SELECT * FROM myview1 WHERE i = 1`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT table_catalog, table_schema, table_name, table_type, table_comment FROM information_schema.tables WHERE table_schema = 'mydb' and table_type IN ('VIEW') ORDER BY TABLE_NAME;`,
				Expected: []sql.Row{
					{"def", "mydb", "myview", "VIEW", "VIEW"},
					{"def", "mydb", "myview1", "VIEW", "VIEW"},
					{"def", "mydb", "myview2", "VIEW", "VIEW"},
				},
			},
			{
				Query: "SELECT table_rows as count FROM information_schema.TABLES WHERE TABLE_SCHEMA='mydb' AND TABLE_NAME='bigtable';",
				Expected: []sql.Row{
					{uint64(5)},
				},
			},
		},
	},
	{
		Name: "column specific tests on information_schema table, check and referential constraints",
		SetUpScript: []string{
			`CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c varchar(20))`,
			`ALTER TABLE checks ADD CONSTRAINT chk1 CHECK (B > 0)`,
			`ALTER TABLE checks ADD CONSTRAINT chk2 CHECK (b > 0) NOT ENFORCED`,
			`ALTER TABLE checks ADD CONSTRAINT chk3 CHECK (B > 1)`,
			`ALTER TABLE checks ADD CONSTRAINT chk4 CHECK (upper(C) = c)`,

			`create table ptable (i int primary key, b blob, c char(10))`,
			`alter table ptable add index (c(3))`,
			`alter table ptable add unique index (b(4))`,
			`create index b_and_c on ptable (b(5), c(6))`,
			`ALTER TABLE ptable ADD CONSTRAINT ptable_checks FOREIGN KEY (i) REFERENCES checks(a)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT TC.CONSTRAINT_NAME, CC.CHECK_CLAUSE, TC.ENFORCED 
FROM information_schema.TABLE_CONSTRAINTS TC, information_schema.CHECK_CONSTRAINTS CC 
WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'checks' AND TC.TABLE_SCHEMA = CC.CONSTRAINT_SCHEMA AND TC.CONSTRAINT_NAME = CC.CONSTRAINT_NAME AND TC.CONSTRAINT_TYPE = 'CHECK';`,
				Expected: []sql.Row{
					{"chk1", "(b > 0)", "YES"},
					{"chk2", "(b > 0)", "NO"},
					{"chk3", "(b > 1)", "YES"},
					{"chk4", "(upper(c) = c)", "YES"},
				},
			},
			{
				Query: `select * from information_schema.table_constraints where table_schema = 'mydb' and table_name = 'checks';`,
				Expected: []sql.Row{
					{"def", "mydb", "PRIMARY", "mydb", "checks", "PRIMARY KEY", "YES"},
					{"def", "mydb", "chk1", "mydb", "checks", "CHECK", "YES"},
					{"def", "mydb", "chk2", "mydb", "checks", "CHECK", "NO"},
					{"def", "mydb", "chk3", "mydb", "checks", "CHECK", "YES"},
					{"def", "mydb", "chk4", "mydb", "checks", "CHECK", "YES"},
				},
			},
			{
				Query: `select * from information_schema.check_constraints where constraint_schema = 'mydb';`,
				Expected: []sql.Row{
					{"def", "mydb", "chk1", "(b > 0)"},
					{"def", "mydb", "chk2", "(b > 0)"},
					{"def", "mydb", "chk3", "(b > 1)"},
					{"def", "mydb", "chk4", "(upper(c) = c)"},
				},
			},
			{
				Query: `select * from information_schema.table_constraints where table_schema = 'mydb' and table_name = 'ptable';`,
				Expected: []sql.Row{
					{"def", "mydb", "PRIMARY", "mydb", "ptable", "PRIMARY KEY", "YES"},
					{"def", "mydb", "b", "mydb", "ptable", "UNIQUE", "YES"},
					{"def", "mydb", "ptable_checks", "mydb", "ptable", "FOREIGN KEY", "YES"},
				},
			},
		},
	},
	{
		Name: "column specific tests on information_schema.routines table",
		SetUpScript: []string{
			`CREATE DEFINER=root@localhost PROCEDURE count_i_from_mytable(OUT total_i INT)
    READS SQL DATA
BEGIN
     SELECT SUM(i)
     FROM mytable
     INTO total_i;
END ;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `select specific_name, routine_catalog, routine_schema, routine_name, routine_type, data_type,
routine_body, external_language, parameter_style, is_deterministic, sql_data_access, security_type, sql_mode, 
routine_comment, definer, character_set_client, collation_connection, database_collation
from information_schema.routines where routine_schema = 'mydb' and routine_type like 'PROCEDURE' order by routine_name;`,
				Expected: []sql.Row{
					{"count_i_from_mytable", "def", "mydb", "count_i_from_mytable", "PROCEDURE", "", "SQL", "SQL", "SQL", "NO",
						"READS SQL DATA", "DEFINER", "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY",
						"", "root@localhost", "utf8mb4", "utf8mb4_0900_bin", "utf8mb4_0900_bin"},
				},
			},
			{
				Query: `select routine_definition from information_schema.routines where routine_schema = 'mydb' and routine_type like 'PROCEDURE' order by routine_name;`,
				Expected: []sql.Row{
					{"BEGIN\n     SELECT SUM(i)\n     FROM mytable\n     INTO total_i;\nEND"},
				},
			},
		},
	},
	{
		Name: "column specific tests on information_schema.tables table",
		SetUpScript: []string{
			`create table bigtable (text varchar(20) primary key, number mediumint, pt point default (POINT(1,1)))`,
			`insert into bigtable values ('a',4,POINT(1,4)),('b',2,null),('c',0,null),('d',2,POINT(1, 2)),('e',2,POINT(1, 2))`,
			`create index bigtable_number on bigtable (number)`,
			`CREATE TABLE names (actor_id smallint PRIMARY KEY AUTO_INCREMENT, first_name varchar(45) NOT NULL);`,
			`INSERT INTO names (first_name) VALUES ('PENELOPE'), ('NICK'), ('JUNE');`,
			`CREATE VIEW myview1 AS SELECT * FROM myview WHERE i = 1`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT table_catalog, table_schema, table_name, table_type, engine, version, row_format, table_rows,
				auto_increment, table_collation, checksum, create_options, table_comment
				FROM information_schema.tables where table_schema = 'mydb' order by table_name`,
				Expected: []sql.Row{
					{"def", "mydb", "bigtable", "BASE TABLE", "InnoDB", 10, "Dynamic", uint64(5), nil, "utf8mb4_0900_bin", nil, "", ""},
					{"def", "mydb", "fk_tbl", "BASE TABLE", "InnoDB", 10, "Dynamic", uint64(0), nil, "utf8mb4_0900_bin", nil, "", ""},
					{"def", "mydb", "mytable", "BASE TABLE", "InnoDB", 10, "Dynamic", uint64(3), nil, "utf8mb4_0900_bin", nil, "", ""},
					{"def", "mydb", "myview", "VIEW", nil, nil, nil, nil, nil, nil, nil, nil, "VIEW"},
					{"def", "mydb", "myview1", "VIEW", nil, nil, nil, nil, nil, nil, nil, nil, "VIEW"},
					{"def", "mydb", "names", "BASE TABLE", "InnoDB", 10, "Dynamic", uint64(3), uint64(4), "utf8mb4_0900_bin", nil, "", ""},
				},
			},
			{
				Query: "SELECT table_comment,table_rows,auto_increment FROM information_schema.tables WHERE TABLE_NAME = 'names' AND TABLE_SCHEMA = 'mydb';",
				Expected: []sql.Row{
					{"", uint64(3), uint64(4)},
				},
			},
		},
	},
	{
		Name: "information_schema.views has definer and security information",
		SetUpScript: []string{
			"create view myview1 as select count(*) from mytable;",
			"CREATE ALGORITHM=TEMPTABLE DEFINER=UserName@localhost SQL SECURITY INVOKER VIEW myview2 AS SELECT * FROM myview WHERE i > 1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from information_schema.views where table_schema = 'mydb' order by table_name",
				Expected: []sql.Row{
					{"def", "mydb", "myview", "SELECT * FROM mytable", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"},
					{"def", "mydb", "myview1", "select count(*) from mytable", "NONE", "NO", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"},
					{"def", "mydb", "myview2", "SELECT * FROM myview WHERE i > 1", "NONE", "NO", "UserName@localhost", "INVOKER", "utf8mb4", "utf8mb4_0900_bin"},
				},
			},
		},
	},
	{
		Name: "information_schema.schemata shows all column values",
		SetUpScript: []string{
			"CREATE DATABASE mydb1 COLLATE latin1_general_ci;",
			"CREATE DATABASE mydb2 COLLATE utf8mb3_general_ci;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.schemata where schema_name like 'mydb%' order by schema_name",
				Expected: []sql.Row{
					{"def", "mydb", "utf8mb4", "utf8mb4_0900_bin", nil, "NO"},
					{"def", "mydb1", "latin1", "latin1_general_ci", nil, "NO"},
					{"def", "mydb2", "utf8mb3", "utf8mb3_general_ci", nil, "NO"},
				},
			},
		},
	},
	{
		Name: "information_schema.st_geometry_columns shows all column values",
		SetUpScript: []string{
			"CREATE TABLE spatial_table (id INT PRIMARY KEY, g GEOMETRY SRID 0, m MULTIPOINT, p POLYGON SRID 4326);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.st_geometry_columns where table_schema = 'mydb' order by column_name",
				Expected: []sql.Row{
					{"def", "mydb", "spatial_table", "g", "", uint32(0), "geometry"},
					{"def", "mydb", "spatial_table", "m", nil, nil, "multipoint"},
					{"def", "mydb", "spatial_table", "p", "WGS 84", uint32(4326), "polygon"},
				},
			},
		},
	},
	{
		Name: "information_schema.parameters shows all column values",
		SetUpScript: []string{
			"CREATE PROCEDURE testabc(IN x DOUBLE, IN y FLOAT, OUT abc DECIMAL(5,1)) SELECT x*y INTO abc",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.parameters where specific_name = 'testabc'",
				Expected: []sql.Row{
					{"def", "mydb", "testabc", uint64(1), "IN", "x", "double", nil, nil, 22, 0, nil, nil, nil, "double", "PROCEDURE"},
					{"def", "mydb", "testabc", uint64(2), "IN", "y", "float", nil, nil, 12, 0, nil, nil, nil, "float", "PROCEDURE"},
					{"def", "mydb", "testabc", uint64(3), "OUT", "abc", "decimal", nil, nil, 5, 1, nil, nil, nil, "decimal(5,1)", "PROCEDURE"},
				},
			},
		},
	},
}
View Source
var InsertBrokenScripts = []ScriptTest{

	{
		Name: "Test that INSERT IGNORE works with FK Violations",
		SetUpScript: []string{
			"CREATE TABLE t1 (id INT PRIMARY KEY, v int);",
			"CREATE TABLE t2 (id INT PRIMARY KEY, v2 int, CONSTRAINT mfk FOREIGN KEY (v2) REFERENCES t1(id));",
			"INSERT INTO t1 values (1,1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "INSERT IGNORE INTO t2 VALUES (1,2);",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 0}},
				},
				ExpectedWarning: mysql.ErNoReferencedRow2,
			},
		},
	},

	{
		Name: "Test that INSERT IGNORE assigns the closest dataype correctly",
		SetUpScript: []string{
			"CREATE TABLE x (pk int primary key, c1 varchar(20) NOT NULL);",
			`INSERT IGNORE INTO x VALUES (1, "one"), (2, TRUE), (3, "three")`,
			"CREATE TABLE y (pk int primary key, c1 int NOT NULL);",
			`INSERT IGNORE INTO y VALUES (1, 1), (2, "two"), (3,3);`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM x",
				Expected: []sql.Row{
					{1, "one"}, {2, 1}, {3, "three"},
				},
			},
			{
				Query: "SELECT * FROM y",
				Expected: []sql.Row{
					{1, 1}, {2, 0}, {3, 3},
				},
			},
			{
				Query: `INSERT IGNORE INTO y VALUES (4, "four")`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
			},
		},
	},
}
View Source
var InsertDuplicateKeyKeyless = []ScriptTest{
	{
		Name: "insert on duplicate key for keyless table",
		SetUpScript: []string{
			`create table t (i int unique, j varchar(128))`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into t values (0, "first")`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `insert into t values (0, "second") on duplicate key update j = "third"`,
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: `select i, j from t order by i`,
				Expected: []sql.Row{
					{0, "third"},
				},
			},
		},
	},
	{
		Name: "insert on duplicate key for keyless table multiple unique columns",
		SetUpScript: []string{
			`create table t (c1 int, c2 int, c3 int, unique key(c1,c2))`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0) on duplicate key update c3 = 0`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, 0, 0},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 1) on duplicate key update c3 = 0`,
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, 0, 0},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0) on duplicate key update c3 = 1`,
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, 0, 1},
				},
			},
		},
	},
	{
		Name: "insert on duplicate key for keyless tables with nulls",
		SetUpScript: []string{
			`create table t (c1 int, c2 int, c3 int, unique key(c1, c2))`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into t(c1, c2, c3) values (0, null, 0) on duplicate key update c3 = 0`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, nil, 0},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, null, 1) on duplicate key update c3 = 0`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, nil, 0},
					{0, nil, 1},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, null, 0) on duplicate key update c3 = 1`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, nil, 0},
					{0, nil, 0},
					{0, nil, 1},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0) on duplicate key update c3 = null`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, nil, 0},
					{0, nil, 0},
					{0, nil, 1},
					{0, 0, 0},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0) on duplicate key update c3 = null`,
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, nil, 0},
					{0, nil, 0},
					{0, nil, 1},
					{0, 0, nil},
				},
			},
		},
	},
	{
		Name: "insert on duplicate key for keyless table mixed ordering",
		SetUpScript: []string{
			`create table t (c1 int, c2 int, c3 int, unique key(c2, c1))`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0) on duplicate key update c3 = 0`,
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, 0, 0},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 1) on duplicate key update c3 = 0`,
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, 0, 0},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0) on duplicate key update c3 = 1`,
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1`,
				Expected: []sql.Row{
					{0, 0, 1},
				},
			},
		},
	},
	{
		Name: "insert on duplicate key for keyless table multiple unique columns batched",
		SetUpScript: []string{
			`create table t (c1 int, c2 int, c3 int, unique key(c1,c2))`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 0), (0, 0, 0), (0, 0, 1), (0, 0, 1) on duplicate key update c3 = 1`,
				Expected: []sql.Row{
					{types.NewOkResult(3)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, 0, 1},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4) on duplicate key update c3 = 100`,
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, 0, 100},
				},
			},
			{
				Query: `insert into t(c1, c2, c3) values (0, 0, 1), (0, 1, 1), (0, 2, 2), (0, 3, 3) on duplicate key update c3 = 200`,
				Expected: []sql.Row{
					{types.NewOkResult(5)},
				},
			},
			{
				Query: `select c1, c2, c3 from t order by c1, c2, c3`,
				Expected: []sql.Row{
					{0, 0, 200},
					{0, 1, 1},
					{0, 2, 2},
					{0, 3, 3},
				},
			},
		},
	},
}
View Source
var InsertErrorScripts = []ScriptTest{
	{
		Name:        "create table with non-pk auto_increment column",
		Query:       "create table bad (pk int primary key, c0 int auto_increment);",
		ExpectedErr: sql.ErrInvalidAutoIncCols,
	},
	{
		Name:        "create multiple auto_increment columns",
		Query:       "create table bad (pk1 int auto_increment, pk2 int auto_increment, primary key (pk1,pk2));",
		ExpectedErr: sql.ErrInvalidAutoIncCols,
	},
	{
		Name:        "create auto_increment column with default",
		Query:       "create table bad (pk1 int auto_increment default 10, c0 int);",
		ExpectedErr: sql.ErrInvalidAutoIncCols,
	},
	{
		Name: "try inserting string that is too long",
		SetUpScript: []string{
			"create table bad (s varchar(9))",
		},
		Query:       "insert into bad values ('1234567890')",
		ExpectedErr: types.ErrLengthBeyondLimit,
	},
	{
		Name: "try inserting varbinary larger than max limit",
		SetUpScript: []string{
			"create table bad (vb varbinary(65535))",
		},
		Query:       "insert into bad values (repeat('0', 65536))",
		ExpectedErr: types.ErrLengthBeyondLimit,
	},
}
View Source
var InsertErrorTests = []GenericErrorQueryTest{
	{
		Name:  "try to insert empty into col without default value",
		Query: "INSERT INTO mytable VALUES ();",
	},
	{
		Name:  "try to insert empty into col without default value",
		Query: "INSERT INTO mytable () VALUES ();",
	},
	{
		Name:  "too few values",
		Query: "INSERT INTO mytable (s, i) VALUES ('x');",
	},
	{
		Name:  "too many values one column",
		Query: "INSERT INTO mytable (s) VALUES ('x', 999);",
	},
	{
		Name:  "missing binding",
		Query: "INSERT INTO mytable (s) VALUES (?);",
	},
	{
		Name:  "too many values two columns",
		Query: "INSERT INTO mytable (i, s) VALUES (999, 'x', 'y');",
	},
	{
		Name:  "too few values no columns specified",
		Query: "INSERT INTO mytable VALUES (999);",
	},
	{
		Name:  "too many values no columns specified",
		Query: "INSERT INTO mytable VALUES (999, 'x', 'y');",
	},
	{
		Name:  "non-existent column values",
		Query: "INSERT INTO mytable (i, s, z) VALUES (999, 'x', 999);",
	},
	{
		Name:  "non-existent column set",
		Query: "INSERT INTO mytable SET i = 999, s = 'x', z = 999;",
	},
	{
		Name:  "duplicate column",
		Query: "INSERT INTO mytable (i, s, s) VALUES (999, 'x', 'x');",
	},
	{
		Name:  "duplicate column set",
		Query: "INSERT INTO mytable SET i = 999, s = 'y', s = 'y';",
	},
	{
		Name:  "null given to non-nullable",
		Query: "INSERT INTO mytable (i, s) VALUES (null, 'y');",
	},
	{
		Name:  "incompatible types",
		Query: "INSERT INTO mytable (i, s) select * FROM othertable",
	},
	{
		Name:  "column count mismatch in select",
		Query: "INSERT INTO mytable (i) select * FROM othertable",
	},
	{
		Name:  "column count mismatch in select",
		Query: "INSERT INTO mytable select s FROM othertable",
	},
	{
		Name:  "column count mismatch in join select",
		Query: "INSERT INTO mytable (s,i) SELECT * FROM othertable o JOIN mytable m ON m.i=o.i2",
	},
	{
		Name:  "duplicate key",
		Query: "INSERT INTO mytable (i,s) values (1, 'hello')",
	},
	{
		Name:  "duplicate keys",
		Query: "INSERT INTO mytable SELECT * from mytable",
	},
	{
		Name:  "bad column in on duplicate key update clause",
		Query: "INSERT INTO mytable values (10, 'b') ON DUPLICATE KEY UPDATE notExist = 1",
	},
}
View Source
var InsertIgnoreScripts = []ScriptTest{
	{
		Name: "Test that INSERT IGNORE with Non nullable columns works",
		SetUpScript: []string{
			"CREATE TABLE x (pk int primary key, c1 varchar(20) NOT NULL);",
			"INSERT IGNORE INTO x VALUES (1, NULL)",
			"CREATE TABLE y (pk int primary key, c1 int NOT NULL);",
			"INSERT IGNORE INTO y VALUES (1, NULL);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM x",
				Expected: []sql.Row{
					{1, ""},
				},
			},
			{
				Query: "SELECT * FROM y",
				Expected: []sql.Row{
					{1, 0},
				},
			},
			{
				Query: "INSERT IGNORE INTO y VALUES (2, NULL)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERBadNullError,
			},
		},
	},
	{
		Name: "Test that INSERT IGNORE properly addresses data conversion",
		SetUpScript: []string{
			"CREATE TABLE t1 (pk int primary key, v1 int)",
			"CREATE TABLE t2 (pk int primary key, v2 varchar(1))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "INSERT IGNORE INTO t1 VALUES (1, 'dasd')",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
			},
			{
				Query: "SELECT * FROM t1",
				Expected: []sql.Row{
					{1, 0},
				},
			},
			{
				Query: "INSERT IGNORE INTO t2 values (1, 'adsda')",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERUnknownError,
			},
			{
				Query: "SELECT * FROM t2",
				Expected: []sql.Row{
					{1, "a"},
				},
			},
		},
	},
	{
		Name: "Insert Ignore works correctly with ON DUPLICATE UPDATE",
		SetUpScript: []string{
			"CREATE TABLE t1 (id INT PRIMARY KEY, v int);",
			"INSERT INTO t1 VALUES (1,1)",
			"CREATE TABLE t2 (pk int primary key, v2 varchar(1))",
			"ALTER TABLE t2 ADD CONSTRAINT cx CHECK (pk < 100)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "INSERT IGNORE INTO t1 VALUES (1,2) ON DUPLICATE KEY UPDATE v='dsd';",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
			},
			{
				Query: "SELECT * FROM t1",
				Expected: []sql.Row{
					{1, 0},
				},
			},
			{
				Query: "INSERT IGNORE INTO t2 values (1, 'adsda')",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERUnknownError,
			},
			{
				Query: "SELECT * FROM t2",
				Expected: []sql.Row{
					{1, "a"},
				},
			},
			{
				Query:    "INSERT IGNORE INTO t2 VALUES (1, 's') ON DUPLICATE KEY UPDATE pk = 1000",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0}}},
			},
			{
				Query: "SELECT * FROM t2",
				Expected: []sql.Row{
					{1, "a"},
				},
			},
		},
	},
	{
		Name: "Test that INSERT IGNORE INTO works with unique keys",
		SetUpScript: []string{
			"CREATE TABLE one_uniq(pk int PRIMARY KEY, col1 int UNIQUE)",
			"CREATE TABLE two_uniq(pk int PRIMARY KEY, col1 int, col2 int, UNIQUE KEY col1_col2_uniq (col1, col2))",
			"INSERT INTO one_uniq values (1, 1)",
			"INSERT INTO two_uniq values (1, 1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "INSERT IGNORE INTO one_uniq VALUES (3, 2), (2, 1), (4, null), (5, null)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 3}},
				},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query: "SELECT * from one_uniq;",
				Expected: []sql.Row{
					{1, 1}, {3, 2}, {4, nil}, {5, nil},
				},
			},
			{
				Query: "INSERT IGNORE INTO two_uniq VALUES (4, 1, 2), (5, 2, 1), (6, null, 1), (7, null, 1), (12, 1, 1), (8, 1, null), (9, 1, null), (10, null, null), (11, null, null)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 8}},
				},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query: "SELECT * from two_uniq;",
				Expected: []sql.Row{
					{1, 1, 1}, {4, 1, 2}, {5, 2, 1}, {6, nil, 1}, {7, nil, 1}, {8, 1, nil}, {9, 1, nil}, {10, nil, nil}, {11, nil, nil},
				},
			},
		},
	},
}
View Source
var InsertQueries = []WriteQueryTest{
	{
		WriteQuery:          "INSERT INTO keyless VALUES ();",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM keyless WHERE c0 IS NULL;",
		ExpectedSelect:      []sql.Row{{nil, nil}},
	},
	{
		WriteQuery:          "INSERT INTO keyless () VALUES ();",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM keyless WHERE c0 IS NULL;",
		ExpectedSelect:      []sql.Row{{nil, nil}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (s, i) VALUES ('x', '10.0');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(10)}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (s, i) VALUES ('x', '64.6');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(64)}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (s, i) VALUES ('x', 999);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "INSERT INTO niltable (i, f) VALUES (10, 10.0), (12, 12.0);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT i,f FROM niltable WHERE f IN (10.0, 12.0) ORDER BY f;",
		ExpectedSelect:      []sql.Row{{int64(10), 10.0}, {int64(12), 12.0}},
	},
	{
		WriteQuery:          "INSERT INTO mytable SET s = 'x', i = 999;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "INSERT INTO mytable VALUES (999, 'x');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "INSERT INTO mytable SET i = 999, s = 'x';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "INSERT INTO mytable VALUES (999, _binary 'x');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT s FROM mytable WHERE i = 999;",
		ExpectedSelect:      []sql.Row{{"x"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable SET i = 999, s = _binary 'x';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT s FROM mytable WHERE i = 999;",
		ExpectedSelect:      []sql.Row{{"x"}},
	},
	{
		WriteQuery: `INSERT INTO typestable VALUES (
			999, 127, 32767, 2147483647, 9223372036854775807,
			255, 65535, 4294967295, 18446744073709551615,
			3.40282346638528859811704183484516925440e+38, 1.797693134862315708145274237317043567981e+308,
			'2037-04-05 12:51:36', '2231-11-07',
			'random text', true, '{"key":"value"}', 'blobdata', 'v1', 'v2'
			);`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(math.MaxInt8), int16(math.MaxInt16), int32(math.MaxInt32), int64(math.MaxInt64),
			uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64),
			float32(math.MaxFloat32), float64(math.MaxFloat64),
			sql.MustConvert(types.Timestamp.Convert("2037-04-05 12:51:36")), sql.MustConvert(types.Date.Convert("2231-11-07")),
			"random text", sql.True, types.MustJSON(`{"key":"value"}`), []byte("blobdata"), uint(2), uint(4),
		}},
	},
	{
		WriteQuery: `INSERT INTO typestable SET
			id = 999, i8 = 127, i16 = 32767, i32 = 2147483647, i64 = 9223372036854775807,
			u8 = 255, u16 = 65535, u32 = 4294967295, u64 = 18446744073709551615,
			f32 = 3.40282346638528859811704183484516925440e+38, f64 = 1.797693134862315708145274237317043567981e+308,
			ti = '2037-04-05 12:51:36', da = '2231-11-07',
			te = 'random text', bo = true, js = '{"key":"value"}', bl = 'blobdata', e1 = 'v1', s1 = 'v2'
			;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(math.MaxInt8), int16(math.MaxInt16), int32(math.MaxInt32), int64(math.MaxInt64),
			uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64),
			float32(math.MaxFloat32), float64(math.MaxFloat64),
			sql.MustConvert(types.Timestamp.Convert("2037-04-05 12:51:36")), sql.MustConvert(types.Date.Convert("2231-11-07")),
			"random text", sql.True, types.MustJSON(`{"key":"value"}`), []byte("blobdata"), uint(2), uint(4),
		}},
	},
	{
		WriteQuery: `INSERT INTO typestable VALUES (
			999, -128, -32768, -2147483648, -9223372036854775808,
			0, 0, 0, 0,
			1.401298464324817070923729583289916131280e-45, 4.940656458412465441765687928682213723651e-324,
			'0000-00-00 00:00:00', '0000-00-00',
			'', false, '""', '', '', ''
			);`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(-math.MaxInt8 - 1), int16(-math.MaxInt16 - 1), int32(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
			uint8(0), uint16(0), uint32(0), uint64(0),
			float32(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
			types.Timestamp.Zero(), types.Date.Zero(),
			"", sql.False, types.MustJSON(`""`), []byte(""), uint(1), uint(0),
		}},
	},
	{
		WriteQuery: `INSERT INTO typestable SET
			id = 999, i8 = -128, i16 = -32768, i32 = -2147483648, i64 = -9223372036854775808,
			u8 = 0, u16 = 0, u32 = 0, u64 = 0,
			f32 = 1.401298464324817070923729583289916131280e-45, f64 = 4.940656458412465441765687928682213723651e-324,
			ti = '0000-00-00 00:00:00', da = '0000-00-00',
			te = '', bo = false, js = '""', bl = '', e1 = 'v1', s1 = 'v2'
			;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(-math.MaxInt8 - 1), int16(-math.MaxInt16 - 1), int32(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
			uint8(0), uint16(0), uint32(0), uint64(0),
			float32(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
			types.Timestamp.Zero(), types.Date.Zero(),
			"", sql.False, types.MustJSON(`""`), []byte(""), uint(2), uint(4),
		}},
	},
	{
		WriteQuery: `INSERT INTO typestable SET
			id = 999, i8 = -128, i16 = -32768, i32 = -2147483648, i64 = -9223372036854775808,
			u8 = 0, u16 = 0, u32 = 0, u64 = 0,
			f32 = 1.401298464324817070923729583289916131280e-45, f64 = 4.940656458412465441765687928682213723651e-324,
			ti = '2037-04-05 12:51:36 -0000 UTC', da = '0000-00-00',
			te = '', bo = false, js = '""', bl = '', e1 = 'v1', s1 = 'v2'
			;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(-math.MaxInt8 - 1), int16(-math.MaxInt16 - 1), int32(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
			uint8(0), uint16(0), uint32(0), uint64(0),
			float32(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
			sql.MustConvert(types.Timestamp.Convert("2037-04-05 12:51:36")), types.Date.Zero(),
			"", sql.False, types.MustJSON(`""`), []byte(""), uint(2), uint(4),
		}},
	},
	{
		WriteQuery:          `INSERT INTO mytable (i,s) VALUES (10, 'NULL')`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 10;",
		ExpectedSelect:      []sql.Row{{int64(10), "NULL"}},
	},
	{
		WriteQuery: `INSERT INTO typestable VALUES (999, null, null, null, null, null, null, null, null,
			null, null, null, null, null, null, null, null, null, null);`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect:      []sql.Row{{int64(999), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}},
	},
	{
		WriteQuery:          `INSERT INTO typestable (id, ti, da) VALUES (999, '2021-09-1', '2021-9-01');`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT id, ti, da FROM typestable WHERE id = 999;",
		ExpectedSelect:      []sql.Row{{int64(999), sql.MustConvert(types.Timestamp.Convert("2021-09-01")), sql.MustConvert(types.Date.Convert("2021-09-01"))}},
	},
	{
		WriteQuery: `INSERT INTO typestable SET id=999, i8=null, i16=null, i32=null, i64=null, u8=null, u16=null, u32=null, u64=null,
			f32=null, f64=null, ti=null, da=null, te=null, bo=null, js=null, bl=null, e1=null, s1=null;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect:      []sql.Row{{int64(999), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}},
	},
	{
		WriteQuery:          "INSERT INTO mytable SELECT i+100,s FROM mytable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "second row"},
			{int64(3), "third row"},
			{int64(101), "first row"},
			{int64(102), "second row"},
			{int64(103), "third row"},
		},
	},
	{
		WriteQuery:          "INSERT INTO emptytable SELECT * FROM mytable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "second row"},
			{int64(3), "third row"},
		},
	},
	{
		WriteQuery:          "INSERT INTO emptytable SELECT * FROM mytable where mytable.i > 2",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i",
		ExpectedSelect: []sql.Row{
			{int64(3), "third row"},
		},
	},
	{
		WriteQuery:          "INSERT INTO niltable (i,f) SELECT i+10, NULL FROM mytable where mytable.i > 2",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM niltable where i > 10 ORDER BY i",
		ExpectedSelect: []sql.Row{
			{13, nil, nil, nil},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) SELECT i+10, 'new' FROM mytable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "second row"},
			{int64(3), "third row"},
			{int64(11), "new"},
			{int64(12), "new"},
			{int64(13), "new"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable SELECT i2+100, s2 FROM othertable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "second row"},
			{int64(3), "third row"},
			{int64(101), "third"},
			{int64(102), "second"},
			{int64(103), "first"},
		},
	},
	{
		WriteQuery:          "INSERT INTO emptytable (s,i) SELECT * FROM othertable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "third"},
			{int64(2), "second"},
			{int64(3), "first"},
		},
	},
	{
		WriteQuery:          "INSERT INTO emptytable (s,i) SELECT concat(m.s, o.s2), m.i FROM othertable o JOIN mytable m ON m.i=o.i2",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first rowthird"},
			{int64(2), "second rowsecond"},
			{int64(3), "third rowfirst"},
		},
	},
	{
		WriteQuery: `INSERT INTO emptytable (s,i) SELECT s,i from mytable where i = 1 
			union select s,i from mytable where i = 3`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(3), "third row"},
		},
	},
	{
		WriteQuery: `INSERT INTO emptytable (s,i) SELECT s,i from mytable where i = 1 
			union select s,i from mytable where i = 3 
			union select s,i from mytable where i > 2`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(3), "third row"},
		},
	},
	{
		WriteQuery: `INSERT INTO emptytable (s,i) 
			SELECT s,i from mytable where i = 1 
			union all select s,i+1 from mytable where i < 2 
			union all select s,i+2 from mytable where i in (1)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "first row"},
			{int64(3), "first row"},
		},
	},
	{
		WriteQuery:          "INSERT INTO emptytable (s,i) SELECT distinct s,i from mytable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM emptytable ORDER BY i,s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "second row"},
			{int64(3), "third row"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) SELECT (i + 10.0) / 10.0 + 10 + i, concat(s, ' new') FROM mytable",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{int64(1), "first row"},
			{int64(2), "second row"},
			{int64(3), "third row"},
			{int64(12), "first row new"},
			{int64(13), "second row new"},
			{int64(14), "third row new"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) SELECT CHAR_LENGTH(s), concat('numrows: ', count(*)) from mytable group by 1",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
			{9, "numrows: 2"},
			{10, "numrows: 1"},
		},
	},

	{
		WriteQuery:          "INSERT INTO mytable (i,s) SELECT CHAR_LENGTH(s), concat('numrows: ', count(*)) from mytable group by 1 HAVING CHAR_LENGTH(s)  > 9",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
			{10, "numrows: 1"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) SELECT i * 2, concat(s,s) from mytable order by 1 desc limit 1",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
			{6, "third rowthird row"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) SELECT i + 3, concat(s,s) from mytable order by 1 desc",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
			{4, "first rowfirst row"},
			{5, "second rowsecond row"},
			{6, "third rowthird row"},
		},
	},
	{
		WriteQuery: `INSERT INTO mytable (i,s) SELECT sub.i + 10, ot.s2 
				FROM othertable ot INNER JOIN 
					(SELECT i, i2, s2 FROM mytable INNER JOIN othertable ON i = i2) sub 
				ON sub.i = ot.i2 order by 1`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable where i > 10 ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{11, "third"},
			{12, "second"},
			{13, "first"},
		},
	},
	{
		WriteQuery: `INSERT INTO mytable (i,s) SELECT sub.i + 10, ot.s2 
				FROM (SELECT i, i2, s2 FROM mytable INNER JOIN othertable ON i = i2) sub
				INNER JOIN othertable ot ON sub.i = ot.i2 order by 1`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(3)}},
		SelectQuery:         "SELECT * FROM mytable where i > 10 ORDER BY i, s",
		ExpectedSelect: []sql.Row{
			{11, "third"},
			{12, "second"},
			{13, "first"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1, 'hello') ON DUPLICATE KEY UPDATE s='hello'",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 1",
		ExpectedSelect:      []sql.Row{{int64(1), "hello"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1, 'hello2') ON DUPLICATE KEY UPDATE s='hello3'",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 1",
		ExpectedSelect:      []sql.Row{{int64(1), "hello3"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1, 'hello') ON DUPLICATE KEY UPDATE i=10",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 10",
		ExpectedSelect:      []sql.Row{{int64(10), "first row"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1, 'hello2') ON DUPLICATE KEY UPDATE s='hello3'",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 1",
		ExpectedSelect:      []sql.Row{{int64(1), "hello3"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1, 'hello2'), (2, 'hello3'), (4, 'no conflict') ON DUPLICATE KEY UPDATE s='hello4'",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(5)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY 1",
		ExpectedSelect: []sql.Row{
			{1, "hello4"},
			{2, "hello4"},
			{3, "third row"},
			{4, "no conflict"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (10, 'hello') ON DUPLICATE KEY UPDATE s='hello'",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM mytable ORDER BY 1",
		ExpectedSelect: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"},
			{10, "hello"},
		},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1,'hi') ON DUPLICATE KEY UPDATE s=VALUES(s)",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 1",
		ExpectedSelect:      []sql.Row{{int64(1), "hi"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (s,i) values ('dup',1) ON DUPLICATE KEY UPDATE s=CONCAT(VALUES(s), 'licate')",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 1",
		ExpectedSelect:      []sql.Row{{int64(1), "duplicate"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1,'mar'), (2,'par') ON DUPLICATE KEY UPDATE s=CONCAT(VALUES(s), 'tial')",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(4)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i IN (1,2) ORDER BY i",
		ExpectedSelect:      []sql.Row{{int64(1), "martial"}, {int64(2), "partial"}},
	},
	{
		WriteQuery:          "INSERT INTO mytable (i,s) values (1,'maybe') ON DUPLICATE KEY UPDATE i=VALUES(i)+8000, s=VALUES(s)",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM mytable WHERE i = 8001",
		ExpectedSelect:      []sql.Row{{int64(8001), "maybe"}},
	},
	{
		WriteQuery:          "INSERT INTO auto_increment_tbl (c0) values (44)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 4}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl ORDER BY pk",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{4, 44},
		},
	},
	{
		WriteQuery:          "INSERT INTO auto_increment_tbl (c0) values (44),(55)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 4}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl ORDER BY pk",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{4, 44},
			{5, 55},
		},
	},
	{
		WriteQuery:          "INSERT INTO auto_increment_tbl values (NULL, 44)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 4}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl ORDER BY pk",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{4, 44},
		},
	},
	{
		WriteQuery:          "INSERT INTO auto_increment_tbl values (0, 44)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 4}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl ORDER BY pk",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{4, 44},
		},
	},
	{
		WriteQuery:          "INSERT INTO auto_increment_tbl values (5, 44)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 5}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl ORDER BY pk",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{5, 44},
		},
	},
	{
		WriteQuery: "INSERT INTO auto_increment_tbl values " +
			"(NULL, 44), (NULL, 55), (9, 99), (NULL, 110), (NULL, 121)",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 5, InsertID: 4}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl ORDER BY pk",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{4, 44},
			{5, 55},
			{9, 99},
			{10, 110},
			{11, 121},
		},
	},
	{
		WriteQuery:          `INSERT INTO auto_increment_tbl (c0) SELECT 44 FROM dual`,
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 4}}},
		SelectQuery:         "SELECT * FROM auto_increment_tbl",
		ExpectedSelect: []sql.Row{
			{1, 11},
			{2, 22},
			{3, 33},
			{4, 44},
		},
	},
	{
		WriteQuery:          `INSERT INTO othertable VALUES ("fourth", 1) ON DUPLICATE KEY UPDATE s2="fourth"`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM othertable",
		ExpectedSelect: []sql.Row{
			sql.NewRow("first", int64(3)),
			sql.NewRow("second", int64(2)),
			sql.NewRow("fourth", int64(1)),
		},
	},
	{
		WriteQuery:          `INSERT INTO othertable(S2,I2) values ('fourth',0)`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         `SELECT * FROM othertable where s2='fourth'`,
		ExpectedSelect: []sql.Row{
			{"fourth", 0},
		},
	},
	{
		WriteQuery: `INSERT INTO auto_increment_tbl VALUES ('4', 44)`,
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{InsertID: 4, RowsAffected: 1}},
		},
		SelectQuery: `SELECT * from auto_increment_tbl where pk=4`,
		ExpectedSelect: []sql.Row{
			{4, 44},
		},
	},
	{
		WriteQuery:          `INSERT INTO keyless (c0, c1) SELECT * from keyless where c0=0 and c1=0`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         `SELECT * from keyless where c0=0`,
		ExpectedSelect: []sql.Row{
			{0, 0},
			{0, 0},
		},
	},
	{
		WriteQuery:          `insert into keyless (c0, c1) select a.c0, a.c1 from (select 1, 1) as a(c0, c1) join keyless on a.c0 = keyless.c0`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         `SELECT * from keyless where c0=1`,
		ExpectedSelect: []sql.Row{
			{1, 1},
			{1, 1},
			{1, 1},
			{1, 1},
		},
	},
	{
		WriteQuery:          "with t (i,f) as (select 4,'fourth row' from dual) insert into mytable select i,f from t",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 1}}},
		SelectQuery:         "select * from mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "first row"),
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
			sql.NewRow(4, "fourth row"),
		},
	},
	{
		WriteQuery:          "with recursive t (i,f) as (select 4,4 from dual union all select i + 1, i + 1 from t where i < 5) insert into mytable select i,f from t",
		ExpectedWriteResult: []sql.Row{{types.OkResult{RowsAffected: 2}}},
		SelectQuery:         "select * from mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "first row"),
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
			sql.NewRow(4, "4"),
			sql.NewRow(5, "5"),
		},
	},
}
View Source
var InsertScripts = []ScriptTest{
	{

		Name: "issue 4857: insert cte column alias with table alias qualify panic",
		SetUpScript: []string{
			"create table xy (x int primary key, y int)",
			"insert into xy values (0,0), (1,1), (2,2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `With a as (
  With b as (
    Select sum(x) as x, y from xy where x < 2 group by y
  )
  Select * from b d
) insert into xy (x,y) select x+9,y+9 from a;`,
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 0}}},
			},
		},
	},
	{
		Name: "INSERT zero date DATETIME NOT NULL is valid",
		SetUpScript: []string{
			"CREATE TABLE t1 (dt datetime not null)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO t1 (dt) VALUES ('0001-01-01 00:00:00');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "insert into sparse auto_increment table",
		SetUpScript: []string{
			"create table auto (pk int primary key auto_increment)",
			"insert into auto values (10), (20), (30)",
			"insert into auto values (NULL)",
			"insert into auto values (40)",
			"insert into auto values (0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{10}, {20}, {30}, {31}, {40}, {41},
				},
			},
		},
	},
	{
		Name: "insert negative values into auto_increment values",
		SetUpScript: []string{
			"create table auto (pk int primary key auto_increment)",
			"insert into auto values (10), (20), (30)",
			"insert into auto values (-1), (-2), (-3)",
			"insert into auto () values ()",
			"insert into auto values (0), (0), (0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{-3}, {-2}, {-1}, {10}, {20}, {30}, {31}, {32}, {33}, {34},
				},
			},
		},
	},
	{
		Name: "insert into auto_increment unique key column",
		SetUpScript: []string{
			"create table auto (pk int primary key, npk int unique auto_increment)",
			"insert into auto (pk) values (10), (20), (30)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{10, 1}, {20, 2}, {30, 3},
				},
			},
		},
	},
	{
		Name: "insert into auto_increment with multiple unique key columns",
		SetUpScript: []string{
			"create table auto (pk int primary key, npk1 int auto_increment, npk2 int, unique(npk1, npk2))",
			"insert into auto (pk) values (10), (20), (30)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{10, 1, nil}, {20, 2, nil}, {30, 3, nil},
				},
			},
		},
	},
	{
		Name: "insert into auto_increment key/index column",
		SetUpScript: []string{
			"create table auto_no_primary (i int auto_increment, index(i))",
			"insert into auto_no_primary (i) values (0), (0), (0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto_no_primary order by 1",
				Expected: []sql.Row{
					{1}, {2}, {3},
				},
			},
		},
	},
	{
		Name: "insert into auto_increment with multiple key/index columns",
		SetUpScript: []string{
			"create table auto_no_primary (i int auto_increment, j int, index(i))",
			"insert into auto_no_primary (i) values (0), (0), (0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto_no_primary order by 1",
				Expected: []sql.Row{
					{1, nil}, {2, nil}, {3, nil},
				},
			},
		},
	},
	{
		Name: "auto increment table handles deletes",
		SetUpScript: []string{
			"create table auto (pk int primary key auto_increment)",
			"insert into auto values (10)",
			"delete from auto where pk = 10",
			"insert into auto values (NULL)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{11},
				},
			},
		},
	},
	{
		Name: "create auto_increment table with out-of-line primary key def",
		SetUpScript: []string{
			`create table auto (
				pk int auto_increment,
				c0 int,
				primary key(pk)
			);`,
			"insert into auto values (NULL,10), (NULL,20), (NULL,30)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1, 10}, {2, 20}, {3, 30},
				},
			},
		},
	},
	{
		Name: "alter auto_increment value",
		SetUpScript: []string{
			`create table auto (
				pk int auto_increment,
				c0 int,
				primary key(pk)
			);`,
			"insert into auto values (NULL,10), (NULL,20), (NULL,30)",
			"alter table auto auto_increment 9;",
			"insert into auto values (NULL,90)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1, 10}, {2, 20}, {3, 30}, {9, 90},
				},
			},
		},
	},
	{
		Name: "alter auto_increment value to float",
		SetUpScript: []string{
			`create table auto (
				pk int auto_increment,
				c0 int,
				primary key(pk)
			);`,
			"insert into auto values (NULL,10), (NULL,20), (NULL,30)",
			"alter table auto auto_increment = 19.9;",
			"insert into auto values (NULL,190)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1, 10}, {2, 20}, {3, 30}, {19, 190},
				},
			},
		},
	},
	{
		Name: "auto increment on tinyint",
		SetUpScript: []string{
			"create table auto (pk tinyint primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1}, {10}, {11},
				},
			},
		},
	},
	{
		Name: "auto increment on smallint",
		SetUpScript: []string{
			"create table auto (pk smallint primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1}, {10}, {11},
				},
			},
		},
	},
	{
		Name: "auto increment on mediumint",
		SetUpScript: []string{
			"create table auto (pk mediumint primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1}, {10}, {11},
				},
			},
		},
	},
	{
		Name: "auto increment on int",
		SetUpScript: []string{
			"create table auto (pk int primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1}, {10}, {11},
				},
			},
		},
	},
	{
		Name: "auto increment on bigint",
		SetUpScript: []string{
			"create table auto (pk bigint primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{1}, {10}, {11},
				},
			},
		},
	},
	{
		Name: "auto increment on tinyint unsigned",
		SetUpScript: []string{
			"create table auto (pk tinyint unsigned primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{uint64(1)}, {uint64(10)}, {uint64(11)},
				},
			},
		},
	},
	{
		Name: "auto increment on smallint unsigned",
		SetUpScript: []string{
			"create table auto (pk smallint unsigned primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{uint64(1)}, {uint64(10)}, {uint64(11)},
				},
			},
		},
	},
	{
		Name: "auto increment on mediumint unsigned",
		SetUpScript: []string{
			"create table auto (pk mediumint unsigned primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{uint64(1)}, {uint64(10)}, {uint64(11)},
				},
			},
		},
	},
	{
		Name: "auto increment on int unsigned",
		SetUpScript: []string{
			"create table auto (pk int unsigned primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{uint64(1)}, {uint64(10)}, {uint64(11)},
				},
			},
		},
	},
	{
		Name: "auto increment on bigint unsigned",
		SetUpScript: []string{
			"create table auto (pk bigint unsigned primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{uint64(1)}, {uint64(10)}, {uint64(11)},
				},
			},
		},
	},
	{
		Name: "auto increment on float",
		SetUpScript: []string{
			"create table auto (pk float primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{float64(1)}, {float64(10)}, {float64(11)},
				},
			},
		},
	},
	{
		Name: "auto increment on double",
		SetUpScript: []string{
			"create table auto (pk double primary key auto_increment)",
			"insert into auto values (NULL),(10),(0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from auto order by 1",
				Expected: []sql.Row{
					{float64(1)}, {float64(10)}, {float64(11)},
				},
			},
		},
	},
	{
		Name: "explicit DEFAULT",
		SetUpScript: []string{
			"CREATE TABLE t1(id int DEFAULT '2', dt datetime DEFAULT now());",
			"CREATE TABLE t2(id varchar(100) DEFAULT (uuid()));",
			"CREATE TABLE t3(a int DEFAULT '1', b int default (2 * a));",
			"CREATE TABLE t4(c0 varchar(10) null default 'c0', c1 varchar(10) null default 'c1');",

			"CREATE TABLE t5(c0 varchar(100) DEFAULT (repeat('_', 100)), c1 datetime DEFAULT current_timestamp());",

			"create table t6 (color enum('red', 'blue', 'green') default 'blue', createdAt timestamp default (current_timestamp()));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO T1 values (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "INSERT INTO t1 (id, dt) values (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "INSERT INTO t1 (dt, ID) values (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "INSERT INTO t1 (ID) values (DEFAULT), (3)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t1 (dt) values (DEFAULT), ('1981-02-16 00:00:00')",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t1 values (100, '2000-01-01 12:34:56'), (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t1 (id, dt) values (100, '2022-01-01 01:01:01'), (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t1 (id) values (10), (DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t1 (DT) values ('2022-02-02 02:02:02'), (DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t2 values ('10'), (DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2}}},
			},
			{
				Query:    "INSERT INTO t2 (id) values (DEFAULT), ('11'), (DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 3}}},
			},
			{
				Query:    "select count(distinct id) from t2",
				Expected: []sql.Row{{5}},
			},
			{
				Query:    "INSERT INTO t3 (a) values (DEFAULT), ('2'), (DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 3}}},
			},
			{
				Query:    "SELECT b from t3 order by b asc",
				Expected: []sql.Row{{2}, {2}, {4}},
			},
			{
				Query:    "INSERT INTO T4 (c1, c0) values (DEFAULT, NULL)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "select * from t4",
				Expected: []sql.Row{{nil, "c1"}},
			},
			{
				Query:    "INSERT INTO T5 values (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "INSERT INTO T5 (c0, c1) values (DEFAULT, DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "INSERT INTO T5 (c1) values (DEFAULT)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{

				Query:    "insert into T6(createdAt, color) values (DEFAULT, DEFAULT);",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
		},
	},
	{
		Name: "Try INSERT IGNORE with primary key, non null, and single row violations",
		SetUpScript: []string{
			"CREATE TABLE y (pk int primary key, c1 int NOT NULL);",
			"INSERT IGNORE INTO y VALUES (1, 1), (1,2), (2, 2), (3, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM y",
				Expected: []sql.Row{
					{1, 1}, {2, 2}, {3, 3},
				},
			},
			{
				Query: "INSERT IGNORE INTO y VALUES (1, 2), (4,4)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query: "INSERT IGNORE INTO y VALUES (5, NULL)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERBadNullError,
			},
			{
				Query: "INSERT IGNORE INTO y SELECT * FROM y WHERE pk=(SELECT pk+10 FROM y WHERE pk > 1);",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 0}},
				},
				ExpectedWarning: mysql.ERSubqueryNo1Row,
			},
			{
				Query: "INSERT IGNORE INTO y SELECT 10, 0 FROM dual WHERE 1=(SELECT 1 FROM dual UNION SELECT 2 FROM dual);",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 0}},
				},
				ExpectedWarning: mysql.ERSubqueryNo1Row,
			},
			{
				Query: "INSERT IGNORE INTO y SELECT 11, 0 FROM dual WHERE 1=(SELECT 1 FROM dual UNION SELECT 2 FROM dual) UNION SELECT 12, 0 FROM dual;",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERSubqueryNo1Row,
			},
			{
				Query: "INSERT IGNORE INTO y SELECT 13, 0 FROM dual UNION SELECT 14, 0 FROM dual WHERE 1=(SELECT 1 FROM dual UNION SELECT 2 FROM dual);",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
				ExpectedWarning: mysql.ERSubqueryNo1Row,
			},
			{
				Query: "INSERT IGNORE INTO y VALUES (3, 8)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 0}},
				},
				ExpectedWarning: mysql.ERDupEntry,
			},
		},
	},
	{
		Name: "INSERT Accumulator tests",
		SetUpScript: []string{
			"CREATE TABLE test(pk int primary key, val int)",
			"INSERT INTO test values (1,1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       `INSERT INTO test VALUES (2,2),(2,3)`,
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query:    `DELETE FROM test where pk = 1;`,
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query: `INSERT INTO test VALUES (1,1)`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
		},
	},
	{
		Name: "INSERT Case Sensitivity",
		SetUpScript: []string{
			"CREATE TABLE test (PK int PRIMARY KEY);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "insert into test(pk) values (1)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "INSERT string with exact char length but extra byte length",
		SetUpScript: []string{
			"CREATE TABLE city (id int PRIMARY KEY, district char(20) NOT NULL DEFAULT '');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO city VALUES (1,'San Pedro de Macorís');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "Insert on duplicate key",
		SetUpScript: []string{
			`CREATE TABLE users (
				id varchar(42) PRIMARY KEY
			)`,
			`CREATE TABLE nodes (
			    id varchar(42) PRIMARY KEY,
			    owner varchar(42),
			    status varchar(12),
			    timestamp bigint NOT NULL,
			    FOREIGN KEY(owner) REFERENCES users(id)
			)`,
			"INSERT INTO users values ('milo'), ('dabe')",
			"INSERT INTO nodes values ('id1', 'milo', 'off', 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into nodes(id,owner,status,timestamp) values('id1','dabe','off',2) on duplicate key update owner='milo',status='on'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "insert into nodes(id,owner,status,timestamp) values('id2','dabe','off',3) on duplicate key update owner='milo',status='on'",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query: "select * from nodes",
				Expected: []sql.Row{
					{"id1", "milo", "on", 1},
					{"id2", "dabe", "off", 3},
				},
			},
		},
	},
	{
		Name: "Insert on duplicate key references table in subquery",
		SetUpScript: []string{
			`create table a (i int primary key)`,
			`insert into a values (1)`,
			`create table b (j int primary key)`,
			`insert into b values (1), (2), (3)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into a (select * from b) on duplicate key update a.i = b.j + 100`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{101},
					{2},
					{3},
				},
			},
		},
	},
	{
		Name: "Insert on duplicate key references table in aliased subquery",
		SetUpScript: []string{
			`create table a (i int primary key)`,
			`insert into a values (1)`,
			`create table b (j int primary key)`,
			`insert into b values (1), (2), (3)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       `insert into a (select * from b as t) on duplicate key update a.i = b.j + 100`,
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query: `insert into a (select * from b as t) on duplicate key update a.i = t.j + 100`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{101},
					{2},
					{3},
				},
			},
		},
	},
	{
		Name: "insert on duplicate key update errors",
		SetUpScript: []string{
			`create table a (i int primary key)`,
			`create table b (i int primary key)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       `insert into a (select * from b) on duplicate key update i = i`,
				ExpectedErr: sql.ErrAmbiguousColumnName,
			},
			{
				Query:       `insert into a (select * from b) on duplicate key update b.i = a.i`,
				ExpectedErr: sql.ErrTableNotFound,
			},
		},
	},
	{
		Name: "Insert on duplicate key references table in subquery with join",
		SetUpScript: []string{
			`create table a (i int primary key, j int)`,
			`insert into a values (1,1)`,
			`create table b (x int primary key)`,
			`insert into b values (1), (2), (3)`,
			`create table c (y int primary key)`,
			`insert into c values (1), (2), (3)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into a (select * from b join c where b.x = c.y) on duplicate key update a.j = b.x + c.y + 100`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{1, 102},
					{2, 2},
					{3, 3},
				},
			},
		},
	},
	{
		Name: "Insert on duplicate key references table in subquery with alias",
		SetUpScript: []string{
			`create table a (i int primary key)`,
			`insert into a values (1)`,
			`create table b (i int primary key)`,
			`insert into b values (1), (2), (3)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into a (select t.i from b as t, b where t.i = b.i) on duplicate key update i = b.i;`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{1},
					{2},
					{3},
				},
			},
		},
	},
	{
		Name: "Insert on duplicate key references table in cte",
		SetUpScript: []string{
			`create table a (i int primary key)`,
			`insert into a values (1)`,
			`create table b (j int primary key)`,
			`insert into b values (1), (2), (3)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `insert into a with cte as (select * from b) select * from cte on duplicate key update a.i = cte.j + 100`,
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 4}},
				},
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{101},
					{2},
					{3},
				},
			},
		},
	},
	{
		Name: "Insert throws primary key violations",
		SetUpScript: []string{
			"CREATE TABLE t (pk int PRIMARY key);",
			"CREATE TABLE t2 (pk1 int, pk2 int, PRIMARY KEY (pk1, pk2));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO t VALUES (1), (2);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:       "INSERT into t VALUES (1);",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query:    "SELECT * from t;",
				Expected: []sql.Row{{1}, {2}},
			},
			{
				Query:    "INSERT into t2 VALUES (1, 1), (2, 2);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:       "INSERT into t2 VALUES (1, 1);",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
		},
	},
	{
		Name: "Insert throws unique key violations",
		SetUpScript: []string{
			"CREATE TABLE t (pk int PRIMARY key, col1 int UNIQUE);",
			"CREATE TABLE t2 (pk int PRIMARY key, col1 int, col2 int, UNIQUE KEY (col1, col2));",
			"INSERT into t VALUES (1, 1);",
			"INSERT into t2 VALUES (1, 1, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "INSERT INTO t VALUES (2, 2), (3, 1), (4, 4);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:       "INSERT INTO t2 VALUES (2, 2, 2), (3, 1, 1), (4, 4, 4);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1, 1}},
			},
			{
				Query:       "INSERT INTO t VALUES (5, 2), (6, 2);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:       "INSERT INTO t2 VALUES (5, 2, 2), (6, 2, 2);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1, 1}},
			},
			{
				Query:    "INSERT into t2 VALUES (5, NULL, 1), (6, NULL, 1), (7, 1, NULL), (8, 1, NULL), (9, NULL, NULL), (10, NULL, NULL)",
				Expected: []sql.Row{{types.NewOkResult(6)}},
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1, 1}, {5, nil, 1}, {6, nil, 1}, {7, 1, nil}, {8, 1, nil}, {9, nil, nil}, {10, nil, nil}},
			},
		},
	},
	{
		Name: "Insert throws unique key violations for keyless tables",
		SetUpScript: []string{
			"CREATE TABLE t (not_pk int NOT NULL, col1 int UNIQUE);",
			"CREATE TABLE t2 (not_pk int NOT NULL, col1 int, col2 int, UNIQUE KEY (col1, col2));",
			"INSERT into t VALUES (1, 1);",
			"INSERT into t2 VALUES (1, 1, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "INSERT INTO t VALUES (2, 2), (3, 1), (4, 4);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:       "INSERT INTO t2 VALUES (2, 2, 2), (3, 1, 1), (4, 4, 4);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1, 1}},
			},
			{
				Query:       "INSERT INTO t VALUES (5, 2), (6, 2);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t;",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:       "INSERT INTO t2 VALUES (5, 2, 2), (6, 2, 2);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1, 1}},
			},
			{
				Query:    "INSERT into t2 VALUES (5, NULL, 1), (6, NULL, 1), (7, 1, NULL), (8, 1, NULL), (9, NULL, NULL), (10, NULL, NULL)",
				Expected: []sql.Row{{types.NewOkResult(6)}},
			},
			{
				Query:    "SELECT * from t2;",
				Expected: []sql.Row{{1, 1, 1}, {5, nil, 1}, {6, nil, 1}, {7, 1, nil}, {8, 1, nil}, {9, nil, nil}, {10, nil, nil}},
			},
		},
	},
	{
		Name: "Insert into unique key that overlaps with primary key",
		SetUpScript: []string{
			"CREATE TABLE t (pk1 int, pk2 int, col int, PRIMARY KEY(pk1, pk2), UNIQUE KEY(col, pk2));",
			"INSERT into t (pk1, pk2, col) VALUES (1, 1, 1), (2, 1, 2);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "INSERT INTO t (pk1, pk2, col) VALUES (3, 1, 1);",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
			{
				Query:       "UPDATE t SET col = col + 1",
				ExpectedErr: sql.ErrUniqueKeyViolation,
			},
		},
	},
	{
		Name: "INSERT INTO ... SELECT works properly with ENUM",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY NOT NULL, v1 ENUM('a','b','c'));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO test (pk, v1) VALUES (1, 'a');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO test (pk, v1) SELECT 2 as pk, 'a' as v1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "INSERT INTO ... SELECT works properly with SET",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY NOT NULL, v1 SET('a','b','c'));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO test (pk, v1) VALUES (1, 'a');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "INSERT INTO test (pk, v1) SELECT 2 as pk, 'a' as v1;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{

		Name: "Defaults with escaped strings",
		SetUpScript: []string{
			`CREATE TABLE escpe (
                               id int NOT NULL AUTO_INCREMENT,
                               t1 varchar(15) DEFAULT 'foo''s baz',
                               t2 varchar(15) DEFAULT 'who\'s dat',
                               t3 varchar(15) DEFAULT "joe\'s bar",
                               t4 varchar(15) DEFAULT "quote""bazzar",
                               t5 varchar(15) DEFAULT 'back\\''slash',
                               t6 varchar(15) DEFAULT 'tab\ttab',
                               t7 varchar(15) DEFAULT 'new\nline',
                               PRIMARY KEY (id)
                     );`,
			"INSERT INTO escpe VALUES ();",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT t1 from escpe",
				Expected: []sql.Row{{"foo's baz"}},
			},
			{
				Query:    "SELECT t2 from escpe",
				Expected: []sql.Row{{"who's dat"}},
			},
			{
				Query:    "SELECT t3 from escpe",
				Expected: []sql.Row{{"joe's bar"}},
			},
			{
				Query:    "SELECT t4 from escpe",
				Expected: []sql.Row{{"quote\"bazzar"}},
			},
			{
				Query:    "SELECT t5 from escpe",
				Expected: []sql.Row{{"back\\'slash"}},
			},
			{
				Query:    "SELECT t6 from escpe",
				Expected: []sql.Row{{"tab\ttab"}},
			},
			{
				Query:    "SELECT t7 from escpe",
				Expected: []sql.Row{{"new\nline"}},
			},
		},
	},
	{

		Name: "check constrains with escaped strings",
		SetUpScript: []string{
			`CREATE TABLE quoted ( id int NOT NULL AUTO_INCREMENT,
                                   val varchar(15) NOT NULL CHECK (val IN ('joe''s',
                                                                           "jan's",
                                                                           'mia\\''s',
                                                                           'bob\'s',
                                                                           'tab\tvs\tcoke',
                                                                           'percent\%')),
                                   PRIMARY KEY (id));`,
			`INSERT INTO quoted VALUES (0,"joe's");`,
			`INSERT INTO quoted VALUES (0,"jan's");`,
			`INSERT INTO quoted VALUES (0,"mia\\'s");`,
			`INSERT INTO quoted VALUES (0,"bob's");`,
			`INSERT INTO quoted VALUES (0,"tab\tvs\tcoke");`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT val from quoted order by id",
				Expected: []sql.Row{
					{"joe's"},
					{"jan's"},
					{"mia\\'s"},
					{"bob's"},
					{"tab\tvs\tcoke"}},
			},
		},
	},
}
View Source
var IntegrationPlanTests = []QueryPlanTest{
	{
		Query: `
SELECT
    id, FTQLQ
FROM
    YK2GW
WHERE
    id NOT IN (SELECT IXUXU FROM THNTS)
;`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [YK2GW.id:0!null, YK2GW.FTQLQ:1!null]\n" +
			" └─ AntiLookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ YK2GW.id:0!null\n" +
			"     │   └─ applySubq0.IXUXU:30\n" +
			"     ├─ Table\n" +
			"     │   ├─ name: YK2GW\n" +
			"     │   └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"     └─ TableAlias(applySubq0)\n" +
			"         └─ IndexedTableAccess(THNTS)\n" +
			"             ├─ index: [THNTS.IXUXU]\n" +
			"             └─ columns: [ixuxu]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   PBMRX.id AS id,
	   PBMRX.TW55N AS TEYBZ,
	   PBMRX.ZH72S AS FB6N7
	FROM
	   (
	       SELECT
	           ZH72S AS ZH72S,
	           COUNT(ZH72S) AS JTOA7,
	           MIN(WGBRL) AS TTDPM,
	           SUM(WGBRL) AS FBSRS
	       FROM
	           (
	           SELECT
	               nd.id AS id,
	               nd.ZH72S AS ZH72S,
	               (SELECT COUNT(*) FROM HDDVB WHERE UJ6XY = nd.id) AS WGBRL
	           FROM
	               E2I7U nd
	           WHERE nd.ZH72S IS NOT NULL
	           ) CCEFL
	       GROUP BY
	           ZH72S
	       HAVING
	           JTOA7 > 1
	   ) CL3DT
	INNER JOIN
	   E2I7U PBMRX
	ON
	   PBMRX.ZH72S IS NOT NULL AND PBMRX.ZH72S = CL3DT.ZH72S
	WHERE
	       CL3DT.TTDPM = 0
	   AND
	       CL3DT.FBSRS > 0
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [PBMRX.id:4!null as id, PBMRX.TW55N:5!null as TEYBZ, PBMRX.ZH72S:6 as FB6N7]\n" +
			" └─ LookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ PBMRX.ZH72S:6\n" +
			"     │   └─ CL3DT.ZH72S:0\n" +
			"     ├─ SubqueryAlias\n" +
			"     │   ├─ name: CL3DT\n" +
			"     │   ├─ outerVisibility: false\n" +
			"     │   ├─ cacheable: true\n" +
			"     │   └─ Filter\n" +
			"     │       ├─ AND\n" +
			"     │       │   ├─ Eq\n" +
			"     │       │   │   ├─ TTDPM:2!null\n" +
			"     │       │   │   └─ 0 (tinyint)\n" +
			"     │       │   └─ GreaterThan\n" +
			"     │       │       ├─ FBSRS:3!null\n" +
			"     │       │       └─ 0 (tinyint)\n" +
			"     │       └─ Having\n" +
			"     │           ├─ GreaterThan\n" +
			"     │           │   ├─ JTOA7:1!null\n" +
			"     │           │   └─ 1 (tinyint)\n" +
			"     │           └─ Project\n" +
			"     │               ├─ columns: [ZH72S:0, COUNT(CCEFL.ZH72S):1!null as JTOA7, MIN(CCEFL.WGBRL):2!null as TTDPM, SUM(CCEFL.WGBRL):3!null as FBSRS]\n" +
			"     │               └─ GroupBy\n" +
			"     │                   ├─ select: ZH72S:0, COUNT(CCEFL.ZH72S:2), MIN(CCEFL.WGBRL:1), SUM(CCEFL.WGBRL:1)\n" +
			"     │                   ├─ group: ZH72S:0\n" +
			"     │                   └─ Project\n" +
			"     │                       ├─ columns: [CCEFL.ZH72S:1 as ZH72S, CCEFL.WGBRL:2, CCEFL.ZH72S:1]\n" +
			"     │                       └─ SubqueryAlias\n" +
			"     │                           ├─ name: CCEFL\n" +
			"     │                           ├─ outerVisibility: false\n" +
			"     │                           ├─ cacheable: true\n" +
			"     │                           └─ Project\n" +
			"     │                               ├─ columns: [nd.id:0!null as id, nd.ZH72S:7 as ZH72S, Subquery\n" +
			"     │                               │   ├─ cacheable: false\n" +
			"     │                               │   └─ Project\n" +
			"     │                               │       ├─ columns: [COUNT(1):17!null as COUNT(*)]\n" +
			"     │                               │       └─ GroupBy\n" +
			"     │                               │           ├─ select: COUNT(1 (bigint))\n" +
			"     │                               │           ├─ group: \n" +
			"     │                               │           └─ Filter\n" +
			"     │                               │               ├─ Eq\n" +
			"     │                               │               │   ├─ HDDVB.UJ6XY:17!null\n" +
			"     │                               │               │   └─ nd.id:0!null\n" +
			"     │                               │               └─ Table\n" +
			"     │                               │                   ├─ name: HDDVB\n" +
			"     │                               │                   └─ columns: [uj6xy]\n" +
			"     │                               │   as WGBRL]\n" +
			"     │                               └─ Filter\n" +
			"     │                                   ├─ NOT\n" +
			"     │                                   │   └─ nd.ZH72S:7 IS NULL\n" +
			"     │                                   └─ TableAlias(nd)\n" +
			"     │                                       └─ IndexedTableAccess(E2I7U)\n" +
			"     │                                           ├─ index: [E2I7U.ZH72S]\n" +
			"     │                                           ├─ static: [{(NULL, ∞)}]\n" +
			"     │                                           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     └─ Filter\n" +
			"         ├─ NOT\n" +
			"         │   └─ PBMRX.ZH72S:2 IS NULL\n" +
			"         └─ TableAlias(PBMRX)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.ZH72S]\n" +
			"                 └─ columns: [id tw55n zh72s]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ism.*
	FROM
	   HDDVB ism
	WHERE
	(
	       ism.PRUV2 IS NOT NULL
	   AND
	       (
	               (SELECT NHMXW.SWCQV FROM WGSDC NHMXW WHERE NHMXW.id = ism.PRUV2) = 1
	           OR
	               (
	                       (
	                           ism.FV24E IS NOT NULL
	                       AND
	                           (SELECT nd.id FROM E2I7U nd WHERE nd.TW55N =
	                               (SELECT NHMXW.FZXV5 FROM WGSDC NHMXW
	                               WHERE NHMXW.id = ism.PRUV2))
	                           <> ism.FV24E
	                       )
	                   OR
	                       (
	                           ism.UJ6XY IS NOT NULL
	                       AND
	                           (SELECT nd.id FROM E2I7U nd WHERE nd.TW55N =
	                               (SELECT NHMXW.DQYGV FROM WGSDC NHMXW
	                               WHERE NHMXW.id = ism.PRUV2))
	                           <> ism.UJ6XY
	                       )
	               )
	       )
	)
	OR
	(
	       ism.ETPQV IS NOT NULL
	   AND
	       ism.ETPQV IN
	       (
	       SELECT
	           TIZHK.id AS FWATE
	       FROM
	           WGSDC NHMXW
	       INNER JOIN
	           WRZVO TIZHK
	       ON
	               TIZHK.TVNW2 = NHMXW.NOHHR
	           AND
	               TIZHK.ZHITY = NHMXW.AVPYF
	           AND
	               TIZHK.SYPKF = NHMXW.SYPKF
	           AND
	               TIZHK.IDUT2 = NHMXW.IDUT2
	       WHERE
	               NHMXW.SWCQV = 0
	           AND
	               NHMXW.id NOT IN (SELECT PRUV2 FROM HDDVB WHERE PRUV2 IS NOT NULL)
	       )
	)
	`,
		ExpectedPlan: "Filter\n" +
			" ├─ Or\n" +
			" │   ├─ AND\n" +
			" │   │   ├─ NOT\n" +
			" │   │   │   └─ ism.PRUV2:6 IS NULL\n" +
			" │   │   └─ Or\n" +
			" │   │       ├─ Eq\n" +
			" │   │       │   ├─ Subquery\n" +
			" │   │       │   │   ├─ cacheable: false\n" +
			" │   │       │   │   └─ Project\n" +
			" │   │       │   │       ├─ columns: [NHMXW.SWCQV:10!null]\n" +
			" │   │       │   │       └─ Filter\n" +
			" │   │       │   │           ├─ Eq\n" +
			" │   │       │   │           │   ├─ NHMXW.id:9!null\n" +
			" │   │       │   │           │   └─ ism.PRUV2:6\n" +
			" │   │       │   │           └─ TableAlias(NHMXW)\n" +
			" │   │       │   │               └─ Table\n" +
			" │   │       │   │                   ├─ name: WGSDC\n" +
			" │   │       │   │                   └─ columns: [id swcqv]\n" +
			" │   │       │   └─ 1 (tinyint)\n" +
			" │   │       └─ Or\n" +
			" │   │           ├─ AND\n" +
			" │   │           │   ├─ NOT\n" +
			" │   │           │   │   └─ ism.FV24E:1!null IS NULL\n" +
			" │   │           │   └─ NOT\n" +
			" │   │           │       └─ Eq\n" +
			" │   │           │           ├─ Subquery\n" +
			" │   │           │           │   ├─ cacheable: false\n" +
			" │   │           │           │   └─ Project\n" +
			" │   │           │           │       ├─ columns: [nd.id:9!null]\n" +
			" │   │           │           │       └─ Filter\n" +
			" │   │           │           │           ├─ Eq\n" +
			" │   │           │           │           │   ├─ nd.TW55N:12!null\n" +
			" │   │           │           │           │   └─ Subquery\n" +
			" │   │           │           │           │       ├─ cacheable: false\n" +
			" │   │           │           │           │       └─ Project\n" +
			" │   │           │           │           │           ├─ columns: [NHMXW.FZXV5:27]\n" +
			" │   │           │           │           │           └─ Filter\n" +
			" │   │           │           │           │               ├─ Eq\n" +
			" │   │           │           │           │               │   ├─ NHMXW.id:26!null\n" +
			" │   │           │           │           │               │   └─ ism.PRUV2:6\n" +
			" │   │           │           │           │               └─ TableAlias(NHMXW)\n" +
			" │   │           │           │           │                   └─ Table\n" +
			" │   │           │           │           │                       ├─ name: WGSDC\n" +
			" │   │           │           │           │                       └─ columns: [id fzxv5]\n" +
			" │   │           │           │           └─ TableAlias(nd)\n" +
			" │   │           │           │               └─ Table\n" +
			" │   │           │           │                   ├─ name: E2I7U\n" +
			" │   │           │           │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │   │           │           └─ ism.FV24E:1!null\n" +
			" │   │           └─ AND\n" +
			" │   │               ├─ NOT\n" +
			" │   │               │   └─ ism.UJ6XY:2!null IS NULL\n" +
			" │   │               └─ NOT\n" +
			" │   │                   └─ Eq\n" +
			" │   │                       ├─ Subquery\n" +
			" │   │                       │   ├─ cacheable: false\n" +
			" │   │                       │   └─ Project\n" +
			" │   │                       │       ├─ columns: [nd.id:9!null]\n" +
			" │   │                       │       └─ Filter\n" +
			" │   │                       │           ├─ Eq\n" +
			" │   │                       │           │   ├─ nd.TW55N:12!null\n" +
			" │   │                       │           │   └─ Subquery\n" +
			" │   │                       │           │       ├─ cacheable: false\n" +
			" │   │                       │           │       └─ Project\n" +
			" │   │                       │           │           ├─ columns: [NHMXW.DQYGV:27]\n" +
			" │   │                       │           │           └─ Filter\n" +
			" │   │                       │           │               ├─ Eq\n" +
			" │   │                       │           │               │   ├─ NHMXW.id:26!null\n" +
			" │   │                       │           │               │   └─ ism.PRUV2:6\n" +
			" │   │                       │           │               └─ TableAlias(NHMXW)\n" +
			" │   │                       │           │                   └─ Table\n" +
			" │   │                       │           │                       ├─ name: WGSDC\n" +
			" │   │                       │           │                       └─ columns: [id dqygv]\n" +
			" │   │                       │           └─ TableAlias(nd)\n" +
			" │   │                       │               └─ Table\n" +
			" │   │                       │                   ├─ name: E2I7U\n" +
			" │   │                       │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │   │                       └─ ism.UJ6XY:2!null\n" +
			" │   └─ AND\n" +
			" │       ├─ NOT\n" +
			" │       │   └─ ism.ETPQV:5 IS NULL\n" +
			" │       └─ InSubquery\n" +
			" │           ├─ left: ism.ETPQV:5\n" +
			" │           └─ right: Subquery\n" +
			" │               ├─ cacheable: true\n" +
			" │               └─ Project\n" +
			" │                   ├─ columns: [TIZHK.id:19!null as FWATE]\n" +
			" │                   └─ Filter\n" +
			" │                       ├─ NOT\n" +
			" │                       │   └─ InSubquery\n" +
			" │                       │       ├─ left: NHMXW.id:9!null\n" +
			" │                       │       └─ right: Subquery\n" +
			" │                       │           ├─ cacheable: true\n" +
			" │                       │           └─ Filter\n" +
			" │                       │               ├─ NOT\n" +
			" │                       │               │   └─ HDDVB.PRUV2:29 IS NULL\n" +
			" │                       │               └─ IndexedTableAccess(HDDVB)\n" +
			" │                       │                   ├─ index: [HDDVB.PRUV2]\n" +
			" │                       │                   ├─ static: [{(NULL, ∞)}]\n" +
			" │                       │                   └─ columns: [pruv2]\n" +
			" │                       └─ LookupJoin\n" +
			" │                           ├─ AND\n" +
			" │                           │   ├─ AND\n" +
			" │                           │   │   ├─ AND\n" +
			" │                           │   │   │   ├─ Eq\n" +
			" │                           │   │   │   │   ├─ TIZHK.TVNW2:20\n" +
			" │                           │   │   │   │   └─ NHMXW.NOHHR:10!null\n" +
			" │                           │   │   │   └─ Eq\n" +
			" │                           │   │   │       ├─ TIZHK.ZHITY:21\n" +
			" │                           │   │   │       └─ NHMXW.AVPYF:11!null\n" +
			" │                           │   │   └─ Eq\n" +
			" │                           │   │       ├─ TIZHK.SYPKF:22\n" +
			" │                           │   │       └─ NHMXW.SYPKF:12!null\n" +
			" │                           │   └─ Eq\n" +
			" │                           │       ├─ TIZHK.IDUT2:23\n" +
			" │                           │       └─ NHMXW.IDUT2:13!null\n" +
			" │                           ├─ Filter\n" +
			" │                           │   ├─ Eq\n" +
			" │                           │   │   ├─ NHMXW.SWCQV:16!null\n" +
			" │                           │   │   └─ 0 (tinyint)\n" +
			" │                           │   └─ TableAlias(NHMXW)\n" +
			" │                           │       └─ Table\n" +
			" │                           │           ├─ name: WGSDC\n" +
			" │                           │           └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			" │                           └─ TableAlias(TIZHK)\n" +
			" │                               └─ IndexedTableAccess(WRZVO)\n" +
			" │                                   ├─ index: [WRZVO.TVNW2]\n" +
			" │                                   └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			" └─ TableAlias(ism)\n" +
			"     └─ Table\n" +
			"         ├─ name: HDDVB\n" +
			"         └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   TIZHK.*
	FROM
	   WRZVO TIZHK
	WHERE id IN
	   (
	       SELECT /*+ JOIN_ORDER( J4JYP, TIZHK, RHUZN, mf, aac ) */DISTINCT
	           TIZHK.id
	       FROM
	           WRZVO TIZHK
	       INNER JOIN
	           E2I7U J4JYP
	       ON
	           J4JYP.ZH72S = TIZHK.TVNW2
	       INNER JOIN
	           E2I7U RHUZN
	       ON
	           RHUZN.ZH72S = TIZHK.ZHITY
	       INNER JOIN
	           HGMQ6 mf ON mf.LUEVY = J4JYP.id
	       INNER JOIN
	           TPXBU aac ON aac.id = mf.M22QN
	       WHERE
	           aac.BTXC5 = TIZHK.SYPKF
	   )
	   AND
	       TIZHK.id NOT IN (SELECT ETPQV FROM HDDVB)
	`,
		ExpectedPlan: "AntiLookupJoin\n" +
			" ├─ Eq\n" +
			" │   ├─ TIZHK.id:0!null\n" +
			" │   └─ applySubq1.ETPQV:10\n" +
			" ├─ RightSemiLookupJoin\n" +
			" │   ├─ Eq\n" +
			" │   │   ├─ TIZHK.id:1!null\n" +
			" │   │   └─ applySubq0.id:0!null\n" +
			" │   ├─ Distinct\n" +
			" │   │   └─ SubqueryAlias\n" +
			" │   │       ├─ name: applySubq0\n" +
			" │   │       ├─ outerVisibility: false\n" +
			" │   │       ├─ cacheable: true\n" +
			" │   │       └─ Distinct\n" +
			" │   │           └─ Project\n" +
			" │   │               ├─ columns: [TIZHK.id:17!null]\n" +
			" │   │               └─ Filter\n" +
			" │   │                   ├─ Eq\n" +
			" │   │                   │   ├─ aac.BTXC5:62\n" +
			" │   │                   │   └─ TIZHK.SYPKF:20\n" +
			" │   │                   └─ LookupJoin\n" +
			" │   │                       ├─ Eq\n" +
			" │   │                       │   ├─ aac.id:61!null\n" +
			" │   │                       │   └─ mf.M22QN:47!null\n" +
			" │   │                       ├─ LookupJoin\n" +
			" │   │                       │   ├─ Eq\n" +
			" │   │                       │   │   ├─ mf.LUEVY:46!null\n" +
			" │   │                       │   │   └─ J4JYP.id:0!null\n" +
			" │   │                       │   ├─ LookupJoin\n" +
			" │   │                       │   │   ├─ Eq\n" +
			" │   │                       │   │   │   ├─ RHUZN.ZH72S:34\n" +
			" │   │                       │   │   │   └─ TIZHK.ZHITY:19\n" +
			" │   │                       │   │   ├─ LookupJoin\n" +
			" │   │                       │   │   │   ├─ Eq\n" +
			" │   │                       │   │   │   │   ├─ J4JYP.ZH72S:7\n" +
			" │   │                       │   │   │   │   └─ TIZHK.TVNW2:18\n" +
			" │   │                       │   │   │   ├─ TableAlias(J4JYP)\n" +
			" │   │                       │   │   │   │   └─ Table\n" +
			" │   │                       │   │   │   │       ├─ name: E2I7U\n" +
			" │   │                       │   │   │   │       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │   │                       │   │   │   └─ TableAlias(TIZHK)\n" +
			" │   │                       │   │   │       └─ IndexedTableAccess(WRZVO)\n" +
			" │   │                       │   │   │           ├─ index: [WRZVO.TVNW2]\n" +
			" │   │                       │   │   │           └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			" │   │                       │   │   └─ TableAlias(RHUZN)\n" +
			" │   │                       │   │       └─ IndexedTableAccess(E2I7U)\n" +
			" │   │                       │   │           ├─ index: [E2I7U.ZH72S]\n" +
			" │   │                       │   │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │   │                       │   └─ TableAlias(mf)\n" +
			" │   │                       │       └─ IndexedTableAccess(HGMQ6)\n" +
			" │   │                       │           ├─ index: [HGMQ6.LUEVY]\n" +
			" │   │                       │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			" │   │                       └─ TableAlias(aac)\n" +
			" │   │                           └─ IndexedTableAccess(TPXBU)\n" +
			" │   │                               ├─ index: [TPXBU.id]\n" +
			" │   │                               └─ columns: [id btxc5 fhcyt]\n" +
			" │   └─ TableAlias(TIZHK)\n" +
			" │       └─ IndexedTableAccess(WRZVO)\n" +
			" │           ├─ index: [WRZVO.id]\n" +
			" │           └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			" └─ TableAlias(applySubq1)\n" +
			"     └─ IndexedTableAccess(HDDVB)\n" +
			"         ├─ index: [HDDVB.ETPQV]\n" +
			"         └─ columns: [etpqv]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   TIZHK.*
	FROM
	   WRZVO TIZHK
	WHERE id IN
	   (
	       SELECT DISTINCT
	           TIZHK.id
	       FROM
	           WRZVO TIZHK
	       INNER JOIN
	           E2I7U J4JYP
	       ON
	           J4JYP.ZH72S = TIZHK.TVNW2
	       INNER JOIN
	           E2I7U RHUZN
	       ON
	           RHUZN.ZH72S = TIZHK.ZHITY
	       INNER JOIN
	           HGMQ6 mf ON mf.LUEVY = J4JYP.id
	       INNER JOIN
	           TPXBU aac ON aac.id = mf.M22QN
	       WHERE
	           aac.BTXC5 = TIZHK.SYPKF
	   )
	   AND
	       TIZHK.id NOT IN (SELECT ETPQV FROM HDDVB)
	`,
		ExpectedPlan: "AntiLookupJoin\n" +
			" ├─ Eq\n" +
			" │   ├─ TIZHK.id:0!null\n" +
			" │   └─ applySubq1.ETPQV:10\n" +
			" ├─ RightSemiLookupJoin\n" +
			" │   ├─ Eq\n" +
			" │   │   ├─ TIZHK.id:1!null\n" +
			" │   │   └─ applySubq0.id:0!null\n" +
			" │   ├─ Distinct\n" +
			" │   │   └─ SubqueryAlias\n" +
			" │   │       ├─ name: applySubq0\n" +
			" │   │       ├─ outerVisibility: false\n" +
			" │   │       ├─ cacheable: true\n" +
			" │   │       └─ Distinct\n" +
			" │   │           └─ Project\n" +
			" │   │               ├─ columns: [TIZHK.id:37!null]\n" +
			" │   │               └─ Filter\n" +
			" │   │                   ├─ Eq\n" +
			" │   │                   │   ├─ aac.BTXC5:35\n" +
			" │   │                   │   └─ TIZHK.SYPKF:40\n" +
			" │   │                   └─ LookupJoin\n" +
			" │   │                       ├─ Eq\n" +
			" │   │                       │   ├─ RHUZN.ZH72S:54\n" +
			" │   │                       │   └─ TIZHK.ZHITY:39\n" +
			" │   │                       ├─ LookupJoin\n" +
			" │   │                       │   ├─ Eq\n" +
			" │   │                       │   │   ├─ J4JYP.ZH72S:7\n" +
			" │   │                       │   │   └─ TIZHK.TVNW2:38\n" +
			" │   │                       │   ├─ LookupJoin\n" +
			" │   │                       │   │   ├─ Eq\n" +
			" │   │                       │   │   │   ├─ aac.id:34!null\n" +
			" │   │                       │   │   │   └─ mf.M22QN:20!null\n" +
			" │   │                       │   │   ├─ LookupJoin\n" +
			" │   │                       │   │   │   ├─ Eq\n" +
			" │   │                       │   │   │   │   ├─ mf.LUEVY:19!null\n" +
			" │   │                       │   │   │   │   └─ J4JYP.id:0!null\n" +
			" │   │                       │   │   │   ├─ TableAlias(J4JYP)\n" +
			" │   │                       │   │   │   │   └─ Table\n" +
			" │   │                       │   │   │   │       ├─ name: E2I7U\n" +
			" │   │                       │   │   │   │       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │   │                       │   │   │   └─ TableAlias(mf)\n" +
			" │   │                       │   │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			" │   │                       │   │   │           ├─ index: [HGMQ6.LUEVY]\n" +
			" │   │                       │   │   │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			" │   │                       │   │   └─ TableAlias(aac)\n" +
			" │   │                       │   │       └─ IndexedTableAccess(TPXBU)\n" +
			" │   │                       │   │           ├─ index: [TPXBU.id]\n" +
			" │   │                       │   │           └─ columns: [id btxc5 fhcyt]\n" +
			" │   │                       │   └─ TableAlias(TIZHK)\n" +
			" │   │                       │       └─ IndexedTableAccess(WRZVO)\n" +
			" │   │                       │           ├─ index: [WRZVO.TVNW2]\n" +
			" │   │                       │           └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			" │   │                       └─ TableAlias(RHUZN)\n" +
			" │   │                           └─ IndexedTableAccess(E2I7U)\n" +
			" │   │                               ├─ index: [E2I7U.ZH72S]\n" +
			" │   │                               └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │   └─ TableAlias(TIZHK)\n" +
			" │       └─ IndexedTableAccess(WRZVO)\n" +
			" │           ├─ index: [WRZVO.id]\n" +
			" │           └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			" └─ TableAlias(applySubq1)\n" +
			"     └─ IndexedTableAccess(HDDVB)\n" +
			"         ├─ index: [HDDVB.ETPQV]\n" +
			"         └─ columns: [etpqv]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   PBMRX.id AS id,
	   PBMRX.TW55N AS TEYBZ,
	   PBMRX.ZH72S AS FB6N7
	FROM
	   (
	       SELECT
	           ZH72S AS ZH72S,
	           COUNT(ZH72S) AS JTOA7,
	           MIN(LEA4J) AS BADTB,
	           SUM(LEA4J) AS FLHXH
	       FROM
	           (
	           SELECT
	               nd.id AS id,
	               nd.ZH72S AS ZH72S,
	               (SELECT COUNT(*) FROM FLQLP WHERE LUEVY = nd.id) AS LEA4J
	           FROM
	               E2I7U nd
	           WHERE nd.ZH72S IS NOT NULL
	           ) WOOJ5
	       GROUP BY
	           ZH72S
	       HAVING
	           JTOA7 > 1
	   ) CL3DT
	INNER JOIN
	   E2I7U PBMRX
	ON
	   PBMRX.ZH72S IS NOT NULL AND PBMRX.ZH72S = CL3DT.ZH72S
	WHERE
	       CL3DT.BADTB = 0
	   AND
	       CL3DT.FLHXH > 0
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [PBMRX.id:4!null as id, PBMRX.TW55N:5!null as TEYBZ, PBMRX.ZH72S:6 as FB6N7]\n" +
			" └─ LookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ PBMRX.ZH72S:6\n" +
			"     │   └─ CL3DT.ZH72S:0\n" +
			"     ├─ SubqueryAlias\n" +
			"     │   ├─ name: CL3DT\n" +
			"     │   ├─ outerVisibility: false\n" +
			"     │   ├─ cacheable: true\n" +
			"     │   └─ Filter\n" +
			"     │       ├─ AND\n" +
			"     │       │   ├─ Eq\n" +
			"     │       │   │   ├─ BADTB:2!null\n" +
			"     │       │   │   └─ 0 (tinyint)\n" +
			"     │       │   └─ GreaterThan\n" +
			"     │       │       ├─ FLHXH:3!null\n" +
			"     │       │       └─ 0 (tinyint)\n" +
			"     │       └─ Having\n" +
			"     │           ├─ GreaterThan\n" +
			"     │           │   ├─ JTOA7:1!null\n" +
			"     │           │   └─ 1 (tinyint)\n" +
			"     │           └─ Project\n" +
			"     │               ├─ columns: [ZH72S:0, COUNT(WOOJ5.ZH72S):1!null as JTOA7, MIN(WOOJ5.LEA4J):2!null as BADTB, SUM(WOOJ5.LEA4J):3!null as FLHXH]\n" +
			"     │               └─ GroupBy\n" +
			"     │                   ├─ select: ZH72S:0, COUNT(WOOJ5.ZH72S:2), MIN(WOOJ5.LEA4J:1), SUM(WOOJ5.LEA4J:1)\n" +
			"     │                   ├─ group: ZH72S:0\n" +
			"     │                   └─ Project\n" +
			"     │                       ├─ columns: [WOOJ5.ZH72S:1 as ZH72S, WOOJ5.LEA4J:2, WOOJ5.ZH72S:1]\n" +
			"     │                       └─ SubqueryAlias\n" +
			"     │                           ├─ name: WOOJ5\n" +
			"     │                           ├─ outerVisibility: false\n" +
			"     │                           ├─ cacheable: true\n" +
			"     │                           └─ Project\n" +
			"     │                               ├─ columns: [nd.id:0!null as id, nd.ZH72S:7 as ZH72S, Subquery\n" +
			"     │                               │   ├─ cacheable: false\n" +
			"     │                               │   └─ Project\n" +
			"     │                               │       ├─ columns: [COUNT(1):17!null as COUNT(*)]\n" +
			"     │                               │       └─ GroupBy\n" +
			"     │                               │           ├─ select: COUNT(1 (bigint))\n" +
			"     │                               │           ├─ group: \n" +
			"     │                               │           └─ Filter\n" +
			"     │                               │               ├─ Eq\n" +
			"     │                               │               │   ├─ FLQLP.LUEVY:17!null\n" +
			"     │                               │               │   └─ nd.id:0!null\n" +
			"     │                               │               └─ Table\n" +
			"     │                               │                   ├─ name: FLQLP\n" +
			"     │                               │                   └─ columns: [luevy]\n" +
			"     │                               │   as LEA4J]\n" +
			"     │                               └─ Filter\n" +
			"     │                                   ├─ NOT\n" +
			"     │                                   │   └─ nd.ZH72S:7 IS NULL\n" +
			"     │                                   └─ TableAlias(nd)\n" +
			"     │                                       └─ IndexedTableAccess(E2I7U)\n" +
			"     │                                           ├─ index: [E2I7U.ZH72S]\n" +
			"     │                                           ├─ static: [{(NULL, ∞)}]\n" +
			"     │                                           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     └─ Filter\n" +
			"         ├─ NOT\n" +
			"         │   └─ PBMRX.ZH72S:2 IS NULL\n" +
			"         └─ TableAlias(PBMRX)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.ZH72S]\n" +
			"                 └─ columns: [id tw55n zh72s]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ct.id AS id,
	   ci.FTQLQ AS VCGT3,
	   nd.TW55N AS UWBAI,
	   aac.BTXC5 AS TPXBU,
	   ct.V5DPX AS V5DPX,
	   ct.S3Q3Y AS S3Q3Y,
	   ct.ZRV3B AS ZRV3B
	FROM
	   FLQLP ct
	INNER JOIN
	   JDLNA ci
	ON
	   ci.id = ct.FZ2R5
	INNER JOIN
	   E2I7U nd
	ON
	   nd.id = ct.LUEVY
	INNER JOIN
	   TPXBU aac
	ON
	   aac.id = ct.M22QN
	WHERE
	(
	       ct.OCA7E IS NOT NULL
	   AND
	       (
	               (SELECT I7HCR.SWCQV FROM EPZU6 I7HCR WHERE I7HCR.id = ct.OCA7E) = 1
	           OR
	               (SELECT nd.id FROM E2I7U nd WHERE nd.TW55N =
	                   (SELECT I7HCR.FVUCX FROM EPZU6 I7HCR
	                   WHERE I7HCR.id = ct.OCA7E))
	               <> ct.LUEVY
	       )
	)
	OR
	(
	       ct.NRURT IS NOT NULL
	   AND
	       ct.NRURT IN
	       (
	       SELECT
	           uct.id AS FDL23
	       FROM
	           EPZU6 I7HCR
	       INNER JOIN
	           OUBDL uct
	       ON
	               uct.FTQLQ = I7HCR.TOFPN
	           AND
	               uct.ZH72S = I7HCR.SJYN2
	           AND
	               uct.LJLUM = I7HCR.BTXC5
	       WHERE
	               I7HCR.SWCQV = 0
	           AND
	               I7HCR.id NOT IN (SELECT OCA7E FROM FLQLP WHERE OCA7E IS NOT NULL)
	       )
	)
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [ct.id:5!null as id, ci.FTQLQ:1!null as VCGT3, nd.TW55N:23!null as UWBAI, aac.BTXC5:18 as TPXBU, ct.V5DPX:13!null as V5DPX, ct.S3Q3Y:14!null as S3Q3Y, ct.ZRV3B:15!null as ZRV3B]\n" +
			" └─ Filter\n" +
			"     ├─ Or\n" +
			"     │   ├─ AND\n" +
			"     │   │   ├─ NOT\n" +
			"     │   │   │   └─ ct.OCA7E:11 IS NULL\n" +
			"     │   │   └─ Or\n" +
			"     │   │       ├─ Eq\n" +
			"     │   │       │   ├─ Subquery\n" +
			"     │   │       │   │   ├─ cacheable: false\n" +
			"     │   │       │   │   └─ Project\n" +
			"     │   │       │   │       ├─ columns: [I7HCR.SWCQV:38!null]\n" +
			"     │   │       │   │       └─ Filter\n" +
			"     │   │       │   │           ├─ Eq\n" +
			"     │   │       │   │           │   ├─ I7HCR.id:37!null\n" +
			"     │   │       │   │           │   └─ ct.OCA7E:11\n" +
			"     │   │       │   │           └─ TableAlias(I7HCR)\n" +
			"     │   │       │   │               └─ Table\n" +
			"     │   │       │   │                   ├─ name: EPZU6\n" +
			"     │   │       │   │                   └─ columns: [id swcqv]\n" +
			"     │   │       │   └─ 1 (tinyint)\n" +
			"     │   │       └─ NOT\n" +
			"     │   │           └─ Eq\n" +
			"     │   │               ├─ Subquery\n" +
			"     │   │               │   ├─ cacheable: false\n" +
			"     │   │               │   └─ Project\n" +
			"     │   │               │       ├─ columns: [nd.id:37!null]\n" +
			"     │   │               │       └─ Filter\n" +
			"     │   │               │           ├─ Eq\n" +
			"     │   │               │           │   ├─ nd.TW55N:40!null\n" +
			"     │   │               │           │   └─ Subquery\n" +
			"     │   │               │           │       ├─ cacheable: false\n" +
			"     │   │               │           │       └─ Project\n" +
			"     │   │               │           │           ├─ columns: [I7HCR.FVUCX:55!null]\n" +
			"     │   │               │           │           └─ Filter\n" +
			"     │   │               │           │               ├─ Eq\n" +
			"     │   │               │           │               │   ├─ I7HCR.id:54!null\n" +
			"     │   │               │           │               │   └─ ct.OCA7E:11\n" +
			"     │   │               │           │               └─ TableAlias(I7HCR)\n" +
			"     │   │               │           │                   └─ Table\n" +
			"     │   │               │           │                       ├─ name: EPZU6\n" +
			"     │   │               │           │                       └─ columns: [id fvucx]\n" +
			"     │   │               │           └─ TableAlias(nd)\n" +
			"     │   │               │               └─ Table\n" +
			"     │   │               │                   ├─ name: E2I7U\n" +
			"     │   │               │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     │   │               └─ ct.LUEVY:7!null\n" +
			"     │   └─ AND\n" +
			"     │       ├─ NOT\n" +
			"     │       │   └─ ct.NRURT:10 IS NULL\n" +
			"     │       └─ InSubquery\n" +
			"     │           ├─ left: ct.NRURT:10\n" +
			"     │           └─ right: Subquery\n" +
			"     │               ├─ cacheable: true\n" +
			"     │               └─ Project\n" +
			"     │                   ├─ columns: [uct.id:45!null as FDL23]\n" +
			"     │                   └─ Filter\n" +
			"     │                       ├─ NOT\n" +
			"     │                       │   └─ InSubquery\n" +
			"     │                       │       ├─ left: I7HCR.id:37!null\n" +
			"     │                       │       └─ right: Subquery\n" +
			"     │                       │           ├─ cacheable: true\n" +
			"     │                       │           └─ Filter\n" +
			"     │                       │               ├─ NOT\n" +
			"     │                       │               │   └─ FLQLP.OCA7E:58 IS NULL\n" +
			"     │                       │               └─ IndexedTableAccess(FLQLP)\n" +
			"     │                       │                   ├─ index: [FLQLP.OCA7E]\n" +
			"     │                       │                   ├─ static: [{(NULL, ∞)}]\n" +
			"     │                       │                   └─ columns: [oca7e]\n" +
			"     │                       └─ LookupJoin\n" +
			"     │                           ├─ AND\n" +
			"     │                           │   ├─ AND\n" +
			"     │                           │   │   ├─ Eq\n" +
			"     │                           │   │   │   ├─ uct.FTQLQ:46\n" +
			"     │                           │   │   │   └─ I7HCR.TOFPN:38!null\n" +
			"     │                           │   │   └─ Eq\n" +
			"     │                           │   │       ├─ uct.ZH72S:47\n" +
			"     │                           │   │       └─ I7HCR.SJYN2:39!null\n" +
			"     │                           │   └─ Eq\n" +
			"     │                           │       ├─ uct.LJLUM:50\n" +
			"     │                           │       └─ I7HCR.BTXC5:40!null\n" +
			"     │                           ├─ Filter\n" +
			"     │                           │   ├─ Eq\n" +
			"     │                           │   │   ├─ I7HCR.SWCQV:42!null\n" +
			"     │                           │   │   └─ 0 (tinyint)\n" +
			"     │                           │   └─ TableAlias(I7HCR)\n" +
			"     │                           │       └─ Table\n" +
			"     │                           │           ├─ name: EPZU6\n" +
			"     │                           │           └─ columns: [id tofpn sjyn2 btxc5 fvucx swcqv ykssu fhcyt]\n" +
			"     │                           └─ TableAlias(uct)\n" +
			"     │                               └─ IndexedTableAccess(OUBDL)\n" +
			"     │                                   ├─ index: [OUBDL.ZH72S]\n" +
			"     │                                   └─ columns: [id ftqlq zh72s sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e ykssu fhcyt qz6vt]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ nd.id:20!null\n" +
			"         │   └─ ct.LUEVY:7!null\n" +
			"         ├─ LookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ aac.id:17!null\n" +
			"         │   │   └─ ct.M22QN:8!null\n" +
			"         │   ├─ LookupJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ ci.id:0!null\n" +
			"         │   │   │   └─ ct.FZ2R5:6!null\n" +
			"         │   │   ├─ TableAlias(ci)\n" +
			"         │   │   │   └─ Table\n" +
			"         │   │   │       ├─ name: JDLNA\n" +
			"         │   │   │       └─ columns: [id ftqlq fwwiq o3qxw fhcyt]\n" +
			"         │   │   └─ TableAlias(ct)\n" +
			"         │   │       └─ IndexedTableAccess(FLQLP)\n" +
			"         │   │           ├─ index: [FLQLP.FZ2R5]\n" +
			"         │   │           └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"         │   └─ TableAlias(aac)\n" +
			"         │       └─ IndexedTableAccess(TPXBU)\n" +
			"         │           ├─ index: [TPXBU.id]\n" +
			"         │           └─ columns: [id btxc5 fhcyt]\n" +
			"         └─ TableAlias(nd)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.id]\n" +
			"                 └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   uct.*
	FROM
	(
	   SELECT DISTINCT
	       YLKSY.id AS FDL23
	   FROM
	       OUBDL YLKSY
	   INNER JOIN
	       JDLNA ci
	   ON
	       ci.FTQLQ = YLKSY.FTQLQ
	   INNER JOIN
	       E2I7U nd
	   ON
	       nd.ZH72S = YLKSY.ZH72S
	   INNER JOIN
	       TPXBU aac
	   ON
	       aac.BTXC5 = YLKSY.LJLUM
	   WHERE
	       YLKSY.LJLUM NOT LIKE '%|%'
	   AND
	       YLKSY.id NOT IN (SELECT NRURT FROM FLQLP WHERE NRURT IS NOT NULL)
	) FZWBD
	INNER JOIN
	   OUBDL uct
	ON
	   uct.id = FZWBD.FDL23
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [uct.id:1!null, uct.FTQLQ:2, uct.ZH72S:3, uct.SFJ6L:4, uct.V5DPX:5, uct.LJLUM:6, uct.IDPK7:7, uct.NO52D:8, uct.ZRV3B:9, uct.VYO5E:10, uct.YKSSU:11, uct.FHCYT:12, uct.QZ6VT:13]\n" +
			" └─ LookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ uct.id:1!null\n" +
			"     │   └─ FZWBD.FDL23:0!null\n" +
			"     ├─ SubqueryAlias\n" +
			"     │   ├─ name: FZWBD\n" +
			"     │   ├─ outerVisibility: false\n" +
			"     │   ├─ cacheable: true\n" +
			"     │   └─ Distinct\n" +
			"     │       └─ Project\n" +
			"     │           ├─ columns: [YLKSY.id:5!null as FDL23]\n" +
			"     │           └─ AntiLookupJoin\n" +
			"     │               ├─ Eq\n" +
			"     │               │   ├─ YLKSY.id:5!null\n" +
			"     │               │   └─ applySubq0.NRURT:38\n" +
			"     │               ├─ LookupJoin\n" +
			"     │               │   ├─ Eq\n" +
			"     │               │   │   ├─ nd.ZH72S:28\n" +
			"     │               │   │   └─ YLKSY.ZH72S:7\n" +
			"     │               │   ├─ LookupJoin\n" +
			"     │               │   │   ├─ Eq\n" +
			"     │               │   │   │   ├─ aac.BTXC5:19\n" +
			"     │               │   │   │   └─ YLKSY.LJLUM:10\n" +
			"     │               │   │   ├─ LookupJoin\n" +
			"     │               │   │   │   ├─ Eq\n" +
			"     │               │   │   │   │   ├─ ci.FTQLQ:1!null\n" +
			"     │               │   │   │   │   └─ YLKSY.FTQLQ:6\n" +
			"     │               │   │   │   ├─ TableAlias(ci)\n" +
			"     │               │   │   │   │   └─ Table\n" +
			"     │               │   │   │   │       ├─ name: JDLNA\n" +
			"     │               │   │   │   │       └─ columns: [id ftqlq fwwiq o3qxw fhcyt]\n" +
			"     │               │   │   │   └─ Filter\n" +
			"     │               │   │   │       ├─ NOT\n" +
			"     │               │   │   │       │   └─ YLKSY.LJLUM LIKE '%|%'\n" +
			"     │               │   │   │       └─ TableAlias(YLKSY)\n" +
			"     │               │   │   │           └─ IndexedTableAccess(OUBDL)\n" +
			"     │               │   │   │               ├─ index: [OUBDL.FTQLQ]\n" +
			"     │               │   │   │               └─ columns: [id ftqlq zh72s sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e ykssu fhcyt qz6vt]\n" +
			"     │               │   │   └─ TableAlias(aac)\n" +
			"     │               │   │       └─ IndexedTableAccess(TPXBU)\n" +
			"     │               │   │           ├─ index: [TPXBU.BTXC5]\n" +
			"     │               │   │           └─ columns: [id btxc5 fhcyt]\n" +
			"     │               │   └─ TableAlias(nd)\n" +
			"     │               │       └─ IndexedTableAccess(E2I7U)\n" +
			"     │               │           ├─ index: [E2I7U.ZH72S]\n" +
			"     │               │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     │               └─ Filter\n" +
			"     │                   ├─ NOT\n" +
			"     │                   │   └─ applySubq0.NRURT:0 IS NULL\n" +
			"     │                   └─ TableAlias(applySubq0)\n" +
			"     │                       └─ IndexedTableAccess(FLQLP)\n" +
			"     │                           ├─ index: [FLQLP.NRURT]\n" +
			"     │                           └─ columns: [nrurt]\n" +
			"     └─ TableAlias(uct)\n" +
			"         └─ IndexedTableAccess(OUBDL)\n" +
			"             ├─ index: [OUBDL.id]\n" +
			"             └─ columns: [id ftqlq zh72s sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e ykssu fhcyt qz6vt]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ct.id AS id,
	   ci.FTQLQ AS VCGT3,
	   nd.TW55N AS UWBAI,
	   aac.BTXC5 AS TPXBU,
	   ct.V5DPX AS V5DPX,
	   ct.S3Q3Y AS S3Q3Y,
	   ct.ZRV3B AS ZRV3B
	FROM
	   FLQLP ct
	INNER JOIN
	   HU5A5 TVTJS
	ON
	   TVTJS.id = ct.XMM6Q
	INNER JOIN
	   JDLNA ci
	ON
	   ci.id = ct.FZ2R5
	INNER JOIN
	   E2I7U nd
	ON
	   nd.id = ct.LUEVY
	INNER JOIN
	   TPXBU aac
	ON
	   aac.id = ct.M22QN
	WHERE
	   TVTJS.SWCQV = 1
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [ct.id:2!null as id, ci.FTQLQ:15!null as VCGT3, nd.TW55N:13!null as UWBAI, aac.BTXC5:11 as TPXBU, ct.V5DPX:7!null as V5DPX, ct.S3Q3Y:8!null as S3Q3Y, ct.ZRV3B:9!null as ZRV3B]\n" +
			" └─ LookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ ci.id:14!null\n" +
			"     │   └─ ct.FZ2R5:3!null\n" +
			"     ├─ LookupJoin\n" +
			"     │   ├─ Eq\n" +
			"     │   │   ├─ nd.id:12!null\n" +
			"     │   │   └─ ct.LUEVY:4!null\n" +
			"     │   ├─ LookupJoin\n" +
			"     │   │   ├─ Eq\n" +
			"     │   │   │   ├─ aac.id:10!null\n" +
			"     │   │   │   └─ ct.M22QN:5!null\n" +
			"     │   │   ├─ LookupJoin\n" +
			"     │   │   │   ├─ Eq\n" +
			"     │   │   │   │   ├─ TVTJS.id:0!null\n" +
			"     │   │   │   │   └─ ct.XMM6Q:6\n" +
			"     │   │   │   ├─ Filter\n" +
			"     │   │   │   │   ├─ Eq\n" +
			"     │   │   │   │   │   ├─ TVTJS.SWCQV:1!null\n" +
			"     │   │   │   │   │   └─ 1 (tinyint)\n" +
			"     │   │   │   │   └─ TableAlias(TVTJS)\n" +
			"     │   │   │   │       └─ Table\n" +
			"     │   │   │   │           ├─ name: HU5A5\n" +
			"     │   │   │   │           └─ columns: [id swcqv]\n" +
			"     │   │   │   └─ TableAlias(ct)\n" +
			"     │   │   │       └─ IndexedTableAccess(FLQLP)\n" +
			"     │   │   │           ├─ index: [FLQLP.XMM6Q]\n" +
			"     │   │   │           └─ columns: [id fz2r5 luevy m22qn xmm6q v5dpx s3q3y zrv3b]\n" +
			"     │   │   └─ TableAlias(aac)\n" +
			"     │   │       └─ IndexedTableAccess(TPXBU)\n" +
			"     │   │           ├─ index: [TPXBU.id]\n" +
			"     │   │           └─ columns: [id btxc5]\n" +
			"     │   └─ TableAlias(nd)\n" +
			"     │       └─ IndexedTableAccess(E2I7U)\n" +
			"     │           ├─ index: [E2I7U.id]\n" +
			"     │           └─ columns: [id tw55n]\n" +
			"     └─ TableAlias(ci)\n" +
			"         └─ IndexedTableAccess(JDLNA)\n" +
			"             ├─ index: [JDLNA.id]\n" +
			"             └─ columns: [id ftqlq]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   *
	FROM
	   HU5A5
	WHERE
	       id NOT IN
	       (
	           SELECT
	               XMM6Q
	           FROM
	               FLQLP
	           WHERE XMM6Q IS NOT NULL
	       )
	   AND
	       SWCQV = 0
	`,
		ExpectedPlan: "AntiLookupJoin\n" +
			" ├─ Eq\n" +
			" │   ├─ HU5A5.id:0!null\n" +
			" │   └─ applySubq0.XMM6Q:13\n" +
			" ├─ Filter\n" +
			" │   ├─ Eq\n" +
			" │   │   ├─ HU5A5.SWCQV:10!null\n" +
			" │   │   └─ 0 (tinyint)\n" +
			" │   └─ Table\n" +
			" │       ├─ name: HU5A5\n" +
			" │       └─ columns: [id tofpn i3vta sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e swcqv ykssu fhcyt]\n" +
			" └─ Filter\n" +
			"     ├─ NOT\n" +
			"     │   └─ applySubq0.XMM6Q:0 IS NULL\n" +
			"     └─ TableAlias(applySubq0)\n" +
			"         └─ IndexedTableAccess(FLQLP)\n" +
			"             ├─ index: [FLQLP.XMM6Q]\n" +
			"             └─ columns: [xmm6q]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   rn.id AS id,
	   CONCAT(NSPLT.TW55N, 'FDNCN', LQNCX.TW55N) AS X37NA,
	   CONCAT(XLZA5.TW55N, 'FDNCN', AFJMD.TW55N) AS THWCS,
	   rn.HVHRZ AS HVHRZ
	FROM
	   QYWQD rn
	INNER JOIN
	   NOXN3 PV6R5
	ON
	   rn.WNUNU = PV6R5.id
	INNER JOIN
	   NOXN3 ZYUTC
	ON
	   rn.HHVLX = ZYUTC.id
	INNER JOIN
	   E2I7U NSPLT
	ON
	   NSPLT.id = PV6R5.BRQP2
	INNER JOIN
	   E2I7U LQNCX
	ON
	   LQNCX.id = PV6R5.FFTBJ
	INNER JOIN
	   E2I7U XLZA5
	ON
	   XLZA5.id = ZYUTC.BRQP2
	INNER JOIN
	   E2I7U AFJMD
	ON
	   AFJMD.id = ZYUTC.FFTBJ
	WHERE
	       PV6R5.FFTBJ <> ZYUTC.BRQP2
	   OR
	       PV6R5.NUMK2 <> 1
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [rn.id:8!null as id, concat(NSPLT.TW55N:1!null,FDNCN (longtext),LQNCX.TW55N:7!null) as X37NA, concat(XLZA5.TW55N:18!null,FDNCN (longtext),AFJMD.TW55N:16!null) as THWCS, rn.HVHRZ:11!null as HVHRZ]\n" +
			" └─ Filter\n" +
			"     ├─ Or\n" +
			"     │   ├─ NOT\n" +
			"     │   │   └─ Eq\n" +
			"     │   │       ├─ PV6R5.FFTBJ:4!null\n" +
			"     │   │       └─ ZYUTC.BRQP2:13!null\n" +
			"     │   └─ NOT\n" +
			"     │       └─ Eq\n" +
			"     │           ├─ PV6R5.NUMK2:5!null\n" +
			"     │           └─ 1 (tinyint)\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ XLZA5.id:17!null\n" +
			"         │   └─ ZYUTC.BRQP2:13!null\n" +
			"         ├─ LookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ AFJMD.id:15!null\n" +
			"         │   │   └─ ZYUTC.FFTBJ:14!null\n" +
			"         │   ├─ LookupJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ rn.HHVLX:10!null\n" +
			"         │   │   │   └─ ZYUTC.id:12!null\n" +
			"         │   │   ├─ LookupJoin\n" +
			"         │   │   │   ├─ Eq\n" +
			"         │   │   │   │   ├─ rn.WNUNU:9!null\n" +
			"         │   │   │   │   └─ PV6R5.id:2!null\n" +
			"         │   │   │   ├─ LookupJoin\n" +
			"         │   │   │   │   ├─ Eq\n" +
			"         │   │   │   │   │   ├─ LQNCX.id:6!null\n" +
			"         │   │   │   │   │   └─ PV6R5.FFTBJ:4!null\n" +
			"         │   │   │   │   ├─ LookupJoin\n" +
			"         │   │   │   │   │   ├─ Eq\n" +
			"         │   │   │   │   │   │   ├─ NSPLT.id:0!null\n" +
			"         │   │   │   │   │   │   └─ PV6R5.BRQP2:3!null\n" +
			"         │   │   │   │   │   ├─ TableAlias(NSPLT)\n" +
			"         │   │   │   │   │   │   └─ Table\n" +
			"         │   │   │   │   │   │       ├─ name: E2I7U\n" +
			"         │   │   │   │   │   │       └─ columns: [id tw55n]\n" +
			"         │   │   │   │   │   └─ TableAlias(PV6R5)\n" +
			"         │   │   │   │   │       └─ IndexedTableAccess(NOXN3)\n" +
			"         │   │   │   │   │           ├─ index: [NOXN3.BRQP2]\n" +
			"         │   │   │   │   │           └─ columns: [id brqp2 fftbj numk2]\n" +
			"         │   │   │   │   └─ TableAlias(LQNCX)\n" +
			"         │   │   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │   │   │   │           ├─ index: [E2I7U.id]\n" +
			"         │   │   │   │           └─ columns: [id tw55n]\n" +
			"         │   │   │   └─ TableAlias(rn)\n" +
			"         │   │   │       └─ IndexedTableAccess(QYWQD)\n" +
			"         │   │   │           ├─ index: [QYWQD.WNUNU]\n" +
			"         │   │   │           └─ columns: [id wnunu hhvlx hvhrz]\n" +
			"         │   │   └─ TableAlias(ZYUTC)\n" +
			"         │   │       └─ IndexedTableAccess(NOXN3)\n" +
			"         │   │           ├─ index: [NOXN3.id]\n" +
			"         │   │           └─ columns: [id brqp2 fftbj]\n" +
			"         │   └─ TableAlias(AFJMD)\n" +
			"         │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │           ├─ index: [E2I7U.id]\n" +
			"         │           └─ columns: [id tw55n]\n" +
			"         └─ TableAlias(XLZA5)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.id]\n" +
			"                 └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   sn.id AS DRIWM,
	   CONCAT(OE56M.TW55N, 'FDNCN', CGFRZ.TW55N) AS GRVSE,
	   SKPM6.id AS JIEVY,
	   CONCAT(V5SAY.TW55N, 'FDNCN', FQTHF.TW55N) AS ENCM3,
	   1.0 AS OHD3R
	FROM
	   NOXN3 sn
	INNER JOIN
	   NOXN3 SKPM6
	ON
	   SKPM6.BRQP2 = sn.FFTBJ
	LEFT JOIN
	   QYWQD rn
	ON
	       rn.WNUNU = sn.id
	   AND
	       rn.HHVLX = SKPM6.id
	INNER JOIN
	   E2I7U OE56M
	ON
	   OE56M.id = sn.BRQP2
	INNER JOIN
	   E2I7U CGFRZ
	ON
	   CGFRZ.id = sn.FFTBJ
	INNER JOIN
	   E2I7U V5SAY
	ON
	   V5SAY.id = SKPM6.BRQP2
	INNER JOIN
	   E2I7U FQTHF
	ON
	   FQTHF.id = SKPM6.FFTBJ
	WHERE
	       sn.NUMK2 = 1
	   AND
	       rn.WNUNU IS NULL AND rn.HHVLX IS NULL
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [sn.id:2!null as DRIWM, concat(OE56M.TW55N:1!null,FDNCN (longtext),CGFRZ.TW55N:7!null) as GRVSE, SKPM6.id:8!null as JIEVY, concat(V5SAY.TW55N:12!null,FDNCN (longtext),FQTHF.TW55N:14!null) as ENCM3, 1 (decimal(2,1)) as OHD3R]\n" +
			" └─ Filter\n" +
			"     ├─ AND\n" +
			"     │   ├─ rn.WNUNU:15 IS NULL\n" +
			"     │   └─ rn.HHVLX:16 IS NULL\n" +
			"     └─ LeftOuterLookupJoin\n" +
			"         ├─ AND\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ rn.WNUNU:15!null\n" +
			"         │   │   └─ sn.id:2!null\n" +
			"         │   └─ Eq\n" +
			"         │       ├─ rn.HHVLX:16!null\n" +
			"         │       └─ SKPM6.id:8!null\n" +
			"         ├─ LookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ FQTHF.id:13!null\n" +
			"         │   │   └─ SKPM6.FFTBJ:10!null\n" +
			"         │   ├─ LookupJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ V5SAY.id:11!null\n" +
			"         │   │   │   └─ SKPM6.BRQP2:9!null\n" +
			"         │   │   ├─ LookupJoin\n" +
			"         │   │   │   ├─ Eq\n" +
			"         │   │   │   │   ├─ SKPM6.BRQP2:9!null\n" +
			"         │   │   │   │   └─ sn.FFTBJ:4!null\n" +
			"         │   │   │   ├─ LookupJoin\n" +
			"         │   │   │   │   ├─ Eq\n" +
			"         │   │   │   │   │   ├─ CGFRZ.id:6!null\n" +
			"         │   │   │   │   │   └─ sn.FFTBJ:4!null\n" +
			"         │   │   │   │   ├─ LookupJoin\n" +
			"         │   │   │   │   │   ├─ Eq\n" +
			"         │   │   │   │   │   │   ├─ OE56M.id:0!null\n" +
			"         │   │   │   │   │   │   └─ sn.BRQP2:3!null\n" +
			"         │   │   │   │   │   ├─ TableAlias(OE56M)\n" +
			"         │   │   │   │   │   │   └─ Table\n" +
			"         │   │   │   │   │   │       ├─ name: E2I7U\n" +
			"         │   │   │   │   │   │       └─ columns: [id tw55n]\n" +
			"         │   │   │   │   │   └─ Filter\n" +
			"         │   │   │   │   │       ├─ Eq\n" +
			"         │   │   │   │   │       │   ├─ sn.NUMK2:3!null\n" +
			"         │   │   │   │   │       │   └─ 1 (tinyint)\n" +
			"         │   │   │   │   │       └─ TableAlias(sn)\n" +
			"         │   │   │   │   │           └─ IndexedTableAccess(NOXN3)\n" +
			"         │   │   │   │   │               ├─ index: [NOXN3.BRQP2]\n" +
			"         │   │   │   │   │               └─ columns: [id brqp2 fftbj numk2]\n" +
			"         │   │   │   │   └─ TableAlias(CGFRZ)\n" +
			"         │   │   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │   │   │   │           ├─ index: [E2I7U.id]\n" +
			"         │   │   │   │           └─ columns: [id tw55n]\n" +
			"         │   │   │   └─ TableAlias(SKPM6)\n" +
			"         │   │   │       └─ IndexedTableAccess(NOXN3)\n" +
			"         │   │   │           ├─ index: [NOXN3.BRQP2]\n" +
			"         │   │   │           └─ columns: [id brqp2 fftbj]\n" +
			"         │   │   └─ TableAlias(V5SAY)\n" +
			"         │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │   │           ├─ index: [E2I7U.id]\n" +
			"         │   │           └─ columns: [id tw55n]\n" +
			"         │   └─ TableAlias(FQTHF)\n" +
			"         │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │           ├─ index: [E2I7U.id]\n" +
			"         │           └─ columns: [id tw55n]\n" +
			"         └─ TableAlias(rn)\n" +
			"             └─ IndexedTableAccess(QYWQD)\n" +
			"                 ├─ index: [QYWQD.HHVLX]\n" +
			"                 └─ columns: [wnunu hhvlx]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   id, FGG57, SSHPJ, SFJ6L
	FROM
	   TDRVG
	WHERE
	   id IN
	   (SELECT
	       (SELECT id FROM TDRVG WHERE SSHPJ = S7BYT.SSHPJ ORDER BY id LIMIT 1) AS id
	   FROM
	       (SELECT DISTINCT
	           S5KBM.SSHPJ AS SSHPJ,
	           S5KBM.SFJ6L AS SFJ6L
	       FROM
	           TDRVG S5KBM
	       INNER JOIN
	           E2I7U nd
	       ON
	           nd.FGG57 = S5KBM.FGG57) S7BYT
	   WHERE
	       S7BYT.SSHPJ NOT IN (SELECT SSHPJ FROM WE72E)
	   )
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [TDRVG.id:0!null, TDRVG.FGG57:1!null, TDRVG.SSHPJ:2!null, TDRVG.SFJ6L:3!null]\n" +
			" └─ RightSemiLookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ TDRVG.id:1!null\n" +
			"     │   └─ applySubq0.id:0\n" +
			"     ├─ Distinct\n" +
			"     │   └─ SubqueryAlias\n" +
			"     │       ├─ name: applySubq0\n" +
			"     │       ├─ outerVisibility: false\n" +
			"     │       ├─ cacheable: true\n" +
			"     │       └─ Project\n" +
			"     │           ├─ columns: [Subquery\n" +
			"     │           │   ├─ cacheable: false\n" +
			"     │           │   └─ Limit(1)\n" +
			"     │           │       └─ TopN(Limit: [1 (tinyint)]; TDRVG.id:2!null ASC nullsFirst)\n" +
			"     │           │           └─ Project\n" +
			"     │           │               ├─ columns: [TDRVG.id:2!null]\n" +
			"     │           │               └─ Filter\n" +
			"     │           │                   ├─ Eq\n" +
			"     │           │                   │   ├─ TDRVG.SSHPJ:3!null\n" +
			"     │           │                   │   └─ S7BYT.SSHPJ:0!null\n" +
			"     │           │                   └─ Table\n" +
			"     │           │                       ├─ name: TDRVG\n" +
			"     │           │                       └─ columns: [id sshpj]\n" +
			"     │           │   as id]\n" +
			"     │           └─ AntiLookupJoin\n" +
			"     │               ├─ Eq\n" +
			"     │               │   ├─ S7BYT.SSHPJ:0!null\n" +
			"     │               │   └─ applySubq0.SSHPJ:2!null\n" +
			"     │               ├─ SubqueryAlias\n" +
			"     │               │   ├─ name: S7BYT\n" +
			"     │               │   ├─ outerVisibility: true\n" +
			"     │               │   ├─ cacheable: true\n" +
			"     │               │   └─ Distinct\n" +
			"     │               │       └─ Project\n" +
			"     │               │           ├─ columns: [S5KBM.SSHPJ:19!null as SSHPJ, S5KBM.SFJ6L:20!null as SFJ6L]\n" +
			"     │               │           └─ LookupJoin\n" +
			"     │               │               ├─ Eq\n" +
			"     │               │               │   ├─ nd.FGG57:6\n" +
			"     │               │               │   └─ S5KBM.FGG57:18!null\n" +
			"     │               │               ├─ TableAlias(nd)\n" +
			"     │               │               │   └─ Table\n" +
			"     │               │               │       ├─ name: E2I7U\n" +
			"     │               │               │       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     │               │               └─ TableAlias(S5KBM)\n" +
			"     │               │                   └─ IndexedTableAccess(TDRVG)\n" +
			"     │               │                       ├─ index: [TDRVG.FGG57]\n" +
			"     │               │                       └─ columns: [id fgg57 sshpj sfj6l zh72s]\n" +
			"     │               └─ TableAlias(applySubq0)\n" +
			"     │                   └─ IndexedTableAccess(WE72E)\n" +
			"     │                       ├─ index: [WE72E.SSHPJ]\n" +
			"     │                       └─ columns: [sshpj]\n" +
			"     └─ IndexedTableAccess(TDRVG)\n" +
			"         ├─ index: [TDRVG.id]\n" +
			"         └─ columns: [id fgg57 sshpj sfj6l zh72s]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   PBMRX.id AS id,
	   PBMRX.TW55N AS UYOGN,
	   PBMRX.ZH72S AS H4JEA
	FROM
	   (
	       SELECT
	           ZH72S AS ZH72S,
	           COUNT(ZH72S) AS JTOA7,
	           MIN(TJ66D) AS B4OVH,
	           SUM(TJ66D) AS R5CKX
	       FROM
	           (
	           SELECT
	               nd.id AS id,
	               nd.ZH72S AS ZH72S,
	               (SELECT COUNT(*) FROM AMYXQ WHERE LUEVY = nd.id) AS TJ66D
	           FROM
	               E2I7U nd
	           WHERE nd.ZH72S IS NOT NULL
	           ) TQ57W
	       GROUP BY
	           ZH72S
	       HAVING
	           JTOA7 > 1
	   ) CL3DT
	INNER JOIN
	   E2I7U PBMRX
	ON
	   PBMRX.ZH72S IS NOT NULL AND PBMRX.ZH72S = CL3DT.ZH72S
	WHERE
	       CL3DT.B4OVH = 0
	   AND
	       CL3DT.R5CKX > 0
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [PBMRX.id:4!null as id, PBMRX.TW55N:5!null as UYOGN, PBMRX.ZH72S:6 as H4JEA]\n" +
			" └─ LookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ PBMRX.ZH72S:6\n" +
			"     │   └─ CL3DT.ZH72S:0\n" +
			"     ├─ SubqueryAlias\n" +
			"     │   ├─ name: CL3DT\n" +
			"     │   ├─ outerVisibility: false\n" +
			"     │   ├─ cacheable: true\n" +
			"     │   └─ Filter\n" +
			"     │       ├─ AND\n" +
			"     │       │   ├─ Eq\n" +
			"     │       │   │   ├─ B4OVH:2!null\n" +
			"     │       │   │   └─ 0 (tinyint)\n" +
			"     │       │   └─ GreaterThan\n" +
			"     │       │       ├─ R5CKX:3!null\n" +
			"     │       │       └─ 0 (tinyint)\n" +
			"     │       └─ Having\n" +
			"     │           ├─ GreaterThan\n" +
			"     │           │   ├─ JTOA7:1!null\n" +
			"     │           │   └─ 1 (tinyint)\n" +
			"     │           └─ Project\n" +
			"     │               ├─ columns: [ZH72S:0, COUNT(TQ57W.ZH72S):1!null as JTOA7, MIN(TQ57W.TJ66D):2!null as B4OVH, SUM(TQ57W.TJ66D):3!null as R5CKX]\n" +
			"     │               └─ GroupBy\n" +
			"     │                   ├─ select: ZH72S:0, COUNT(TQ57W.ZH72S:2), MIN(TQ57W.TJ66D:1), SUM(TQ57W.TJ66D:1)\n" +
			"     │                   ├─ group: ZH72S:0\n" +
			"     │                   └─ Project\n" +
			"     │                       ├─ columns: [TQ57W.ZH72S:1 as ZH72S, TQ57W.TJ66D:2, TQ57W.ZH72S:1]\n" +
			"     │                       └─ SubqueryAlias\n" +
			"     │                           ├─ name: TQ57W\n" +
			"     │                           ├─ outerVisibility: false\n" +
			"     │                           ├─ cacheable: true\n" +
			"     │                           └─ Project\n" +
			"     │                               ├─ columns: [nd.id:0!null as id, nd.ZH72S:7 as ZH72S, Subquery\n" +
			"     │                               │   ├─ cacheable: false\n" +
			"     │                               │   └─ Project\n" +
			"     │                               │       ├─ columns: [COUNT(1):17!null as COUNT(*)]\n" +
			"     │                               │       └─ GroupBy\n" +
			"     │                               │           ├─ select: COUNT(1 (bigint))\n" +
			"     │                               │           ├─ group: \n" +
			"     │                               │           └─ Filter\n" +
			"     │                               │               ├─ Eq\n" +
			"     │                               │               │   ├─ AMYXQ.LUEVY:17!null\n" +
			"     │                               │               │   └─ nd.id:0!null\n" +
			"     │                               │               └─ Table\n" +
			"     │                               │                   ├─ name: AMYXQ\n" +
			"     │                               │                   └─ columns: [luevy]\n" +
			"     │                               │   as TJ66D]\n" +
			"     │                               └─ Filter\n" +
			"     │                                   ├─ NOT\n" +
			"     │                                   │   └─ nd.ZH72S:7 IS NULL\n" +
			"     │                                   └─ TableAlias(nd)\n" +
			"     │                                       └─ IndexedTableAccess(E2I7U)\n" +
			"     │                                           ├─ index: [E2I7U.ZH72S]\n" +
			"     │                                           ├─ static: [{(NULL, ∞)}]\n" +
			"     │                                           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     └─ Filter\n" +
			"         ├─ NOT\n" +
			"         │   └─ PBMRX.ZH72S:2 IS NULL\n" +
			"         └─ TableAlias(PBMRX)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.ZH72S]\n" +
			"                 └─ columns: [id tw55n zh72s]\n" +
			"",
	},
	{
		Query: `
	SELECT /*+ JOIN_ORDER(ufc, nd, cla) */ DISTINCT
	   ufc.*
	FROM
	   SISUT ufc
	INNER JOIN
	   E2I7U nd
	ON
	   nd.ZH72S = ufc.ZH72S
	INNER JOIN
	   YK2GW cla
	ON
	   cla.FTQLQ = ufc.T4IBQ
	WHERE
	       nd.ZH72S IS NOT NULL
	   AND
	       ufc.id NOT IN (SELECT KKGN5 FROM AMYXQ)
	`,
		ExpectedPlan: "Distinct\n" +
			" └─ Project\n" +
			"     ├─ columns: [ufc.id:30!null, ufc.T4IBQ:31, ufc.ZH72S:32, ufc.AMYXQ:33, ufc.KTNZ2:34, ufc.HIID2:35, ufc.DN3OQ:36, ufc.VVKNB:37, ufc.SH7TP:38, ufc.SRZZO:39, ufc.QZ6VT:40]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ nd.ZH72S:48\n" +
			"         │   └─ ufc.ZH72S:32\n" +
			"         ├─ AntiLookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ ufc.id:30!null\n" +
			"         │   │   └─ applySubq0.KKGN5:41\n" +
			"         │   ├─ LookupJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ cla.FTQLQ:1!null\n" +
			"         │   │   │   └─ ufc.T4IBQ:31\n" +
			"         │   │   ├─ TableAlias(cla)\n" +
			"         │   │   │   └─ Table\n" +
			"         │   │   │       ├─ name: YK2GW\n" +
			"         │   │   │       └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"         │   │   └─ TableAlias(ufc)\n" +
			"         │   │       └─ IndexedTableAccess(SISUT)\n" +
			"         │   │           ├─ index: [SISUT.T4IBQ]\n" +
			"         │   │           └─ columns: [id t4ibq zh72s amyxq ktnz2 hiid2 dn3oq vvknb sh7tp srzzo qz6vt]\n" +
			"         │   └─ TableAlias(applySubq0)\n" +
			"         │       └─ IndexedTableAccess(AMYXQ)\n" +
			"         │           ├─ index: [AMYXQ.KKGN5]\n" +
			"         │           └─ columns: [kkgn5]\n" +
			"         └─ Filter\n" +
			"             ├─ NOT\n" +
			"             │   └─ nd.ZH72S:7 IS NULL\n" +
			"             └─ TableAlias(nd)\n" +
			"                 └─ IndexedTableAccess(E2I7U)\n" +
			"                     ├─ index: [E2I7U.ZH72S]\n" +
			"                     └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"",
	},
	{
		Query: `
	SELECT DISTINCT
	   ufc.*
	FROM
	   SISUT ufc
	INNER JOIN
	   E2I7U nd
	ON
	   nd.ZH72S = ufc.ZH72S
	INNER JOIN
	   YK2GW cla
	ON
	   cla.FTQLQ = ufc.T4IBQ
	WHERE
	       nd.ZH72S IS NOT NULL
	   AND
	       ufc.id NOT IN (SELECT KKGN5 FROM AMYXQ)
	`,
		ExpectedPlan: "Distinct\n" +
			" └─ Project\n" +
			"     ├─ columns: [ufc.id:30!null, ufc.T4IBQ:31, ufc.ZH72S:32, ufc.AMYXQ:33, ufc.KTNZ2:34, ufc.HIID2:35, ufc.DN3OQ:36, ufc.VVKNB:37, ufc.SH7TP:38, ufc.SRZZO:39, ufc.QZ6VT:40]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ nd.ZH72S:48\n" +
			"         │   └─ ufc.ZH72S:32\n" +
			"         ├─ AntiLookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ ufc.id:30!null\n" +
			"         │   │   └─ applySubq0.KKGN5:41\n" +
			"         │   ├─ LookupJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ cla.FTQLQ:1!null\n" +
			"         │   │   │   └─ ufc.T4IBQ:31\n" +
			"         │   │   ├─ TableAlias(cla)\n" +
			"         │   │   │   └─ Table\n" +
			"         │   │   │       ├─ name: YK2GW\n" +
			"         │   │   │       └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"         │   │   └─ TableAlias(ufc)\n" +
			"         │   │       └─ IndexedTableAccess(SISUT)\n" +
			"         │   │           ├─ index: [SISUT.T4IBQ]\n" +
			"         │   │           └─ columns: [id t4ibq zh72s amyxq ktnz2 hiid2 dn3oq vvknb sh7tp srzzo qz6vt]\n" +
			"         │   └─ TableAlias(applySubq0)\n" +
			"         │       └─ IndexedTableAccess(AMYXQ)\n" +
			"         │           ├─ index: [AMYXQ.KKGN5]\n" +
			"         │           └─ columns: [kkgn5]\n" +
			"         └─ Filter\n" +
			"             ├─ NOT\n" +
			"             │   └─ nd.ZH72S:7 IS NULL\n" +
			"             └─ TableAlias(nd)\n" +
			"                 └─ IndexedTableAccess(E2I7U)\n" +
			"                     ├─ index: [E2I7U.ZH72S]\n" +
			"                     └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ums.*
	FROM
	   FG26Y ums
	INNER JOIN
	   YK2GW cla
	ON
	   cla.FTQLQ = ums.T4IBQ
	WHERE
	   ums.id NOT IN (SELECT JOGI6 FROM SZQWJ)
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [ums.id:0!null, ums.T4IBQ:1, ums.ner:2, ums.ber:3, ums.hr:4, ums.mmr:5, ums.QZ6VT:6]\n" +
			" └─ AntiLookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ ums.id:0!null\n" +
			"     │   └─ applySubq0.JOGI6:37\n" +
			"     ├─ LookupJoin\n" +
			"     │   ├─ Eq\n" +
			"     │   │   ├─ cla.FTQLQ:8!null\n" +
			"     │   │   └─ ums.T4IBQ:1\n" +
			"     │   ├─ TableAlias(ums)\n" +
			"     │   │   └─ Table\n" +
			"     │   │       ├─ name: FG26Y\n" +
			"     │   │       └─ columns: [id t4ibq ner ber hr mmr qz6vt]\n" +
			"     │   └─ TableAlias(cla)\n" +
			"     │       └─ IndexedTableAccess(YK2GW)\n" +
			"     │           ├─ index: [YK2GW.FTQLQ]\n" +
			"     │           └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"     └─ TableAlias(applySubq0)\n" +
			"         └─ IndexedTableAccess(SZQWJ)\n" +
			"             ├─ index: [SZQWJ.JOGI6]\n" +
			"             └─ columns: [jogi6]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   mf.id AS id,
	   cla.FTQLQ AS T4IBQ,
	   nd.TW55N AS UWBAI,
	   aac.BTXC5 AS TPXBU,
	   mf.FSDY2 AS FSDY2
	FROM
	   HGMQ6 mf
	INNER JOIN
	   THNTS bs
	ON
	   bs.id = mf.GXLUB
	INNER JOIN
	   YK2GW cla
	ON
	   cla.id = bs.IXUXU
	INNER JOIN
	   E2I7U nd
	ON
	   nd.id = mf.LUEVY
	INNER JOIN
	   TPXBU aac
	ON
	   aac.id = mf.M22QN
	WHERE
	(
	       mf.QQV4M IS NOT NULL
	   AND
	       (
	               (SELECT TJ5D2.SWCQV FROM SZW6V TJ5D2 WHERE TJ5D2.id = mf.QQV4M) = 1
	           OR
	               (SELECT nd.id FROM E2I7U nd WHERE nd.TW55N =
	                   (SELECT TJ5D2.H4DMT FROM SZW6V TJ5D2
	                   WHERE TJ5D2.id = mf.QQV4M))
	               <> mf.LUEVY
	       )
	)
	OR
	(
	       mf.TEUJA IS NOT NULL
	   AND
	       mf.TEUJA IN
	       (
	       SELECT
	           umf.id AS ORB3K
	       FROM
	           SZW6V TJ5D2
	       INNER JOIN
	           NZKPM umf
	       ON
	               umf.T4IBQ = TJ5D2.T4IBQ
	           AND
	               umf.FGG57 = TJ5D2.V7UFH
	           AND
	               umf.SYPKF = TJ5D2.SYPKF
	       WHERE
	               TJ5D2.SWCQV = 0
	           AND
	               TJ5D2.id NOT IN (SELECT QQV4M FROM HGMQ6 WHERE QQV4M IS NOT NULL)
	       )
	)
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [mf.id:4!null as id, cla.FTQLQ:39!null as T4IBQ, nd.TW55N:24!null as UWBAI, aac.BTXC5:69 as TPXBU, mf.FSDY2:14!null as FSDY2]\n" +
			" └─ Filter\n" +
			"     ├─ Or\n" +
			"     │   ├─ AND\n" +
			"     │   │   ├─ NOT\n" +
			"     │   │   │   └─ mf.QQV4M:19 IS NULL\n" +
			"     │   │   └─ Or\n" +
			"     │   │       ├─ Eq\n" +
			"     │   │       │   ├─ Subquery\n" +
			"     │   │       │   │   ├─ cacheable: false\n" +
			"     │   │       │   │   └─ Project\n" +
			"     │   │       │   │       ├─ columns: [TJ5D2.SWCQV:72!null]\n" +
			"     │   │       │   │       └─ Filter\n" +
			"     │   │       │   │           ├─ Eq\n" +
			"     │   │       │   │           │   ├─ TJ5D2.id:71!null\n" +
			"     │   │       │   │           │   └─ mf.QQV4M:19\n" +
			"     │   │       │   │           └─ TableAlias(TJ5D2)\n" +
			"     │   │       │   │               └─ Table\n" +
			"     │   │       │   │                   ├─ name: SZW6V\n" +
			"     │   │       │   │                   └─ columns: [id swcqv]\n" +
			"     │   │       │   └─ 1 (tinyint)\n" +
			"     │   │       └─ NOT\n" +
			"     │   │           └─ Eq\n" +
			"     │   │               ├─ Subquery\n" +
			"     │   │               │   ├─ cacheable: false\n" +
			"     │   │               │   └─ Project\n" +
			"     │   │               │       ├─ columns: [nd.id:71!null]\n" +
			"     │   │               │       └─ Filter\n" +
			"     │   │               │           ├─ Eq\n" +
			"     │   │               │           │   ├─ nd.TW55N:74!null\n" +
			"     │   │               │           │   └─ Subquery\n" +
			"     │   │               │           │       ├─ cacheable: false\n" +
			"     │   │               │           │       └─ Project\n" +
			"     │   │               │           │           ├─ columns: [TJ5D2.H4DMT:89!null]\n" +
			"     │   │               │           │           └─ Filter\n" +
			"     │   │               │           │               ├─ Eq\n" +
			"     │   │               │           │               │   ├─ TJ5D2.id:88!null\n" +
			"     │   │               │           │               │   └─ mf.QQV4M:19\n" +
			"     │   │               │           │               └─ TableAlias(TJ5D2)\n" +
			"     │   │               │           │                   └─ Table\n" +
			"     │   │               │           │                       ├─ name: SZW6V\n" +
			"     │   │               │           │                       └─ columns: [id h4dmt]\n" +
			"     │   │               │           └─ TableAlias(nd)\n" +
			"     │   │               │               └─ Table\n" +
			"     │   │               │                   ├─ name: E2I7U\n" +
			"     │   │               │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     │   │               └─ mf.LUEVY:6!null\n" +
			"     │   └─ AND\n" +
			"     │       ├─ NOT\n" +
			"     │       │   └─ mf.TEUJA:18 IS NULL\n" +
			"     │       └─ InSubquery\n" +
			"     │           ├─ left: mf.TEUJA:18\n" +
			"     │           └─ right: Subquery\n" +
			"     │               ├─ cacheable: true\n" +
			"     │               └─ Project\n" +
			"     │                   ├─ columns: [umf.id:79!null as ORB3K]\n" +
			"     │                   └─ Filter\n" +
			"     │                       ├─ NOT\n" +
			"     │                       │   └─ InSubquery\n" +
			"     │                       │       ├─ left: TJ5D2.id:71!null\n" +
			"     │                       │       └─ right: Subquery\n" +
			"     │                       │           ├─ cacheable: true\n" +
			"     │                       │           └─ Filter\n" +
			"     │                       │               ├─ NOT\n" +
			"     │                       │               │   └─ HGMQ6.QQV4M:104 IS NULL\n" +
			"     │                       │               └─ IndexedTableAccess(HGMQ6)\n" +
			"     │                       │                   ├─ index: [HGMQ6.QQV4M]\n" +
			"     │                       │                   ├─ static: [{(NULL, ∞)}]\n" +
			"     │                       │                   └─ columns: [qqv4m]\n" +
			"     │                       └─ LookupJoin\n" +
			"     │                           ├─ AND\n" +
			"     │                           │   ├─ AND\n" +
			"     │                           │   │   ├─ Eq\n" +
			"     │                           │   │   │   ├─ umf.T4IBQ:80\n" +
			"     │                           │   │   │   └─ TJ5D2.T4IBQ:72!null\n" +
			"     │                           │   │   └─ Eq\n" +
			"     │                           │   │       ├─ umf.FGG57:81\n" +
			"     │                           │   │       └─ TJ5D2.V7UFH:73!null\n" +
			"     │                           │   └─ Eq\n" +
			"     │                           │       ├─ umf.SYPKF:87\n" +
			"     │                           │       └─ TJ5D2.SYPKF:74!null\n" +
			"     │                           ├─ Filter\n" +
			"     │                           │   ├─ Eq\n" +
			"     │                           │   │   ├─ TJ5D2.SWCQV:76!null\n" +
			"     │                           │   │   └─ 0 (tinyint)\n" +
			"     │                           │   └─ TableAlias(TJ5D2)\n" +
			"     │                           │       └─ Table\n" +
			"     │                           │           ├─ name: SZW6V\n" +
			"     │                           │           └─ columns: [id t4ibq v7ufh sypkf h4dmt swcqv ykssu fhcyt]\n" +
			"     │                           └─ TableAlias(umf)\n" +
			"     │                               └─ IndexedTableAccess(NZKPM)\n" +
			"     │                                   ├─ index: [NZKPM.FGG57]\n" +
			"     │                                   └─ columns: [id t4ibq fgg57 sshpj nla6o sfj6l tjpt7 arn5p sypkf ivfmk ide43 az6sp fsdy2 xosd4 hmw4h s76om vaf zroh6 qcgts lnfm6 tvawl hdlcl bhhw6 fhcyt qz6vt]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ aac.id:68!null\n" +
			"         │   └─ mf.M22QN:7!null\n" +
			"         ├─ LookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ cla.id:38!null\n" +
			"         │   │   └─ bs.IXUXU:2\n" +
			"         │   ├─ LookupJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ nd.id:21!null\n" +
			"         │   │   │   └─ mf.LUEVY:6!null\n" +
			"         │   │   ├─ LookupJoin\n" +
			"         │   │   │   ├─ Eq\n" +
			"         │   │   │   │   ├─ bs.id:0!null\n" +
			"         │   │   │   │   └─ mf.GXLUB:5!null\n" +
			"         │   │   │   ├─ TableAlias(bs)\n" +
			"         │   │   │   │   └─ Table\n" +
			"         │   │   │   │       ├─ name: THNTS\n" +
			"         │   │   │   │       └─ columns: [id nfryn ixuxu fhcyt]\n" +
			"         │   │   │   └─ TableAlias(mf)\n" +
			"         │   │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			"         │   │   │           ├─ index: [HGMQ6.GXLUB]\n" +
			"         │   │   │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			"         │   │   └─ TableAlias(nd)\n" +
			"         │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │   │           ├─ index: [E2I7U.id]\n" +
			"         │   │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"         │   └─ TableAlias(cla)\n" +
			"         │       └─ IndexedTableAccess(YK2GW)\n" +
			"         │           ├─ index: [YK2GW.id]\n" +
			"         │           └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"         └─ TableAlias(aac)\n" +
			"             └─ IndexedTableAccess(TPXBU)\n" +
			"                 ├─ index: [TPXBU.id]\n" +
			"                 └─ columns: [id btxc5 fhcyt]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   umf.*
	FROM
	   NZKPM umf
	INNER JOIN
	   E2I7U nd
	ON
	   nd.FGG57 = umf.FGG57
	INNER JOIN
	   YK2GW cla
	ON
	   cla.FTQLQ = umf.T4IBQ
	WHERE
	       nd.FGG57 IS NOT NULL
	   AND
	       umf.ARN5P <> 'N/A'
	   AND
	       umf.id NOT IN (SELECT TEUJA FROM HGMQ6)
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [umf.id:30!null, umf.T4IBQ:31, umf.FGG57:32, umf.SSHPJ:33, umf.NLA6O:34, umf.SFJ6L:35, umf.TJPT7:36, umf.ARN5P:37, umf.SYPKF:38, umf.IVFMK:39, umf.IDE43:40, umf.AZ6SP:41, umf.FSDY2:42, umf.XOSD4:43, umf.HMW4H:44, umf.S76OM:45, umf.vaf:46, umf.ZROH6:47, umf.QCGTS:48, umf.LNFM6:49, umf.TVAWL:50, umf.HDLCL:51, umf.BHHW6:52, umf.FHCYT:53, umf.QZ6VT:54]\n" +
			" └─ AntiLookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ umf.id:30!null\n" +
			"     │   └─ applySubq0.TEUJA:72\n" +
			"     ├─ LookupJoin\n" +
			"     │   ├─ Eq\n" +
			"     │   │   ├─ nd.FGG57:61\n" +
			"     │   │   └─ umf.FGG57:32\n" +
			"     │   ├─ LookupJoin\n" +
			"     │   │   ├─ Eq\n" +
			"     │   │   │   ├─ cla.FTQLQ:1!null\n" +
			"     │   │   │   └─ umf.T4IBQ:31\n" +
			"     │   │   ├─ TableAlias(cla)\n" +
			"     │   │   │   └─ Table\n" +
			"     │   │   │       ├─ name: YK2GW\n" +
			"     │   │   │       └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"     │   │   └─ Filter\n" +
			"     │   │       ├─ NOT\n" +
			"     │   │       │   └─ Eq\n" +
			"     │   │       │       ├─ umf.ARN5P:7\n" +
			"     │   │       │       └─ N/A (longtext)\n" +
			"     │   │       └─ TableAlias(umf)\n" +
			"     │   │           └─ IndexedTableAccess(NZKPM)\n" +
			"     │   │               ├─ index: [NZKPM.T4IBQ]\n" +
			"     │   │               └─ columns: [id t4ibq fgg57 sshpj nla6o sfj6l tjpt7 arn5p sypkf ivfmk ide43 az6sp fsdy2 xosd4 hmw4h s76om vaf zroh6 qcgts lnfm6 tvawl hdlcl bhhw6 fhcyt qz6vt]\n" +
			"     │   └─ Filter\n" +
			"     │       ├─ NOT\n" +
			"     │       │   └─ nd.FGG57:6 IS NULL\n" +
			"     │       └─ TableAlias(nd)\n" +
			"     │           └─ IndexedTableAccess(E2I7U)\n" +
			"     │               ├─ index: [E2I7U.FGG57]\n" +
			"     │               └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     └─ TableAlias(applySubq0)\n" +
			"         └─ IndexedTableAccess(HGMQ6)\n" +
			"             ├─ index: [HGMQ6.TEUJA]\n" +
			"             └─ columns: [teuja]\n" +
			"",
	},
	{
		Query: `SELECT
	   HVHRZ
	FROM
	   QYWQD
	ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [QYWQD.HVHRZ:1!null]\n" +
			" └─ IndexedTableAccess(QYWQD)\n" +
			"     ├─ index: [QYWQD.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id hvhrz]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   cla.FTQLQ AS T4IBQ,
	   SL3S5.TOFPN AS DL754,
	   sn.id AS BDNYB,
	   SL3S5.ADURZ AS ADURZ,
	   (SELECT aac.BTXC5 FROM TPXBU aac WHERE aac.id = SL3S5.M22QN) AS TPXBU,
	   SL3S5.NO52D AS NO52D,
	   SL3S5.IDPK7 AS IDPK7
	FROM
	   YK2GW cla
	INNER JOIN THNTS bs ON cla.id = bs.IXUXU
	INNER JOIN HGMQ6 mf ON bs.id = mf.GXLUB
	INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
	INNER JOIN
	   (
	   SELECT /*+ JOIN_ORDER( ci, ct, cec, KHJJO ) */
	       KHJJO.BDNYB AS BDNYB,
	       ci.FTQLQ AS TOFPN,
	       ct.M22QN AS M22QN,
	       cec.ADURZ AS ADURZ,
	       cec.NO52D AS NO52D,
	       ct.S3Q3Y AS IDPK7
	   FROM
	       (
	       SELECT DISTINCT
	           mf.M22QN AS M22QN,
	           sn.id AS BDNYB,
	           mf.LUEVY AS LUEVY
	       FROM
	           HGMQ6 mf
	       INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
	       ) KHJJO
	   INNER JOIN
	       FLQLP ct
	   ON
	           ct.M22QN = KHJJO.M22QN
	       AND
	           ct.LUEVY = KHJJO.LUEVY
	   INNER JOIN JDLNA ci ON  ci.id = ct.FZ2R5 AND ct.ZRV3B = '='
	   INNER JOIN SFEGG cec ON cec.id = ct.OVE3E
	   WHERE
	       ci.FTQLQ IN ('SQ1')
	   ) SL3S5
	ON
	       SL3S5.BDNYB = sn.id
	   AND
	       SL3S5.M22QN = mf.M22QN
	WHERE
	   cla.FTQLQ IN ('SQ1')
	UNION ALL
	
	SELECT
	   AOEV5.*,
	   VUMUY.*
	FROM (
	SELECT
	   SL3S5.TOFPN AS DL754,
	   sn.id AS BDNYB,
	   SL3S5.ADURZ AS ADURZ,
	   (SELECT aac.BTXC5 FROM TPXBU aac WHERE aac.id = SL3S5.M22QN) AS TPXBU,
	   SL3S5.NO52D AS NO52D,
	   SL3S5.IDPK7 AS IDPK7
	FROM
	   NOXN3 sn
	INNER JOIN
	   (
	   SELECT
	       sn.id AS BDNYB,
	       ci.FTQLQ AS TOFPN,
	       ct.M22QN AS M22QN,
	       cec.ADURZ AS ADURZ,
	       cec.NO52D AS NO52D,
	       ct.S3Q3Y AS IDPK7
	   FROM
	       NOXN3 sn
	   INNER JOIN
	       FLQLP ct
	   ON
	           ct.M22QN = (SELECT aac.id FROM TPXBU aac WHERE BTXC5 = 'WT')
	       AND
	           ct.LUEVY = sn.BRQP2
	   INNER JOIN JDLNA ci ON  ci.id = ct.FZ2R5 AND ct.ZRV3B = '='
	   INNER JOIN SFEGG cec ON cec.id = ct.OVE3E
	   WHERE
	       ci.FTQLQ IN ('SQ1')
	   ) SL3S5
	ON
	       SL3S5.BDNYB = sn.id ) VUMUY
	CROSS JOIN
	   (
	   SELECT * FROM (VALUES
	      ROW("1"),
	      ROW("2"),
	      ROW("3"),
	      ROW("4"),
	      ROW("5")
	       ) AS temp_AOEV5(T4IBQ)
	   ) AOEV5`,
		ExpectedPlan: "Union all\n" +
			" ├─ Project\n" +
			" │   ├─ columns: [convert\n" +
			" │   │   ├─ type: char\n" +
			" │   │   └─ T4IBQ:0!null\n" +
			" │   │   as T4IBQ, DL754:1!null, BDNYB:2!null, ADURZ:3!null, TPXBU:4, NO52D:5!null, IDPK7:6!null]\n" +
			" │   └─ Project\n" +
			" │       ├─ columns: [cla.FTQLQ:38!null as T4IBQ, SL3S5.TOFPN:1!null as DL754, sn.id:6!null as BDNYB, SL3S5.ADURZ:3!null as ADURZ, Subquery\n" +
			" │       │   ├─ cacheable: false\n" +
			" │       │   └─ Project\n" +
			" │       │       ├─ columns: [aac.BTXC5:68]\n" +
			" │       │       └─ Filter\n" +
			" │       │           ├─ Eq\n" +
			" │       │           │   ├─ aac.id:67!null\n" +
			" │       │           │   └─ SL3S5.M22QN:2!null\n" +
			" │       │           └─ TableAlias(aac)\n" +
			" │       │               └─ IndexedTableAccess(TPXBU)\n" +
			" │       │                   ├─ index: [TPXBU.id]\n" +
			" │       │                   └─ columns: [id btxc5]\n" +
			" │       │   as TPXBU, SL3S5.NO52D:4!null as NO52D, SL3S5.IDPK7:5!null as IDPK7]\n" +
			" │       └─ LookupJoin\n" +
			" │           ├─ Eq\n" +
			" │           │   ├─ cla.id:37!null\n" +
			" │           │   └─ bs.IXUXU:35\n" +
			" │           ├─ LookupJoin\n" +
			" │           │   ├─ Eq\n" +
			" │           │   │   ├─ bs.id:33!null\n" +
			" │           │   │   └─ mf.GXLUB:17!null\n" +
			" │           │   ├─ LookupJoin\n" +
			" │           │   │   ├─ AND\n" +
			" │           │   │   │   ├─ Eq\n" +
			" │           │   │   │   │   ├─ sn.BRQP2:7!null\n" +
			" │           │   │   │   │   └─ mf.LUEVY:18!null\n" +
			" │           │   │   │   └─ Eq\n" +
			" │           │   │   │       ├─ SL3S5.M22QN:2!null\n" +
			" │           │   │   │       └─ mf.M22QN:19!null\n" +
			" │           │   │   ├─ LookupJoin\n" +
			" │           │   │   │   ├─ Eq\n" +
			" │           │   │   │   │   ├─ SL3S5.BDNYB:0!null\n" +
			" │           │   │   │   │   └─ sn.id:6!null\n" +
			" │           │   │   │   ├─ SubqueryAlias\n" +
			" │           │   │   │   │   ├─ name: SL3S5\n" +
			" │           │   │   │   │   ├─ outerVisibility: false\n" +
			" │           │   │   │   │   ├─ cacheable: true\n" +
			" │           │   │   │   │   └─ Project\n" +
			" │           │   │   │   │       ├─ columns: [KHJJO.BDNYB:12!null as BDNYB, ci.FTQLQ:1!null as TOFPN, ct.M22QN:4!null as M22QN, cec.ADURZ:10!null as ADURZ, cec.NO52D:9!null as NO52D, ct.S3Q3Y:6!null as IDPK7]\n" +
			" │           │   │   │   │       └─ HashJoin\n" +
			" │           │   │   │   │           ├─ AND\n" +
			" │           │   │   │   │           │   ├─ Eq\n" +
			" │           │   │   │   │           │   │   ├─ ct.M22QN:4!null\n" +
			" │           │   │   │   │           │   │   └─ KHJJO.M22QN:11!null\n" +
			" │           │   │   │   │           │   └─ Eq\n" +
			" │           │   │   │   │           │       ├─ ct.LUEVY:3!null\n" +
			" │           │   │   │   │           │       └─ KHJJO.LUEVY:13!null\n" +
			" │           │   │   │   │           ├─ LookupJoin\n" +
			" │           │   │   │   │           │   ├─ Eq\n" +
			" │           │   │   │   │           │   │   ├─ cec.id:8!null\n" +
			" │           │   │   │   │           │   │   └─ ct.OVE3E:5!null\n" +
			" │           │   │   │   │           │   ├─ LookupJoin\n" +
			" │           │   │   │   │           │   │   ├─ Eq\n" +
			" │           │   │   │   │           │   │   │   ├─ ci.id:0!null\n" +
			" │           │   │   │   │           │   │   │   └─ ct.FZ2R5:2!null\n" +
			" │           │   │   │   │           │   │   ├─ Filter\n" +
			" │           │   │   │   │           │   │   │   ├─ HashIn\n" +
			" │           │   │   │   │           │   │   │   │   ├─ ci.FTQLQ:1!null\n" +
			" │           │   │   │   │           │   │   │   │   └─ TUPLE(SQ1 (longtext))\n" +
			" │           │   │   │   │           │   │   │   └─ TableAlias(ci)\n" +
			" │           │   │   │   │           │   │   │       └─ IndexedTableAccess(JDLNA)\n" +
			" │           │   │   │   │           │   │   │           ├─ index: [JDLNA.FTQLQ]\n" +
			" │           │   │   │   │           │   │   │           ├─ static: [{[SQ1, SQ1]}]\n" +
			" │           │   │   │   │           │   │   │           └─ columns: [id ftqlq]\n" +
			" │           │   │   │   │           │   │   └─ Filter\n" +
			" │           │   │   │   │           │   │       ├─ Eq\n" +
			" │           │   │   │   │           │   │       │   ├─ ct.ZRV3B:5!null\n" +
			" │           │   │   │   │           │   │       │   └─ = (longtext)\n" +
			" │           │   │   │   │           │   │       └─ TableAlias(ct)\n" +
			" │           │   │   │   │           │   │           └─ IndexedTableAccess(FLQLP)\n" +
			" │           │   │   │   │           │   │               ├─ index: [FLQLP.FZ2R5]\n" +
			" │           │   │   │   │           │   │               └─ columns: [fz2r5 luevy m22qn ove3e s3q3y zrv3b]\n" +
			" │           │   │   │   │           │   └─ TableAlias(cec)\n" +
			" │           │   │   │   │           │       └─ IndexedTableAccess(SFEGG)\n" +
			" │           │   │   │   │           │           ├─ index: [SFEGG.id]\n" +
			" │           │   │   │   │           │           └─ columns: [id no52d adurz]\n" +
			" │           │   │   │   │           └─ HashLookup\n" +
			" │           │   │   │   │               ├─ source: TUPLE(ct.M22QN:4!null, ct.LUEVY:3!null)\n" +
			" │           │   │   │   │               ├─ target: TUPLE(KHJJO.M22QN:0!null, KHJJO.LUEVY:2!null)\n" +
			" │           │   │   │   │               └─ CachedResults\n" +
			" │           │   │   │   │                   └─ SubqueryAlias\n" +
			" │           │   │   │   │                       ├─ name: KHJJO\n" +
			" │           │   │   │   │                       ├─ outerVisibility: false\n" +
			" │           │   │   │   │                       ├─ cacheable: true\n" +
			" │           │   │   │   │                       └─ Distinct\n" +
			" │           │   │   │   │                           └─ Project\n" +
			" │           │   │   │   │                               ├─ columns: [mf.M22QN:13!null as M22QN, sn.id:0!null as BDNYB, mf.LUEVY:12!null as LUEVY]\n" +
			" │           │   │   │   │                               └─ LookupJoin\n" +
			" │           │   │   │   │                                   ├─ Eq\n" +
			" │           │   │   │   │                                   │   ├─ sn.BRQP2:1!null\n" +
			" │           │   │   │   │                                   │   └─ mf.LUEVY:12!null\n" +
			" │           │   │   │   │                                   ├─ TableAlias(sn)\n" +
			" │           │   │   │   │                                   │   └─ Table\n" +
			" │           │   │   │   │                                   │       ├─ name: NOXN3\n" +
			" │           │   │   │   │                                   │       └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			" │           │   │   │   │                                   └─ TableAlias(mf)\n" +
			" │           │   │   │   │                                       └─ IndexedTableAccess(HGMQ6)\n" +
			" │           │   │   │   │                                           ├─ index: [HGMQ6.LUEVY]\n" +
			" │           │   │   │   │                                           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			" │           │   │   │   └─ TableAlias(sn)\n" +
			" │           │   │   │       └─ IndexedTableAccess(NOXN3)\n" +
			" │           │   │   │           ├─ index: [NOXN3.id]\n" +
			" │           │   │   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			" │           │   │   └─ TableAlias(mf)\n" +
			" │           │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			" │           │   │           ├─ index: [HGMQ6.LUEVY]\n" +
			" │           │   │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			" │           │   └─ TableAlias(bs)\n" +
			" │           │       └─ IndexedTableAccess(THNTS)\n" +
			" │           │           ├─ index: [THNTS.id]\n" +
			" │           │           └─ columns: [id nfryn ixuxu fhcyt]\n" +
			" │           └─ Filter\n" +
			" │               ├─ HashIn\n" +
			" │               │   ├─ cla.FTQLQ:1!null\n" +
			" │               │   └─ TUPLE(SQ1 (longtext))\n" +
			" │               └─ TableAlias(cla)\n" +
			" │                   └─ IndexedTableAccess(YK2GW)\n" +
			" │                       ├─ index: [YK2GW.id]\n" +
			" │                       └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			" └─ Project\n" +
			"     ├─ columns: [AOEV5.T4IBQ:0!null as T4IBQ, VUMUY.DL754:1!null, VUMUY.BDNYB:2!null, VUMUY.ADURZ:3!null, VUMUY.TPXBU:4, VUMUY.NO52D:5!null, VUMUY.IDPK7:6!null]\n" +
			"     └─ Project\n" +
			"         ├─ columns: [AOEV5.T4IBQ:6!null, VUMUY.DL754:0!null, VUMUY.BDNYB:1!null, VUMUY.ADURZ:2!null, VUMUY.TPXBU:3, VUMUY.NO52D:4!null, VUMUY.IDPK7:5!null]\n" +
			"         └─ CrossJoin\n" +
			"             ├─ SubqueryAlias\n" +
			"             │   ├─ name: VUMUY\n" +
			"             │   ├─ outerVisibility: false\n" +
			"             │   ├─ cacheable: true\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [SL3S5.TOFPN:1!null as DL754, sn.id:6!null as BDNYB, SL3S5.ADURZ:3!null as ADURZ, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [aac.BTXC5:17]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ aac.id:16!null\n" +
			"             │       │           │   └─ SL3S5.M22QN:2!null\n" +
			"             │       │           └─ TableAlias(aac)\n" +
			"             │       │               └─ IndexedTableAccess(TPXBU)\n" +
			"             │       │                   ├─ index: [TPXBU.id]\n" +
			"             │       │                   └─ columns: [id btxc5]\n" +
			"             │       │   as TPXBU, SL3S5.NO52D:4!null as NO52D, SL3S5.IDPK7:5!null as IDPK7]\n" +
			"             │       └─ LookupJoin\n" +
			"             │           ├─ Eq\n" +
			"             │           │   ├─ SL3S5.BDNYB:0!null\n" +
			"             │           │   └─ sn.id:6!null\n" +
			"             │           ├─ SubqueryAlias\n" +
			"             │           │   ├─ name: SL3S5\n" +
			"             │           │   ├─ outerVisibility: false\n" +
			"             │           │   ├─ cacheable: true\n" +
			"             │           │   └─ Project\n" +
			"             │           │       ├─ columns: [sn.id:17!null as BDNYB, ci.FTQLQ:16!null as TOFPN, ct.M22QN:6!null as M22QN, cec.ADURZ:2!null as ADURZ, cec.NO52D:1!null as NO52D, ct.S3Q3Y:12!null as IDPK7]\n" +
			"             │           │       └─ Filter\n" +
			"             │           │           ├─ Eq\n" +
			"             │           │           │   ├─ ct.M22QN:6!null\n" +
			"             │           │           │   └─ Subquery\n" +
			"             │           │           │       ├─ cacheable: true\n" +
			"             │           │           │       └─ Project\n" +
			"             │           │           │           ├─ columns: [aac.id:27!null]\n" +
			"             │           │           │           └─ Filter\n" +
			"             │           │           │               ├─ Eq\n" +
			"             │           │           │               │   ├─ aac.BTXC5:28\n" +
			"             │           │           │               │   └─ WT (longtext)\n" +
			"             │           │           │               └─ TableAlias(aac)\n" +
			"             │           │           │                   └─ IndexedTableAccess(TPXBU)\n" +
			"             │           │           │                       ├─ index: [TPXBU.BTXC5]\n" +
			"             │           │           │                       ├─ static: [{[WT, WT]}]\n" +
			"             │           │           │                       └─ columns: [id btxc5]\n" +
			"             │           │           └─ LookupJoin\n" +
			"             │           │               ├─ Eq\n" +
			"             │           │               │   ├─ ct.LUEVY:5!null\n" +
			"             │           │               │   └─ sn.BRQP2:18!null\n" +
			"             │           │               ├─ LookupJoin\n" +
			"             │           │               │   ├─ Eq\n" +
			"             │           │               │   │   ├─ ci.id:15!null\n" +
			"             │           │               │   │   └─ ct.FZ2R5:4!null\n" +
			"             │           │               │   ├─ LookupJoin\n" +
			"             │           │               │   │   ├─ Eq\n" +
			"             │           │               │   │   │   ├─ cec.id:0!null\n" +
			"             │           │               │   │   │   └─ ct.OVE3E:7!null\n" +
			"             │           │               │   │   ├─ TableAlias(cec)\n" +
			"             │           │               │   │   │   └─ Table\n" +
			"             │           │               │   │   │       ├─ name: SFEGG\n" +
			"             │           │               │   │   │       └─ columns: [id no52d adurz]\n" +
			"             │           │               │   │   └─ Filter\n" +
			"             │           │               │   │       ├─ Eq\n" +
			"             │           │               │   │       │   ├─ ct.ZRV3B:10!null\n" +
			"             │           │               │   │       │   └─ = (longtext)\n" +
			"             │           │               │   │       └─ TableAlias(ct)\n" +
			"             │           │               │   │           └─ IndexedTableAccess(FLQLP)\n" +
			"             │           │               │   │               ├─ index: [FLQLP.OVE3E]\n" +
			"             │           │               │   │               └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"             │           │               │   └─ Filter\n" +
			"             │           │               │       ├─ HashIn\n" +
			"             │           │               │       │   ├─ ci.FTQLQ:1!null\n" +
			"             │           │               │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"             │           │               │       └─ TableAlias(ci)\n" +
			"             │           │               │           └─ IndexedTableAccess(JDLNA)\n" +
			"             │           │               │               ├─ index: [JDLNA.id]\n" +
			"             │           │               │               └─ columns: [id ftqlq]\n" +
			"             │           │               └─ TableAlias(sn)\n" +
			"             │           │                   └─ IndexedTableAccess(NOXN3)\n" +
			"             │           │                       ├─ index: [NOXN3.BRQP2]\n" +
			"             │           │                       └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"             │           └─ TableAlias(sn)\n" +
			"             │               └─ IndexedTableAccess(NOXN3)\n" +
			"             │                   ├─ index: [NOXN3.id]\n" +
			"             │                   └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"             └─ SubqueryAlias\n" +
			"                 ├─ name: AOEV5\n" +
			"                 ├─ outerVisibility: false\n" +
			"                 ├─ cacheable: true\n" +
			"                 └─ Values() as temp_AOEV5\n" +
			"                     ├─ Row(\n" +
			"                     │  1 (longtext))\n" +
			"                     ├─ Row(\n" +
			"                     │  2 (longtext))\n" +
			"                     ├─ Row(\n" +
			"                     │  3 (longtext))\n" +
			"                     ├─ Row(\n" +
			"                     │  4 (longtext))\n" +
			"                     └─ Row(\n" +
			"                        5 (longtext))\n" +
			"",
	},
	{
		Query: `
	SELECT
	   cla.FTQLQ AS T4IBQ,
	   SL3S5.TOFPN AS DL754,
	   sn.id AS BDNYB,
	   SL3S5.ADURZ AS ADURZ,
	   (SELECT aac.BTXC5 FROM TPXBU aac WHERE aac.id = SL3S5.M22QN) AS TPXBU,
	   SL3S5.NO52D AS NO52D,
	   SL3S5.IDPK7 AS IDPK7
	FROM
	   YK2GW cla
	INNER JOIN THNTS bs ON cla.id = bs.IXUXU
	INNER JOIN HGMQ6 mf ON bs.id = mf.GXLUB
	INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
	INNER JOIN
	   (
	   SELECT
	       KHJJO.BDNYB AS BDNYB,
	       ci.FTQLQ AS TOFPN,
	       ct.M22QN AS M22QN,
	       cec.ADURZ AS ADURZ,
	       cec.NO52D AS NO52D,
	       ct.S3Q3Y AS IDPK7
	   FROM
	       (
	       SELECT DISTINCT
	           mf.M22QN AS M22QN,
	           sn.id AS BDNYB,
	           mf.LUEVY AS LUEVY
	       FROM
	           HGMQ6 mf
	       INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
	       ) KHJJO
	   INNER JOIN
	       FLQLP ct
	   ON
	           ct.M22QN = KHJJO.M22QN
	       AND
	           ct.LUEVY = KHJJO.LUEVY
	   INNER JOIN JDLNA ci ON  ci.id = ct.FZ2R5 AND ct.ZRV3B = '='
	   INNER JOIN SFEGG cec ON cec.id = ct.OVE3E
	   WHERE
	       ci.FTQLQ IN ('SQ1')
	   ) SL3S5
	ON
	       SL3S5.BDNYB = sn.id
	   AND
	       SL3S5.M22QN = mf.M22QN
	WHERE
	   cla.FTQLQ IN ('SQ1')
	UNION ALL
	
	SELECT
	   AOEV5.*,
	   VUMUY.*
	FROM (
	SELECT
	   SL3S5.TOFPN AS DL754,
	   sn.id AS BDNYB,
	   SL3S5.ADURZ AS ADURZ,
	   (SELECT aac.BTXC5 FROM TPXBU aac WHERE aac.id = SL3S5.M22QN) AS TPXBU,
	   SL3S5.NO52D AS NO52D,
	   SL3S5.IDPK7 AS IDPK7
	FROM
	   NOXN3 sn
	INNER JOIN
	   (
	   SELECT
	       sn.id AS BDNYB,
	       ci.FTQLQ AS TOFPN,
	       ct.M22QN AS M22QN,
	       cec.ADURZ AS ADURZ,
	       cec.NO52D AS NO52D,
	       ct.S3Q3Y AS IDPK7
	   FROM
	       NOXN3 sn
	   INNER JOIN
	       FLQLP ct
	   ON
	           ct.M22QN = (SELECT aac.id FROM TPXBU aac WHERE BTXC5 = 'WT')
	       AND
	           ct.LUEVY = sn.BRQP2
	   INNER JOIN JDLNA ci ON  ci.id = ct.FZ2R5 AND ct.ZRV3B = '='
	   INNER JOIN SFEGG cec ON cec.id = ct.OVE3E
	   WHERE
	       ci.FTQLQ IN ('SQ1')
	   ) SL3S5
	ON
	       SL3S5.BDNYB = sn.id ) VUMUY
	CROSS JOIN
	   (
	   SELECT * FROM (VALUES
	      ROW("1"),
	      ROW("2"),
	      ROW("3"),
	      ROW("4"),
	      ROW("5")
	       ) AS temp_AOEV5(T4IBQ)
	   ) AOEV5`,
		ExpectedPlan: "Union all\n" +
			" ├─ Project\n" +
			" │   ├─ columns: [convert\n" +
			" │   │   ├─ type: char\n" +
			" │   │   └─ T4IBQ:0!null\n" +
			" │   │   as T4IBQ, DL754:1!null, BDNYB:2!null, ADURZ:3!null, TPXBU:4, NO52D:5!null, IDPK7:6!null]\n" +
			" │   └─ Project\n" +
			" │       ├─ columns: [cla.FTQLQ:38!null as T4IBQ, SL3S5.TOFPN:1!null as DL754, sn.id:6!null as BDNYB, SL3S5.ADURZ:3!null as ADURZ, Subquery\n" +
			" │       │   ├─ cacheable: false\n" +
			" │       │   └─ Project\n" +
			" │       │       ├─ columns: [aac.BTXC5:68]\n" +
			" │       │       └─ Filter\n" +
			" │       │           ├─ Eq\n" +
			" │       │           │   ├─ aac.id:67!null\n" +
			" │       │           │   └─ SL3S5.M22QN:2!null\n" +
			" │       │           └─ TableAlias(aac)\n" +
			" │       │               └─ IndexedTableAccess(TPXBU)\n" +
			" │       │                   ├─ index: [TPXBU.id]\n" +
			" │       │                   └─ columns: [id btxc5]\n" +
			" │       │   as TPXBU, SL3S5.NO52D:4!null as NO52D, SL3S5.IDPK7:5!null as IDPK7]\n" +
			" │       └─ LookupJoin\n" +
			" │           ├─ Eq\n" +
			" │           │   ├─ cla.id:37!null\n" +
			" │           │   └─ bs.IXUXU:35\n" +
			" │           ├─ LookupJoin\n" +
			" │           │   ├─ Eq\n" +
			" │           │   │   ├─ bs.id:33!null\n" +
			" │           │   │   └─ mf.GXLUB:17!null\n" +
			" │           │   ├─ LookupJoin\n" +
			" │           │   │   ├─ AND\n" +
			" │           │   │   │   ├─ Eq\n" +
			" │           │   │   │   │   ├─ sn.BRQP2:7!null\n" +
			" │           │   │   │   │   └─ mf.LUEVY:18!null\n" +
			" │           │   │   │   └─ Eq\n" +
			" │           │   │   │       ├─ SL3S5.M22QN:2!null\n" +
			" │           │   │   │       └─ mf.M22QN:19!null\n" +
			" │           │   │   ├─ LookupJoin\n" +
			" │           │   │   │   ├─ Eq\n" +
			" │           │   │   │   │   ├─ SL3S5.BDNYB:0!null\n" +
			" │           │   │   │   │   └─ sn.id:6!null\n" +
			" │           │   │   │   ├─ SubqueryAlias\n" +
			" │           │   │   │   │   ├─ name: SL3S5\n" +
			" │           │   │   │   │   ├─ outerVisibility: false\n" +
			" │           │   │   │   │   ├─ cacheable: true\n" +
			" │           │   │   │   │   └─ Project\n" +
			" │           │   │   │   │       ├─ columns: [KHJJO.BDNYB:1!null as BDNYB, ci.FTQLQ:13!null as TOFPN, ct.M22QN:8!null as M22QN, cec.ADURZ:5!null as ADURZ, cec.NO52D:4!null as NO52D, ct.S3Q3Y:10!null as IDPK7]\n" +
			" │           │   │   │   │       └─ HashJoin\n" +
			" │           │   │   │   │           ├─ AND\n" +
			" │           │   │   │   │           │   ├─ Eq\n" +
			" │           │   │   │   │           │   │   ├─ ct.M22QN:8!null\n" +
			" │           │   │   │   │           │   │   └─ KHJJO.M22QN:0!null\n" +
			" │           │   │   │   │           │   └─ Eq\n" +
			" │           │   │   │   │           │       ├─ ct.LUEVY:7!null\n" +
			" │           │   │   │   │           │       └─ KHJJO.LUEVY:2!null\n" +
			" │           │   │   │   │           ├─ SubqueryAlias\n" +
			" │           │   │   │   │           │   ├─ name: KHJJO\n" +
			" │           │   │   │   │           │   ├─ outerVisibility: false\n" +
			" │           │   │   │   │           │   ├─ cacheable: true\n" +
			" │           │   │   │   │           │   └─ Distinct\n" +
			" │           │   │   │   │           │       └─ Project\n" +
			" │           │   │   │   │           │           ├─ columns: [mf.M22QN:13!null as M22QN, sn.id:0!null as BDNYB, mf.LUEVY:12!null as LUEVY]\n" +
			" │           │   │   │   │           │           └─ LookupJoin\n" +
			" │           │   │   │   │           │               ├─ Eq\n" +
			" │           │   │   │   │           │               │   ├─ sn.BRQP2:1!null\n" +
			" │           │   │   │   │           │               │   └─ mf.LUEVY:12!null\n" +
			" │           │   │   │   │           │               ├─ TableAlias(sn)\n" +
			" │           │   │   │   │           │               │   └─ Table\n" +
			" │           │   │   │   │           │               │       ├─ name: NOXN3\n" +
			" │           │   │   │   │           │               │       └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			" │           │   │   │   │           │               └─ TableAlias(mf)\n" +
			" │           │   │   │   │           │                   └─ IndexedTableAccess(HGMQ6)\n" +
			" │           │   │   │   │           │                       ├─ index: [HGMQ6.LUEVY]\n" +
			" │           │   │   │   │           │                       └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			" │           │   │   │   │           └─ HashLookup\n" +
			" │           │   │   │   │               ├─ source: TUPLE(KHJJO.M22QN:0!null, KHJJO.LUEVY:2!null)\n" +
			" │           │   │   │   │               ├─ target: TUPLE(ct.M22QN:5!null, ct.LUEVY:4!null)\n" +
			" │           │   │   │   │               └─ CachedResults\n" +
			" │           │   │   │   │                   └─ LookupJoin\n" +
			" │           │   │   │   │                       ├─ Eq\n" +
			" │           │   │   │   │                       │   ├─ ci.id:12!null\n" +
			" │           │   │   │   │                       │   └─ ct.FZ2R5:6!null\n" +
			" │           │   │   │   │                       ├─ LookupJoin\n" +
			" │           │   │   │   │                       │   ├─ Eq\n" +
			" │           │   │   │   │                       │   │   ├─ cec.id:3!null\n" +
			" │           │   │   │   │                       │   │   └─ ct.OVE3E:9!null\n" +
			" │           │   │   │   │                       │   ├─ TableAlias(cec)\n" +
			" │           │   │   │   │                       │   │   └─ Table\n" +
			" │           │   │   │   │                       │   │       ├─ name: SFEGG\n" +
			" │           │   │   │   │                       │   │       └─ columns: [id no52d adurz]\n" +
			" │           │   │   │   │                       │   └─ Filter\n" +
			" │           │   │   │   │                       │       ├─ Eq\n" +
			" │           │   │   │   │                       │       │   ├─ ct.ZRV3B:5!null\n" +
			" │           │   │   │   │                       │       │   └─ = (longtext)\n" +
			" │           │   │   │   │                       │       └─ TableAlias(ct)\n" +
			" │           │   │   │   │                       │           └─ IndexedTableAccess(FLQLP)\n" +
			" │           │   │   │   │                       │               ├─ index: [FLQLP.OVE3E]\n" +
			" │           │   │   │   │                       │               └─ columns: [fz2r5 luevy m22qn ove3e s3q3y zrv3b]\n" +
			" │           │   │   │   │                       └─ Filter\n" +
			" │           │   │   │   │                           ├─ HashIn\n" +
			" │           │   │   │   │                           │   ├─ ci.FTQLQ:1!null\n" +
			" │           │   │   │   │                           │   └─ TUPLE(SQ1 (longtext))\n" +
			" │           │   │   │   │                           └─ TableAlias(ci)\n" +
			" │           │   │   │   │                               └─ IndexedTableAccess(JDLNA)\n" +
			" │           │   │   │   │                                   ├─ index: [JDLNA.id]\n" +
			" │           │   │   │   │                                   └─ columns: [id ftqlq]\n" +
			" │           │   │   │   └─ TableAlias(sn)\n" +
			" │           │   │   │       └─ IndexedTableAccess(NOXN3)\n" +
			" │           │   │   │           ├─ index: [NOXN3.id]\n" +
			" │           │   │   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			" │           │   │   └─ TableAlias(mf)\n" +
			" │           │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			" │           │   │           ├─ index: [HGMQ6.LUEVY]\n" +
			" │           │   │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			" │           │   └─ TableAlias(bs)\n" +
			" │           │       └─ IndexedTableAccess(THNTS)\n" +
			" │           │           ├─ index: [THNTS.id]\n" +
			" │           │           └─ columns: [id nfryn ixuxu fhcyt]\n" +
			" │           └─ Filter\n" +
			" │               ├─ HashIn\n" +
			" │               │   ├─ cla.FTQLQ:1!null\n" +
			" │               │   └─ TUPLE(SQ1 (longtext))\n" +
			" │               └─ TableAlias(cla)\n" +
			" │                   └─ IndexedTableAccess(YK2GW)\n" +
			" │                       ├─ index: [YK2GW.id]\n" +
			" │                       └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			" └─ Project\n" +
			"     ├─ columns: [AOEV5.T4IBQ:0!null as T4IBQ, VUMUY.DL754:1!null, VUMUY.BDNYB:2!null, VUMUY.ADURZ:3!null, VUMUY.TPXBU:4, VUMUY.NO52D:5!null, VUMUY.IDPK7:6!null]\n" +
			"     └─ Project\n" +
			"         ├─ columns: [AOEV5.T4IBQ:6!null, VUMUY.DL754:0!null, VUMUY.BDNYB:1!null, VUMUY.ADURZ:2!null, VUMUY.TPXBU:3, VUMUY.NO52D:4!null, VUMUY.IDPK7:5!null]\n" +
			"         └─ CrossJoin\n" +
			"             ├─ SubqueryAlias\n" +
			"             │   ├─ name: VUMUY\n" +
			"             │   ├─ outerVisibility: false\n" +
			"             │   ├─ cacheable: true\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [SL3S5.TOFPN:1!null as DL754, sn.id:6!null as BDNYB, SL3S5.ADURZ:3!null as ADURZ, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [aac.BTXC5:17]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ aac.id:16!null\n" +
			"             │       │           │   └─ SL3S5.M22QN:2!null\n" +
			"             │       │           └─ TableAlias(aac)\n" +
			"             │       │               └─ IndexedTableAccess(TPXBU)\n" +
			"             │       │                   ├─ index: [TPXBU.id]\n" +
			"             │       │                   └─ columns: [id btxc5]\n" +
			"             │       │   as TPXBU, SL3S5.NO52D:4!null as NO52D, SL3S5.IDPK7:5!null as IDPK7]\n" +
			"             │       └─ LookupJoin\n" +
			"             │           ├─ Eq\n" +
			"             │           │   ├─ SL3S5.BDNYB:0!null\n" +
			"             │           │   └─ sn.id:6!null\n" +
			"             │           ├─ SubqueryAlias\n" +
			"             │           │   ├─ name: SL3S5\n" +
			"             │           │   ├─ outerVisibility: false\n" +
			"             │           │   ├─ cacheable: true\n" +
			"             │           │   └─ Project\n" +
			"             │           │       ├─ columns: [sn.id:17!null as BDNYB, ci.FTQLQ:16!null as TOFPN, ct.M22QN:6!null as M22QN, cec.ADURZ:2!null as ADURZ, cec.NO52D:1!null as NO52D, ct.S3Q3Y:12!null as IDPK7]\n" +
			"             │           │       └─ Filter\n" +
			"             │           │           ├─ Eq\n" +
			"             │           │           │   ├─ ct.M22QN:6!null\n" +
			"             │           │           │   └─ Subquery\n" +
			"             │           │           │       ├─ cacheable: true\n" +
			"             │           │           │       └─ Project\n" +
			"             │           │           │           ├─ columns: [aac.id:27!null]\n" +
			"             │           │           │           └─ Filter\n" +
			"             │           │           │               ├─ Eq\n" +
			"             │           │           │               │   ├─ aac.BTXC5:28\n" +
			"             │           │           │               │   └─ WT (longtext)\n" +
			"             │           │           │               └─ TableAlias(aac)\n" +
			"             │           │           │                   └─ IndexedTableAccess(TPXBU)\n" +
			"             │           │           │                       ├─ index: [TPXBU.BTXC5]\n" +
			"             │           │           │                       ├─ static: [{[WT, WT]}]\n" +
			"             │           │           │                       └─ columns: [id btxc5]\n" +
			"             │           │           └─ LookupJoin\n" +
			"             │           │               ├─ Eq\n" +
			"             │           │               │   ├─ ct.LUEVY:5!null\n" +
			"             │           │               │   └─ sn.BRQP2:18!null\n" +
			"             │           │               ├─ LookupJoin\n" +
			"             │           │               │   ├─ Eq\n" +
			"             │           │               │   │   ├─ ci.id:15!null\n" +
			"             │           │               │   │   └─ ct.FZ2R5:4!null\n" +
			"             │           │               │   ├─ LookupJoin\n" +
			"             │           │               │   │   ├─ Eq\n" +
			"             │           │               │   │   │   ├─ cec.id:0!null\n" +
			"             │           │               │   │   │   └─ ct.OVE3E:7!null\n" +
			"             │           │               │   │   ├─ TableAlias(cec)\n" +
			"             │           │               │   │   │   └─ Table\n" +
			"             │           │               │   │   │       ├─ name: SFEGG\n" +
			"             │           │               │   │   │       └─ columns: [id no52d adurz]\n" +
			"             │           │               │   │   └─ Filter\n" +
			"             │           │               │   │       ├─ Eq\n" +
			"             │           │               │   │       │   ├─ ct.ZRV3B:10!null\n" +
			"             │           │               │   │       │   └─ = (longtext)\n" +
			"             │           │               │   │       └─ TableAlias(ct)\n" +
			"             │           │               │   │           └─ IndexedTableAccess(FLQLP)\n" +
			"             │           │               │   │               ├─ index: [FLQLP.OVE3E]\n" +
			"             │           │               │   │               └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"             │           │               │   └─ Filter\n" +
			"             │           │               │       ├─ HashIn\n" +
			"             │           │               │       │   ├─ ci.FTQLQ:1!null\n" +
			"             │           │               │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"             │           │               │       └─ TableAlias(ci)\n" +
			"             │           │               │           └─ IndexedTableAccess(JDLNA)\n" +
			"             │           │               │               ├─ index: [JDLNA.id]\n" +
			"             │           │               │               └─ columns: [id ftqlq]\n" +
			"             │           │               └─ TableAlias(sn)\n" +
			"             │           │                   └─ IndexedTableAccess(NOXN3)\n" +
			"             │           │                       ├─ index: [NOXN3.BRQP2]\n" +
			"             │           │                       └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"             │           └─ TableAlias(sn)\n" +
			"             │               └─ IndexedTableAccess(NOXN3)\n" +
			"             │                   ├─ index: [NOXN3.id]\n" +
			"             │                   └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"             └─ SubqueryAlias\n" +
			"                 ├─ name: AOEV5\n" +
			"                 ├─ outerVisibility: false\n" +
			"                 ├─ cacheable: true\n" +
			"                 └─ Values() as temp_AOEV5\n" +
			"                     ├─ Row(\n" +
			"                     │  1 (longtext))\n" +
			"                     ├─ Row(\n" +
			"                     │  2 (longtext))\n" +
			"                     ├─ Row(\n" +
			"                     │  3 (longtext))\n" +
			"                     ├─ Row(\n" +
			"                     │  4 (longtext))\n" +
			"                     └─ Row(\n" +
			"                        5 (longtext))\n" +
			"",
	},
	{
		Query: `
	SELECT COUNT(*) FROM NOXN3`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [COUNT(1):0!null as COUNT(*)]\n" +
			" └─ GroupBy\n" +
			"     ├─ select: COUNT(1 (bigint))\n" +
			"     ├─ group: \n" +
			"     └─ Table\n" +
			"         ├─ name: NOXN3\n" +
			"         └─ columns: []\n" +
			"",
	},
	{
		Query: `
	SELECT
	   NB6PJ.Y3IOU AS Y3IOU,
	   S7EGW.TW55N AS FJVD7,
	   TYMVL.TW55N AS KBXXJ,
	   NB6PJ.NUMK2 AS NUMK2,
	   NB6PJ.LETOE AS LETOE
	FROM
	   (SELECT
	       ROW_NUMBER() OVER (ORDER BY id ASC) Y3IOU,
	       id,
	       BRQP2,
	       FFTBJ,
	       NUMK2,
	       LETOE
	   FROM
	       NOXN3
	   ORDER BY id ASC) NB6PJ
	INNER JOIN
	   E2I7U S7EGW
	ON
	   S7EGW.id = NB6PJ.BRQP2
	INNER JOIN
	   E2I7U TYMVL
	ON
	   TYMVL.id = NB6PJ.FFTBJ
	ORDER BY Y3IOU`,
		ExpectedPlan: "Sort(Y3IOU:0!null ASC nullsFirst)\n" +
			" └─ Project\n" +
			"     ├─ columns: [NB6PJ.Y3IOU:0!null as Y3IOU, S7EGW.TW55N:9!null as FJVD7, TYMVL.TW55N:7!null as KBXXJ, NB6PJ.NUMK2:4!null as NUMK2, NB6PJ.LETOE:5!null as LETOE]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ S7EGW.id:8!null\n" +
			"         │   └─ NB6PJ.BRQP2:2!null\n" +
			"         ├─ LookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ TYMVL.id:6!null\n" +
			"         │   │   └─ NB6PJ.FFTBJ:3!null\n" +
			"         │   ├─ SubqueryAlias\n" +
			"         │   │   ├─ name: NB6PJ\n" +
			"         │   │   ├─ outerVisibility: false\n" +
			"         │   │   ├─ cacheable: true\n" +
			"         │   │   └─ Sort(NOXN3.id:1!null ASC nullsFirst)\n" +
			"         │   │       └─ Project\n" +
			"         │   │           ├─ columns: [row_number() over ( order by NOXN3.id ASC):0!null as Y3IOU, NOXN3.id:1!null, NOXN3.BRQP2:2!null, NOXN3.FFTBJ:3!null, NOXN3.NUMK2:4!null, NOXN3.LETOE:5!null]\n" +
			"         │   │           └─ Window\n" +
			"         │   │               ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"         │   │               ├─ NOXN3.id:0!null\n" +
			"         │   │               ├─ NOXN3.BRQP2:1!null\n" +
			"         │   │               ├─ NOXN3.FFTBJ:2!null\n" +
			"         │   │               ├─ NOXN3.NUMK2:3!null\n" +
			"         │   │               ├─ NOXN3.LETOE:4!null\n" +
			"         │   │               └─ Table\n" +
			"         │   │                   ├─ name: NOXN3\n" +
			"         │   │                   └─ columns: [id brqp2 fftbj numk2 letoe]\n" +
			"         │   └─ TableAlias(TYMVL)\n" +
			"         │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │           ├─ index: [E2I7U.id]\n" +
			"         │           └─ columns: [id tw55n]\n" +
			"         └─ TableAlias(S7EGW)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.id]\n" +
			"                 └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   nd.TW55N AS TW55N,
	   NB6PJ.Y3IOU AS Y3IOU
	FROM
	   (SELECT
	       ROW_NUMBER() OVER (ORDER BY id ASC) Y3IOU,
	       id,
	       BRQP2,
	       FFTBJ,
	       NUMK2,
	       LETOE
	   FROM
	       NOXN3
	   ORDER BY id ASC) NB6PJ
	INNER JOIN
	   E2I7U nd
	ON
	   nd.id = NB6PJ.BRQP2
	ORDER BY TW55N, Y3IOU`,
		ExpectedPlan: "Sort(TW55N:0!null ASC nullsFirst, Y3IOU:1!null ASC nullsFirst)\n" +
			" └─ Project\n" +
			"     ├─ columns: [nd.TW55N:7!null as TW55N, NB6PJ.Y3IOU:0!null as Y3IOU]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ nd.id:6!null\n" +
			"         │   └─ NB6PJ.BRQP2:2!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: NB6PJ\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Sort(NOXN3.id:1!null ASC nullsFirst)\n" +
			"         │       └─ Project\n" +
			"         │           ├─ columns: [row_number() over ( order by NOXN3.id ASC):0!null as Y3IOU, NOXN3.id:1!null, NOXN3.BRQP2:2!null, NOXN3.FFTBJ:3!null, NOXN3.NUMK2:4!null, NOXN3.LETOE:5!null]\n" +
			"         │           └─ Window\n" +
			"         │               ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"         │               ├─ NOXN3.id:0!null\n" +
			"         │               ├─ NOXN3.BRQP2:1!null\n" +
			"         │               ├─ NOXN3.FFTBJ:2!null\n" +
			"         │               ├─ NOXN3.NUMK2:3!null\n" +
			"         │               ├─ NOXN3.LETOE:4!null\n" +
			"         │               └─ Table\n" +
			"         │                   ├─ name: NOXN3\n" +
			"         │                   └─ columns: [id brqp2 fftbj numk2 letoe]\n" +
			"         └─ TableAlias(nd)\n" +
			"             └─ IndexedTableAccess(E2I7U)\n" +
			"                 ├─ index: [E2I7U.id]\n" +
			"                 └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ROW_NUMBER() OVER (ORDER BY sn.id ASC) - 1 M6T2N,
	   S7EGW.TW55N FJVD7,
	   TYMVL.TW55N KBXXJ,
	   NUMK2,
	   LETOE,
	   sn.id XLFIA
	FROM
	   NOXN3 sn
	INNER JOIN
	   E2I7U S7EGW ON (sn.BRQP2 = S7EGW.id)
	INNER JOIN
	   E2I7U TYMVL ON (sn.FFTBJ = TYMVL.id)
	ORDER BY M6T2N ASC`,
		ExpectedPlan: "Sort(M6T2N:0!null ASC nullsFirst)\n" +
			" └─ Project\n" +
			"     ├─ columns: [(row_number() over ( order by sn.id ASC):0!null - 1 (tinyint)) as M6T2N, FJVD7:1!null, KBXXJ:2!null, sn.NUMK2:3!null, sn.LETOE:4!null, XLFIA:5!null]\n" +
			"     └─ Window\n" +
			"         ├─ row_number() over ( order by sn.id ASC)\n" +
			"         ├─ S7EGW.TW55N:8!null as FJVD7\n" +
			"         ├─ TYMVL.TW55N:1!null as KBXXJ\n" +
			"         ├─ sn.NUMK2:5!null\n" +
			"         ├─ sn.LETOE:6!null\n" +
			"         ├─ sn.id:2!null as XLFIA\n" +
			"         └─ LookupJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ sn.BRQP2:3!null\n" +
			"             │   └─ S7EGW.id:7!null\n" +
			"             ├─ LookupJoin\n" +
			"             │   ├─ Eq\n" +
			"             │   │   ├─ sn.FFTBJ:4!null\n" +
			"             │   │   └─ TYMVL.id:0!null\n" +
			"             │   ├─ TableAlias(TYMVL)\n" +
			"             │   │   └─ Table\n" +
			"             │   │       ├─ name: E2I7U\n" +
			"             │   │       └─ columns: [id tw55n]\n" +
			"             │   └─ TableAlias(sn)\n" +
			"             │       └─ IndexedTableAccess(NOXN3)\n" +
			"             │           ├─ index: [NOXN3.FFTBJ]\n" +
			"             │           └─ columns: [id brqp2 fftbj numk2 letoe]\n" +
			"             └─ TableAlias(S7EGW)\n" +
			"                 └─ IndexedTableAccess(E2I7U)\n" +
			"                     ├─ index: [E2I7U.id]\n" +
			"                     └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
	SELECT id FZZVR, ROW_NUMBER() OVER (ORDER BY sn.id ASC) - 1 M6T2N FROM NOXN3 sn`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [FZZVR:0!null, (row_number() over ( order by sn.id ASC):1!null - 1 (tinyint)) as M6T2N]\n" +
			" └─ Window\n" +
			"     ├─ sn.id:0!null as FZZVR\n" +
			"     ├─ row_number() over ( order by sn.id ASC)\n" +
			"     └─ TableAlias(sn)\n" +
			"         └─ Table\n" +
			"             ├─ name: NOXN3\n" +
			"             └─ columns: [id]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   nd.TW55N,
	   il.LIILR,
	   il.KSFXH,
	   il.KLMAU,
	   il.ecm
	FROM RLOHD il
	INNER JOIN E2I7U nd
	   ON il.LUEVY = nd.id
	INNER JOIN F35MI nt
	   ON nd.DKCAJ = nt.id
	WHERE nt.DZLIM <> 'SUZTA'
	
	ORDER BY nd.TW55N`,
		ExpectedPlan: "Sort(nd.TW55N:0!null ASC nullsFirst)\n" +
			" └─ Project\n" +
			"     ├─ columns: [nd.TW55N:4!null, il.LIILR:6, il.KSFXH:7, il.KLMAU:8, il.ecm:9]\n" +
			"     └─ LookupJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ il.LUEVY:5!null\n" +
			"         │   └─ nd.id:2!null\n" +
			"         ├─ LookupJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ nd.DKCAJ:3!null\n" +
			"         │   │   └─ nt.id:0!null\n" +
			"         │   ├─ Filter\n" +
			"         │   │   ├─ NOT\n" +
			"         │   │   │   └─ Eq\n" +
			"         │   │   │       ├─ nt.DZLIM:1!null\n" +
			"         │   │   │       └─ SUZTA (longtext)\n" +
			"         │   │   └─ TableAlias(nt)\n" +
			"         │   │       └─ IndexedTableAccess(F35MI)\n" +
			"         │   │           ├─ index: [F35MI.DZLIM]\n" +
			"         │   │           ├─ static: [{(SUZTA, ∞)}, {(NULL, SUZTA)}]\n" +
			"         │   │           └─ columns: [id dzlim]\n" +
			"         │   └─ TableAlias(nd)\n" +
			"         │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │           ├─ index: [E2I7U.DKCAJ]\n" +
			"         │           └─ columns: [id dkcaj tw55n]\n" +
			"         └─ TableAlias(il)\n" +
			"             └─ IndexedTableAccess(RLOHD)\n" +
			"                 ├─ index: [RLOHD.LUEVY]\n" +
			"                 └─ columns: [luevy liilr ksfxh klmau ecm]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   FTQLQ, TPNJ6
	FROM YK2GW
	WHERE FTQLQ IN ('SQ1')`,
		ExpectedPlan: "Filter\n" +
			" ├─ HashIn\n" +
			" │   ├─ YK2GW.FTQLQ:0!null\n" +
			" │   └─ TUPLE(SQ1 (longtext))\n" +
			" └─ IndexedTableAccess(YK2GW)\n" +
			"     ├─ index: [YK2GW.FTQLQ]\n" +
			"     ├─ static: [{[SQ1, SQ1]}]\n" +
			"     └─ columns: [ftqlq tpnj6]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ATHCU.T4IBQ AS T4IBQ,
	   ATHCU.TW55N AS TW55N,
	   CASE
	       WHEN fc.OZTQF IS NULL THEN 0
	       WHEN ATHCU.SJ5DU IN ('log', 'com', 'ex') THEN 0
	       WHEN ATHCU.SOWRY = 'CRZ2X' THEN 0
	       WHEN ATHCU.SOWRY = 'z' THEN fc.OZTQF
	       WHEN ATHCU.SOWRY = 'o' THEN fc.OZTQF - 1
	   END AS OZTQF
	FROM
	(
	   SELECT
	       B2TX3,
	       T4IBQ,
	       nd.id AS YYKXN,
	       nd.TW55N AS TW55N,
	       nd.FSK67 AS SOWRY,
	       (SELECT nt.DZLIM FROM F35MI nt WHERE nt.id = nd.DKCAJ) AS SJ5DU
	   FROM
	   (
	       SELECT
	           bs.id AS B2TX3,
	           cla.FTQLQ AS T4IBQ
	       FROM
	           YK2GW cla
	       INNER JOIN
	           THNTS bs
	       ON
	           bs.IXUXU = cla.id
	       WHERE
	           cla.FTQLQ IN ('SQ1')
	   ) TMDTP
	   CROSS JOIN
	       E2I7U nd
	) ATHCU
	LEFT JOIN
	   AMYXQ fc
	ON
	   fc.LUEVY = YYKXN
	   AND
	   fc.GXLUB = B2TX3
	ORDER BY
	   YYKXN
	`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [ATHCU.T4IBQ:1!null as T4IBQ, ATHCU.TW55N:3!null as TW55N, CASE  WHEN fc.OZTQF:8 IS NULL THEN 0 (tinyint) WHEN IN\n" +
			" │   ├─ left: ATHCU.SJ5DU:5\n" +
			" │   └─ right: TUPLE(log (longtext), com (longtext), ex (longtext))\n" +
			" │   THEN 0 (tinyint) WHEN Eq\n" +
			" │   ├─ ATHCU.SOWRY:4!null\n" +
			" │   └─ CRZ2X (longtext)\n" +
			" │   THEN 0 (tinyint) WHEN Eq\n" +
			" │   ├─ ATHCU.SOWRY:4!null\n" +
			" │   └─ z (longtext)\n" +
			" │   THEN fc.OZTQF:8 WHEN Eq\n" +
			" │   ├─ ATHCU.SOWRY:4!null\n" +
			" │   └─ o (longtext)\n" +
			" │   THEN (fc.OZTQF:8 - 1 (tinyint)) END as OZTQF]\n" +
			" └─ Sort(ATHCU.YYKXN:2!null ASC nullsFirst)\n" +
			"     └─ LeftOuterLookupJoin\n" +
			"         ├─ AND\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ fc.LUEVY:7!null\n" +
			"         │   │   └─ ATHCU.YYKXN:2!null\n" +
			"         │   └─ Eq\n" +
			"         │       ├─ fc.GXLUB:6!null\n" +
			"         │       └─ ATHCU.B2TX3:0!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: ATHCU\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Project\n" +
			"         │       ├─ columns: [TMDTP.B2TX3:0!null, TMDTP.T4IBQ:1!null, nd.id:2!null as YYKXN, nd.TW55N:5!null as TW55N, nd.FSK67:10!null as SOWRY, Subquery\n" +
			"         │       │   ├─ cacheable: false\n" +
			"         │       │   └─ Project\n" +
			"         │       │       ├─ columns: [nt.DZLIM:20!null]\n" +
			"         │       │       └─ Filter\n" +
			"         │       │           ├─ Eq\n" +
			"         │       │           │   ├─ nt.id:19!null\n" +
			"         │       │           │   └─ nd.DKCAJ:3!null\n" +
			"         │       │           └─ TableAlias(nt)\n" +
			"         │       │               └─ IndexedTableAccess(F35MI)\n" +
			"         │       │                   ├─ index: [F35MI.id]\n" +
			"         │       │                   └─ columns: [id dzlim]\n" +
			"         │       │   as SJ5DU]\n" +
			"         │       └─ CrossJoin\n" +
			"         │           ├─ SubqueryAlias\n" +
			"         │           │   ├─ name: TMDTP\n" +
			"         │           │   ├─ outerVisibility: false\n" +
			"         │           │   ├─ cacheable: true\n" +
			"         │           │   └─ Project\n" +
			"         │           │       ├─ columns: [bs.id:0!null as B2TX3, cla.FTQLQ:3!null as T4IBQ]\n" +
			"         │           │       └─ MergeJoin\n" +
			"         │           │           ├─ cmp: Eq\n" +
			"         │           │           │   ├─ bs.IXUXU:1\n" +
			"         │           │           │   └─ cla.id:2!null\n" +
			"         │           │           ├─ TableAlias(bs)\n" +
			"         │           │           │   └─ IndexedTableAccess(THNTS)\n" +
			"         │           │           │       ├─ index: [THNTS.IXUXU]\n" +
			"         │           │           │       ├─ static: [{[NULL, ∞)}]\n" +
			"         │           │           │       └─ columns: [id ixuxu]\n" +
			"         │           │           └─ Filter\n" +
			"         │           │               ├─ HashIn\n" +
			"         │           │               │   ├─ cla.FTQLQ:1!null\n" +
			"         │           │               │   └─ TUPLE(SQ1 (longtext))\n" +
			"         │           │               └─ TableAlias(cla)\n" +
			"         │           │                   └─ IndexedTableAccess(YK2GW)\n" +
			"         │           │                       ├─ index: [YK2GW.id]\n" +
			"         │           │                       ├─ static: [{[NULL, ∞)}]\n" +
			"         │           │                       └─ columns: [id ftqlq]\n" +
			"         │           └─ TableAlias(nd)\n" +
			"         │               └─ Table\n" +
			"         │                   ├─ name: E2I7U\n" +
			"         │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"         └─ TableAlias(fc)\n" +
			"             └─ IndexedTableAccess(AMYXQ)\n" +
			"                 ├─ index: [AMYXQ.GXLUB,AMYXQ.LUEVY]\n" +
			"                 └─ columns: [gxlub luevy oztqf]\n" +
			"",
	},
	{
		Query: `
	WITH AX7FV AS
	   (SELECT
	       bs.T4IBQ AS T4IBQ,
	       pa.DZLIM AS ECUWU,
	       pga.DZLIM AS GSTQA,
	       pog.B5OUF,
	       fc.OZTQF,
	       F26ZW.YHYLK,
	       nd.TW55N AS TW55N
	   FROM
	       SZQWJ ms
	   INNER JOIN XOAOP pa
	       ON ms.CH3FR = pa.id
	   LEFT JOIN NPCYY pog
	       ON pa.id = pog.CH3FR
	   INNER JOIN PG27A pga
	       ON pog.XVSBH = pga.id
	   INNER JOIN FEIOE GZ7Z4
	       ON pog.id = GZ7Z4.GMSGA
	   INNER JOIN E2I7U nd
	       ON GZ7Z4.LUEVY = nd.id
	   RIGHT JOIN (
	       SELECT
	           THNTS.id,
	           YK2GW.FTQLQ AS T4IBQ
	       FROM THNTS
	       INNER JOIN YK2GW
	       ON IXUXU = YK2GW.id
	   ) bs
	       ON ms.GXLUB = bs.id
	   LEFT JOIN AMYXQ fc
	       ON bs.id = fc.GXLUB AND nd.id = fc.LUEVY
	   LEFT JOIN (
	       SELECT
	           iq.T4IBQ,
	           iq.BRQP2,
	           iq.Z7CP5,
	           CASE
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P = 'L5Q44' AND iq.IDWIO = 'KAOAS'
	               THEN 0
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P = 'L5Q44' AND iq.IDWIO = 'OG'
	               THEN 0
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P = 'L5Q44' AND iq.IDWIO = 'TSG'
	               THEN 0
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P <> 'L5Q44' AND iq.IDWIO = 'W6W24'
	               THEN 1
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P <> 'L5Q44' AND iq.IDWIO = 'OG'
	               THEN 1
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P <> 'L5Q44' AND iq.IDWIO = 'TSG'
	               THEN 0
	               ELSE NULL
	           END AS YHYLK
	       FROM (
	           SELECT /*+ JOIN_ORDER( cla, bs, mf, nd, nma, sn ) */
	               cla.FTQLQ AS T4IBQ,
	               sn.BRQP2,
	               mf.id AS Z7CP5,
	               mf.FSDY2,
	               nma.DZLIM AS IDWIO
	           FROM
	               HGMQ6 mf
	           INNER JOIN THNTS bs
	               ON mf.GXLUB = bs.id
	           INNER JOIN YK2GW cla
	               ON bs.IXUXU = cla.id
	           INNER JOIN E2I7U nd
	               ON mf.LUEVY = nd.id
	           INNER JOIN TNMXI nma
	               ON nd.HPCMS = nma.id
	           INNER JOIN NOXN3 sn
	               ON sn.BRQP2 = nd.id
	           WHERE cla.FTQLQ IN ('SQ1')
	       ) iq
	       LEFT JOIN SEQS3 W2MAO
	           ON iq.Z7CP5 = W2MAO.Z7CP5
	       LEFT JOIN D34QP vc
	           ON W2MAO.YH4XB = vc.id
	   ) F26ZW
	       ON F26ZW.T4IBQ = bs.T4IBQ AND F26ZW.BRQP2 = nd.id
	   LEFT JOIN TNMXI nma
	       ON nd.HPCMS = nma.id
	   WHERE bs.T4IBQ IN ('SQ1') AND ms.D237E = TRUE)
	SELECT
	   XPRW6.T4IBQ AS T4IBQ,
	   XPRW6.ECUWU AS ECUWU,
	   SUM(XPRW6.B5OUF) AS B5OUF,
	   SUM(XPRW6.SP4SI) AS SP4SI
	FROM (
	   SELECT
	       NRFJ3.T4IBQ AS T4IBQ,
	       NRFJ3.ECUWU AS ECUWU,
	       NRFJ3.GSTQA AS GSTQA,
	       NRFJ3.B5OUF AS B5OUF,
	       SUM(CASE
	               WHEN NRFJ3.OZTQF < 0.5 OR NRFJ3.YHYLK = 0 THEN 1
	               ELSE 0
	           END) AS SP4SI
	   FROM (
	       SELECT DISTINCT
	           T4IBQ,
	           ECUWU,
	           GSTQA,
	           B5OUF,
	           TW55N,
	           OZTQF,
	           YHYLK
	       FROM
	           AX7FV) NRFJ3
	   GROUP BY T4IBQ, ECUWU, GSTQA
	) XPRW6
	GROUP BY T4IBQ, ECUWU`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [T4IBQ:0!null, ECUWU:1, SUM(XPRW6.B5OUF):2!null as B5OUF, SUM(XPRW6.SP4SI):3!null as SP4SI]\n" +
			" └─ GroupBy\n" +
			"     ├─ select: T4IBQ:0!null, ECUWU:1, SUM(XPRW6.B5OUF:2), SUM(XPRW6.SP4SI:3!null)\n" +
			"     ├─ group: T4IBQ:0!null, ECUWU:1\n" +
			"     └─ Project\n" +
			"         ├─ columns: [XPRW6.T4IBQ:0!null as T4IBQ, XPRW6.ECUWU:1 as ECUWU, XPRW6.B5OUF:3, XPRW6.SP4SI:4!null]\n" +
			"         └─ SubqueryAlias\n" +
			"             ├─ name: XPRW6\n" +
			"             ├─ outerVisibility: false\n" +
			"             ├─ cacheable: true\n" +
			"             └─ Project\n" +
			"                 ├─ columns: [T4IBQ:0!null, ECUWU:1, GSTQA:2, B5OUF:3, SUM(CASE  WHEN ((NRFJ3.OZTQF < 0.5) OR (NRFJ3.YHYLK = 0)) THEN 1 ELSE 0 END):4!null as SP4SI]\n" +
			"                 └─ GroupBy\n" +
			"                     ├─ select: T4IBQ:0!null, ECUWU:1, GSTQA:2, NRFJ3.B5OUF:3 as B5OUF, SUM(CASE  WHEN Or\n" +
			"                     │   ├─ LessThan\n" +
			"                     │   │   ├─ NRFJ3.OZTQF:4\n" +
			"                     │   │   └─ 0.500000 (double)\n" +
			"                     │   └─ Eq\n" +
			"                     │       ├─ NRFJ3.YHYLK:5\n" +
			"                     │       └─ 0 (tinyint)\n" +
			"                     │   THEN 1 (tinyint) ELSE 0 (tinyint) END)\n" +
			"                     ├─ group: T4IBQ:0!null, ECUWU:1, GSTQA:2\n" +
			"                     └─ Project\n" +
			"                         ├─ columns: [NRFJ3.T4IBQ:0!null as T4IBQ, NRFJ3.ECUWU:1 as ECUWU, NRFJ3.GSTQA:2 as GSTQA, NRFJ3.B5OUF:3, NRFJ3.OZTQF:5, NRFJ3.YHYLK:6]\n" +
			"                         └─ SubqueryAlias\n" +
			"                             ├─ name: NRFJ3\n" +
			"                             ├─ outerVisibility: false\n" +
			"                             ├─ cacheable: true\n" +
			"                             └─ Distinct\n" +
			"                                 └─ Project\n" +
			"                                     ├─ columns: [AX7FV.T4IBQ:0!null, AX7FV.ECUWU:1, AX7FV.GSTQA:2, AX7FV.B5OUF:3, AX7FV.TW55N:6, AX7FV.OZTQF:4, AX7FV.YHYLK:5]\n" +
			"                                     └─ SubqueryAlias\n" +
			"                                         ├─ name: AX7FV\n" +
			"                                         ├─ outerVisibility: false\n" +
			"                                         ├─ cacheable: true\n" +
			"                                         └─ Project\n" +
			"                                             ├─ columns: [bs.T4IBQ:1!null as T4IBQ, pa.DZLIM:3 as ECUWU, pga.DZLIM:12 as GSTQA, pog.B5OUF:10, fc.OZTQF:20, F26ZW.YHYLK:24, nd.TW55N:16 as TW55N]\n" +
			"                                             └─ Filter\n" +
			"                                                 ├─ Eq\n" +
			"                                                 │   ├─ ms.D237E:6\n" +
			"                                                 │   └─ %!s(bool=true) (tinyint)\n" +
			"                                                 └─ LeftOuterLookupJoin\n" +
			"                                                     ├─ Eq\n" +
			"                                                     │   ├─ nd.HPCMS:17\n" +
			"                                                     │   └─ nma.id:25!null\n" +
			"                                                     ├─ LeftOuterJoin\n" +
			"                                                     │   ├─ AND\n" +
			"                                                     │   │   ├─ Eq\n" +
			"                                                     │   │   │   ├─ F26ZW.T4IBQ:21!null\n" +
			"                                                     │   │   │   └─ bs.T4IBQ:1!null\n" +
			"                                                     │   │   └─ Eq\n" +
			"                                                     │   │       ├─ F26ZW.BRQP2:22!null\n" +
			"                                                     │   │       └─ nd.id:15\n" +
			"                                                     │   ├─ LeftOuterLookupJoin\n" +
			"                                                     │   │   ├─ AND\n" +
			"                                                     │   │   │   ├─ Eq\n" +
			"                                                     │   │   │   │   ├─ bs.id:0!null\n" +
			"                                                     │   │   │   │   └─ fc.GXLUB:18!null\n" +
			"                                                     │   │   │   └─ Eq\n" +
			"                                                     │   │   │       ├─ nd.id:15\n" +
			"                                                     │   │   │       └─ fc.LUEVY:19!null\n" +
			"                                                     │   │   ├─ LeftOuterJoin\n" +
			"                                                     │   │   │   ├─ Eq\n" +
			"                                                     │   │   │   │   ├─ ms.GXLUB:4!null\n" +
			"                                                     │   │   │   │   └─ bs.id:0!null\n" +
			"                                                     │   │   │   ├─ SubqueryAlias\n" +
			"                                                     │   │   │   │   ├─ name: bs\n" +
			"                                                     │   │   │   │   ├─ outerVisibility: false\n" +
			"                                                     │   │   │   │   ├─ cacheable: true\n" +
			"                                                     │   │   │   │   └─ Filter\n" +
			"                                                     │   │   │   │       ├─ HashIn\n" +
			"                                                     │   │   │   │       │   ├─ T4IBQ:1!null\n" +
			"                                                     │   │   │   │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"                                                     │   │   │   │       └─ Project\n" +
			"                                                     │   │   │   │           ├─ columns: [THNTS.id:2!null, YK2GW.FTQLQ:1!null as T4IBQ]\n" +
			"                                                     │   │   │   │           └─ MergeJoin\n" +
			"                                                     │   │   │   │               ├─ cmp: Eq\n" +
			"                                                     │   │   │   │               │   ├─ YK2GW.id:0!null\n" +
			"                                                     │   │   │   │               │   └─ THNTS.IXUXU:3\n" +
			"                                                     │   │   │   │               ├─ IndexedTableAccess(YK2GW)\n" +
			"                                                     │   │   │   │               │   ├─ index: [YK2GW.id]\n" +
			"                                                     │   │   │   │               │   ├─ static: [{[NULL, ∞)}]\n" +
			"                                                     │   │   │   │               │   └─ columns: [id ftqlq]\n" +
			"                                                     │   │   │   │               └─ IndexedTableAccess(THNTS)\n" +
			"                                                     │   │   │   │                   ├─ index: [THNTS.IXUXU]\n" +
			"                                                     │   │   │   │                   ├─ static: [{[NULL, ∞)}]\n" +
			"                                                     │   │   │   │                   └─ columns: [id ixuxu]\n" +
			"                                                     │   │   │   └─ LookupJoin\n" +
			"                                                     │   │   │       ├─ Eq\n" +
			"                                                     │   │   │       │   ├─ GZ7Z4.LUEVY:13!null\n" +
			"                                                     │   │   │       │   └─ nd.id:15!null\n" +
			"                                                     │   │   │       ├─ LookupJoin\n" +
			"                                                     │   │   │       │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   ├─ pog.id:7\n" +
			"                                                     │   │   │       │   │   └─ GZ7Z4.GMSGA:14!null\n" +
			"                                                     │   │   │       │   ├─ LookupJoin\n" +
			"                                                     │   │   │       │   │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   │   ├─ pog.XVSBH:9\n" +
			"                                                     │   │   │       │   │   │   └─ pga.id:11!null\n" +
			"                                                     │   │   │       │   │   ├─ LeftOuterLookupJoin\n" +
			"                                                     │   │   │       │   │   │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   │   │   ├─ pa.id:2!null\n" +
			"                                                     │   │   │       │   │   │   │   └─ pog.CH3FR:8!null\n" +
			"                                                     │   │   │       │   │   │   ├─ LookupJoin\n" +
			"                                                     │   │   │       │   │   │   │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   │   │   │   ├─ ms.CH3FR:5!null\n" +
			"                                                     │   │   │       │   │   │   │   │   └─ pa.id:2!null\n" +
			"                                                     │   │   │       │   │   │   │   ├─ TableAlias(pa)\n" +
			"                                                     │   │   │       │   │   │   │   │   └─ Table\n" +
			"                                                     │   │   │       │   │   │   │   │       ├─ name: XOAOP\n" +
			"                                                     │   │   │       │   │   │   │   │       └─ columns: [id dzlim]\n" +
			"                                                     │   │   │       │   │   │   │   └─ TableAlias(ms)\n" +
			"                                                     │   │   │       │   │   │   │       └─ IndexedTableAccess(SZQWJ)\n" +
			"                                                     │   │   │       │   │   │   │           ├─ index: [SZQWJ.CH3FR]\n" +
			"                                                     │   │   │       │   │   │   │           └─ columns: [gxlub ch3fr d237e]\n" +
			"                                                     │   │   │       │   │   │   └─ TableAlias(pog)\n" +
			"                                                     │   │   │       │   │   │       └─ IndexedTableAccess(NPCYY)\n" +
			"                                                     │   │   │       │   │   │           ├─ index: [NPCYY.CH3FR,NPCYY.XVSBH]\n" +
			"                                                     │   │   │       │   │   │           └─ columns: [id ch3fr xvsbh b5ouf]\n" +
			"                                                     │   │   │       │   │   └─ TableAlias(pga)\n" +
			"                                                     │   │   │       │   │       └─ IndexedTableAccess(PG27A)\n" +
			"                                                     │   │   │       │   │           ├─ index: [PG27A.id]\n" +
			"                                                     │   │   │       │   │           └─ columns: [id dzlim]\n" +
			"                                                     │   │   │       │   └─ TableAlias(GZ7Z4)\n" +
			"                                                     │   │   │       │       └─ IndexedTableAccess(FEIOE)\n" +
			"                                                     │   │   │       │           ├─ index: [FEIOE.GMSGA]\n" +
			"                                                     │   │   │       │           └─ columns: [luevy gmsga]\n" +
			"                                                     │   │   │       └─ TableAlias(nd)\n" +
			"                                                     │   │   │           └─ IndexedTableAccess(E2I7U)\n" +
			"                                                     │   │   │               ├─ index: [E2I7U.id]\n" +
			"                                                     │   │   │               └─ columns: [id tw55n hpcms]\n" +
			"                                                     │   │   └─ TableAlias(fc)\n" +
			"                                                     │   │       └─ IndexedTableAccess(AMYXQ)\n" +
			"                                                     │   │           ├─ index: [AMYXQ.GXLUB,AMYXQ.LUEVY]\n" +
			"                                                     │   │           └─ columns: [gxlub luevy oztqf]\n" +
			"                                                     │   └─ SubqueryAlias\n" +
			"                                                     │       ├─ name: F26ZW\n" +
			"                                                     │       ├─ outerVisibility: false\n" +
			"                                                     │       ├─ cacheable: true\n" +
			"                                                     │       └─ Project\n" +
			"                                                     │           ├─ columns: [iq.T4IBQ:0!null, iq.BRQP2:1!null, iq.Z7CP5:2!null, CASE  WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ Eq\n" +
			"                                                     │           │   │       ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │       └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ KAOAS (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ Eq\n" +
			"                                                     │           │   │       ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │       └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ OG (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ Eq\n" +
			"                                                     │           │   │       ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │       └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ TSG (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ NOT\n" +
			"                                                     │           │   │       └─ Eq\n" +
			"                                                     │           │   │           ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │           └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ W6W24 (longtext)\n" +
			"                                                     │           │   THEN 1 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ NOT\n" +
			"                                                     │           │   │       └─ Eq\n" +
			"                                                     │           │   │           ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │           └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ OG (longtext)\n" +
			"                                                     │           │   THEN 1 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ NOT\n" +
			"                                                     │           │   │       └─ Eq\n" +
			"                                                     │           │   │           ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │           └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ TSG (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) ELSE NULL (null) END as YHYLK]\n" +
			"                                                     │           └─ LeftOuterHashJoin\n" +
			"                                                     │               ├─ Eq\n" +
			"                                                     │               │   ├─ W2MAO.YH4XB:6\n" +
			"                                                     │               │   └─ vc.id:7!null\n" +
			"                                                     │               ├─ LeftOuterLookupJoin\n" +
			"                                                     │               │   ├─ Eq\n" +
			"                                                     │               │   │   ├─ iq.Z7CP5:2!null\n" +
			"                                                     │               │   │   └─ W2MAO.Z7CP5:5!null\n" +
			"                                                     │               │   ├─ SubqueryAlias\n" +
			"                                                     │               │   │   ├─ name: iq\n" +
			"                                                     │               │   │   ├─ outerVisibility: false\n" +
			"                                                     │               │   │   ├─ cacheable: true\n" +
			"                                                     │               │   │   └─ Project\n" +
			"                                                     │               │   │       ├─ columns: [cla.FTQLQ:1!null as T4IBQ, sn.BRQP2:12!null, mf.id:4!null as Z7CP5, mf.FSDY2:7!null, nma.DZLIM:11!null as IDWIO]\n" +
			"                                                     │               │   │       └─ HashJoin\n" +
			"                                                     │               │   │           ├─ Eq\n" +
			"                                                     │               │   │           │   ├─ bs.IXUXU:3\n" +
			"                                                     │               │   │           │   └─ cla.id:0!null\n" +
			"                                                     │               │   │           ├─ Filter\n" +
			"                                                     │               │   │           │   ├─ HashIn\n" +
			"                                                     │               │   │           │   │   ├─ cla.FTQLQ:1!null\n" +
			"                                                     │               │   │           │   │   └─ TUPLE(SQ1 (longtext))\n" +
			"                                                     │               │   │           │   └─ TableAlias(cla)\n" +
			"                                                     │               │   │           │       └─ IndexedTableAccess(YK2GW)\n" +
			"                                                     │               │   │           │           ├─ index: [YK2GW.FTQLQ]\n" +
			"                                                     │               │   │           │           ├─ static: [{[SQ1, SQ1]}]\n" +
			"                                                     │               │   │           │           └─ columns: [id ftqlq]\n" +
			"                                                     │               │   │           └─ HashLookup\n" +
			"                                                     │               │   │               ├─ source: TUPLE(cla.id:0!null)\n" +
			"                                                     │               │   │               ├─ target: TUPLE(bs.IXUXU:1)\n" +
			"                                                     │               │   │               └─ CachedResults\n" +
			"                                                     │               │   │                   └─ LookupJoin\n" +
			"                                                     │               │   │                       ├─ Eq\n" +
			"                                                     │               │   │                       │   ├─ sn.BRQP2:12!null\n" +
			"                                                     │               │   │                       │   └─ nd.id:8!null\n" +
			"                                                     │               │   │                       ├─ HashJoin\n" +
			"                                                     │               │   │                       │   ├─ Eq\n" +
			"                                                     │               │   │                       │   │   ├─ nd.HPCMS:9!null\n" +
			"                                                     │               │   │                       │   │   └─ nma.id:10!null\n" +
			"                                                     │               │   │                       │   ├─ LookupJoin\n" +
			"                                                     │               │   │                       │   │   ├─ Eq\n" +
			"                                                     │               │   │                       │   │   │   ├─ mf.LUEVY:6!null\n" +
			"                                                     │               │   │                       │   │   │   └─ nd.id:8!null\n" +
			"                                                     │               │   │                       │   │   ├─ LookupJoin\n" +
			"                                                     │               │   │                       │   │   │   ├─ Eq\n" +
			"                                                     │               │   │                       │   │   │   │   ├─ mf.GXLUB:5!null\n" +
			"                                                     │               │   │                       │   │   │   │   └─ bs.id:2!null\n" +
			"                                                     │               │   │                       │   │   │   ├─ TableAlias(bs)\n" +
			"                                                     │               │   │                       │   │   │   │   └─ Table\n" +
			"                                                     │               │   │                       │   │   │   │       ├─ name: THNTS\n" +
			"                                                     │               │   │                       │   │   │   │       └─ columns: [id ixuxu]\n" +
			"                                                     │               │   │                       │   │   │   └─ TableAlias(mf)\n" +
			"                                                     │               │   │                       │   │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			"                                                     │               │   │                       │   │   │           ├─ index: [HGMQ6.GXLUB]\n" +
			"                                                     │               │   │                       │   │   │           └─ columns: [id gxlub luevy fsdy2]\n" +
			"                                                     │               │   │                       │   │   └─ TableAlias(nd)\n" +
			"                                                     │               │   │                       │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"                                                     │               │   │                       │   │           ├─ index: [E2I7U.id]\n" +
			"                                                     │               │   │                       │   │           └─ columns: [id hpcms]\n" +
			"                                                     │               │   │                       │   └─ HashLookup\n" +
			"                                                     │               │   │                       │       ├─ source: TUPLE(nd.HPCMS:9!null)\n" +
			"                                                     │               │   │                       │       ├─ target: TUPLE(nma.id:0!null)\n" +
			"                                                     │               │   │                       │       └─ CachedResults\n" +
			"                                                     │               │   │                       │           └─ TableAlias(nma)\n" +
			"                                                     │               │   │                       │               └─ Table\n" +
			"                                                     │               │   │                       │                   ├─ name: TNMXI\n" +
			"                                                     │               │   │                       │                   └─ columns: [id dzlim]\n" +
			"                                                     │               │   │                       └─ TableAlias(sn)\n" +
			"                                                     │               │   │                           └─ IndexedTableAccess(NOXN3)\n" +
			"                                                     │               │   │                               ├─ index: [NOXN3.BRQP2]\n" +
			"                                                     │               │   │                               └─ columns: [brqp2]\n" +
			"                                                     │               │   └─ TableAlias(W2MAO)\n" +
			"                                                     │               │       └─ IndexedTableAccess(SEQS3)\n" +
			"                                                     │               │           ├─ index: [SEQS3.Z7CP5,SEQS3.YH4XB]\n" +
			"                                                     │               │           └─ columns: [z7cp5 yh4xb]\n" +
			"                                                     │               └─ HashLookup\n" +
			"                                                     │                   ├─ source: TUPLE(W2MAO.YH4XB:6)\n" +
			"                                                     │                   ├─ target: TUPLE(vc.id:0!null)\n" +
			"                                                     │                   └─ CachedResults\n" +
			"                                                     │                       └─ TableAlias(vc)\n" +
			"                                                     │                           └─ Table\n" +
			"                                                     │                               ├─ name: D34QP\n" +
			"                                                     │                               └─ columns: [id znp4p]\n" +
			"                                                     └─ TableAlias(nma)\n" +
			"                                                         └─ IndexedTableAccess(TNMXI)\n" +
			"                                                             ├─ index: [TNMXI.id]\n" +
			"                                                             └─ columns: [id]\n" +
			"",
	},
	{
		Query: `
	WITH AX7FV AS
	   (SELECT
	       bs.T4IBQ AS T4IBQ,
	       pa.DZLIM AS ECUWU,
	       pga.DZLIM AS GSTQA,
	       pog.B5OUF,
	       fc.OZTQF,
	       F26ZW.YHYLK,
	       nd.TW55N AS TW55N
	   FROM
	       SZQWJ ms
	   INNER JOIN XOAOP pa
	       ON ms.CH3FR = pa.id
	   LEFT JOIN NPCYY pog
	       ON pa.id = pog.CH3FR
	   INNER JOIN PG27A pga
	       ON pog.XVSBH = pga.id
	   INNER JOIN FEIOE GZ7Z4
	       ON pog.id = GZ7Z4.GMSGA
	   INNER JOIN E2I7U nd
	       ON GZ7Z4.LUEVY = nd.id
	   RIGHT JOIN (
	       SELECT
	           THNTS.id,
	           YK2GW.FTQLQ AS T4IBQ
	       FROM THNTS
	       INNER JOIN YK2GW
	       ON IXUXU = YK2GW.id
	   ) bs
	       ON ms.GXLUB = bs.id
	   LEFT JOIN AMYXQ fc
	       ON bs.id = fc.GXLUB AND nd.id = fc.LUEVY
	   LEFT JOIN (
	       SELECT
	           iq.T4IBQ,
	           iq.BRQP2,
	           iq.Z7CP5,
	           CASE
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P = 'L5Q44' AND iq.IDWIO = 'KAOAS'
	               THEN 0
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P = 'L5Q44' AND iq.IDWIO = 'OG'
	               THEN 0
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P = 'L5Q44' AND iq.IDWIO = 'TSG'
	               THEN 0
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P <> 'L5Q44' AND iq.IDWIO = 'W6W24'
	               THEN 1
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P <> 'L5Q44' AND iq.IDWIO = 'OG'
	               THEN 1
	               WHEN iq.FSDY2 IN ('SRARY','UBQWG') AND vc.ZNP4P <> 'L5Q44' AND iq.IDWIO = 'TSG'
	               THEN 0
	               ELSE NULL
	           END AS YHYLK
	       FROM (
	           SELECT
	               cla.FTQLQ AS T4IBQ,
	               sn.BRQP2,
	               mf.id AS Z7CP5,
	               mf.FSDY2,
	               nma.DZLIM AS IDWIO
	           FROM
	               HGMQ6 mf
	           INNER JOIN THNTS bs
	               ON mf.GXLUB = bs.id
	           INNER JOIN YK2GW cla
	               ON bs.IXUXU = cla.id
	           INNER JOIN E2I7U nd
	               ON mf.LUEVY = nd.id
	           INNER JOIN TNMXI nma
	               ON nd.HPCMS = nma.id
	           INNER JOIN NOXN3 sn
	               ON sn.BRQP2 = nd.id
	           WHERE cla.FTQLQ IN ('SQ1')
	       ) iq
	       LEFT JOIN SEQS3 W2MAO
	           ON iq.Z7CP5 = W2MAO.Z7CP5
	       LEFT JOIN D34QP vc
	           ON W2MAO.YH4XB = vc.id
	   ) F26ZW
	       ON F26ZW.T4IBQ = bs.T4IBQ AND F26ZW.BRQP2 = nd.id
	   LEFT JOIN TNMXI nma
	       ON nd.HPCMS = nma.id
	   WHERE bs.T4IBQ IN ('SQ1') AND ms.D237E = TRUE)
	SELECT
	   XPRW6.T4IBQ AS T4IBQ,
	   XPRW6.ECUWU AS ECUWU,
	   SUM(XPRW6.B5OUF) AS B5OUF,
	   SUM(XPRW6.SP4SI) AS SP4SI
	FROM (
	   SELECT
	       NRFJ3.T4IBQ AS T4IBQ,
	       NRFJ3.ECUWU AS ECUWU,
	       NRFJ3.GSTQA AS GSTQA,
	       NRFJ3.B5OUF AS B5OUF,
	       SUM(CASE
	               WHEN NRFJ3.OZTQF < 0.5 OR NRFJ3.YHYLK = 0 THEN 1
	               ELSE 0
	           END) AS SP4SI
	   FROM (
	       SELECT DISTINCT
	           T4IBQ,
	           ECUWU,
	           GSTQA,
	           B5OUF,
	           TW55N,
	           OZTQF,
	           YHYLK
	       FROM
	           AX7FV) NRFJ3
	   GROUP BY T4IBQ, ECUWU, GSTQA
	) XPRW6
	GROUP BY T4IBQ, ECUWU`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [T4IBQ:0!null, ECUWU:1, SUM(XPRW6.B5OUF):2!null as B5OUF, SUM(XPRW6.SP4SI):3!null as SP4SI]\n" +
			" └─ GroupBy\n" +
			"     ├─ select: T4IBQ:0!null, ECUWU:1, SUM(XPRW6.B5OUF:2), SUM(XPRW6.SP4SI:3!null)\n" +
			"     ├─ group: T4IBQ:0!null, ECUWU:1\n" +
			"     └─ Project\n" +
			"         ├─ columns: [XPRW6.T4IBQ:0!null as T4IBQ, XPRW6.ECUWU:1 as ECUWU, XPRW6.B5OUF:3, XPRW6.SP4SI:4!null]\n" +
			"         └─ SubqueryAlias\n" +
			"             ├─ name: XPRW6\n" +
			"             ├─ outerVisibility: false\n" +
			"             ├─ cacheable: true\n" +
			"             └─ Project\n" +
			"                 ├─ columns: [T4IBQ:0!null, ECUWU:1, GSTQA:2, B5OUF:3, SUM(CASE  WHEN ((NRFJ3.OZTQF < 0.5) OR (NRFJ3.YHYLK = 0)) THEN 1 ELSE 0 END):4!null as SP4SI]\n" +
			"                 └─ GroupBy\n" +
			"                     ├─ select: T4IBQ:0!null, ECUWU:1, GSTQA:2, NRFJ3.B5OUF:3 as B5OUF, SUM(CASE  WHEN Or\n" +
			"                     │   ├─ LessThan\n" +
			"                     │   │   ├─ NRFJ3.OZTQF:4\n" +
			"                     │   │   └─ 0.500000 (double)\n" +
			"                     │   └─ Eq\n" +
			"                     │       ├─ NRFJ3.YHYLK:5\n" +
			"                     │       └─ 0 (tinyint)\n" +
			"                     │   THEN 1 (tinyint) ELSE 0 (tinyint) END)\n" +
			"                     ├─ group: T4IBQ:0!null, ECUWU:1, GSTQA:2\n" +
			"                     └─ Project\n" +
			"                         ├─ columns: [NRFJ3.T4IBQ:0!null as T4IBQ, NRFJ3.ECUWU:1 as ECUWU, NRFJ3.GSTQA:2 as GSTQA, NRFJ3.B5OUF:3, NRFJ3.OZTQF:5, NRFJ3.YHYLK:6]\n" +
			"                         └─ SubqueryAlias\n" +
			"                             ├─ name: NRFJ3\n" +
			"                             ├─ outerVisibility: false\n" +
			"                             ├─ cacheable: true\n" +
			"                             └─ Distinct\n" +
			"                                 └─ Project\n" +
			"                                     ├─ columns: [AX7FV.T4IBQ:0!null, AX7FV.ECUWU:1, AX7FV.GSTQA:2, AX7FV.B5OUF:3, AX7FV.TW55N:6, AX7FV.OZTQF:4, AX7FV.YHYLK:5]\n" +
			"                                     └─ SubqueryAlias\n" +
			"                                         ├─ name: AX7FV\n" +
			"                                         ├─ outerVisibility: false\n" +
			"                                         ├─ cacheable: true\n" +
			"                                         └─ Project\n" +
			"                                             ├─ columns: [bs.T4IBQ:1!null as T4IBQ, pa.DZLIM:3 as ECUWU, pga.DZLIM:12 as GSTQA, pog.B5OUF:10, fc.OZTQF:20, F26ZW.YHYLK:24, nd.TW55N:16 as TW55N]\n" +
			"                                             └─ Filter\n" +
			"                                                 ├─ Eq\n" +
			"                                                 │   ├─ ms.D237E:6\n" +
			"                                                 │   └─ %!s(bool=true) (tinyint)\n" +
			"                                                 └─ LeftOuterLookupJoin\n" +
			"                                                     ├─ Eq\n" +
			"                                                     │   ├─ nd.HPCMS:17\n" +
			"                                                     │   └─ nma.id:25!null\n" +
			"                                                     ├─ LeftOuterJoin\n" +
			"                                                     │   ├─ AND\n" +
			"                                                     │   │   ├─ Eq\n" +
			"                                                     │   │   │   ├─ F26ZW.T4IBQ:21!null\n" +
			"                                                     │   │   │   └─ bs.T4IBQ:1!null\n" +
			"                                                     │   │   └─ Eq\n" +
			"                                                     │   │       ├─ F26ZW.BRQP2:22!null\n" +
			"                                                     │   │       └─ nd.id:15\n" +
			"                                                     │   ├─ LeftOuterLookupJoin\n" +
			"                                                     │   │   ├─ AND\n" +
			"                                                     │   │   │   ├─ Eq\n" +
			"                                                     │   │   │   │   ├─ bs.id:0!null\n" +
			"                                                     │   │   │   │   └─ fc.GXLUB:18!null\n" +
			"                                                     │   │   │   └─ Eq\n" +
			"                                                     │   │   │       ├─ nd.id:15\n" +
			"                                                     │   │   │       └─ fc.LUEVY:19!null\n" +
			"                                                     │   │   ├─ LeftOuterJoin\n" +
			"                                                     │   │   │   ├─ Eq\n" +
			"                                                     │   │   │   │   ├─ ms.GXLUB:4!null\n" +
			"                                                     │   │   │   │   └─ bs.id:0!null\n" +
			"                                                     │   │   │   ├─ SubqueryAlias\n" +
			"                                                     │   │   │   │   ├─ name: bs\n" +
			"                                                     │   │   │   │   ├─ outerVisibility: false\n" +
			"                                                     │   │   │   │   ├─ cacheable: true\n" +
			"                                                     │   │   │   │   └─ Filter\n" +
			"                                                     │   │   │   │       ├─ HashIn\n" +
			"                                                     │   │   │   │       │   ├─ T4IBQ:1!null\n" +
			"                                                     │   │   │   │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"                                                     │   │   │   │       └─ Project\n" +
			"                                                     │   │   │   │           ├─ columns: [THNTS.id:2!null, YK2GW.FTQLQ:1!null as T4IBQ]\n" +
			"                                                     │   │   │   │           └─ MergeJoin\n" +
			"                                                     │   │   │   │               ├─ cmp: Eq\n" +
			"                                                     │   │   │   │               │   ├─ YK2GW.id:0!null\n" +
			"                                                     │   │   │   │               │   └─ THNTS.IXUXU:3\n" +
			"                                                     │   │   │   │               ├─ IndexedTableAccess(YK2GW)\n" +
			"                                                     │   │   │   │               │   ├─ index: [YK2GW.id]\n" +
			"                                                     │   │   │   │               │   ├─ static: [{[NULL, ∞)}]\n" +
			"                                                     │   │   │   │               │   └─ columns: [id ftqlq]\n" +
			"                                                     │   │   │   │               └─ IndexedTableAccess(THNTS)\n" +
			"                                                     │   │   │   │                   ├─ index: [THNTS.IXUXU]\n" +
			"                                                     │   │   │   │                   ├─ static: [{[NULL, ∞)}]\n" +
			"                                                     │   │   │   │                   └─ columns: [id ixuxu]\n" +
			"                                                     │   │   │   └─ LookupJoin\n" +
			"                                                     │   │   │       ├─ Eq\n" +
			"                                                     │   │   │       │   ├─ GZ7Z4.LUEVY:13!null\n" +
			"                                                     │   │   │       │   └─ nd.id:15!null\n" +
			"                                                     │   │   │       ├─ LookupJoin\n" +
			"                                                     │   │   │       │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   ├─ pog.id:7\n" +
			"                                                     │   │   │       │   │   └─ GZ7Z4.GMSGA:14!null\n" +
			"                                                     │   │   │       │   ├─ LookupJoin\n" +
			"                                                     │   │   │       │   │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   │   ├─ pog.XVSBH:9\n" +
			"                                                     │   │   │       │   │   │   └─ pga.id:11!null\n" +
			"                                                     │   │   │       │   │   ├─ LeftOuterLookupJoin\n" +
			"                                                     │   │   │       │   │   │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   │   │   ├─ pa.id:2!null\n" +
			"                                                     │   │   │       │   │   │   │   └─ pog.CH3FR:8!null\n" +
			"                                                     │   │   │       │   │   │   ├─ LookupJoin\n" +
			"                                                     │   │   │       │   │   │   │   ├─ Eq\n" +
			"                                                     │   │   │       │   │   │   │   │   ├─ ms.CH3FR:5!null\n" +
			"                                                     │   │   │       │   │   │   │   │   └─ pa.id:2!null\n" +
			"                                                     │   │   │       │   │   │   │   ├─ TableAlias(pa)\n" +
			"                                                     │   │   │       │   │   │   │   │   └─ Table\n" +
			"                                                     │   │   │       │   │   │   │   │       ├─ name: XOAOP\n" +
			"                                                     │   │   │       │   │   │   │   │       └─ columns: [id dzlim]\n" +
			"                                                     │   │   │       │   │   │   │   └─ TableAlias(ms)\n" +
			"                                                     │   │   │       │   │   │   │       └─ IndexedTableAccess(SZQWJ)\n" +
			"                                                     │   │   │       │   │   │   │           ├─ index: [SZQWJ.CH3FR]\n" +
			"                                                     │   │   │       │   │   │   │           └─ columns: [gxlub ch3fr d237e]\n" +
			"                                                     │   │   │       │   │   │   └─ TableAlias(pog)\n" +
			"                                                     │   │   │       │   │   │       └─ IndexedTableAccess(NPCYY)\n" +
			"                                                     │   │   │       │   │   │           ├─ index: [NPCYY.CH3FR,NPCYY.XVSBH]\n" +
			"                                                     │   │   │       │   │   │           └─ columns: [id ch3fr xvsbh b5ouf]\n" +
			"                                                     │   │   │       │   │   └─ TableAlias(pga)\n" +
			"                                                     │   │   │       │   │       └─ IndexedTableAccess(PG27A)\n" +
			"                                                     │   │   │       │   │           ├─ index: [PG27A.id]\n" +
			"                                                     │   │   │       │   │           └─ columns: [id dzlim]\n" +
			"                                                     │   │   │       │   └─ TableAlias(GZ7Z4)\n" +
			"                                                     │   │   │       │       └─ IndexedTableAccess(FEIOE)\n" +
			"                                                     │   │   │       │           ├─ index: [FEIOE.GMSGA]\n" +
			"                                                     │   │   │       │           └─ columns: [luevy gmsga]\n" +
			"                                                     │   │   │       └─ TableAlias(nd)\n" +
			"                                                     │   │   │           └─ IndexedTableAccess(E2I7U)\n" +
			"                                                     │   │   │               ├─ index: [E2I7U.id]\n" +
			"                                                     │   │   │               └─ columns: [id tw55n hpcms]\n" +
			"                                                     │   │   └─ TableAlias(fc)\n" +
			"                                                     │   │       └─ IndexedTableAccess(AMYXQ)\n" +
			"                                                     │   │           ├─ index: [AMYXQ.GXLUB,AMYXQ.LUEVY]\n" +
			"                                                     │   │           └─ columns: [gxlub luevy oztqf]\n" +
			"                                                     │   └─ SubqueryAlias\n" +
			"                                                     │       ├─ name: F26ZW\n" +
			"                                                     │       ├─ outerVisibility: false\n" +
			"                                                     │       ├─ cacheable: true\n" +
			"                                                     │       └─ Project\n" +
			"                                                     │           ├─ columns: [iq.T4IBQ:0!null, iq.BRQP2:1!null, iq.Z7CP5:2!null, CASE  WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ Eq\n" +
			"                                                     │           │   │       ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │       └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ KAOAS (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ Eq\n" +
			"                                                     │           │   │       ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │       └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ OG (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ Eq\n" +
			"                                                     │           │   │       ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │       └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ TSG (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ NOT\n" +
			"                                                     │           │   │       └─ Eq\n" +
			"                                                     │           │   │           ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │           └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ W6W24 (longtext)\n" +
			"                                                     │           │   THEN 1 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ NOT\n" +
			"                                                     │           │   │       └─ Eq\n" +
			"                                                     │           │   │           ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │           └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ OG (longtext)\n" +
			"                                                     │           │   THEN 1 (tinyint) WHEN AND\n" +
			"                                                     │           │   ├─ AND\n" +
			"                                                     │           │   │   ├─ IN\n" +
			"                                                     │           │   │   │   ├─ left: iq.FSDY2:3!null\n" +
			"                                                     │           │   │   │   └─ right: TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"                                                     │           │   │   └─ NOT\n" +
			"                                                     │           │   │       └─ Eq\n" +
			"                                                     │           │   │           ├─ vc.ZNP4P:8\n" +
			"                                                     │           │   │           └─ L5Q44 (longtext)\n" +
			"                                                     │           │   └─ Eq\n" +
			"                                                     │           │       ├─ iq.IDWIO:4!null\n" +
			"                                                     │           │       └─ TSG (longtext)\n" +
			"                                                     │           │   THEN 0 (tinyint) ELSE NULL (null) END as YHYLK]\n" +
			"                                                     │           └─ LeftOuterHashJoin\n" +
			"                                                     │               ├─ Eq\n" +
			"                                                     │               │   ├─ W2MAO.YH4XB:6\n" +
			"                                                     │               │   └─ vc.id:7!null\n" +
			"                                                     │               ├─ LeftOuterLookupJoin\n" +
			"                                                     │               │   ├─ Eq\n" +
			"                                                     │               │   │   ├─ iq.Z7CP5:2!null\n" +
			"                                                     │               │   │   └─ W2MAO.Z7CP5:5!null\n" +
			"                                                     │               │   ├─ SubqueryAlias\n" +
			"                                                     │               │   │   ├─ name: iq\n" +
			"                                                     │               │   │   ├─ outerVisibility: false\n" +
			"                                                     │               │   │   ├─ cacheable: true\n" +
			"                                                     │               │   │   └─ Project\n" +
			"                                                     │               │   │       ├─ columns: [cla.FTQLQ:11!null as T4IBQ, sn.BRQP2:12!null, mf.id:4!null as Z7CP5, mf.FSDY2:7!null, nma.DZLIM:1!null as IDWIO]\n" +
			"                                                     │               │   │       └─ LookupJoin\n" +
			"                                                     │               │   │           ├─ Eq\n" +
			"                                                     │               │   │           │   ├─ sn.BRQP2:12!null\n" +
			"                                                     │               │   │           │   └─ nd.id:2!null\n" +
			"                                                     │               │   │           ├─ LookupJoin\n" +
			"                                                     │               │   │           │   ├─ Eq\n" +
			"                                                     │               │   │           │   │   ├─ bs.IXUXU:9\n" +
			"                                                     │               │   │           │   │   └─ cla.id:10!null\n" +
			"                                                     │               │   │           │   ├─ LookupJoin\n" +
			"                                                     │               │   │           │   │   ├─ Eq\n" +
			"                                                     │               │   │           │   │   │   ├─ mf.GXLUB:5!null\n" +
			"                                                     │               │   │           │   │   │   └─ bs.id:8!null\n" +
			"                                                     │               │   │           │   │   ├─ LookupJoin\n" +
			"                                                     │               │   │           │   │   │   ├─ Eq\n" +
			"                                                     │               │   │           │   │   │   │   ├─ mf.LUEVY:6!null\n" +
			"                                                     │               │   │           │   │   │   │   └─ nd.id:2!null\n" +
			"                                                     │               │   │           │   │   │   ├─ LookupJoin\n" +
			"                                                     │               │   │           │   │   │   │   ├─ Eq\n" +
			"                                                     │               │   │           │   │   │   │   │   ├─ nd.HPCMS:3!null\n" +
			"                                                     │               │   │           │   │   │   │   │   └─ nma.id:0!null\n" +
			"                                                     │               │   │           │   │   │   │   ├─ TableAlias(nma)\n" +
			"                                                     │               │   │           │   │   │   │   │   └─ Table\n" +
			"                                                     │               │   │           │   │   │   │   │       ├─ name: TNMXI\n" +
			"                                                     │               │   │           │   │   │   │   │       └─ columns: [id dzlim]\n" +
			"                                                     │               │   │           │   │   │   │   └─ TableAlias(nd)\n" +
			"                                                     │               │   │           │   │   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"                                                     │               │   │           │   │   │   │           ├─ index: [E2I7U.HPCMS]\n" +
			"                                                     │               │   │           │   │   │   │           └─ columns: [id hpcms]\n" +
			"                                                     │               │   │           │   │   │   └─ TableAlias(mf)\n" +
			"                                                     │               │   │           │   │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			"                                                     │               │   │           │   │   │           ├─ index: [HGMQ6.LUEVY]\n" +
			"                                                     │               │   │           │   │   │           └─ columns: [id gxlub luevy fsdy2]\n" +
			"                                                     │               │   │           │   │   └─ TableAlias(bs)\n" +
			"                                                     │               │   │           │   │       └─ IndexedTableAccess(THNTS)\n" +
			"                                                     │               │   │           │   │           ├─ index: [THNTS.id]\n" +
			"                                                     │               │   │           │   │           └─ columns: [id ixuxu]\n" +
			"                                                     │               │   │           │   └─ Filter\n" +
			"                                                     │               │   │           │       ├─ HashIn\n" +
			"                                                     │               │   │           │       │   ├─ cla.FTQLQ:1!null\n" +
			"                                                     │               │   │           │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"                                                     │               │   │           │       └─ TableAlias(cla)\n" +
			"                                                     │               │   │           │           └─ IndexedTableAccess(YK2GW)\n" +
			"                                                     │               │   │           │               ├─ index: [YK2GW.id]\n" +
			"                                                     │               │   │           │               └─ columns: [id ftqlq]\n" +
			"                                                     │               │   │           └─ TableAlias(sn)\n" +
			"                                                     │               │   │               └─ IndexedTableAccess(NOXN3)\n" +
			"                                                     │               │   │                   ├─ index: [NOXN3.BRQP2]\n" +
			"                                                     │               │   │                   └─ columns: [brqp2]\n" +
			"                                                     │               │   └─ TableAlias(W2MAO)\n" +
			"                                                     │               │       └─ IndexedTableAccess(SEQS3)\n" +
			"                                                     │               │           ├─ index: [SEQS3.Z7CP5,SEQS3.YH4XB]\n" +
			"                                                     │               │           └─ columns: [z7cp5 yh4xb]\n" +
			"                                                     │               └─ HashLookup\n" +
			"                                                     │                   ├─ source: TUPLE(W2MAO.YH4XB:6)\n" +
			"                                                     │                   ├─ target: TUPLE(vc.id:0!null)\n" +
			"                                                     │                   └─ CachedResults\n" +
			"                                                     │                       └─ TableAlias(vc)\n" +
			"                                                     │                           └─ Table\n" +
			"                                                     │                               ├─ name: D34QP\n" +
			"                                                     │                               └─ columns: [id znp4p]\n" +
			"                                                     └─ TableAlias(nma)\n" +
			"                                                         └─ IndexedTableAccess(TNMXI)\n" +
			"                                                             ├─ index: [TNMXI.id]\n" +
			"                                                             └─ columns: [id]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   TUSAY.Y3IOU AS RWGEU
	FROM
	   (SELECT
	       id AS Y46B2,
	       WNUNU AS WNUNU,
	       HVHRZ AS HVHRZ
	   FROM
	       QYWQD) XJ2RD
	INNER JOIN
	   (SELECT
	       ROW_NUMBER() OVER (ORDER BY id ASC) Y3IOU,
	       id AS XLFIA
	   FROM
	       NOXN3) TUSAY
	
	   ON XJ2RD.WNUNU = TUSAY.XLFIA
	ORDER BY Y46B2 ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [TUSAY.Y3IOU:0!null as RWGEU]\n" +
			" └─ Sort(XJ2RD.Y46B2:2!null ASC nullsFirst)\n" +
			"     └─ HashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ XJ2RD.WNUNU:3!null\n" +
			"         │   └─ TUSAY.XLFIA:1!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: TUSAY\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Project\n" +
			"         │       ├─ columns: [row_number() over ( order by NOXN3.id ASC):0!null as Y3IOU, XLFIA:1!null]\n" +
			"         │       └─ Window\n" +
			"         │           ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"         │           ├─ NOXN3.id:0!null as XLFIA\n" +
			"         │           └─ Table\n" +
			"         │               ├─ name: NOXN3\n" +
			"         │               └─ columns: [id]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(TUSAY.XLFIA:1!null)\n" +
			"             ├─ target: TUPLE(XJ2RD.WNUNU:1!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ SubqueryAlias\n" +
			"                     ├─ name: XJ2RD\n" +
			"                     ├─ outerVisibility: false\n" +
			"                     ├─ cacheable: true\n" +
			"                     └─ Project\n" +
			"                         ├─ columns: [QYWQD.id:0!null as Y46B2, QYWQD.WNUNU:1!null as WNUNU, QYWQD.HVHRZ:2!null as HVHRZ]\n" +
			"                         └─ Table\n" +
			"                             ├─ name: QYWQD\n" +
			"                             └─ columns: [id wnunu hvhrz]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   ECXAJ
	FROM
	   E2I7U
	ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [E2I7U.ECXAJ:1!null]\n" +
			" └─ IndexedTableAccess(E2I7U)\n" +
			"     ├─ index: [E2I7U.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id ecxaj]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   CASE
	       WHEN YZXYP.Z35GY IS NOT NULL THEN YZXYP.Z35GY
	       ELSE -1
	   END AS FMSOH
	   FROM
	   (SELECT
	       nd.T722E,
	       fc.Z35GY
	   FROM
	       (SELECT
	           id AS T722E
	       FROM
	           E2I7U) nd
	       LEFT JOIN
	       (SELECT
	           LUEVY AS ZPAIK,
	           MAX(Z35GY) AS Z35GY
	       FROM AMYXQ
	       GROUP BY LUEVY) fc
	       ON nd.T722E = fc.ZPAIK
	   ORDER BY nd.T722E ASC) YZXYP`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [CASE  WHEN NOT\n" +
			" │   └─ YZXYP.Z35GY:1 IS NULL\n" +
			" │   THEN YZXYP.Z35GY:1 ELSE -1 (tinyint) END as FMSOH]\n" +
			" └─ SubqueryAlias\n" +
			"     ├─ name: YZXYP\n" +
			"     ├─ outerVisibility: false\n" +
			"     ├─ cacheable: true\n" +
			"     └─ Sort(nd.T722E:0!null ASC nullsFirst)\n" +
			"         └─ Project\n" +
			"             ├─ columns: [nd.T722E:0!null, fc.Z35GY:2]\n" +
			"             └─ LeftOuterHashJoin\n" +
			"                 ├─ Eq\n" +
			"                 │   ├─ nd.T722E:0!null\n" +
			"                 │   └─ fc.ZPAIK:1!null\n" +
			"                 ├─ SubqueryAlias\n" +
			"                 │   ├─ name: nd\n" +
			"                 │   ├─ outerVisibility: false\n" +
			"                 │   ├─ cacheable: true\n" +
			"                 │   └─ Project\n" +
			"                 │       ├─ columns: [E2I7U.id:0!null as T722E]\n" +
			"                 │       └─ Table\n" +
			"                 │           ├─ name: E2I7U\n" +
			"                 │           └─ columns: [id]\n" +
			"                 └─ HashLookup\n" +
			"                     ├─ source: TUPLE(nd.T722E:0!null)\n" +
			"                     ├─ target: TUPLE(fc.ZPAIK:0!null)\n" +
			"                     └─ CachedResults\n" +
			"                         └─ SubqueryAlias\n" +
			"                             ├─ name: fc\n" +
			"                             ├─ outerVisibility: false\n" +
			"                             ├─ cacheable: true\n" +
			"                             └─ Project\n" +
			"                                 ├─ columns: [ZPAIK:0!null, MAX(AMYXQ.Z35GY):1!null as Z35GY]\n" +
			"                                 └─ GroupBy\n" +
			"                                     ├─ select: AMYXQ.LUEVY:0!null as ZPAIK, MAX(AMYXQ.Z35GY:1!null)\n" +
			"                                     ├─ group: AMYXQ.LUEVY:0!null\n" +
			"                                     └─ Table\n" +
			"                                         ├─ name: AMYXQ\n" +
			"                                         └─ columns: [luevy z35gy]\n" +
			"",
	},
	{
		Query: `
	SELECT
	   CASE
	       WHEN
	           FGG57 IS NULL
	           THEN 0
	       WHEN
	           id IN (SELECT id FROM E2I7U WHERE NOT id IN (SELECT LUEVY FROM AMYXQ))
	           THEN 1
	       WHEN
	           FSK67 = 'z'
	           THEN 2
	       WHEN
	           FSK67 = 'CRZ2X'
	           THEN 0
	       ELSE 3
	   END AS SZ6KK
	   FROM E2I7U
	   ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [CASE  WHEN E2I7U.FGG57:6 IS NULL THEN 0 (tinyint) WHEN InSubquery\n" +
			" │   ├─ left: E2I7U.id:0!null\n" +
			" │   └─ right: Subquery\n" +
			" │       ├─ cacheable: true\n" +
			" │       └─ Project\n" +
			" │           ├─ columns: [E2I7U.id:17!null]\n" +
			" │           └─ AntiLookupJoin\n" +
			" │               ├─ Eq\n" +
			" │               │   ├─ E2I7U.id:17!null\n" +
			" │               │   └─ applySubq0.LUEVY:34!null\n" +
			" │               ├─ Table\n" +
			" │               │   ├─ name: E2I7U\n" +
			" │               │   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			" │               └─ TableAlias(applySubq0)\n" +
			" │                   └─ IndexedTableAccess(AMYXQ)\n" +
			" │                       ├─ index: [AMYXQ.LUEVY]\n" +
			" │                       └─ columns: [luevy]\n" +
			" │   THEN 1 (tinyint) WHEN Eq\n" +
			" │   ├─ E2I7U.FSK67:8!null\n" +
			" │   └─ z (longtext)\n" +
			" │   THEN 2 (tinyint) WHEN Eq\n" +
			" │   ├─ E2I7U.FSK67:8!null\n" +
			" │   └─ CRZ2X (longtext)\n" +
			" │   THEN 0 (tinyint) ELSE 3 (tinyint) END as SZ6KK]\n" +
			" └─ IndexedTableAccess(E2I7U)\n" +
			"     ├─ index: [E2I7U.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"",
	},
	{
		Query: `
	WITH
	   BMRZU AS
	           (SELECT /*+ JOIN_ORDER( cla, bs, mf, sn, aac, W2MAO, vc ) */
	               cla.FTQLQ AS T4IBQ,
	               sn.id AS BDNYB,
	               aac.BTXC5 AS BTXC5,
	               mf.id AS Z7CP5,
	               CASE
	                   WHEN mf.LT7K6 IS NOT NULL THEN mf.LT7K6
	                   ELSE mf.SPPYD
	               END AS vaf,
	               CASE
	                   WHEN mf.QCGTS IS NOT NULL THEN QCGTS
	                   ELSE 0.5
	               END AS QCGTS,
	               CASE
	                   WHEN vc.ZNP4P = 'L5Q44' THEN 1
	                   ELSE 0
	               END AS SNY4H
	           FROM YK2GW cla
	           INNER JOIN THNTS bs ON bs.IXUXU = cla.id
	           INNER JOIN HGMQ6 mf ON mf.GXLUB = bs.id
	           INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
	           INNER JOIN TPXBU aac ON aac.id = mf.M22QN
	           INNER JOIN SEQS3 W2MAO ON W2MAO.Z7CP5 = mf.id
	           INNER JOIN D34QP vc ON vc.id = W2MAO.YH4XB
	           WHERE cla.FTQLQ IN ('SQ1')
	AND mf.FSDY2 IN ('SRARY', 'UBQWG')),
	   YU7NY AS
	           (SELECT
	               nd.TW55N AS KUXQY,
	               sn.id AS BDNYB,
	               nma.DZLIM AS YHVEZ,
	               CASE
	                   WHEN nd.TCE7A < 0.9 THEN 1
	                   ELSE 0
	               END AS YAZ4X
	           FROM NOXN3 sn
	           LEFT JOIN E2I7U nd ON sn.BRQP2 = nd.id
	           LEFT JOIN TNMXI nma ON nd.HPCMS = nma.id
	           WHERE nma.DZLIM != 'Q5I4E'
	           ORDER BY sn.id ASC)
	SELECT DISTINCT
	   OXXEI.T4IBQ,
	   OXXEI.Z7CP5,
	   E52AP.KUXQY,
	   OXXEI.BDNYB,
	   CKELE.M6T2N,
	   OXXEI.BTXC5 as BTXC5,
	   OXXEI.vaf as vaf,
	   OXXEI.QCGTS as QCGTS,
	   OXXEI.SNY4H as SNY4H,
	   E52AP.YHVEZ as YHVEZ,
	   E52AP.YAZ4X as YAZ4X
	FROM
	   BMRZU OXXEI
	INNER JOIN YU7NY E52AP ON E52AP.BDNYB = OXXEI.BDNYB
	INNER JOIN
	   (SELECT
	       NOXN3.id as LWQ6O,
	       ROW_NUMBER() OVER (ORDER BY NOXN3.id ASC) M6T2N
	   FROM NOXN3) CKELE
	ON CKELE.LWQ6O = OXXEI.BDNYB
	ORDER BY CKELE.M6T2N ASC`,
		ExpectedPlan: "Sort(CKELE.M6T2N:4!null ASC nullsFirst)\n" +
			" └─ Distinct\n" +
			"     └─ Project\n" +
			"         ├─ columns: [OXXEI.T4IBQ:2!null, OXXEI.Z7CP5:5!null, E52AP.KUXQY:9, OXXEI.BDNYB:3!null, CKELE.M6T2N:1!null, OXXEI.BTXC5:4 as BTXC5, OXXEI.vaf:6 as vaf, OXXEI.QCGTS:7 as QCGTS, OXXEI.SNY4H:8!null as SNY4H, E52AP.YHVEZ:11 as YHVEZ, E52AP.YAZ4X:12!null as YAZ4X]\n" +
			"         └─ HashJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ E52AP.BDNYB:10!null\n" +
			"             │   └─ OXXEI.BDNYB:3!null\n" +
			"             ├─ HashJoin\n" +
			"             │   ├─ Eq\n" +
			"             │   │   ├─ CKELE.LWQ6O:0!null\n" +
			"             │   │   └─ OXXEI.BDNYB:3!null\n" +
			"             │   ├─ SubqueryAlias\n" +
			"             │   │   ├─ name: CKELE\n" +
			"             │   │   ├─ outerVisibility: false\n" +
			"             │   │   ├─ cacheable: true\n" +
			"             │   │   └─ Project\n" +
			"             │   │       ├─ columns: [LWQ6O:0!null, row_number() over ( order by NOXN3.id ASC):1!null as M6T2N]\n" +
			"             │   │       └─ Window\n" +
			"             │   │           ├─ NOXN3.id:0!null as LWQ6O\n" +
			"             │   │           ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"             │   │           └─ Table\n" +
			"             │   │               ├─ name: NOXN3\n" +
			"             │   │               └─ columns: [id]\n" +
			"             │   └─ HashLookup\n" +
			"             │       ├─ source: TUPLE(CKELE.LWQ6O:0!null)\n" +
			"             │       ├─ target: TUPLE(OXXEI.BDNYB:1!null)\n" +
			"             │       └─ CachedResults\n" +
			"             │           └─ SubqueryAlias\n" +
			"             │               ├─ name: OXXEI\n" +
			"             │               ├─ outerVisibility: false\n" +
			"             │               ├─ cacheable: true\n" +
			"             │               └─ Project\n" +
			"             │                   ├─ columns: [cla.FTQLQ:1!null as T4IBQ, sn.id:12!null as BDNYB, aac.BTXC5:15 as BTXC5, mf.id:4!null as Z7CP5, CASE  WHEN NOT\n" +
			"             │                   │   └─ mf.LT7K6:9 IS NULL\n" +
			"             │                   │   THEN mf.LT7K6:9 ELSE mf.SPPYD:10 END as vaf, CASE  WHEN NOT\n" +
			"             │                   │   └─ mf.QCGTS:11 IS NULL\n" +
			"             │                   │   THEN mf.QCGTS:11 ELSE 0.500000 (double) END as QCGTS, CASE  WHEN Eq\n" +
			"             │                   │   ├─ vc.ZNP4P:19!null\n" +
			"             │                   │   └─ L5Q44 (longtext)\n" +
			"             │                   │   THEN 1 (tinyint) ELSE 0 (tinyint) END as SNY4H]\n" +
			"             │                   └─ HashJoin\n" +
			"             │                       ├─ Eq\n" +
			"             │                       │   ├─ bs.IXUXU:3\n" +
			"             │                       │   └─ cla.id:0!null\n" +
			"             │                       ├─ Filter\n" +
			"             │                       │   ├─ HashIn\n" +
			"             │                       │   │   ├─ cla.FTQLQ:1!null\n" +
			"             │                       │   │   └─ TUPLE(SQ1 (longtext))\n" +
			"             │                       │   └─ TableAlias(cla)\n" +
			"             │                       │       └─ IndexedTableAccess(YK2GW)\n" +
			"             │                       │           ├─ index: [YK2GW.FTQLQ]\n" +
			"             │                       │           ├─ static: [{[SQ1, SQ1]}]\n" +
			"             │                       │           └─ columns: [id ftqlq]\n" +
			"             │                       └─ HashLookup\n" +
			"             │                           ├─ source: TUPLE(cla.id:0!null)\n" +
			"             │                           ├─ target: TUPLE(bs.IXUXU:1)\n" +
			"             │                           └─ CachedResults\n" +
			"             │                               └─ LookupJoin\n" +
			"             │                                   ├─ Eq\n" +
			"             │                                   │   ├─ vc.id:18!null\n" +
			"             │                                   │   └─ W2MAO.YH4XB:17!null\n" +
			"             │                                   ├─ LookupJoin\n" +
			"             │                                   │   ├─ Eq\n" +
			"             │                                   │   │   ├─ W2MAO.Z7CP5:16!null\n" +
			"             │                                   │   │   └─ mf.id:4!null\n" +
			"             │                                   │   ├─ LookupJoin\n" +
			"             │                                   │   │   ├─ Eq\n" +
			"             │                                   │   │   │   ├─ aac.id:14!null\n" +
			"             │                                   │   │   │   └─ mf.M22QN:7!null\n" +
			"             │                                   │   │   ├─ LookupJoin\n" +
			"             │                                   │   │   │   ├─ Eq\n" +
			"             │                                   │   │   │   │   ├─ sn.BRQP2:13!null\n" +
			"             │                                   │   │   │   │   └─ mf.LUEVY:6!null\n" +
			"             │                                   │   │   │   ├─ LookupJoin\n" +
			"             │                                   │   │   │   │   ├─ Eq\n" +
			"             │                                   │   │   │   │   │   ├─ mf.GXLUB:5!null\n" +
			"             │                                   │   │   │   │   │   └─ bs.id:2!null\n" +
			"             │                                   │   │   │   │   ├─ TableAlias(bs)\n" +
			"             │                                   │   │   │   │   │   └─ Table\n" +
			"             │                                   │   │   │   │   │       ├─ name: THNTS\n" +
			"             │                                   │   │   │   │   │       └─ columns: [id ixuxu]\n" +
			"             │                                   │   │   │   │   └─ Filter\n" +
			"             │                                   │   │   │   │       ├─ HashIn\n" +
			"             │                                   │   │   │   │       │   ├─ mf.FSDY2:4!null\n" +
			"             │                                   │   │   │   │       │   └─ TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"             │                                   │   │   │   │       └─ TableAlias(mf)\n" +
			"             │                                   │   │   │   │           └─ IndexedTableAccess(HGMQ6)\n" +
			"             │                                   │   │   │   │               ├─ index: [HGMQ6.GXLUB]\n" +
			"             │                                   │   │   │   │               └─ columns: [id gxlub luevy m22qn fsdy2 lt7k6 sppyd qcgts]\n" +
			"             │                                   │   │   │   └─ TableAlias(sn)\n" +
			"             │                                   │   │   │       └─ IndexedTableAccess(NOXN3)\n" +
			"             │                                   │   │   │           ├─ index: [NOXN3.BRQP2]\n" +
			"             │                                   │   │   │           └─ columns: [id brqp2]\n" +
			"             │                                   │   │   └─ TableAlias(aac)\n" +
			"             │                                   │   │       └─ IndexedTableAccess(TPXBU)\n" +
			"             │                                   │   │           ├─ index: [TPXBU.id]\n" +
			"             │                                   │   │           └─ columns: [id btxc5]\n" +
			"             │                                   │   └─ TableAlias(W2MAO)\n" +
			"             │                                   │       └─ IndexedTableAccess(SEQS3)\n" +
			"             │                                   │           ├─ index: [SEQS3.Z7CP5,SEQS3.YH4XB]\n" +
			"             │                                   │           └─ columns: [z7cp5 yh4xb]\n" +
			"             │                                   └─ TableAlias(vc)\n" +
			"             │                                       └─ IndexedTableAccess(D34QP)\n" +
			"             │                                           ├─ index: [D34QP.id]\n" +
			"             │                                           └─ columns: [id znp4p]\n" +
			"             └─ HashLookup\n" +
			"                 ├─ source: TUPLE(OXXEI.BDNYB:3!null)\n" +
			"                 ├─ target: TUPLE(E52AP.BDNYB:1!null)\n" +
			"                 └─ CachedResults\n" +
			"                     └─ SubqueryAlias\n" +
			"                         ├─ name: E52AP\n" +
			"                         ├─ outerVisibility: false\n" +
			"                         ├─ cacheable: true\n" +
			"                         └─ Sort(BDNYB:1!null ASC nullsFirst)\n" +
			"                             └─ Project\n" +
			"                                 ├─ columns: [nd.TW55N:3 as KUXQY, sn.id:0!null as BDNYB, nma.DZLIM:7 as YHVEZ, CASE  WHEN LessThan\n" +
			"                                 │   ├─ nd.TCE7A:4\n" +
			"                                 │   └─ 0.900000 (double)\n" +
			"                                 │   THEN 1 (tinyint) ELSE 0 (tinyint) END as YAZ4X]\n" +
			"                                 └─ Filter\n" +
			"                                     ├─ NOT\n" +
			"                                     │   └─ Eq\n" +
			"                                     │       ├─ nma.DZLIM:7\n" +
			"                                     │       └─ Q5I4E (longtext)\n" +
			"                                     └─ LeftOuterHashJoin\n" +
			"                                         ├─ Eq\n" +
			"                                         │   ├─ nd.HPCMS:5\n" +
			"                                         │   └─ nma.id:6!null\n" +
			"                                         ├─ LeftOuterMergeJoin\n" +
			"                                         │   ├─ cmp: Eq\n" +
			"                                         │   │   ├─ sn.BRQP2:1!null\n" +
			"                                         │   │   └─ nd.id:2!null\n" +
			"                                         │   ├─ TableAlias(sn)\n" +
			"                                         │   │   └─ IndexedTableAccess(NOXN3)\n" +
			"                                         │   │       ├─ index: [NOXN3.BRQP2]\n" +
			"                                         │   │       ├─ static: [{[NULL, ∞)}]\n" +
			"                                         │   │       └─ columns: [id brqp2]\n" +
			"                                         │   └─ TableAlias(nd)\n" +
			"                                         │       └─ IndexedTableAccess(E2I7U)\n" +
			"                                         │           ├─ index: [E2I7U.id]\n" +
			"                                         │           ├─ static: [{[NULL, ∞)}]\n" +
			"                                         │           └─ columns: [id tw55n tce7a hpcms]\n" +
			"                                         └─ HashLookup\n" +
			"                                             ├─ source: TUPLE(nd.HPCMS:5)\n" +
			"                                             ├─ target: TUPLE(nma.id:0!null)\n" +
			"                                             └─ CachedResults\n" +
			"                                                 └─ TableAlias(nma)\n" +
			"                                                     └─ Table\n" +
			"                                                         ├─ name: TNMXI\n" +
			"                                                         └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `
	WITH
	   BMRZU AS
	           (SELECT
	               cla.FTQLQ AS T4IBQ,
	               sn.id AS BDNYB,
	               aac.BTXC5 AS BTXC5,
	               mf.id AS Z7CP5,
	               CASE
	                   WHEN mf.LT7K6 IS NOT NULL THEN mf.LT7K6
	                   ELSE mf.SPPYD
	               END AS vaf,
	               CASE
	                   WHEN mf.QCGTS IS NOT NULL THEN QCGTS
	                   ELSE 0.5
	               END AS QCGTS,
	               CASE
	                   WHEN vc.ZNP4P = 'L5Q44' THEN 1
	                   ELSE 0
	               END AS SNY4H
	           FROM YK2GW cla
	           INNER JOIN THNTS bs ON bs.IXUXU = cla.id
	           INNER JOIN HGMQ6 mf ON mf.GXLUB = bs.id
	           INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
	           INNER JOIN TPXBU aac ON aac.id = mf.M22QN
	           INNER JOIN SEQS3 W2MAO ON W2MAO.Z7CP5 = mf.id
	           INNER JOIN D34QP vc ON vc.id = W2MAO.YH4XB
	           WHERE cla.FTQLQ IN ('SQ1')
	AND mf.FSDY2 IN ('SRARY', 'UBQWG')),
	   YU7NY AS
	           (SELECT
	               nd.TW55N AS KUXQY,
	               sn.id AS BDNYB,
	               nma.DZLIM AS YHVEZ,
	               CASE
	                   WHEN nd.TCE7A < 0.9 THEN 1
	                   ELSE 0
	               END AS YAZ4X
	           FROM NOXN3 sn
	           LEFT JOIN E2I7U nd ON sn.BRQP2 = nd.id
	           LEFT JOIN TNMXI nma ON nd.HPCMS = nma.id
	           WHERE nma.DZLIM != 'Q5I4E'
	           ORDER BY sn.id ASC)
	SELECT DISTINCT
	   OXXEI.T4IBQ,
	   OXXEI.Z7CP5,
	   E52AP.KUXQY,
	   OXXEI.BDNYB,
	   CKELE.M6T2N,
	   OXXEI.BTXC5 as BTXC5,
	   OXXEI.vaf as vaf,
	   OXXEI.QCGTS as QCGTS,
	   OXXEI.SNY4H as SNY4H,
	   E52AP.YHVEZ as YHVEZ,
	   E52AP.YAZ4X as YAZ4X
	FROM
	   BMRZU OXXEI
	INNER JOIN YU7NY E52AP ON E52AP.BDNYB = OXXEI.BDNYB
	INNER JOIN
	   (SELECT
	       NOXN3.id as LWQ6O,
	       ROW_NUMBER() OVER (ORDER BY NOXN3.id ASC) M6T2N
	   FROM NOXN3) CKELE
	ON CKELE.LWQ6O = OXXEI.BDNYB
	ORDER BY CKELE.M6T2N ASC`,
		ExpectedPlan: "Sort(CKELE.M6T2N:4!null ASC nullsFirst)\n" +
			" └─ Distinct\n" +
			"     └─ Project\n" +
			"         ├─ columns: [OXXEI.T4IBQ:2!null, OXXEI.Z7CP5:5!null, E52AP.KUXQY:9, OXXEI.BDNYB:3!null, CKELE.M6T2N:1!null, OXXEI.BTXC5:4 as BTXC5, OXXEI.vaf:6 as vaf, OXXEI.QCGTS:7 as QCGTS, OXXEI.SNY4H:8!null as SNY4H, E52AP.YHVEZ:11 as YHVEZ, E52AP.YAZ4X:12!null as YAZ4X]\n" +
			"         └─ HashJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ E52AP.BDNYB:10!null\n" +
			"             │   └─ OXXEI.BDNYB:3!null\n" +
			"             ├─ HashJoin\n" +
			"             │   ├─ Eq\n" +
			"             │   │   ├─ CKELE.LWQ6O:0!null\n" +
			"             │   │   └─ OXXEI.BDNYB:3!null\n" +
			"             │   ├─ SubqueryAlias\n" +
			"             │   │   ├─ name: CKELE\n" +
			"             │   │   ├─ outerVisibility: false\n" +
			"             │   │   ├─ cacheable: true\n" +
			"             │   │   └─ Project\n" +
			"             │   │       ├─ columns: [LWQ6O:0!null, row_number() over ( order by NOXN3.id ASC):1!null as M6T2N]\n" +
			"             │   │       └─ Window\n" +
			"             │   │           ├─ NOXN3.id:0!null as LWQ6O\n" +
			"             │   │           ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"             │   │           └─ Table\n" +
			"             │   │               ├─ name: NOXN3\n" +
			"             │   │               └─ columns: [id]\n" +
			"             │   └─ HashLookup\n" +
			"             │       ├─ source: TUPLE(CKELE.LWQ6O:0!null)\n" +
			"             │       ├─ target: TUPLE(OXXEI.BDNYB:1!null)\n" +
			"             │       └─ CachedResults\n" +
			"             │           └─ SubqueryAlias\n" +
			"             │               ├─ name: OXXEI\n" +
			"             │               ├─ outerVisibility: false\n" +
			"             │               ├─ cacheable: true\n" +
			"             │               └─ Project\n" +
			"             │                   ├─ columns: [cla.FTQLQ:15!null as T4IBQ, sn.id:18!null as BDNYB, aac.BTXC5:17 as BTXC5, mf.id:4!null as Z7CP5, CASE  WHEN NOT\n" +
			"             │                   │   └─ mf.LT7K6:9 IS NULL\n" +
			"             │                   │   THEN mf.LT7K6:9 ELSE mf.SPPYD:10 END as vaf, CASE  WHEN NOT\n" +
			"             │                   │   └─ mf.QCGTS:11 IS NULL\n" +
			"             │                   │   THEN mf.QCGTS:11 ELSE 0.500000 (double) END as QCGTS, CASE  WHEN Eq\n" +
			"             │                   │   ├─ vc.ZNP4P:1!null\n" +
			"             │                   │   └─ L5Q44 (longtext)\n" +
			"             │                   │   THEN 1 (tinyint) ELSE 0 (tinyint) END as SNY4H]\n" +
			"             │                   └─ LookupJoin\n" +
			"             │                       ├─ Eq\n" +
			"             │                       │   ├─ sn.BRQP2:19!null\n" +
			"             │                       │   └─ mf.LUEVY:6!null\n" +
			"             │                       ├─ LookupJoin\n" +
			"             │                       │   ├─ Eq\n" +
			"             │                       │   │   ├─ aac.id:16!null\n" +
			"             │                       │   │   └─ mf.M22QN:7!null\n" +
			"             │                       │   ├─ LookupJoin\n" +
			"             │                       │   │   ├─ Eq\n" +
			"             │                       │   │   │   ├─ bs.IXUXU:13\n" +
			"             │                       │   │   │   └─ cla.id:14!null\n" +
			"             │                       │   │   ├─ LookupJoin\n" +
			"             │                       │   │   │   ├─ Eq\n" +
			"             │                       │   │   │   │   ├─ mf.GXLUB:5!null\n" +
			"             │                       │   │   │   │   └─ bs.id:12!null\n" +
			"             │                       │   │   │   ├─ LookupJoin\n" +
			"             │                       │   │   │   │   ├─ Eq\n" +
			"             │                       │   │   │   │   │   ├─ W2MAO.Z7CP5:2!null\n" +
			"             │                       │   │   │   │   │   └─ mf.id:4!null\n" +
			"             │                       │   │   │   │   ├─ LookupJoin\n" +
			"             │                       │   │   │   │   │   ├─ Eq\n" +
			"             │                       │   │   │   │   │   │   ├─ vc.id:0!null\n" +
			"             │                       │   │   │   │   │   │   └─ W2MAO.YH4XB:3!null\n" +
			"             │                       │   │   │   │   │   ├─ TableAlias(vc)\n" +
			"             │                       │   │   │   │   │   │   └─ Table\n" +
			"             │                       │   │   │   │   │   │       ├─ name: D34QP\n" +
			"             │                       │   │   │   │   │   │       └─ columns: [id znp4p]\n" +
			"             │                       │   │   │   │   │   └─ TableAlias(W2MAO)\n" +
			"             │                       │   │   │   │   │       └─ IndexedTableAccess(SEQS3)\n" +
			"             │                       │   │   │   │   │           ├─ index: [SEQS3.YH4XB]\n" +
			"             │                       │   │   │   │   │           └─ columns: [z7cp5 yh4xb]\n" +
			"             │                       │   │   │   │   └─ Filter\n" +
			"             │                       │   │   │   │       ├─ HashIn\n" +
			"             │                       │   │   │   │       │   ├─ mf.FSDY2:4!null\n" +
			"             │                       │   │   │   │       │   └─ TUPLE(SRARY (longtext), UBQWG (longtext))\n" +
			"             │                       │   │   │   │       └─ TableAlias(mf)\n" +
			"             │                       │   │   │   │           └─ IndexedTableAccess(HGMQ6)\n" +
			"             │                       │   │   │   │               ├─ index: [HGMQ6.id]\n" +
			"             │                       │   │   │   │               └─ columns: [id gxlub luevy m22qn fsdy2 lt7k6 sppyd qcgts]\n" +
			"             │                       │   │   │   └─ TableAlias(bs)\n" +
			"             │                       │   │   │       └─ IndexedTableAccess(THNTS)\n" +
			"             │                       │   │   │           ├─ index: [THNTS.id]\n" +
			"             │                       │   │   │           └─ columns: [id ixuxu]\n" +
			"             │                       │   │   └─ Filter\n" +
			"             │                       │   │       ├─ HashIn\n" +
			"             │                       │   │       │   ├─ cla.FTQLQ:1!null\n" +
			"             │                       │   │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"             │                       │   │       └─ TableAlias(cla)\n" +
			"             │                       │   │           └─ IndexedTableAccess(YK2GW)\n" +
			"             │                       │   │               ├─ index: [YK2GW.id]\n" +
			"             │                       │   │               └─ columns: [id ftqlq]\n" +
			"             │                       │   └─ TableAlias(aac)\n" +
			"             │                       │       └─ IndexedTableAccess(TPXBU)\n" +
			"             │                       │           ├─ index: [TPXBU.id]\n" +
			"             │                       │           └─ columns: [id btxc5]\n" +
			"             │                       └─ TableAlias(sn)\n" +
			"             │                           └─ IndexedTableAccess(NOXN3)\n" +
			"             │                               ├─ index: [NOXN3.BRQP2]\n" +
			"             │                               └─ columns: [id brqp2]\n" +
			"             └─ HashLookup\n" +
			"                 ├─ source: TUPLE(OXXEI.BDNYB:3!null)\n" +
			"                 ├─ target: TUPLE(E52AP.BDNYB:1!null)\n" +
			"                 └─ CachedResults\n" +
			"                     └─ SubqueryAlias\n" +
			"                         ├─ name: E52AP\n" +
			"                         ├─ outerVisibility: false\n" +
			"                         ├─ cacheable: true\n" +
			"                         └─ Sort(BDNYB:1!null ASC nullsFirst)\n" +
			"                             └─ Project\n" +
			"                                 ├─ columns: [nd.TW55N:3 as KUXQY, sn.id:0!null as BDNYB, nma.DZLIM:7 as YHVEZ, CASE  WHEN LessThan\n" +
			"                                 │   ├─ nd.TCE7A:4\n" +
			"                                 │   └─ 0.900000 (double)\n" +
			"                                 │   THEN 1 (tinyint) ELSE 0 (tinyint) END as YAZ4X]\n" +
			"                                 └─ Filter\n" +
			"                                     ├─ NOT\n" +
			"                                     │   └─ Eq\n" +
			"                                     │       ├─ nma.DZLIM:7\n" +
			"                                     │       └─ Q5I4E (longtext)\n" +
			"                                     └─ LeftOuterHashJoin\n" +
			"                                         ├─ Eq\n" +
			"                                         │   ├─ nd.HPCMS:5\n" +
			"                                         │   └─ nma.id:6!null\n" +
			"                                         ├─ LeftOuterMergeJoin\n" +
			"                                         │   ├─ cmp: Eq\n" +
			"                                         │   │   ├─ sn.BRQP2:1!null\n" +
			"                                         │   │   └─ nd.id:2!null\n" +
			"                                         │   ├─ TableAlias(sn)\n" +
			"                                         │   │   └─ IndexedTableAccess(NOXN3)\n" +
			"                                         │   │       ├─ index: [NOXN3.BRQP2]\n" +
			"                                         │   │       ├─ static: [{[NULL, ∞)}]\n" +
			"                                         │   │       └─ columns: [id brqp2]\n" +
			"                                         │   └─ TableAlias(nd)\n" +
			"                                         │       └─ IndexedTableAccess(E2I7U)\n" +
			"                                         │           ├─ index: [E2I7U.id]\n" +
			"                                         │           ├─ static: [{[NULL, ∞)}]\n" +
			"                                         │           └─ columns: [id tw55n tce7a hpcms]\n" +
			"                                         └─ HashLookup\n" +
			"                                             ├─ source: TUPLE(nd.HPCMS:5)\n" +
			"                                             ├─ target: TUPLE(nma.id:0!null)\n" +
			"                                             └─ CachedResults\n" +
			"                                                 └─ TableAlias(nma)\n" +
			"                                                     └─ Table\n" +
			"                                                         ├─ name: TNMXI\n" +
			"                                                         └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `
	WITH
	   FZFVD AS (
	       SELECT id, ROW_NUMBER() OVER (ORDER BY id ASC) - 1 AS M6T2N FROM NOXN3),
	   JCHIR AS (
	       SELECT
	       ism.FV24E AS FJDP5,
	       CPMFE.id AS BJUF2,
	       CPMFE.TW55N AS PSMU6,
	       ism.M22QN AS M22QN,
	       G3YXS.GE5EL,
	       G3YXS.F7A4Q,
	       G3YXS.ESFVY,
	       CASE
	           WHEN G3YXS.SL76B IN ('FO422', 'SJ53H') THEN 0
	           WHEN G3YXS.SL76B IN ('DCV4Z', 'UOSM4', 'FUGIP', 'H5MCC', 'YKEQE', 'D3AKL') THEN 1
	           WHEN G3YXS.SL76B IN ('QJEXM', 'J6S7P', 'VT7FI') THEN 2
	           WHEN G3YXS.SL76B IN ('Y62X7') THEN 3
	       END AS CC4AX,
	       G3YXS.SL76B AS SL76B,
	       YQIF4.id AS QNI57,
	       YVHJZ.id AS TDEIU
	       FROM
	       HDDVB ism
	       INNER JOIN YYBCX G3YXS ON G3YXS.id = ism.NZ4MQ
	       LEFT JOIN
	       WGSDC NHMXW
	       ON
	       NHMXW.id = ism.PRUV2
	       LEFT JOIN
	       E2I7U CPMFE
	       ON
	       CPMFE.ZH72S = NHMXW.NOHHR AND CPMFE.id <> ism.FV24E
	       LEFT JOIN
	       NOXN3 YQIF4
	       ON
	           YQIF4.BRQP2 = ism.FV24E
	       AND
	           YQIF4.FFTBJ = ism.UJ6XY
	       LEFT JOIN
	       NOXN3 YVHJZ
	       ON
	           YVHJZ.BRQP2 = ism.UJ6XY
	       AND
	           YVHJZ.FFTBJ = ism.FV24E
	       WHERE
	           YQIF4.id IS NOT NULL
	       OR
	           YVHJZ.id IS NOT NULL
	),
	OXDGK AS (
	   SELECT
	       FJDP5,
	       BJUF2,
	       PSMU6,
	       M22QN,
	       GE5EL,
	       F7A4Q,
	       ESFVY,
	       CC4AX,
	       SL76B,
	       QNI57,
	       TDEIU
	   FROM
	       JCHIR
	   WHERE
	           (QNI57 IS NOT NULL AND TDEIU IS NULL)
	       OR
	           (QNI57 IS NULL AND TDEIU IS NOT NULL)
	   UNION
	   SELECT
	       FJDP5,
	       BJUF2,
	       PSMU6,
	       M22QN,
	       GE5EL,
	       F7A4Q,
	       ESFVY,
	       CC4AX,
	       SL76B,
	       QNI57,
	       NULL AS TDEIU
	   FROM
	       JCHIR
	   WHERE
	       (QNI57 IS NOT NULL AND TDEIU IS NOT NULL)
	   UNION
	   SELECT
	       FJDP5,
	       BJUF2,
	       PSMU6,
	       M22QN,
	       GE5EL,
	       F7A4Q,
	       ESFVY,
	       CC4AX,
	       SL76B,
	       NULL AS QNI57,
	       TDEIU
	   FROM
	       JCHIR
	   WHERE
	       (QNI57 IS NOT NULL AND TDEIU IS NOT NULL)
	)
	SELECT
	mf.FTQLQ AS T4IBQ,
	
	CASE
	   WHEN MJR3D.QNI57 IS NOT NULL
	   THEN (SELECT ei.M6T2N FROM FZFVD ei WHERE ei.id = MJR3D.QNI57)
	   WHEN MJR3D.TDEIU IS NOT NULL
	   THEN (SELECT ei.M6T2N FROM FZFVD ei WHERE ei.id = MJR3D.TDEIU)
	END AS M6T2N,
	
	GE5EL AS GE5EL,
	F7A4Q AS F7A4Q,
	CC4AX AS CC4AX,
	SL76B AS SL76B,
	aac.BTXC5 AS YEBDJ,
	PSMU6
	
	FROM
	OXDGK MJR3D
	LEFT JOIN
	NOXN3 sn
	ON
	(
	   QNI57 IS NOT NULL
	   AND
	   sn.id = MJR3D.QNI57
	   AND
	   MJR3D.BJUF2 IS NULL
	)
	OR
	(
	   QNI57 IS NOT NULL
	   AND
	   MJR3D.BJUF2 IS NOT NULL
	   AND
	   sn.id IN (SELECT JTEHG.id FROM NOXN3 JTEHG WHERE BRQP2 = MJR3D.BJUF2)
	)
	OR
	(
	   TDEIU IS NOT NULL
	   AND
	   MJR3D.BJUF2 IS NULL
	   AND
	   sn.id IN (SELECT XMAFZ.id FROM NOXN3 XMAFZ WHERE BRQP2 = MJR3D.FJDP5)
	)
	OR
	(
	   TDEIU IS NOT NULL
	   AND
	   MJR3D.BJUF2 IS NOT NULL
	   AND
	   sn.id IN (SELECT XMAFZ.id FROM NOXN3 XMAFZ WHERE BRQP2 = MJR3D.BJUF2)
	)
	INNER JOIN
	(
	   SELECT FTQLQ, mf.LUEVY, mf.M22QN
	   FROM YK2GW cla
	   INNER JOIN THNTS bs ON cla.id = bs.IXUXU
	   INNER JOIN HGMQ6 mf ON bs.id = mf.GXLUB
	   WHERE cla.FTQLQ IN ('SQ1')
	) mf
	ON mf.LUEVY = sn.BRQP2 AND mf.M22QN = MJR3D.M22QN
	INNER JOIN
	   (SELECT * FROM TPXBU) aac
	ON aac.id = MJR3D.M22QN`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [mf.FTQLQ:24!null as T4IBQ, CASE  WHEN NOT\n" +
			" │   └─ MJR3D.QNI57:9 IS NULL\n" +
			" │   THEN Subquery\n" +
			" │   ├─ cacheable: false\n" +
			" │   └─ Project\n" +
			" │       ├─ columns: [ei.M6T2N:28!null]\n" +
			" │       └─ Filter\n" +
			" │           ├─ Eq\n" +
			" │           │   ├─ ei.id:27!null\n" +
			" │           │   └─ MJR3D.QNI57:9\n" +
			" │           └─ SubqueryAlias\n" +
			" │               ├─ name: ei\n" +
			" │               ├─ outerVisibility: true\n" +
			" │               ├─ cacheable: true\n" +
			" │               └─ Project\n" +
			" │                   ├─ columns: [NOXN3.id:27!null, (row_number() over ( order by NOXN3.id ASC):28!null - 1 (tinyint)) as M6T2N]\n" +
			" │                   └─ Window\n" +
			" │                       ├─ NOXN3.id:27!null\n" +
			" │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			" │                       └─ Table\n" +
			" │                           ├─ name: NOXN3\n" +
			" │                           └─ columns: [id]\n" +
			" │   WHEN NOT\n" +
			" │   └─ MJR3D.TDEIU:10 IS NULL\n" +
			" │   THEN Subquery\n" +
			" │   ├─ cacheable: false\n" +
			" │   └─ Project\n" +
			" │       ├─ columns: [ei.M6T2N:28!null]\n" +
			" │       └─ Filter\n" +
			" │           ├─ Eq\n" +
			" │           │   ├─ ei.id:27!null\n" +
			" │           │   └─ MJR3D.TDEIU:10\n" +
			" │           └─ SubqueryAlias\n" +
			" │               ├─ name: ei\n" +
			" │               ├─ outerVisibility: true\n" +
			" │               ├─ cacheable: true\n" +
			" │               └─ Project\n" +
			" │                   ├─ columns: [NOXN3.id:27!null, (row_number() over ( order by NOXN3.id ASC):28!null - 1 (tinyint)) as M6T2N]\n" +
			" │                   └─ Window\n" +
			" │                       ├─ NOXN3.id:27!null\n" +
			" │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			" │                       └─ Table\n" +
			" │                           ├─ name: NOXN3\n" +
			" │                           └─ columns: [id]\n" +
			" │   END as M6T2N, MJR3D.GE5EL:4 as GE5EL, MJR3D.F7A4Q:5 as F7A4Q, MJR3D.CC4AX:7 as CC4AX, MJR3D.SL76B:8!null as SL76B, aac.BTXC5:22 as YEBDJ, MJR3D.PSMU6:2]\n" +
			" └─ HashJoin\n" +
			"     ├─ AND\n" +
			"     │   ├─ Eq\n" +
			"     │   │   ├─ mf.LUEVY:25!null\n" +
			"     │   │   └─ sn.BRQP2:12\n" +
			"     │   └─ Eq\n" +
			"     │       ├─ mf.M22QN:26!null\n" +
			"     │       └─ MJR3D.M22QN:3!null\n" +
			"     ├─ HashJoin\n" +
			"     │   ├─ Eq\n" +
			"     │   │   ├─ aac.id:21!null\n" +
			"     │   │   └─ MJR3D.M22QN:3!null\n" +
			"     │   ├─ LeftOuterJoin\n" +
			"     │   │   ├─ Or\n" +
			"     │   │   │   ├─ Or\n" +
			"     │   │   │   │   ├─ Or\n" +
			"     │   │   │   │   │   ├─ AND\n" +
			"     │   │   │   │   │   │   ├─ AND\n" +
			"     │   │   │   │   │   │   │   ├─ NOT\n" +
			"     │   │   │   │   │   │   │   │   └─ MJR3D.QNI57:9 IS NULL\n" +
			"     │   │   │   │   │   │   │   └─ Eq\n" +
			"     │   │   │   │   │   │   │       ├─ sn.id:11!null\n" +
			"     │   │   │   │   │   │   │       └─ MJR3D.QNI57:9\n" +
			"     │   │   │   │   │   │   └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │   │   │   │   │   └─ AND\n" +
			"     │   │   │   │   │       ├─ AND\n" +
			"     │   │   │   │   │       │   ├─ NOT\n" +
			"     │   │   │   │   │       │   │   └─ MJR3D.QNI57:9 IS NULL\n" +
			"     │   │   │   │   │       │   └─ NOT\n" +
			"     │   │   │   │   │       │       └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │   │   │   │   │       └─ InSubquery\n" +
			"     │   │   │   │   │           ├─ left: sn.id:11!null\n" +
			"     │   │   │   │   │           └─ right: Subquery\n" +
			"     │   │   │   │   │               ├─ cacheable: false\n" +
			"     │   │   │   │   │               └─ Project\n" +
			"     │   │   │   │   │                   ├─ columns: [JTEHG.id:21!null]\n" +
			"     │   │   │   │   │                   └─ Filter\n" +
			"     │   │   │   │   │                       ├─ Eq\n" +
			"     │   │   │   │   │                       │   ├─ JTEHG.BRQP2:22!null\n" +
			"     │   │   │   │   │                       │   └─ MJR3D.BJUF2:1\n" +
			"     │   │   │   │   │                       └─ TableAlias(JTEHG)\n" +
			"     │   │   │   │   │                           └─ Table\n" +
			"     │   │   │   │   │                               ├─ name: NOXN3\n" +
			"     │   │   │   │   │                               └─ columns: [id brqp2]\n" +
			"     │   │   │   │   └─ AND\n" +
			"     │   │   │   │       ├─ AND\n" +
			"     │   │   │   │       │   ├─ NOT\n" +
			"     │   │   │   │       │   │   └─ MJR3D.TDEIU:10 IS NULL\n" +
			"     │   │   │   │       │   └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │   │   │   │       └─ InSubquery\n" +
			"     │   │   │   │           ├─ left: sn.id:11!null\n" +
			"     │   │   │   │           └─ right: Subquery\n" +
			"     │   │   │   │               ├─ cacheable: false\n" +
			"     │   │   │   │               └─ Project\n" +
			"     │   │   │   │                   ├─ columns: [XMAFZ.id:21!null]\n" +
			"     │   │   │   │                   └─ Filter\n" +
			"     │   │   │   │                       ├─ Eq\n" +
			"     │   │   │   │                       │   ├─ XMAFZ.BRQP2:22!null\n" +
			"     │   │   │   │                       │   └─ MJR3D.FJDP5:0!null\n" +
			"     │   │   │   │                       └─ TableAlias(XMAFZ)\n" +
			"     │   │   │   │                           └─ Table\n" +
			"     │   │   │   │                               ├─ name: NOXN3\n" +
			"     │   │   │   │                               └─ columns: [id brqp2]\n" +
			"     │   │   │   └─ AND\n" +
			"     │   │   │       ├─ AND\n" +
			"     │   │   │       │   ├─ NOT\n" +
			"     │   │   │       │   │   └─ MJR3D.TDEIU:10 IS NULL\n" +
			"     │   │   │       │   └─ NOT\n" +
			"     │   │   │       │       └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │   │   │       └─ InSubquery\n" +
			"     │   │   │           ├─ left: sn.id:11!null\n" +
			"     │   │   │           └─ right: Subquery\n" +
			"     │   │   │               ├─ cacheable: false\n" +
			"     │   │   │               └─ Project\n" +
			"     │   │   │                   ├─ columns: [XMAFZ.id:21!null]\n" +
			"     │   │   │                   └─ Filter\n" +
			"     │   │   │                       ├─ Eq\n" +
			"     │   │   │                       │   ├─ XMAFZ.BRQP2:22!null\n" +
			"     │   │   │                       │   └─ MJR3D.BJUF2:1\n" +
			"     │   │   │                       └─ TableAlias(XMAFZ)\n" +
			"     │   │   │                           └─ Table\n" +
			"     │   │   │                               ├─ name: NOXN3\n" +
			"     │   │   │                               └─ columns: [id brqp2]\n" +
			"     │   │   ├─ SubqueryAlias\n" +
			"     │   │   │   ├─ name: MJR3D\n" +
			"     │   │   │   ├─ outerVisibility: false\n" +
			"     │   │   │   ├─ cacheable: true\n" +
			"     │   │   │   └─ Union distinct\n" +
			"     │   │   │       ├─ Project\n" +
			"     │   │   │       │   ├─ columns: [JCHIR.FJDP5:0!null, JCHIR.BJUF2:1, JCHIR.PSMU6:2, JCHIR.M22QN:3!null, JCHIR.GE5EL:4, JCHIR.F7A4Q:5, JCHIR.ESFVY:6!null, JCHIR.CC4AX:7, JCHIR.SL76B:8!null, convert\n" +
			"     │   │   │       │   │   ├─ type: char\n" +
			"     │   │   │       │   │   └─ JCHIR.QNI57:9\n" +
			"     │   │   │       │   │   as QNI57, TDEIU:10 as TDEIU]\n" +
			"     │   │   │       │   └─ Union distinct\n" +
			"     │   │   │       │       ├─ Project\n" +
			"     │   │   │       │       │   ├─ columns: [JCHIR.FJDP5:0!null, JCHIR.BJUF2:1, JCHIR.PSMU6:2, JCHIR.M22QN:3!null, JCHIR.GE5EL:4, JCHIR.F7A4Q:5, JCHIR.ESFVY:6!null, JCHIR.CC4AX:7, JCHIR.SL76B:8!null, JCHIR.QNI57:9, convert\n" +
			"     │   │   │       │       │   │   ├─ type: char\n" +
			"     │   │   │       │       │   │   └─ JCHIR.TDEIU:10\n" +
			"     │   │   │       │       │   │   as TDEIU]\n" +
			"     │   │   │       │       │   └─ SubqueryAlias\n" +
			"     │   │   │       │       │       ├─ name: JCHIR\n" +
			"     │   │   │       │       │       ├─ outerVisibility: false\n" +
			"     │   │   │       │       │       ├─ cacheable: true\n" +
			"     │   │   │       │       │       └─ Filter\n" +
			"     │   │   │       │       │           ├─ Or\n" +
			"     │   │   │       │       │           │   ├─ AND\n" +
			"     │   │   │       │       │           │   │   ├─ NOT\n" +
			"     │   │   │       │       │           │   │   │   └─ QNI57:9 IS NULL\n" +
			"     │   │   │       │       │           │   │   └─ TDEIU:10 IS NULL\n" +
			"     │   │   │       │       │           │   └─ AND\n" +
			"     │   │   │       │       │           │       ├─ QNI57:9 IS NULL\n" +
			"     │   │   │       │       │           │       └─ NOT\n" +
			"     │   │   │       │       │           │           └─ TDEIU:10 IS NULL\n" +
			"     │   │   │       │       │           └─ Project\n" +
			"     │   │   │       │       │               ├─ columns: [ism.FV24E:0!null as FJDP5, CPMFE.id:12 as BJUF2, CPMFE.TW55N:13 as PSMU6, ism.M22QN:2!null as M22QN, G3YXS.GE5EL:8, G3YXS.F7A4Q:9, G3YXS.ESFVY:6!null, CASE  WHEN IN\n" +
			"     │   │   │       │       │               │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │       │               │   └─ right: TUPLE(FO422 (longtext), SJ53H (longtext))\n" +
			"     │   │   │       │       │               │   THEN 0 (tinyint) WHEN IN\n" +
			"     │   │   │       │       │               │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │       │               │   └─ right: TUPLE(DCV4Z (longtext), UOSM4 (longtext), FUGIP (longtext), H5MCC (longtext), YKEQE (longtext), D3AKL (longtext))\n" +
			"     │   │   │       │       │               │   THEN 1 (tinyint) WHEN IN\n" +
			"     │   │   │       │       │               │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │       │               │   └─ right: TUPLE(QJEXM (longtext), J6S7P (longtext), VT7FI (longtext))\n" +
			"     │   │   │       │       │               │   THEN 2 (tinyint) WHEN IN\n" +
			"     │   │   │       │       │               │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │       │               │   └─ right: TUPLE(Y62X7 (longtext))\n" +
			"     │   │   │       │       │               │   THEN 3 (tinyint) END as CC4AX, G3YXS.SL76B:7!null as SL76B, YQIF4.id:15 as QNI57, YVHJZ.id:18 as TDEIU]\n" +
			"     │   │   │       │       │               └─ Filter\n" +
			"     │   │   │       │       │                   ├─ Or\n" +
			"     │   │   │       │       │                   │   ├─ NOT\n" +
			"     │   │   │       │       │                   │   │   └─ YQIF4.id:15 IS NULL\n" +
			"     │   │   │       │       │                   │   └─ NOT\n" +
			"     │   │   │       │       │                   │       └─ YVHJZ.id:18 IS NULL\n" +
			"     │   │   │       │       │                   └─ LeftOuterJoin\n" +
			"     │   │   │       │       │                       ├─ AND\n" +
			"     │   │   │       │       │                       │   ├─ Eq\n" +
			"     │   │   │       │       │                       │   │   ├─ YVHJZ.BRQP2:19!null\n" +
			"     │   │   │       │       │                       │   │   └─ ism.UJ6XY:1!null\n" +
			"     │   │   │       │       │                       │   └─ Eq\n" +
			"     │   │   │       │       │                       │       ├─ YVHJZ.FFTBJ:20!null\n" +
			"     │   │   │       │       │                       │       └─ ism.FV24E:0!null\n" +
			"     │   │   │       │       │                       ├─ LeftOuterJoin\n" +
			"     │   │   │       │       │                       │   ├─ AND\n" +
			"     │   │   │       │       │                       │   │   ├─ Eq\n" +
			"     │   │   │       │       │                       │   │   │   ├─ YQIF4.BRQP2:16!null\n" +
			"     │   │   │       │       │                       │   │   │   └─ ism.FV24E:0!null\n" +
			"     │   │   │       │       │                       │   │   └─ Eq\n" +
			"     │   │   │       │       │                       │   │       ├─ YQIF4.FFTBJ:17!null\n" +
			"     │   │   │       │       │                       │   │       └─ ism.UJ6XY:1!null\n" +
			"     │   │   │       │       │                       │   ├─ LeftOuterJoin\n" +
			"     │   │   │       │       │                       │   │   ├─ AND\n" +
			"     │   │   │       │       │                       │   │   │   ├─ Eq\n" +
			"     │   │   │       │       │                       │   │   │   │   ├─ CPMFE.ZH72S:14\n" +
			"     │   │   │       │       │                       │   │   │   │   └─ NHMXW.NOHHR:11\n" +
			"     │   │   │       │       │                       │   │   │   └─ NOT\n" +
			"     │   │   │       │       │                       │   │   │       └─ Eq\n" +
			"     │   │   │       │       │                       │   │   │           ├─ CPMFE.id:12!null\n" +
			"     │   │   │       │       │                       │   │   │           └─ ism.FV24E:0!null\n" +
			"     │   │   │       │       │                       │   │   ├─ LeftOuterJoin\n" +
			"     │   │   │       │       │                       │   │   │   ├─ Eq\n" +
			"     │   │   │       │       │                       │   │   │   │   ├─ NHMXW.id:10!null\n" +
			"     │   │   │       │       │                       │   │   │   │   └─ ism.PRUV2:4\n" +
			"     │   │   │       │       │                       │   │   │   ├─ InnerJoin\n" +
			"     │   │   │       │       │                       │   │   │   │   ├─ Eq\n" +
			"     │   │   │       │       │                       │   │   │   │   │   ├─ G3YXS.id:5!null\n" +
			"     │   │   │       │       │                       │   │   │   │   │   └─ ism.NZ4MQ:3!null\n" +
			"     │   │   │       │       │                       │   │   │   │   ├─ TableAlias(ism)\n" +
			"     │   │   │       │       │                       │   │   │   │   │   └─ Table\n" +
			"     │   │   │       │       │                       │   │   │   │   │       ├─ name: HDDVB\n" +
			"     │   │   │       │       │                       │   │   │   │   │       └─ columns: [fv24e uj6xy m22qn nz4mq pruv2]\n" +
			"     │   │   │       │       │                       │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"     │   │   │       │       │                       │   │   │   │       └─ Table\n" +
			"     │   │   │       │       │                       │   │   │   │           ├─ name: YYBCX\n" +
			"     │   │   │       │       │                       │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q]\n" +
			"     │   │   │       │       │                       │   │   │   └─ TableAlias(NHMXW)\n" +
			"     │   │   │       │       │                       │   │   │       └─ Table\n" +
			"     │   │   │       │       │                       │   │   │           ├─ name: WGSDC\n" +
			"     │   │   │       │       │                       │   │   │           └─ columns: [id nohhr]\n" +
			"     │   │   │       │       │                       │   │   └─ TableAlias(CPMFE)\n" +
			"     │   │   │       │       │                       │   │       └─ Table\n" +
			"     │   │   │       │       │                       │   │           ├─ name: E2I7U\n" +
			"     │   │   │       │       │                       │   │           └─ columns: [id tw55n zh72s]\n" +
			"     │   │   │       │       │                       │   └─ TableAlias(YQIF4)\n" +
			"     │   │   │       │       │                       │       └─ Table\n" +
			"     │   │   │       │       │                       │           ├─ name: NOXN3\n" +
			"     │   │   │       │       │                       │           └─ columns: [id brqp2 fftbj]\n" +
			"     │   │   │       │       │                       └─ TableAlias(YVHJZ)\n" +
			"     │   │   │       │       │                           └─ Table\n" +
			"     │   │   │       │       │                               ├─ name: NOXN3\n" +
			"     │   │   │       │       │                               └─ columns: [id brqp2 fftbj]\n" +
			"     │   │   │       │       └─ Project\n" +
			"     │   │   │       │           ├─ columns: [JCHIR.FJDP5:0!null, JCHIR.BJUF2:1, JCHIR.PSMU6:2, JCHIR.M22QN:3!null, JCHIR.GE5EL:4, JCHIR.F7A4Q:5, JCHIR.ESFVY:6!null, JCHIR.CC4AX:7, JCHIR.SL76B:8!null, JCHIR.QNI57:9, convert\n" +
			"     │   │   │       │           │   ├─ type: char\n" +
			"     │   │   │       │           │   └─ TDEIU:10\n" +
			"     │   │   │       │           │   as TDEIU]\n" +
			"     │   │   │       │           └─ Project\n" +
			"     │   │   │       │               ├─ columns: [JCHIR.FJDP5:0!null, JCHIR.BJUF2:1, JCHIR.PSMU6:2, JCHIR.M22QN:3!null, JCHIR.GE5EL:4, JCHIR.F7A4Q:5, JCHIR.ESFVY:6!null, JCHIR.CC4AX:7, JCHIR.SL76B:8!null, JCHIR.QNI57:9, NULL (null) as TDEIU]\n" +
			"     │   │   │       │               └─ SubqueryAlias\n" +
			"     │   │   │       │                   ├─ name: JCHIR\n" +
			"     │   │   │       │                   ├─ outerVisibility: false\n" +
			"     │   │   │       │                   ├─ cacheable: true\n" +
			"     │   │   │       │                   └─ Filter\n" +
			"     │   │   │       │                       ├─ AND\n" +
			"     │   │   │       │                       │   ├─ NOT\n" +
			"     │   │   │       │                       │   │   └─ QNI57:9 IS NULL\n" +
			"     │   │   │       │                       │   └─ NOT\n" +
			"     │   │   │       │                       │       └─ TDEIU:10 IS NULL\n" +
			"     │   │   │       │                       └─ Project\n" +
			"     │   │   │       │                           ├─ columns: [ism.FV24E:0!null as FJDP5, CPMFE.id:12 as BJUF2, CPMFE.TW55N:13 as PSMU6, ism.M22QN:2!null as M22QN, G3YXS.GE5EL:8, G3YXS.F7A4Q:9, G3YXS.ESFVY:6!null, CASE  WHEN IN\n" +
			"     │   │   │       │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │                           │   └─ right: TUPLE(FO422 (longtext), SJ53H (longtext))\n" +
			"     │   │   │       │                           │   THEN 0 (tinyint) WHEN IN\n" +
			"     │   │   │       │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │                           │   └─ right: TUPLE(DCV4Z (longtext), UOSM4 (longtext), FUGIP (longtext), H5MCC (longtext), YKEQE (longtext), D3AKL (longtext))\n" +
			"     │   │   │       │                           │   THEN 1 (tinyint) WHEN IN\n" +
			"     │   │   │       │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │                           │   └─ right: TUPLE(QJEXM (longtext), J6S7P (longtext), VT7FI (longtext))\n" +
			"     │   │   │       │                           │   THEN 2 (tinyint) WHEN IN\n" +
			"     │   │   │       │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │       │                           │   └─ right: TUPLE(Y62X7 (longtext))\n" +
			"     │   │   │       │                           │   THEN 3 (tinyint) END as CC4AX, G3YXS.SL76B:7!null as SL76B, YQIF4.id:15 as QNI57, YVHJZ.id:18 as TDEIU]\n" +
			"     │   │   │       │                           └─ Filter\n" +
			"     │   │   │       │                               ├─ Or\n" +
			"     │   │   │       │                               │   ├─ NOT\n" +
			"     │   │   │       │                               │   │   └─ YQIF4.id:15 IS NULL\n" +
			"     │   │   │       │                               │   └─ NOT\n" +
			"     │   │   │       │                               │       └─ YVHJZ.id:18 IS NULL\n" +
			"     │   │   │       │                               └─ LeftOuterJoin\n" +
			"     │   │   │       │                                   ├─ AND\n" +
			"     │   │   │       │                                   │   ├─ Eq\n" +
			"     │   │   │       │                                   │   │   ├─ YVHJZ.BRQP2:19!null\n" +
			"     │   │   │       │                                   │   │   └─ ism.UJ6XY:1!null\n" +
			"     │   │   │       │                                   │   └─ Eq\n" +
			"     │   │   │       │                                   │       ├─ YVHJZ.FFTBJ:20!null\n" +
			"     │   │   │       │                                   │       └─ ism.FV24E:0!null\n" +
			"     │   │   │       │                                   ├─ LeftOuterJoin\n" +
			"     │   │   │       │                                   │   ├─ AND\n" +
			"     │   │   │       │                                   │   │   ├─ Eq\n" +
			"     │   │   │       │                                   │   │   │   ├─ YQIF4.BRQP2:16!null\n" +
			"     │   │   │       │                                   │   │   │   └─ ism.FV24E:0!null\n" +
			"     │   │   │       │                                   │   │   └─ Eq\n" +
			"     │   │   │       │                                   │   │       ├─ YQIF4.FFTBJ:17!null\n" +
			"     │   │   │       │                                   │   │       └─ ism.UJ6XY:1!null\n" +
			"     │   │   │       │                                   │   ├─ LeftOuterJoin\n" +
			"     │   │   │       │                                   │   │   ├─ AND\n" +
			"     │   │   │       │                                   │   │   │   ├─ Eq\n" +
			"     │   │   │       │                                   │   │   │   │   ├─ CPMFE.ZH72S:14\n" +
			"     │   │   │       │                                   │   │   │   │   └─ NHMXW.NOHHR:11\n" +
			"     │   │   │       │                                   │   │   │   └─ NOT\n" +
			"     │   │   │       │                                   │   │   │       └─ Eq\n" +
			"     │   │   │       │                                   │   │   │           ├─ CPMFE.id:12!null\n" +
			"     │   │   │       │                                   │   │   │           └─ ism.FV24E:0!null\n" +
			"     │   │   │       │                                   │   │   ├─ LeftOuterJoin\n" +
			"     │   │   │       │                                   │   │   │   ├─ Eq\n" +
			"     │   │   │       │                                   │   │   │   │   ├─ NHMXW.id:10!null\n" +
			"     │   │   │       │                                   │   │   │   │   └─ ism.PRUV2:4\n" +
			"     │   │   │       │                                   │   │   │   ├─ InnerJoin\n" +
			"     │   │   │       │                                   │   │   │   │   ├─ Eq\n" +
			"     │   │   │       │                                   │   │   │   │   │   ├─ G3YXS.id:5!null\n" +
			"     │   │   │       │                                   │   │   │   │   │   └─ ism.NZ4MQ:3!null\n" +
			"     │   │   │       │                                   │   │   │   │   ├─ TableAlias(ism)\n" +
			"     │   │   │       │                                   │   │   │   │   │   └─ Table\n" +
			"     │   │   │       │                                   │   │   │   │   │       ├─ name: HDDVB\n" +
			"     │   │   │       │                                   │   │   │   │   │       └─ columns: [fv24e uj6xy m22qn nz4mq pruv2]\n" +
			"     │   │   │       │                                   │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"     │   │   │       │                                   │   │   │   │       └─ Table\n" +
			"     │   │   │       │                                   │   │   │   │           ├─ name: YYBCX\n" +
			"     │   │   │       │                                   │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q]\n" +
			"     │   │   │       │                                   │   │   │   └─ TableAlias(NHMXW)\n" +
			"     │   │   │       │                                   │   │   │       └─ Table\n" +
			"     │   │   │       │                                   │   │   │           ├─ name: WGSDC\n" +
			"     │   │   │       │                                   │   │   │           └─ columns: [id nohhr]\n" +
			"     │   │   │       │                                   │   │   └─ TableAlias(CPMFE)\n" +
			"     │   │   │       │                                   │   │       └─ Table\n" +
			"     │   │   │       │                                   │   │           ├─ name: E2I7U\n" +
			"     │   │   │       │                                   │   │           └─ columns: [id tw55n zh72s]\n" +
			"     │   │   │       │                                   │   └─ TableAlias(YQIF4)\n" +
			"     │   │   │       │                                   │       └─ Table\n" +
			"     │   │   │       │                                   │           ├─ name: NOXN3\n" +
			"     │   │   │       │                                   │           └─ columns: [id brqp2 fftbj]\n" +
			"     │   │   │       │                                   └─ TableAlias(YVHJZ)\n" +
			"     │   │   │       │                                       └─ Table\n" +
			"     │   │   │       │                                           ├─ name: NOXN3\n" +
			"     │   │   │       │                                           └─ columns: [id brqp2 fftbj]\n" +
			"     │   │   │       └─ Project\n" +
			"     │   │   │           ├─ columns: [JCHIR.FJDP5:0!null, JCHIR.BJUF2:1, JCHIR.PSMU6:2, JCHIR.M22QN:3!null, JCHIR.GE5EL:4, JCHIR.F7A4Q:5, JCHIR.ESFVY:6!null, JCHIR.CC4AX:7, JCHIR.SL76B:8!null, convert\n" +
			"     │   │   │           │   ├─ type: char\n" +
			"     │   │   │           │   └─ QNI57:9\n" +
			"     │   │   │           │   as QNI57, convert\n" +
			"     │   │   │           │   ├─ type: char\n" +
			"     │   │   │           │   └─ JCHIR.TDEIU:10\n" +
			"     │   │   │           │   as TDEIU]\n" +
			"     │   │   │           └─ Project\n" +
			"     │   │   │               ├─ columns: [JCHIR.FJDP5:0!null, JCHIR.BJUF2:1, JCHIR.PSMU6:2, JCHIR.M22QN:3!null, JCHIR.GE5EL:4, JCHIR.F7A4Q:5, JCHIR.ESFVY:6!null, JCHIR.CC4AX:7, JCHIR.SL76B:8!null, NULL (null) as QNI57, JCHIR.TDEIU:10]\n" +
			"     │   │   │               └─ SubqueryAlias\n" +
			"     │   │   │                   ├─ name: JCHIR\n" +
			"     │   │   │                   ├─ outerVisibility: false\n" +
			"     │   │   │                   ├─ cacheable: true\n" +
			"     │   │   │                   └─ Filter\n" +
			"     │   │   │                       ├─ AND\n" +
			"     │   │   │                       │   ├─ NOT\n" +
			"     │   │   │                       │   │   └─ QNI57:9 IS NULL\n" +
			"     │   │   │                       │   └─ NOT\n" +
			"     │   │   │                       │       └─ TDEIU:10 IS NULL\n" +
			"     │   │   │                       └─ Project\n" +
			"     │   │   │                           ├─ columns: [ism.FV24E:0!null as FJDP5, CPMFE.id:12 as BJUF2, CPMFE.TW55N:13 as PSMU6, ism.M22QN:2!null as M22QN, G3YXS.GE5EL:8, G3YXS.F7A4Q:9, G3YXS.ESFVY:6!null, CASE  WHEN IN\n" +
			"     │   │   │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │                           │   └─ right: TUPLE(FO422 (longtext), SJ53H (longtext))\n" +
			"     │   │   │                           │   THEN 0 (tinyint) WHEN IN\n" +
			"     │   │   │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │                           │   └─ right: TUPLE(DCV4Z (longtext), UOSM4 (longtext), FUGIP (longtext), H5MCC (longtext), YKEQE (longtext), D3AKL (longtext))\n" +
			"     │   │   │                           │   THEN 1 (tinyint) WHEN IN\n" +
			"     │   │   │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │                           │   └─ right: TUPLE(QJEXM (longtext), J6S7P (longtext), VT7FI (longtext))\n" +
			"     │   │   │                           │   THEN 2 (tinyint) WHEN IN\n" +
			"     │   │   │                           │   ├─ left: G3YXS.SL76B:7!null\n" +
			"     │   │   │                           │   └─ right: TUPLE(Y62X7 (longtext))\n" +
			"     │   │   │                           │   THEN 3 (tinyint) END as CC4AX, G3YXS.SL76B:7!null as SL76B, YQIF4.id:15 as QNI57, YVHJZ.id:18 as TDEIU]\n" +
			"     │   │   │                           └─ Filter\n" +
			"     │   │   │                               ├─ Or\n" +
			"     │   │   │                               │   ├─ NOT\n" +
			"     │   │   │                               │   │   └─ YQIF4.id:15 IS NULL\n" +
			"     │   │   │                               │   └─ NOT\n" +
			"     │   │   │                               │       └─ YVHJZ.id:18 IS NULL\n" +
			"     │   │   │                               └─ LeftOuterJoin\n" +
			"     │   │   │                                   ├─ AND\n" +
			"     │   │   │                                   │   ├─ Eq\n" +
			"     │   │   │                                   │   │   ├─ YVHJZ.BRQP2:19!null\n" +
			"     │   │   │                                   │   │   └─ ism.UJ6XY:1!null\n" +
			"     │   │   │                                   │   └─ Eq\n" +
			"     │   │   │                                   │       ├─ YVHJZ.FFTBJ:20!null\n" +
			"     │   │   │                                   │       └─ ism.FV24E:0!null\n" +
			"     │   │   │                                   ├─ LeftOuterJoin\n" +
			"     │   │   │                                   │   ├─ AND\n" +
			"     │   │   │                                   │   │   ├─ Eq\n" +
			"     │   │   │                                   │   │   │   ├─ YQIF4.BRQP2:16!null\n" +
			"     │   │   │                                   │   │   │   └─ ism.FV24E:0!null\n" +
			"     │   │   │                                   │   │   └─ Eq\n" +
			"     │   │   │                                   │   │       ├─ YQIF4.FFTBJ:17!null\n" +
			"     │   │   │                                   │   │       └─ ism.UJ6XY:1!null\n" +
			"     │   │   │                                   │   ├─ LeftOuterJoin\n" +
			"     │   │   │                                   │   │   ├─ AND\n" +
			"     │   │   │                                   │   │   │   ├─ Eq\n" +
			"     │   │   │                                   │   │   │   │   ├─ CPMFE.ZH72S:14\n" +
			"     │   │   │                                   │   │   │   │   └─ NHMXW.NOHHR:11\n" +
			"     │   │   │                                   │   │   │   └─ NOT\n" +
			"     │   │   │                                   │   │   │       └─ Eq\n" +
			"     │   │   │                                   │   │   │           ├─ CPMFE.id:12!null\n" +
			"     │   │   │                                   │   │   │           └─ ism.FV24E:0!null\n" +
			"     │   │   │                                   │   │   ├─ LeftOuterJoin\n" +
			"     │   │   │                                   │   │   │   ├─ Eq\n" +
			"     │   │   │                                   │   │   │   │   ├─ NHMXW.id:10!null\n" +
			"     │   │   │                                   │   │   │   │   └─ ism.PRUV2:4\n" +
			"     │   │   │                                   │   │   │   ├─ InnerJoin\n" +
			"     │   │   │                                   │   │   │   │   ├─ Eq\n" +
			"     │   │   │                                   │   │   │   │   │   ├─ G3YXS.id:5!null\n" +
			"     │   │   │                                   │   │   │   │   │   └─ ism.NZ4MQ:3!null\n" +
			"     │   │   │                                   │   │   │   │   ├─ TableAlias(ism)\n" +
			"     │   │   │                                   │   │   │   │   │   └─ Table\n" +
			"     │   │   │                                   │   │   │   │   │       ├─ name: HDDVB\n" +
			"     │   │   │                                   │   │   │   │   │       └─ columns: [fv24e uj6xy m22qn nz4mq pruv2]\n" +
			"     │   │   │                                   │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"     │   │   │                                   │   │   │   │       └─ Table\n" +
			"     │   │   │                                   │   │   │   │           ├─ name: YYBCX\n" +
			"     │   │   │                                   │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q]\n" +
			"     │   │   │                                   │   │   │   └─ TableAlias(NHMXW)\n" +
			"     │   │   │                                   │   │   │       └─ Table\n" +
			"     │   │   │                                   │   │   │           ├─ name: WGSDC\n" +
			"     │   │   │                                   │   │   │           └─ columns: [id nohhr]\n" +
			"     │   │   │                                   │   │   └─ TableAlias(CPMFE)\n" +
			"     │   │   │                                   │   │       └─ Table\n" +
			"     │   │   │                                   │   │           ├─ name: E2I7U\n" +
			"     │   │   │                                   │   │           └─ columns: [id tw55n zh72s]\n" +
			"     │   │   │                                   │   └─ TableAlias(YQIF4)\n" +
			"     │   │   │                                   │       └─ Table\n" +
			"     │   │   │                                   │           ├─ name: NOXN3\n" +
			"     │   │   │                                   │           └─ columns: [id brqp2 fftbj]\n" +
			"     │   │   │                                   └─ TableAlias(YVHJZ)\n" +
			"     │   │   │                                       └─ Table\n" +
			"     │   │   │                                           ├─ name: NOXN3\n" +
			"     │   │   │                                           └─ columns: [id brqp2 fftbj]\n" +
			"     │   │   └─ TableAlias(sn)\n" +
			"     │   │       └─ Table\n" +
			"     │   │           ├─ name: NOXN3\n" +
			"     │   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │   └─ HashLookup\n" +
			"     │       ├─ source: TUPLE(MJR3D.M22QN:3!null)\n" +
			"     │       ├─ target: TUPLE(aac.id:0!null)\n" +
			"     │       └─ CachedResults\n" +
			"     │           └─ SubqueryAlias\n" +
			"     │               ├─ name: aac\n" +
			"     │               ├─ outerVisibility: false\n" +
			"     │               ├─ cacheable: true\n" +
			"     │               └─ Table\n" +
			"     │                   ├─ name: TPXBU\n" +
			"     │                   └─ columns: [id btxc5 fhcyt]\n" +
			"     └─ HashLookup\n" +
			"         ├─ source: TUPLE(sn.BRQP2:12, MJR3D.M22QN:3!null)\n" +
			"         ├─ target: TUPLE(mf.LUEVY:1!null, mf.M22QN:2!null)\n" +
			"         └─ CachedResults\n" +
			"             └─ SubqueryAlias\n" +
			"                 ├─ name: mf\n" +
			"                 ├─ outerVisibility: false\n" +
			"                 ├─ cacheable: true\n" +
			"                 └─ Project\n" +
			"                     ├─ columns: [cla.FTQLQ:6!null, mf.LUEVY:3!null, mf.M22QN:4!null]\n" +
			"                     └─ LookupJoin\n" +
			"                         ├─ Eq\n" +
			"                         │   ├─ cla.id:5!null\n" +
			"                         │   └─ bs.IXUXU:1\n" +
			"                         ├─ LookupJoin\n" +
			"                         │   ├─ Eq\n" +
			"                         │   │   ├─ bs.id:0!null\n" +
			"                         │   │   └─ mf.GXLUB:2!null\n" +
			"                         │   ├─ TableAlias(bs)\n" +
			"                         │   │   └─ Table\n" +
			"                         │   │       ├─ name: THNTS\n" +
			"                         │   │       └─ columns: [id ixuxu]\n" +
			"                         │   └─ TableAlias(mf)\n" +
			"                         │       └─ IndexedTableAccess(HGMQ6)\n" +
			"                         │           ├─ index: [HGMQ6.GXLUB]\n" +
			"                         │           └─ columns: [gxlub luevy m22qn]\n" +
			"                         └─ Filter\n" +
			"                             ├─ HashIn\n" +
			"                             │   ├─ cla.FTQLQ:1!null\n" +
			"                             │   └─ TUPLE(SQ1 (longtext))\n" +
			"                             └─ TableAlias(cla)\n" +
			"                                 └─ IndexedTableAccess(YK2GW)\n" +
			"                                     ├─ index: [YK2GW.id]\n" +
			"                                     └─ columns: [id ftqlq]\n" +
			"",
	},
	{
		Query: `
WITH
    FZFVD AS (
        SELECT id, ROW_NUMBER() OVER (ORDER BY id ASC) - 1 AS M6T2N FROM NOXN3
    ),
    OXDGK AS (
        SELECT DISTINCT
        ism.FV24E AS FJDP5,
        CPMFE.id AS BJUF2,
        ism.M22QN AS M22QN,
        G3YXS.TUV25 AS TUV25,
        G3YXS.ESFVY AS ESFVY,
        YQIF4.id AS QNI57,
        YVHJZ.id AS TDEIU
        FROM
        HDDVB ism
        INNER JOIN YYBCX G3YXS ON G3YXS.id = ism.NZ4MQ
        LEFT JOIN
        WGSDC NHMXW
        ON
        NHMXW.id = ism.PRUV2
        LEFT JOIN
        E2I7U CPMFE
        ON
        CPMFE.ZH72S = NHMXW.NOHHR AND CPMFE.id <> ism.FV24E
        LEFT JOIN
        NOXN3 YQIF4
        ON
            YQIF4.BRQP2 = ism.FV24E
        AND
            YQIF4.FFTBJ = ism.UJ6XY
        LEFT JOIN
        NOXN3 YVHJZ
        ON
            YVHJZ.BRQP2 = ism.UJ6XY
        AND
            YVHJZ.FFTBJ = ism.FV24E
        WHERE
            G3YXS.TUV25 IS NOT NULL 
        AND
            (YQIF4.id IS NOT NULL
        OR
            YVHJZ.id IS NOT NULL)
    ),

    HTKBS AS (
        SELECT /*+ JOIN_ORDER(cla, bs, mf, sn) */
            cla.FTQLQ AS T4IBQ,
            sn.id AS BDNYB,
            mf.M22QN AS M22QN
        FROM HGMQ6 mf
        INNER JOIN THNTS bs ON bs.id = mf.GXLUB
        INNER JOIN YK2GW cla ON cla.id = bs.IXUXU
        INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
        WHERE cla.FTQLQ IN ('SQ1')
    ),
    JQHRG AS (
        SELECT
            CASE
                    WHEN MJR3D.QNI57 IS NOT NULL
                        THEN (SELECT ei.M6T2N FROM FZFVD ei WHERE ei.id = MJR3D.QNI57)
                    WHEN MJR3D.TDEIU IS NOT NULL
                        THEN (SELECT ei.M6T2N FROM FZFVD ei WHERE ei.id = MJR3D.TDEIU)
            END AS M6T2N,

            aac.BTXC5 AS BTXC5,
            aac.id AS NTOFG,
            sn.id AS LWQ6O,
            MJR3D.TUV25 AS TUV25
            FROM 
                OXDGK MJR3D
            INNER JOIN TPXBU aac ON aac.id = MJR3D.M22QN
            LEFT JOIN
            NOXN3 sn
            ON
            (
                QNI57 IS NOT NULL
                AND
                sn.id = MJR3D.QNI57
                AND
                MJR3D.BJUF2 IS NULL
            )
            OR 
            (
                QNI57 IS NOT NULL
                AND
                sn.id IN (SELECT JTEHG.id FROM NOXN3 JTEHG WHERE BRQP2 = MJR3D.BJUF2)
                AND
                MJR3D.BJUF2 IS NOT NULL
            )
            OR 
            (
                TDEIU IS NOT NULL
                AND
                sn.id IN (SELECT XMAFZ.id FROM NOXN3 XMAFZ WHERE BRQP2 = MJR3D.FJDP5)
                AND
                MJR3D.BJUF2 IS NULL
            )
            OR
            (
                TDEIU IS NOT NULL
                AND
                sn.id IN (SELECT XMAFZ.id FROM NOXN3 XMAFZ WHERE BRQP2 = MJR3D.BJUF2)
                AND
                MJR3D.BJUF2 IS NOT NULL
            )
    ),

    F6BRC AS (
        SELECT
            RSA3Y.T4IBQ AS T4IBQ,
            JMHIE.M6T2N AS M6T2N,
            JMHIE.BTXC5 AS BTXC5,
            JMHIE.TUV25 AS TUV25
        FROM
            (SELECT DISTINCT M6T2N, BTXC5, TUV25 FROM JQHRG) JMHIE
        CROSS JOIN
            (SELECT DISTINCT T4IBQ FROM HTKBS) RSA3Y
    ),

    ZMSPR AS (
        SELECT DISTINCT
            cld.T4IBQ AS T4IBQ,
            P4PJZ.M6T2N AS M6T2N,
            P4PJZ.BTXC5 AS BTXC5,
            P4PJZ.TUV25 AS TUV25
        FROM
            HTKBS cld
        LEFT JOIN
            JQHRG P4PJZ
        ON P4PJZ.LWQ6O = cld.BDNYB AND P4PJZ.NTOFG = cld.M22QN
        WHERE
                P4PJZ.M6T2N IS NOT NULL
    )
SELECT
    fs.T4IBQ AS T4IBQ,
    fs.M6T2N AS M6T2N,
    fs.TUV25 AS TUV25,
    fs.BTXC5 AS YEBDJ
FROM
    F6BRC fs
WHERE
    (fs.T4IBQ, fs.M6T2N, fs.BTXC5, fs.TUV25)
    NOT IN (
        SELECT
            ZMSPR.T4IBQ,
            ZMSPR.M6T2N,
            ZMSPR.BTXC5,
            ZMSPR.TUV25
        FROM
            ZMSPR
    )`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [fs.T4IBQ:0!null as T4IBQ, fs.M6T2N:1 as M6T2N, fs.TUV25:3 as TUV25, fs.BTXC5:2 as YEBDJ]\n" +
			" └─ AntiJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ TUPLE(fs.T4IBQ:0!null, fs.M6T2N:1, fs.BTXC5:2, fs.TUV25:3)\n" +
			"     │   └─ TUPLE(applySubq0.T4IBQ:4!null, applySubq0.M6T2N:5, applySubq0.BTXC5:6, applySubq0.TUV25:7)\n" +
			"     ├─ SubqueryAlias\n" +
			"     │   ├─ name: fs\n" +
			"     │   ├─ outerVisibility: false\n" +
			"     │   ├─ cacheable: true\n" +
			"     │   └─ Project\n" +
			"     │       ├─ columns: [RSA3Y.T4IBQ:3!null as T4IBQ, JMHIE.M6T2N:0 as M6T2N, JMHIE.BTXC5:1 as BTXC5, JMHIE.TUV25:2 as TUV25]\n" +
			"     │       └─ CrossJoin\n" +
			"     │           ├─ SubqueryAlias\n" +
			"     │           │   ├─ name: JMHIE\n" +
			"     │           │   ├─ outerVisibility: false\n" +
			"     │           │   ├─ cacheable: true\n" +
			"     │           │   └─ Distinct\n" +
			"     │           │       └─ Project\n" +
			"     │           │           ├─ columns: [JQHRG.M6T2N:0, JQHRG.BTXC5:1, JQHRG.TUV25:4]\n" +
			"     │           │           └─ SubqueryAlias\n" +
			"     │           │               ├─ name: JQHRG\n" +
			"     │           │               ├─ outerVisibility: false\n" +
			"     │           │               ├─ cacheable: true\n" +
			"     │           │               └─ Project\n" +
			"     │           │                   ├─ columns: [CASE  WHEN NOT\n" +
			"     │           │                   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"     │           │                   │   THEN Subquery\n" +
			"     │           │                   │   ├─ cacheable: false\n" +
			"     │           │                   │   └─ Project\n" +
			"     │           │                   │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"     │           │                   │       └─ Filter\n" +
			"     │           │                   │           ├─ Eq\n" +
			"     │           │                   │           │   ├─ ei.id:20!null\n" +
			"     │           │                   │           │   └─ MJR3D.QNI57:5\n" +
			"     │           │                   │           └─ SubqueryAlias\n" +
			"     │           │                   │               ├─ name: ei\n" +
			"     │           │                   │               ├─ outerVisibility: true\n" +
			"     │           │                   │               ├─ cacheable: true\n" +
			"     │           │                   │               └─ Project\n" +
			"     │           │                   │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"     │           │                   │                   └─ Window\n" +
			"     │           │                   │                       ├─ NOXN3.id:20!null\n" +
			"     │           │                   │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"     │           │                   │                       └─ Table\n" +
			"     │           │                   │                           ├─ name: NOXN3\n" +
			"     │           │                   │                           └─ columns: [id]\n" +
			"     │           │                   │   WHEN NOT\n" +
			"     │           │                   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"     │           │                   │   THEN Subquery\n" +
			"     │           │                   │   ├─ cacheable: false\n" +
			"     │           │                   │   └─ Project\n" +
			"     │           │                   │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"     │           │                   │       └─ Filter\n" +
			"     │           │                   │           ├─ Eq\n" +
			"     │           │                   │           │   ├─ ei.id:20!null\n" +
			"     │           │                   │           │   └─ MJR3D.TDEIU:6\n" +
			"     │           │                   │           └─ SubqueryAlias\n" +
			"     │           │                   │               ├─ name: ei\n" +
			"     │           │                   │               ├─ outerVisibility: true\n" +
			"     │           │                   │               ├─ cacheable: true\n" +
			"     │           │                   │               └─ Project\n" +
			"     │           │                   │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"     │           │                   │                   └─ Window\n" +
			"     │           │                   │                       ├─ NOXN3.id:20!null\n" +
			"     │           │                   │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"     │           │                   │                       └─ Table\n" +
			"     │           │                   │                           ├─ name: NOXN3\n" +
			"     │           │                   │                           └─ columns: [id]\n" +
			"     │           │                   │   END as M6T2N, aac.BTXC5:8 as BTXC5, aac.id:7!null as NTOFG, sn.id:10 as LWQ6O, MJR3D.TUV25:3 as TUV25]\n" +
			"     │           │                   └─ LeftOuterJoin\n" +
			"     │           │                       ├─ Or\n" +
			"     │           │                       │   ├─ Or\n" +
			"     │           │                       │   │   ├─ Or\n" +
			"     │           │                       │   │   │   ├─ AND\n" +
			"     │           │                       │   │   │   │   ├─ AND\n" +
			"     │           │                       │   │   │   │   │   ├─ NOT\n" +
			"     │           │                       │   │   │   │   │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"     │           │                       │   │   │   │   │   └─ Eq\n" +
			"     │           │                       │   │   │   │   │       ├─ sn.id:10!null\n" +
			"     │           │                       │   │   │   │   │       └─ MJR3D.QNI57:5\n" +
			"     │           │                       │   │   │   │   └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       │   │   │   └─ AND\n" +
			"     │           │                       │   │   │       ├─ AND\n" +
			"     │           │                       │   │   │       │   ├─ NOT\n" +
			"     │           │                       │   │   │       │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"     │           │                       │   │   │       │   └─ InSubquery\n" +
			"     │           │                       │   │   │       │       ├─ left: sn.id:10!null\n" +
			"     │           │                       │   │   │       │       └─ right: Subquery\n" +
			"     │           │                       │   │   │       │           ├─ cacheable: false\n" +
			"     │           │                       │   │   │       │           └─ Project\n" +
			"     │           │                       │   │   │       │               ├─ columns: [JTEHG.id:20!null]\n" +
			"     │           │                       │   │   │       │               └─ Filter\n" +
			"     │           │                       │   │   │       │                   ├─ Eq\n" +
			"     │           │                       │   │   │       │                   │   ├─ JTEHG.BRQP2:21!null\n" +
			"     │           │                       │   │   │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"     │           │                       │   │   │       │                   └─ TableAlias(JTEHG)\n" +
			"     │           │                       │   │   │       │                       └─ Table\n" +
			"     │           │                       │   │   │       │                           ├─ name: NOXN3\n" +
			"     │           │                       │   │   │       │                           └─ columns: [id brqp2]\n" +
			"     │           │                       │   │   │       └─ NOT\n" +
			"     │           │                       │   │   │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       │   │   └─ AND\n" +
			"     │           │                       │   │       ├─ AND\n" +
			"     │           │                       │   │       │   ├─ NOT\n" +
			"     │           │                       │   │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"     │           │                       │   │       │   └─ InSubquery\n" +
			"     │           │                       │   │       │       ├─ left: sn.id:10!null\n" +
			"     │           │                       │   │       │       └─ right: Subquery\n" +
			"     │           │                       │   │       │           ├─ cacheable: false\n" +
			"     │           │                       │   │       │           └─ Project\n" +
			"     │           │                       │   │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"     │           │                       │   │       │               └─ Filter\n" +
			"     │           │                       │   │       │                   ├─ Eq\n" +
			"     │           │                       │   │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"     │           │                       │   │       │                   │   └─ MJR3D.FJDP5:0!null\n" +
			"     │           │                       │   │       │                   └─ TableAlias(XMAFZ)\n" +
			"     │           │                       │   │       │                       └─ Table\n" +
			"     │           │                       │   │       │                           ├─ name: NOXN3\n" +
			"     │           │                       │   │       │                           └─ columns: [id brqp2]\n" +
			"     │           │                       │   │       └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       │   └─ AND\n" +
			"     │           │                       │       ├─ AND\n" +
			"     │           │                       │       │   ├─ NOT\n" +
			"     │           │                       │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"     │           │                       │       │   └─ InSubquery\n" +
			"     │           │                       │       │       ├─ left: sn.id:10!null\n" +
			"     │           │                       │       │       └─ right: Subquery\n" +
			"     │           │                       │       │           ├─ cacheable: false\n" +
			"     │           │                       │       │           └─ Project\n" +
			"     │           │                       │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"     │           │                       │       │               └─ Filter\n" +
			"     │           │                       │       │                   ├─ Eq\n" +
			"     │           │                       │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"     │           │                       │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"     │           │                       │       │                   └─ TableAlias(XMAFZ)\n" +
			"     │           │                       │       │                       └─ Table\n" +
			"     │           │                       │       │                           ├─ name: NOXN3\n" +
			"     │           │                       │       │                           └─ columns: [id brqp2]\n" +
			"     │           │                       │       └─ NOT\n" +
			"     │           │                       │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       ├─ LookupJoin\n" +
			"     │           │                       │   ├─ Eq\n" +
			"     │           │                       │   │   ├─ aac.id:7!null\n" +
			"     │           │                       │   │   └─ MJR3D.M22QN:2!null\n" +
			"     │           │                       │   ├─ SubqueryAlias\n" +
			"     │           │                       │   │   ├─ name: MJR3D\n" +
			"     │           │                       │   │   ├─ outerVisibility: false\n" +
			"     │           │                       │   │   ├─ cacheable: true\n" +
			"     │           │                       │   │   └─ Distinct\n" +
			"     │           │                       │   │       └─ Project\n" +
			"     │           │                       │   │           ├─ columns: [ism.FV24E:9!null as FJDP5, CPMFE.id:27 as BJUF2, ism.M22QN:11!null as M22QN, G3YXS.TUV25:5 as TUV25, G3YXS.ESFVY:1!null as ESFVY, YQIF4.id:44 as QNI57, YVHJZ.id:54 as TDEIU]\n" +
			"     │           │                       │   │           └─ Filter\n" +
			"     │           │                       │   │               ├─ Or\n" +
			"     │           │                       │   │               │   ├─ NOT\n" +
			"     │           │                       │   │               │   │   └─ YQIF4.id:44 IS NULL\n" +
			"     │           │                       │   │               │   └─ NOT\n" +
			"     │           │                       │   │               │       └─ YVHJZ.id:54 IS NULL\n" +
			"     │           │                       │   │               └─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   ├─ AND\n" +
			"     │           │                       │   │                   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   ├─ YVHJZ.BRQP2:55!null\n" +
			"     │           │                       │   │                   │   │   └─ ism.UJ6XY:10!null\n" +
			"     │           │                       │   │                   │   └─ Eq\n" +
			"     │           │                       │   │                   │       ├─ YVHJZ.FFTBJ:56!null\n" +
			"     │           │                       │   │                   │       └─ ism.FV24E:9!null\n" +
			"     │           │                       │   │                   ├─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   │   ├─ AND\n" +
			"     │           │                       │   │                   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   ├─ YQIF4.BRQP2:45!null\n" +
			"     │           │                       │   │                   │   │   │   └─ ism.FV24E:9!null\n" +
			"     │           │                       │   │                   │   │   └─ Eq\n" +
			"     │           │                       │   │                   │   │       ├─ YQIF4.FFTBJ:46!null\n" +
			"     │           │                       │   │                   │   │       └─ ism.UJ6XY:10!null\n" +
			"     │           │                       │   │                   │   ├─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   │   │   ├─ AND\n" +
			"     │           │                       │   │                   │   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ CPMFE.ZH72S:34\n" +
			"     │           │                       │   │                   │   │   │   │   └─ NHMXW.NOHHR:18\n" +
			"     │           │                       │   │                   │   │   │   └─ NOT\n" +
			"     │           │                       │   │                   │   │   │       └─ Eq\n" +
			"     │           │                       │   │                   │   │   │           ├─ CPMFE.id:27!null\n" +
			"     │           │                       │   │                   │   │   │           └─ ism.FV24E:9!null\n" +
			"     │           │                       │   │                   │   │   ├─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   │   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ NHMXW.id:17!null\n" +
			"     │           │                       │   │                   │   │   │   │   └─ ism.PRUV2:14\n" +
			"     │           │                       │   │                   │   │   │   ├─ LookupJoin\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   │   │   ├─ G3YXS.id:0!null\n" +
			"     │           │                       │   │                   │   │   │   │   │   └─ ism.NZ4MQ:12!null\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ Filter\n" +
			"     │           │                       │   │                   │   │   │   │   │   ├─ NOT\n" +
			"     │           │                       │   │                   │   │   │   │   │   │   └─ G3YXS.TUV25:5 IS NULL\n" +
			"     │           │                       │   │                   │   │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"     │           │                       │   │                   │   │   │   │   │       └─ Table\n" +
			"     │           │                       │   │                   │   │   │   │   │           ├─ name: YYBCX\n" +
			"     │           │                       │   │                   │   │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" +
			"     │           │                       │   │                   │   │   │   │   └─ TableAlias(ism)\n" +
			"     │           │                       │   │                   │   │   │   │       └─ IndexedTableAccess(HDDVB)\n" +
			"     │           │                       │   │                   │   │   │   │           ├─ index: [HDDVB.NZ4MQ]\n" +
			"     │           │                       │   │                   │   │   │   │           └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"     │           │                       │   │                   │   │   │   └─ TableAlias(NHMXW)\n" +
			"     │           │                       │   │                   │   │   │       └─ IndexedTableAccess(WGSDC)\n" +
			"     │           │                       │   │                   │   │   │           ├─ index: [WGSDC.id]\n" +
			"     │           │                       │   │                   │   │   │           └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			"     │           │                       │   │                   │   │   └─ TableAlias(CPMFE)\n" +
			"     │           │                       │   │                   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"     │           │                       │   │                   │   │           ├─ index: [E2I7U.ZH72S]\n" +
			"     │           │                       │   │                   │   │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     │           │                       │   │                   │   └─ TableAlias(YQIF4)\n" +
			"     │           │                       │   │                   │       └─ IndexedTableAccess(NOXN3)\n" +
			"     │           │                       │   │                   │           ├─ index: [NOXN3.BRQP2]\n" +
			"     │           │                       │   │                   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │           │                       │   │                   └─ TableAlias(YVHJZ)\n" +
			"     │           │                       │   │                       └─ IndexedTableAccess(NOXN3)\n" +
			"     │           │                       │   │                           ├─ index: [NOXN3.BRQP2]\n" +
			"     │           │                       │   │                           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │           │                       │   └─ TableAlias(aac)\n" +
			"     │           │                       │       └─ IndexedTableAccess(TPXBU)\n" +
			"     │           │                       │           ├─ index: [TPXBU.id]\n" +
			"     │           │                       │           └─ columns: [id btxc5 fhcyt]\n" +
			"     │           │                       └─ TableAlias(sn)\n" +
			"     │           │                           └─ Table\n" +
			"     │           │                               ├─ name: NOXN3\n" +
			"     │           │                               └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │           └─ SubqueryAlias\n" +
			"     │               ├─ name: RSA3Y\n" +
			"     │               ├─ outerVisibility: false\n" +
			"     │               ├─ cacheable: true\n" +
			"     │               └─ Distinct\n" +
			"     │                   └─ Project\n" +
			"     │                       ├─ columns: [HTKBS.T4IBQ:0!null]\n" +
			"     │                       └─ SubqueryAlias\n" +
			"     │                           ├─ name: HTKBS\n" +
			"     │                           ├─ outerVisibility: false\n" +
			"     │                           ├─ cacheable: true\n" +
			"     │                           └─ Project\n" +
			"     │                               ├─ columns: [cla.FTQLQ:1!null as T4IBQ, sn.id:7!null as BDNYB, mf.M22QN:6!null as M22QN]\n" +
			"     │                               └─ HashJoin\n" +
			"     │                                   ├─ Eq\n" +
			"     │                                   │   ├─ cla.id:0!null\n" +
			"     │                                   │   └─ bs.IXUXU:3\n" +
			"     │                                   ├─ Filter\n" +
			"     │                                   │   ├─ HashIn\n" +
			"     │                                   │   │   ├─ cla.FTQLQ:1!null\n" +
			"     │                                   │   │   └─ TUPLE(SQ1 (longtext))\n" +
			"     │                                   │   └─ TableAlias(cla)\n" +
			"     │                                   │       └─ IndexedTableAccess(YK2GW)\n" +
			"     │                                   │           ├─ index: [YK2GW.FTQLQ]\n" +
			"     │                                   │           ├─ static: [{[SQ1, SQ1]}]\n" +
			"     │                                   │           └─ columns: [id ftqlq]\n" +
			"     │                                   └─ HashLookup\n" +
			"     │                                       ├─ source: TUPLE(cla.id:0!null)\n" +
			"     │                                       ├─ target: TUPLE(bs.IXUXU:1)\n" +
			"     │                                       └─ CachedResults\n" +
			"     │                                           └─ LookupJoin\n" +
			"     │                                               ├─ Eq\n" +
			"     │                                               │   ├─ sn.BRQP2:8!null\n" +
			"     │                                               │   └─ mf.LUEVY:5!null\n" +
			"     │                                               ├─ LookupJoin\n" +
			"     │                                               │   ├─ Eq\n" +
			"     │                                               │   │   ├─ bs.id:2!null\n" +
			"     │                                               │   │   └─ mf.GXLUB:4!null\n" +
			"     │                                               │   ├─ TableAlias(bs)\n" +
			"     │                                               │   │   └─ Table\n" +
			"     │                                               │   │       ├─ name: THNTS\n" +
			"     │                                               │   │       └─ columns: [id ixuxu]\n" +
			"     │                                               │   └─ TableAlias(mf)\n" +
			"     │                                               │       └─ IndexedTableAccess(HGMQ6)\n" +
			"     │                                               │           ├─ index: [HGMQ6.GXLUB]\n" +
			"     │                                               │           └─ columns: [gxlub luevy m22qn]\n" +
			"     │                                               └─ TableAlias(sn)\n" +
			"     │                                                   └─ IndexedTableAccess(NOXN3)\n" +
			"     │                                                       ├─ index: [NOXN3.BRQP2]\n" +
			"     │                                                       └─ columns: [id brqp2]\n" +
			"     └─ SubqueryAlias\n" +
			"         ├─ name: applySubq0\n" +
			"         ├─ outerVisibility: false\n" +
			"         ├─ cacheable: true\n" +
			"         └─ SubqueryAlias\n" +
			"             ├─ name: ZMSPR\n" +
			"             ├─ outerVisibility: true\n" +
			"             ├─ cacheable: true\n" +
			"             └─ Distinct\n" +
			"                 └─ Project\n" +
			"                     ├─ columns: [cld.T4IBQ:0!null as T4IBQ, P4PJZ.M6T2N:3 as M6T2N, P4PJZ.BTXC5:4 as BTXC5, P4PJZ.TUV25:7 as TUV25]\n" +
			"                     └─ Filter\n" +
			"                         ├─ NOT\n" +
			"                         │   └─ P4PJZ.M6T2N:3 IS NULL\n" +
			"                         └─ LeftOuterHashJoin\n" +
			"                             ├─ AND\n" +
			"                             │   ├─ Eq\n" +
			"                             │   │   ├─ P4PJZ.LWQ6O:6\n" +
			"                             │   │   └─ cld.BDNYB:1!null\n" +
			"                             │   └─ Eq\n" +
			"                             │       ├─ P4PJZ.NTOFG:5!null\n" +
			"                             │       └─ cld.M22QN:2!null\n" +
			"                             ├─ SubqueryAlias\n" +
			"                             │   ├─ name: cld\n" +
			"                             │   ├─ outerVisibility: false\n" +
			"                             │   ├─ cacheable: true\n" +
			"                             │   └─ Project\n" +
			"                             │       ├─ columns: [cla.FTQLQ:1!null as T4IBQ, sn.id:7!null as BDNYB, mf.M22QN:6!null as M22QN]\n" +
			"                             │       └─ HashJoin\n" +
			"                             │           ├─ Eq\n" +
			"                             │           │   ├─ cla.id:0!null\n" +
			"                             │           │   └─ bs.IXUXU:3\n" +
			"                             │           ├─ Filter\n" +
			"                             │           │   ├─ HashIn\n" +
			"                             │           │   │   ├─ cla.FTQLQ:1!null\n" +
			"                             │           │   │   └─ TUPLE(SQ1 (longtext))\n" +
			"                             │           │   └─ TableAlias(cla)\n" +
			"                             │           │       └─ IndexedTableAccess(YK2GW)\n" +
			"                             │           │           ├─ index: [YK2GW.FTQLQ]\n" +
			"                             │           │           ├─ static: [{[SQ1, SQ1]}]\n" +
			"                             │           │           └─ columns: [id ftqlq]\n" +
			"                             │           └─ HashLookup\n" +
			"                             │               ├─ source: TUPLE(cla.id:0!null)\n" +
			"                             │               ├─ target: TUPLE(bs.IXUXU:1)\n" +
			"                             │               └─ CachedResults\n" +
			"                             │                   └─ LookupJoin\n" +
			"                             │                       ├─ Eq\n" +
			"                             │                       │   ├─ sn.BRQP2:8!null\n" +
			"                             │                       │   └─ mf.LUEVY:5!null\n" +
			"                             │                       ├─ LookupJoin\n" +
			"                             │                       │   ├─ Eq\n" +
			"                             │                       │   │   ├─ bs.id:2!null\n" +
			"                             │                       │   │   └─ mf.GXLUB:4!null\n" +
			"                             │                       │   ├─ TableAlias(bs)\n" +
			"                             │                       │   │   └─ Table\n" +
			"                             │                       │   │       ├─ name: THNTS\n" +
			"                             │                       │   │       └─ columns: [id ixuxu]\n" +
			"                             │                       │   └─ TableAlias(mf)\n" +
			"                             │                       │       └─ IndexedTableAccess(HGMQ6)\n" +
			"                             │                       │           ├─ index: [HGMQ6.GXLUB]\n" +
			"                             │                       │           └─ columns: [gxlub luevy m22qn]\n" +
			"                             │                       └─ TableAlias(sn)\n" +
			"                             │                           └─ IndexedTableAccess(NOXN3)\n" +
			"                             │                               ├─ index: [NOXN3.BRQP2]\n" +
			"                             │                               └─ columns: [id brqp2]\n" +
			"                             └─ HashLookup\n" +
			"                                 ├─ source: TUPLE(cld.BDNYB:1!null, cld.M22QN:2!null)\n" +
			"                                 ├─ target: TUPLE(P4PJZ.LWQ6O:3, P4PJZ.NTOFG:2!null)\n" +
			"                                 └─ CachedResults\n" +
			"                                     └─ SubqueryAlias\n" +
			"                                         ├─ name: P4PJZ\n" +
			"                                         ├─ outerVisibility: false\n" +
			"                                         ├─ cacheable: true\n" +
			"                                         └─ Project\n" +
			"                                             ├─ columns: [CASE  WHEN NOT\n" +
			"                                             │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"                                             │   THEN Subquery\n" +
			"                                             │   ├─ cacheable: false\n" +
			"                                             │   └─ Project\n" +
			"                                             │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"                                             │       └─ Filter\n" +
			"                                             │           ├─ Eq\n" +
			"                                             │           │   ├─ ei.id:20!null\n" +
			"                                             │           │   └─ MJR3D.QNI57:5\n" +
			"                                             │           └─ SubqueryAlias\n" +
			"                                             │               ├─ name: ei\n" +
			"                                             │               ├─ outerVisibility: true\n" +
			"                                             │               ├─ cacheable: true\n" +
			"                                             │               └─ Project\n" +
			"                                             │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"                                             │                   └─ Window\n" +
			"                                             │                       ├─ NOXN3.id:20!null\n" +
			"                                             │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"                                             │                       └─ Table\n" +
			"                                             │                           ├─ name: NOXN3\n" +
			"                                             │                           └─ columns: [id]\n" +
			"                                             │   WHEN NOT\n" +
			"                                             │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"                                             │   THEN Subquery\n" +
			"                                             │   ├─ cacheable: false\n" +
			"                                             │   └─ Project\n" +
			"                                             │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"                                             │       └─ Filter\n" +
			"                                             │           ├─ Eq\n" +
			"                                             │           │   ├─ ei.id:20!null\n" +
			"                                             │           │   └─ MJR3D.TDEIU:6\n" +
			"                                             │           └─ SubqueryAlias\n" +
			"                                             │               ├─ name: ei\n" +
			"                                             │               ├─ outerVisibility: true\n" +
			"                                             │               ├─ cacheable: true\n" +
			"                                             │               └─ Project\n" +
			"                                             │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"                                             │                   └─ Window\n" +
			"                                             │                       ├─ NOXN3.id:20!null\n" +
			"                                             │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"                                             │                       └─ Table\n" +
			"                                             │                           ├─ name: NOXN3\n" +
			"                                             │                           └─ columns: [id]\n" +
			"                                             │   END as M6T2N, aac.BTXC5:8 as BTXC5, aac.id:7!null as NTOFG, sn.id:10 as LWQ6O, MJR3D.TUV25:3 as TUV25]\n" +
			"                                             └─ LeftOuterJoin\n" +
			"                                                 ├─ Or\n" +
			"                                                 │   ├─ Or\n" +
			"                                                 │   │   ├─ Or\n" +
			"                                                 │   │   │   ├─ AND\n" +
			"                                                 │   │   │   │   ├─ AND\n" +
			"                                                 │   │   │   │   │   ├─ NOT\n" +
			"                                                 │   │   │   │   │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"                                                 │   │   │   │   │   └─ Eq\n" +
			"                                                 │   │   │   │   │       ├─ sn.id:10!null\n" +
			"                                                 │   │   │   │   │       └─ MJR3D.QNI57:5\n" +
			"                                                 │   │   │   │   └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 │   │   │   └─ AND\n" +
			"                                                 │   │   │       ├─ AND\n" +
			"                                                 │   │   │       │   ├─ NOT\n" +
			"                                                 │   │   │       │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"                                                 │   │   │       │   └─ InSubquery\n" +
			"                                                 │   │   │       │       ├─ left: sn.id:10!null\n" +
			"                                                 │   │   │       │       └─ right: Subquery\n" +
			"                                                 │   │   │       │           ├─ cacheable: false\n" +
			"                                                 │   │   │       │           └─ Project\n" +
			"                                                 │   │   │       │               ├─ columns: [JTEHG.id:20!null]\n" +
			"                                                 │   │   │       │               └─ Filter\n" +
			"                                                 │   │   │       │                   ├─ Eq\n" +
			"                                                 │   │   │       │                   │   ├─ JTEHG.BRQP2:21!null\n" +
			"                                                 │   │   │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"                                                 │   │   │       │                   └─ TableAlias(JTEHG)\n" +
			"                                                 │   │   │       │                       └─ Table\n" +
			"                                                 │   │   │       │                           ├─ name: NOXN3\n" +
			"                                                 │   │   │       │                           └─ columns: [id brqp2]\n" +
			"                                                 │   │   │       └─ NOT\n" +
			"                                                 │   │   │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 │   │   └─ AND\n" +
			"                                                 │   │       ├─ AND\n" +
			"                                                 │   │       │   ├─ NOT\n" +
			"                                                 │   │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"                                                 │   │       │   └─ InSubquery\n" +
			"                                                 │   │       │       ├─ left: sn.id:10!null\n" +
			"                                                 │   │       │       └─ right: Subquery\n" +
			"                                                 │   │       │           ├─ cacheable: false\n" +
			"                                                 │   │       │           └─ Project\n" +
			"                                                 │   │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"                                                 │   │       │               └─ Filter\n" +
			"                                                 │   │       │                   ├─ Eq\n" +
			"                                                 │   │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"                                                 │   │       │                   │   └─ MJR3D.FJDP5:0!null\n" +
			"                                                 │   │       │                   └─ TableAlias(XMAFZ)\n" +
			"                                                 │   │       │                       └─ Table\n" +
			"                                                 │   │       │                           ├─ name: NOXN3\n" +
			"                                                 │   │       │                           └─ columns: [id brqp2]\n" +
			"                                                 │   │       └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 │   └─ AND\n" +
			"                                                 │       ├─ AND\n" +
			"                                                 │       │   ├─ NOT\n" +
			"                                                 │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"                                                 │       │   └─ InSubquery\n" +
			"                                                 │       │       ├─ left: sn.id:10!null\n" +
			"                                                 │       │       └─ right: Subquery\n" +
			"                                                 │       │           ├─ cacheable: false\n" +
			"                                                 │       │           └─ Project\n" +
			"                                                 │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"                                                 │       │               └─ Filter\n" +
			"                                                 │       │                   ├─ Eq\n" +
			"                                                 │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"                                                 │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"                                                 │       │                   └─ TableAlias(XMAFZ)\n" +
			"                                                 │       │                       └─ Table\n" +
			"                                                 │       │                           ├─ name: NOXN3\n" +
			"                                                 │       │                           └─ columns: [id brqp2]\n" +
			"                                                 │       └─ NOT\n" +
			"                                                 │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 ├─ LookupJoin\n" +
			"                                                 │   ├─ Eq\n" +
			"                                                 │   │   ├─ aac.id:7!null\n" +
			"                                                 │   │   └─ MJR3D.M22QN:2!null\n" +
			"                                                 │   ├─ SubqueryAlias\n" +
			"                                                 │   │   ├─ name: MJR3D\n" +
			"                                                 │   │   ├─ outerVisibility: false\n" +
			"                                                 │   │   ├─ cacheable: true\n" +
			"                                                 │   │   └─ Distinct\n" +
			"                                                 │   │       └─ Project\n" +
			"                                                 │   │           ├─ columns: [ism.FV24E:9!null as FJDP5, CPMFE.id:27 as BJUF2, ism.M22QN:11!null as M22QN, G3YXS.TUV25:5 as TUV25, G3YXS.ESFVY:1!null as ESFVY, YQIF4.id:44 as QNI57, YVHJZ.id:54 as TDEIU]\n" +
			"                                                 │   │           └─ Filter\n" +
			"                                                 │   │               ├─ Or\n" +
			"                                                 │   │               │   ├─ NOT\n" +
			"                                                 │   │               │   │   └─ YQIF4.id:44 IS NULL\n" +
			"                                                 │   │               │   └─ NOT\n" +
			"                                                 │   │               │       └─ YVHJZ.id:54 IS NULL\n" +
			"                                                 │   │               └─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   ├─ AND\n" +
			"                                                 │   │                   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   ├─ YVHJZ.BRQP2:55!null\n" +
			"                                                 │   │                   │   │   └─ ism.UJ6XY:10!null\n" +
			"                                                 │   │                   │   └─ Eq\n" +
			"                                                 │   │                   │       ├─ YVHJZ.FFTBJ:56!null\n" +
			"                                                 │   │                   │       └─ ism.FV24E:9!null\n" +
			"                                                 │   │                   ├─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   │   ├─ AND\n" +
			"                                                 │   │                   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   ├─ YQIF4.BRQP2:45!null\n" +
			"                                                 │   │                   │   │   │   └─ ism.FV24E:9!null\n" +
			"                                                 │   │                   │   │   └─ Eq\n" +
			"                                                 │   │                   │   │       ├─ YQIF4.FFTBJ:46!null\n" +
			"                                                 │   │                   │   │       └─ ism.UJ6XY:10!null\n" +
			"                                                 │   │                   │   ├─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   │   │   ├─ AND\n" +
			"                                                 │   │                   │   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   │   ├─ CPMFE.ZH72S:34\n" +
			"                                                 │   │                   │   │   │   │   └─ NHMXW.NOHHR:18\n" +
			"                                                 │   │                   │   │   │   └─ NOT\n" +
			"                                                 │   │                   │   │   │       └─ Eq\n" +
			"                                                 │   │                   │   │   │           ├─ CPMFE.id:27!null\n" +
			"                                                 │   │                   │   │   │           └─ ism.FV24E:9!null\n" +
			"                                                 │   │                   │   │   ├─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   │   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   │   ├─ NHMXW.id:17!null\n" +
			"                                                 │   │                   │   │   │   │   └─ ism.PRUV2:14\n" +
			"                                                 │   │                   │   │   │   ├─ LookupJoin\n" +
			"                                                 │   │                   │   │   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   │   │   ├─ G3YXS.id:0!null\n" +
			"                                                 │   │                   │   │   │   │   │   └─ ism.NZ4MQ:12!null\n" +
			"                                                 │   │                   │   │   │   │   ├─ Filter\n" +
			"                                                 │   │                   │   │   │   │   │   ├─ NOT\n" +
			"                                                 │   │                   │   │   │   │   │   │   └─ G3YXS.TUV25:5 IS NULL\n" +
			"                                                 │   │                   │   │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"                                                 │   │                   │   │   │   │   │       └─ Table\n" +
			"                                                 │   │                   │   │   │   │   │           ├─ name: YYBCX\n" +
			"                                                 │   │                   │   │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" +
			"                                                 │   │                   │   │   │   │   └─ TableAlias(ism)\n" +
			"                                                 │   │                   │   │   │   │       └─ IndexedTableAccess(HDDVB)\n" +
			"                                                 │   │                   │   │   │   │           ├─ index: [HDDVB.NZ4MQ]\n" +
			"                                                 │   │                   │   │   │   │           └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"                                                 │   │                   │   │   │   └─ TableAlias(NHMXW)\n" +
			"                                                 │   │                   │   │   │       └─ IndexedTableAccess(WGSDC)\n" +
			"                                                 │   │                   │   │   │           ├─ index: [WGSDC.id]\n" +
			"                                                 │   │                   │   │   │           └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			"                                                 │   │                   │   │   └─ TableAlias(CPMFE)\n" +
			"                                                 │   │                   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"                                                 │   │                   │   │           ├─ index: [E2I7U.ZH72S]\n" +
			"                                                 │   │                   │   │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"                                                 │   │                   │   └─ TableAlias(YQIF4)\n" +
			"                                                 │   │                   │       └─ IndexedTableAccess(NOXN3)\n" +
			"                                                 │   │                   │           ├─ index: [NOXN3.BRQP2]\n" +
			"                                                 │   │                   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"                                                 │   │                   └─ TableAlias(YVHJZ)\n" +
			"                                                 │   │                       └─ IndexedTableAccess(NOXN3)\n" +
			"                                                 │   │                           ├─ index: [NOXN3.BRQP2]\n" +
			"                                                 │   │                           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"                                                 │   └─ TableAlias(aac)\n" +
			"                                                 │       └─ IndexedTableAccess(TPXBU)\n" +
			"                                                 │           ├─ index: [TPXBU.id]\n" +
			"                                                 │           └─ columns: [id btxc5 fhcyt]\n" +
			"                                                 └─ TableAlias(sn)\n" +
			"                                                     └─ Table\n" +
			"                                                         ├─ name: NOXN3\n" +
			"                                                         └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
WITH

    FZFVD AS (
        SELECT id, ROW_NUMBER() OVER (ORDER BY id ASC) - 1 AS M6T2N FROM NOXN3
    ),
    OXDGK AS (
        SELECT DISTINCT
        ism.FV24E AS FJDP5,
        CPMFE.id AS BJUF2,
        ism.M22QN AS M22QN,
        G3YXS.TUV25 AS TUV25,
        G3YXS.ESFVY AS ESFVY,
        YQIF4.id AS QNI57,
        YVHJZ.id AS TDEIU
        FROM
        HDDVB ism
        INNER JOIN YYBCX G3YXS ON G3YXS.id = ism.NZ4MQ
        LEFT JOIN
        WGSDC NHMXW
        ON
        NHMXW.id = ism.PRUV2
        LEFT JOIN
        E2I7U CPMFE
        ON
        CPMFE.ZH72S = NHMXW.NOHHR AND CPMFE.id <> ism.FV24E
        LEFT JOIN
        NOXN3 YQIF4
        ON
            YQIF4.BRQP2 = ism.FV24E
        AND
            YQIF4.FFTBJ = ism.UJ6XY
        LEFT JOIN
        NOXN3 YVHJZ
        ON
            YVHJZ.BRQP2 = ism.UJ6XY
        AND
            YVHJZ.FFTBJ = ism.FV24E
        WHERE
            G3YXS.TUV25 IS NOT NULL 
        AND
            (YQIF4.id IS NOT NULL
        OR
            YVHJZ.id IS NOT NULL)
    ),

    HTKBS AS (
        SELECT
            cla.FTQLQ AS T4IBQ,
            sn.id AS BDNYB,
            mf.M22QN AS M22QN
        FROM HGMQ6 mf
        INNER JOIN THNTS bs ON bs.id = mf.GXLUB
        INNER JOIN YK2GW cla ON cla.id = bs.IXUXU
        INNER JOIN NOXN3 sn ON sn.BRQP2 = mf.LUEVY
        WHERE cla.FTQLQ IN ('SQ1')
    ),
    JQHRG AS (
        SELECT
            CASE
                    WHEN MJR3D.QNI57 IS NOT NULL
                        THEN (SELECT ei.M6T2N FROM FZFVD ei WHERE ei.id = MJR3D.QNI57)
                    WHEN MJR3D.TDEIU IS NOT NULL
                        THEN (SELECT ei.M6T2N FROM FZFVD ei WHERE ei.id = MJR3D.TDEIU)
            END AS M6T2N,

            aac.BTXC5 AS BTXC5,
            aac.id AS NTOFG,
            sn.id AS LWQ6O,
            MJR3D.TUV25 AS TUV25
            FROM 
                OXDGK MJR3D
            INNER JOIN TPXBU aac ON aac.id = MJR3D.M22QN
            LEFT JOIN
            NOXN3 sn
            ON
            (
                QNI57 IS NOT NULL
                AND
                sn.id = MJR3D.QNI57
                AND
                MJR3D.BJUF2 IS NULL
            )
            OR 
            (
                QNI57 IS NOT NULL
                AND
                sn.id IN (SELECT JTEHG.id FROM NOXN3 JTEHG WHERE BRQP2 = MJR3D.BJUF2)
                AND
                MJR3D.BJUF2 IS NOT NULL
            )
            OR 
            (
                TDEIU IS NOT NULL
                AND
                sn.id IN (SELECT XMAFZ.id FROM NOXN3 XMAFZ WHERE BRQP2 = MJR3D.FJDP5)
                AND
                MJR3D.BJUF2 IS NULL
            )
            OR
            (
                TDEIU IS NOT NULL
                AND
                sn.id IN (SELECT XMAFZ.id FROM NOXN3 XMAFZ WHERE BRQP2 = MJR3D.BJUF2)
                AND
                MJR3D.BJUF2 IS NOT NULL
            )
    ),

    F6BRC AS (
        SELECT
            RSA3Y.T4IBQ AS T4IBQ,
            JMHIE.M6T2N AS M6T2N,
            JMHIE.BTXC5 AS BTXC5,
            JMHIE.TUV25 AS TUV25
        FROM
            (SELECT DISTINCT M6T2N, BTXC5, TUV25 FROM JQHRG) JMHIE
        CROSS JOIN
            (SELECT DISTINCT T4IBQ FROM HTKBS) RSA3Y
    ),

    ZMSPR AS (
        SELECT DISTINCT
            cld.T4IBQ AS T4IBQ,
            P4PJZ.M6T2N AS M6T2N,
            P4PJZ.BTXC5 AS BTXC5,
            P4PJZ.TUV25 AS TUV25
        FROM
            HTKBS cld
        LEFT JOIN
            JQHRG P4PJZ
        ON P4PJZ.LWQ6O = cld.BDNYB AND P4PJZ.NTOFG = cld.M22QN
        WHERE
                P4PJZ.M6T2N IS NOT NULL
    )
SELECT
    fs.T4IBQ AS T4IBQ,
    fs.M6T2N AS M6T2N,
    fs.TUV25 AS TUV25,
    fs.BTXC5 AS YEBDJ
FROM
    F6BRC fs
WHERE
    (fs.T4IBQ, fs.M6T2N, fs.BTXC5, fs.TUV25)
    NOT IN (
        SELECT
            ZMSPR.T4IBQ,
            ZMSPR.M6T2N,
            ZMSPR.BTXC5,
            ZMSPR.TUV25
        FROM
            ZMSPR
    )`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [fs.T4IBQ:0!null as T4IBQ, fs.M6T2N:1 as M6T2N, fs.TUV25:3 as TUV25, fs.BTXC5:2 as YEBDJ]\n" +
			" └─ AntiJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ TUPLE(fs.T4IBQ:0!null, fs.M6T2N:1, fs.BTXC5:2, fs.TUV25:3)\n" +
			"     │   └─ TUPLE(applySubq0.T4IBQ:4!null, applySubq0.M6T2N:5, applySubq0.BTXC5:6, applySubq0.TUV25:7)\n" +
			"     ├─ SubqueryAlias\n" +
			"     │   ├─ name: fs\n" +
			"     │   ├─ outerVisibility: false\n" +
			"     │   ├─ cacheable: true\n" +
			"     │   └─ Project\n" +
			"     │       ├─ columns: [RSA3Y.T4IBQ:3!null as T4IBQ, JMHIE.M6T2N:0 as M6T2N, JMHIE.BTXC5:1 as BTXC5, JMHIE.TUV25:2 as TUV25]\n" +
			"     │       └─ CrossJoin\n" +
			"     │           ├─ SubqueryAlias\n" +
			"     │           │   ├─ name: JMHIE\n" +
			"     │           │   ├─ outerVisibility: false\n" +
			"     │           │   ├─ cacheable: true\n" +
			"     │           │   └─ Distinct\n" +
			"     │           │       └─ Project\n" +
			"     │           │           ├─ columns: [JQHRG.M6T2N:0, JQHRG.BTXC5:1, JQHRG.TUV25:4]\n" +
			"     │           │           └─ SubqueryAlias\n" +
			"     │           │               ├─ name: JQHRG\n" +
			"     │           │               ├─ outerVisibility: false\n" +
			"     │           │               ├─ cacheable: true\n" +
			"     │           │               └─ Project\n" +
			"     │           │                   ├─ columns: [CASE  WHEN NOT\n" +
			"     │           │                   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"     │           │                   │   THEN Subquery\n" +
			"     │           │                   │   ├─ cacheable: false\n" +
			"     │           │                   │   └─ Project\n" +
			"     │           │                   │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"     │           │                   │       └─ Filter\n" +
			"     │           │                   │           ├─ Eq\n" +
			"     │           │                   │           │   ├─ ei.id:20!null\n" +
			"     │           │                   │           │   └─ MJR3D.QNI57:5\n" +
			"     │           │                   │           └─ SubqueryAlias\n" +
			"     │           │                   │               ├─ name: ei\n" +
			"     │           │                   │               ├─ outerVisibility: true\n" +
			"     │           │                   │               ├─ cacheable: true\n" +
			"     │           │                   │               └─ Project\n" +
			"     │           │                   │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"     │           │                   │                   └─ Window\n" +
			"     │           │                   │                       ├─ NOXN3.id:20!null\n" +
			"     │           │                   │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"     │           │                   │                       └─ Table\n" +
			"     │           │                   │                           ├─ name: NOXN3\n" +
			"     │           │                   │                           └─ columns: [id]\n" +
			"     │           │                   │   WHEN NOT\n" +
			"     │           │                   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"     │           │                   │   THEN Subquery\n" +
			"     │           │                   │   ├─ cacheable: false\n" +
			"     │           │                   │   └─ Project\n" +
			"     │           │                   │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"     │           │                   │       └─ Filter\n" +
			"     │           │                   │           ├─ Eq\n" +
			"     │           │                   │           │   ├─ ei.id:20!null\n" +
			"     │           │                   │           │   └─ MJR3D.TDEIU:6\n" +
			"     │           │                   │           └─ SubqueryAlias\n" +
			"     │           │                   │               ├─ name: ei\n" +
			"     │           │                   │               ├─ outerVisibility: true\n" +
			"     │           │                   │               ├─ cacheable: true\n" +
			"     │           │                   │               └─ Project\n" +
			"     │           │                   │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"     │           │                   │                   └─ Window\n" +
			"     │           │                   │                       ├─ NOXN3.id:20!null\n" +
			"     │           │                   │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"     │           │                   │                       └─ Table\n" +
			"     │           │                   │                           ├─ name: NOXN3\n" +
			"     │           │                   │                           └─ columns: [id]\n" +
			"     │           │                   │   END as M6T2N, aac.BTXC5:8 as BTXC5, aac.id:7!null as NTOFG, sn.id:10 as LWQ6O, MJR3D.TUV25:3 as TUV25]\n" +
			"     │           │                   └─ LeftOuterJoin\n" +
			"     │           │                       ├─ Or\n" +
			"     │           │                       │   ├─ Or\n" +
			"     │           │                       │   │   ├─ Or\n" +
			"     │           │                       │   │   │   ├─ AND\n" +
			"     │           │                       │   │   │   │   ├─ AND\n" +
			"     │           │                       │   │   │   │   │   ├─ NOT\n" +
			"     │           │                       │   │   │   │   │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"     │           │                       │   │   │   │   │   └─ Eq\n" +
			"     │           │                       │   │   │   │   │       ├─ sn.id:10!null\n" +
			"     │           │                       │   │   │   │   │       └─ MJR3D.QNI57:5\n" +
			"     │           │                       │   │   │   │   └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       │   │   │   └─ AND\n" +
			"     │           │                       │   │   │       ├─ AND\n" +
			"     │           │                       │   │   │       │   ├─ NOT\n" +
			"     │           │                       │   │   │       │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"     │           │                       │   │   │       │   └─ InSubquery\n" +
			"     │           │                       │   │   │       │       ├─ left: sn.id:10!null\n" +
			"     │           │                       │   │   │       │       └─ right: Subquery\n" +
			"     │           │                       │   │   │       │           ├─ cacheable: false\n" +
			"     │           │                       │   │   │       │           └─ Project\n" +
			"     │           │                       │   │   │       │               ├─ columns: [JTEHG.id:20!null]\n" +
			"     │           │                       │   │   │       │               └─ Filter\n" +
			"     │           │                       │   │   │       │                   ├─ Eq\n" +
			"     │           │                       │   │   │       │                   │   ├─ JTEHG.BRQP2:21!null\n" +
			"     │           │                       │   │   │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"     │           │                       │   │   │       │                   └─ TableAlias(JTEHG)\n" +
			"     │           │                       │   │   │       │                       └─ Table\n" +
			"     │           │                       │   │   │       │                           ├─ name: NOXN3\n" +
			"     │           │                       │   │   │       │                           └─ columns: [id brqp2]\n" +
			"     │           │                       │   │   │       └─ NOT\n" +
			"     │           │                       │   │   │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       │   │   └─ AND\n" +
			"     │           │                       │   │       ├─ AND\n" +
			"     │           │                       │   │       │   ├─ NOT\n" +
			"     │           │                       │   │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"     │           │                       │   │       │   └─ InSubquery\n" +
			"     │           │                       │   │       │       ├─ left: sn.id:10!null\n" +
			"     │           │                       │   │       │       └─ right: Subquery\n" +
			"     │           │                       │   │       │           ├─ cacheable: false\n" +
			"     │           │                       │   │       │           └─ Project\n" +
			"     │           │                       │   │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"     │           │                       │   │       │               └─ Filter\n" +
			"     │           │                       │   │       │                   ├─ Eq\n" +
			"     │           │                       │   │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"     │           │                       │   │       │                   │   └─ MJR3D.FJDP5:0!null\n" +
			"     │           │                       │   │       │                   └─ TableAlias(XMAFZ)\n" +
			"     │           │                       │   │       │                       └─ Table\n" +
			"     │           │                       │   │       │                           ├─ name: NOXN3\n" +
			"     │           │                       │   │       │                           └─ columns: [id brqp2]\n" +
			"     │           │                       │   │       └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       │   └─ AND\n" +
			"     │           │                       │       ├─ AND\n" +
			"     │           │                       │       │   ├─ NOT\n" +
			"     │           │                       │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"     │           │                       │       │   └─ InSubquery\n" +
			"     │           │                       │       │       ├─ left: sn.id:10!null\n" +
			"     │           │                       │       │       └─ right: Subquery\n" +
			"     │           │                       │       │           ├─ cacheable: false\n" +
			"     │           │                       │       │           └─ Project\n" +
			"     │           │                       │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"     │           │                       │       │               └─ Filter\n" +
			"     │           │                       │       │                   ├─ Eq\n" +
			"     │           │                       │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"     │           │                       │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"     │           │                       │       │                   └─ TableAlias(XMAFZ)\n" +
			"     │           │                       │       │                       └─ Table\n" +
			"     │           │                       │       │                           ├─ name: NOXN3\n" +
			"     │           │                       │       │                           └─ columns: [id brqp2]\n" +
			"     │           │                       │       └─ NOT\n" +
			"     │           │                       │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"     │           │                       ├─ LookupJoin\n" +
			"     │           │                       │   ├─ Eq\n" +
			"     │           │                       │   │   ├─ aac.id:7!null\n" +
			"     │           │                       │   │   └─ MJR3D.M22QN:2!null\n" +
			"     │           │                       │   ├─ SubqueryAlias\n" +
			"     │           │                       │   │   ├─ name: MJR3D\n" +
			"     │           │                       │   │   ├─ outerVisibility: false\n" +
			"     │           │                       │   │   ├─ cacheable: true\n" +
			"     │           │                       │   │   └─ Distinct\n" +
			"     │           │                       │   │       └─ Project\n" +
			"     │           │                       │   │           ├─ columns: [ism.FV24E:9!null as FJDP5, CPMFE.id:27 as BJUF2, ism.M22QN:11!null as M22QN, G3YXS.TUV25:5 as TUV25, G3YXS.ESFVY:1!null as ESFVY, YQIF4.id:44 as QNI57, YVHJZ.id:54 as TDEIU]\n" +
			"     │           │                       │   │           └─ Filter\n" +
			"     │           │                       │   │               ├─ Or\n" +
			"     │           │                       │   │               │   ├─ NOT\n" +
			"     │           │                       │   │               │   │   └─ YQIF4.id:44 IS NULL\n" +
			"     │           │                       │   │               │   └─ NOT\n" +
			"     │           │                       │   │               │       └─ YVHJZ.id:54 IS NULL\n" +
			"     │           │                       │   │               └─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   ├─ AND\n" +
			"     │           │                       │   │                   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   ├─ YVHJZ.BRQP2:55!null\n" +
			"     │           │                       │   │                   │   │   └─ ism.UJ6XY:10!null\n" +
			"     │           │                       │   │                   │   └─ Eq\n" +
			"     │           │                       │   │                   │       ├─ YVHJZ.FFTBJ:56!null\n" +
			"     │           │                       │   │                   │       └─ ism.FV24E:9!null\n" +
			"     │           │                       │   │                   ├─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   │   ├─ AND\n" +
			"     │           │                       │   │                   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   ├─ YQIF4.BRQP2:45!null\n" +
			"     │           │                       │   │                   │   │   │   └─ ism.FV24E:9!null\n" +
			"     │           │                       │   │                   │   │   └─ Eq\n" +
			"     │           │                       │   │                   │   │       ├─ YQIF4.FFTBJ:46!null\n" +
			"     │           │                       │   │                   │   │       └─ ism.UJ6XY:10!null\n" +
			"     │           │                       │   │                   │   ├─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   │   │   ├─ AND\n" +
			"     │           │                       │   │                   │   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ CPMFE.ZH72S:34\n" +
			"     │           │                       │   │                   │   │   │   │   └─ NHMXW.NOHHR:18\n" +
			"     │           │                       │   │                   │   │   │   └─ NOT\n" +
			"     │           │                       │   │                   │   │   │       └─ Eq\n" +
			"     │           │                       │   │                   │   │   │           ├─ CPMFE.id:27!null\n" +
			"     │           │                       │   │                   │   │   │           └─ ism.FV24E:9!null\n" +
			"     │           │                       │   │                   │   │   ├─ LeftOuterLookupJoin\n" +
			"     │           │                       │   │                   │   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ NHMXW.id:17!null\n" +
			"     │           │                       │   │                   │   │   │   │   └─ ism.PRUV2:14\n" +
			"     │           │                       │   │                   │   │   │   ├─ LookupJoin\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ Eq\n" +
			"     │           │                       │   │                   │   │   │   │   │   ├─ G3YXS.id:0!null\n" +
			"     │           │                       │   │                   │   │   │   │   │   └─ ism.NZ4MQ:12!null\n" +
			"     │           │                       │   │                   │   │   │   │   ├─ Filter\n" +
			"     │           │                       │   │                   │   │   │   │   │   ├─ NOT\n" +
			"     │           │                       │   │                   │   │   │   │   │   │   └─ G3YXS.TUV25:5 IS NULL\n" +
			"     │           │                       │   │                   │   │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"     │           │                       │   │                   │   │   │   │   │       └─ Table\n" +
			"     │           │                       │   │                   │   │   │   │   │           ├─ name: YYBCX\n" +
			"     │           │                       │   │                   │   │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" +
			"     │           │                       │   │                   │   │   │   │   └─ TableAlias(ism)\n" +
			"     │           │                       │   │                   │   │   │   │       └─ IndexedTableAccess(HDDVB)\n" +
			"     │           │                       │   │                   │   │   │   │           ├─ index: [HDDVB.NZ4MQ]\n" +
			"     │           │                       │   │                   │   │   │   │           └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"     │           │                       │   │                   │   │   │   └─ TableAlias(NHMXW)\n" +
			"     │           │                       │   │                   │   │   │       └─ IndexedTableAccess(WGSDC)\n" +
			"     │           │                       │   │                   │   │   │           ├─ index: [WGSDC.id]\n" +
			"     │           │                       │   │                   │   │   │           └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			"     │           │                       │   │                   │   │   └─ TableAlias(CPMFE)\n" +
			"     │           │                       │   │                   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"     │           │                       │   │                   │   │           ├─ index: [E2I7U.ZH72S]\n" +
			"     │           │                       │   │                   │   │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"     │           │                       │   │                   │   └─ TableAlias(YQIF4)\n" +
			"     │           │                       │   │                   │       └─ IndexedTableAccess(NOXN3)\n" +
			"     │           │                       │   │                   │           ├─ index: [NOXN3.BRQP2]\n" +
			"     │           │                       │   │                   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │           │                       │   │                   └─ TableAlias(YVHJZ)\n" +
			"     │           │                       │   │                       └─ IndexedTableAccess(NOXN3)\n" +
			"     │           │                       │   │                           ├─ index: [NOXN3.BRQP2]\n" +
			"     │           │                       │   │                           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │           │                       │   └─ TableAlias(aac)\n" +
			"     │           │                       │       └─ IndexedTableAccess(TPXBU)\n" +
			"     │           │                       │           ├─ index: [TPXBU.id]\n" +
			"     │           │                       │           └─ columns: [id btxc5 fhcyt]\n" +
			"     │           │                       └─ TableAlias(sn)\n" +
			"     │           │                           └─ Table\n" +
			"     │           │                               ├─ name: NOXN3\n" +
			"     │           │                               └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"     │           └─ SubqueryAlias\n" +
			"     │               ├─ name: RSA3Y\n" +
			"     │               ├─ outerVisibility: false\n" +
			"     │               ├─ cacheable: true\n" +
			"     │               └─ Distinct\n" +
			"     │                   └─ Project\n" +
			"     │                       ├─ columns: [HTKBS.T4IBQ:0!null]\n" +
			"     │                       └─ SubqueryAlias\n" +
			"     │                           ├─ name: HTKBS\n" +
			"     │                           ├─ outerVisibility: false\n" +
			"     │                           ├─ cacheable: true\n" +
			"     │                           └─ Project\n" +
			"     │                               ├─ columns: [cla.FTQLQ:6!null as T4IBQ, sn.id:7!null as BDNYB, mf.M22QN:4!null as M22QN]\n" +
			"     │                               └─ LookupJoin\n" +
			"     │                                   ├─ Eq\n" +
			"     │                                   │   ├─ sn.BRQP2:8!null\n" +
			"     │                                   │   └─ mf.LUEVY:3!null\n" +
			"     │                                   ├─ LookupJoin\n" +
			"     │                                   │   ├─ Eq\n" +
			"     │                                   │   │   ├─ cla.id:5!null\n" +
			"     │                                   │   │   └─ bs.IXUXU:1\n" +
			"     │                                   │   ├─ LookupJoin\n" +
			"     │                                   │   │   ├─ Eq\n" +
			"     │                                   │   │   │   ├─ bs.id:0!null\n" +
			"     │                                   │   │   │   └─ mf.GXLUB:2!null\n" +
			"     │                                   │   │   ├─ TableAlias(bs)\n" +
			"     │                                   │   │   │   └─ Table\n" +
			"     │                                   │   │   │       ├─ name: THNTS\n" +
			"     │                                   │   │   │       └─ columns: [id ixuxu]\n" +
			"     │                                   │   │   └─ TableAlias(mf)\n" +
			"     │                                   │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			"     │                                   │   │           ├─ index: [HGMQ6.GXLUB]\n" +
			"     │                                   │   │           └─ columns: [gxlub luevy m22qn]\n" +
			"     │                                   │   └─ Filter\n" +
			"     │                                   │       ├─ HashIn\n" +
			"     │                                   │       │   ├─ cla.FTQLQ:1!null\n" +
			"     │                                   │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"     │                                   │       └─ TableAlias(cla)\n" +
			"     │                                   │           └─ IndexedTableAccess(YK2GW)\n" +
			"     │                                   │               ├─ index: [YK2GW.id]\n" +
			"     │                                   │               └─ columns: [id ftqlq]\n" +
			"     │                                   └─ TableAlias(sn)\n" +
			"     │                                       └─ IndexedTableAccess(NOXN3)\n" +
			"     │                                           ├─ index: [NOXN3.BRQP2]\n" +
			"     │                                           └─ columns: [id brqp2]\n" +
			"     └─ SubqueryAlias\n" +
			"         ├─ name: applySubq0\n" +
			"         ├─ outerVisibility: false\n" +
			"         ├─ cacheable: true\n" +
			"         └─ SubqueryAlias\n" +
			"             ├─ name: ZMSPR\n" +
			"             ├─ outerVisibility: true\n" +
			"             ├─ cacheable: true\n" +
			"             └─ Distinct\n" +
			"                 └─ Project\n" +
			"                     ├─ columns: [cld.T4IBQ:0!null as T4IBQ, P4PJZ.M6T2N:3 as M6T2N, P4PJZ.BTXC5:4 as BTXC5, P4PJZ.TUV25:7 as TUV25]\n" +
			"                     └─ Filter\n" +
			"                         ├─ NOT\n" +
			"                         │   └─ P4PJZ.M6T2N:3 IS NULL\n" +
			"                         └─ LeftOuterHashJoin\n" +
			"                             ├─ AND\n" +
			"                             │   ├─ Eq\n" +
			"                             │   │   ├─ P4PJZ.LWQ6O:6\n" +
			"                             │   │   └─ cld.BDNYB:1!null\n" +
			"                             │   └─ Eq\n" +
			"                             │       ├─ P4PJZ.NTOFG:5!null\n" +
			"                             │       └─ cld.M22QN:2!null\n" +
			"                             ├─ SubqueryAlias\n" +
			"                             │   ├─ name: cld\n" +
			"                             │   ├─ outerVisibility: false\n" +
			"                             │   ├─ cacheable: true\n" +
			"                             │   └─ Project\n" +
			"                             │       ├─ columns: [cla.FTQLQ:6!null as T4IBQ, sn.id:7!null as BDNYB, mf.M22QN:4!null as M22QN]\n" +
			"                             │       └─ LookupJoin\n" +
			"                             │           ├─ Eq\n" +
			"                             │           │   ├─ sn.BRQP2:8!null\n" +
			"                             │           │   └─ mf.LUEVY:3!null\n" +
			"                             │           ├─ LookupJoin\n" +
			"                             │           │   ├─ Eq\n" +
			"                             │           │   │   ├─ cla.id:5!null\n" +
			"                             │           │   │   └─ bs.IXUXU:1\n" +
			"                             │           │   ├─ LookupJoin\n" +
			"                             │           │   │   ├─ Eq\n" +
			"                             │           │   │   │   ├─ bs.id:0!null\n" +
			"                             │           │   │   │   └─ mf.GXLUB:2!null\n" +
			"                             │           │   │   ├─ TableAlias(bs)\n" +
			"                             │           │   │   │   └─ Table\n" +
			"                             │           │   │   │       ├─ name: THNTS\n" +
			"                             │           │   │   │       └─ columns: [id ixuxu]\n" +
			"                             │           │   │   └─ TableAlias(mf)\n" +
			"                             │           │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			"                             │           │   │           ├─ index: [HGMQ6.GXLUB]\n" +
			"                             │           │   │           └─ columns: [gxlub luevy m22qn]\n" +
			"                             │           │   └─ Filter\n" +
			"                             │           │       ├─ HashIn\n" +
			"                             │           │       │   ├─ cla.FTQLQ:1!null\n" +
			"                             │           │       │   └─ TUPLE(SQ1 (longtext))\n" +
			"                             │           │       └─ TableAlias(cla)\n" +
			"                             │           │           └─ IndexedTableAccess(YK2GW)\n" +
			"                             │           │               ├─ index: [YK2GW.id]\n" +
			"                             │           │               └─ columns: [id ftqlq]\n" +
			"                             │           └─ TableAlias(sn)\n" +
			"                             │               └─ IndexedTableAccess(NOXN3)\n" +
			"                             │                   ├─ index: [NOXN3.BRQP2]\n" +
			"                             │                   └─ columns: [id brqp2]\n" +
			"                             └─ HashLookup\n" +
			"                                 ├─ source: TUPLE(cld.BDNYB:1!null, cld.M22QN:2!null)\n" +
			"                                 ├─ target: TUPLE(P4PJZ.LWQ6O:3, P4PJZ.NTOFG:2!null)\n" +
			"                                 └─ CachedResults\n" +
			"                                     └─ SubqueryAlias\n" +
			"                                         ├─ name: P4PJZ\n" +
			"                                         ├─ outerVisibility: false\n" +
			"                                         ├─ cacheable: true\n" +
			"                                         └─ Project\n" +
			"                                             ├─ columns: [CASE  WHEN NOT\n" +
			"                                             │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"                                             │   THEN Subquery\n" +
			"                                             │   ├─ cacheable: false\n" +
			"                                             │   └─ Project\n" +
			"                                             │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"                                             │       └─ Filter\n" +
			"                                             │           ├─ Eq\n" +
			"                                             │           │   ├─ ei.id:20!null\n" +
			"                                             │           │   └─ MJR3D.QNI57:5\n" +
			"                                             │           └─ SubqueryAlias\n" +
			"                                             │               ├─ name: ei\n" +
			"                                             │               ├─ outerVisibility: true\n" +
			"                                             │               ├─ cacheable: true\n" +
			"                                             │               └─ Project\n" +
			"                                             │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"                                             │                   └─ Window\n" +
			"                                             │                       ├─ NOXN3.id:20!null\n" +
			"                                             │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"                                             │                       └─ Table\n" +
			"                                             │                           ├─ name: NOXN3\n" +
			"                                             │                           └─ columns: [id]\n" +
			"                                             │   WHEN NOT\n" +
			"                                             │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"                                             │   THEN Subquery\n" +
			"                                             │   ├─ cacheable: false\n" +
			"                                             │   └─ Project\n" +
			"                                             │       ├─ columns: [ei.M6T2N:21!null]\n" +
			"                                             │       └─ Filter\n" +
			"                                             │           ├─ Eq\n" +
			"                                             │           │   ├─ ei.id:20!null\n" +
			"                                             │           │   └─ MJR3D.TDEIU:6\n" +
			"                                             │           └─ SubqueryAlias\n" +
			"                                             │               ├─ name: ei\n" +
			"                                             │               ├─ outerVisibility: true\n" +
			"                                             │               ├─ cacheable: true\n" +
			"                                             │               └─ Project\n" +
			"                                             │                   ├─ columns: [NOXN3.id:20!null, (row_number() over ( order by NOXN3.id ASC):21!null - 1 (tinyint)) as M6T2N]\n" +
			"                                             │                   └─ Window\n" +
			"                                             │                       ├─ NOXN3.id:20!null\n" +
			"                                             │                       ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"                                             │                       └─ Table\n" +
			"                                             │                           ├─ name: NOXN3\n" +
			"                                             │                           └─ columns: [id]\n" +
			"                                             │   END as M6T2N, aac.BTXC5:8 as BTXC5, aac.id:7!null as NTOFG, sn.id:10 as LWQ6O, MJR3D.TUV25:3 as TUV25]\n" +
			"                                             └─ LeftOuterJoin\n" +
			"                                                 ├─ Or\n" +
			"                                                 │   ├─ Or\n" +
			"                                                 │   │   ├─ Or\n" +
			"                                                 │   │   │   ├─ AND\n" +
			"                                                 │   │   │   │   ├─ AND\n" +
			"                                                 │   │   │   │   │   ├─ NOT\n" +
			"                                                 │   │   │   │   │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"                                                 │   │   │   │   │   └─ Eq\n" +
			"                                                 │   │   │   │   │       ├─ sn.id:10!null\n" +
			"                                                 │   │   │   │   │       └─ MJR3D.QNI57:5\n" +
			"                                                 │   │   │   │   └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 │   │   │   └─ AND\n" +
			"                                                 │   │   │       ├─ AND\n" +
			"                                                 │   │   │       │   ├─ NOT\n" +
			"                                                 │   │   │       │   │   └─ MJR3D.QNI57:5 IS NULL\n" +
			"                                                 │   │   │       │   └─ InSubquery\n" +
			"                                                 │   │   │       │       ├─ left: sn.id:10!null\n" +
			"                                                 │   │   │       │       └─ right: Subquery\n" +
			"                                                 │   │   │       │           ├─ cacheable: false\n" +
			"                                                 │   │   │       │           └─ Project\n" +
			"                                                 │   │   │       │               ├─ columns: [JTEHG.id:20!null]\n" +
			"                                                 │   │   │       │               └─ Filter\n" +
			"                                                 │   │   │       │                   ├─ Eq\n" +
			"                                                 │   │   │       │                   │   ├─ JTEHG.BRQP2:21!null\n" +
			"                                                 │   │   │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"                                                 │   │   │       │                   └─ TableAlias(JTEHG)\n" +
			"                                                 │   │   │       │                       └─ Table\n" +
			"                                                 │   │   │       │                           ├─ name: NOXN3\n" +
			"                                                 │   │   │       │                           └─ columns: [id brqp2]\n" +
			"                                                 │   │   │       └─ NOT\n" +
			"                                                 │   │   │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 │   │   └─ AND\n" +
			"                                                 │   │       ├─ AND\n" +
			"                                                 │   │       │   ├─ NOT\n" +
			"                                                 │   │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"                                                 │   │       │   └─ InSubquery\n" +
			"                                                 │   │       │       ├─ left: sn.id:10!null\n" +
			"                                                 │   │       │       └─ right: Subquery\n" +
			"                                                 │   │       │           ├─ cacheable: false\n" +
			"                                                 │   │       │           └─ Project\n" +
			"                                                 │   │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"                                                 │   │       │               └─ Filter\n" +
			"                                                 │   │       │                   ├─ Eq\n" +
			"                                                 │   │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"                                                 │   │       │                   │   └─ MJR3D.FJDP5:0!null\n" +
			"                                                 │   │       │                   └─ TableAlias(XMAFZ)\n" +
			"                                                 │   │       │                       └─ Table\n" +
			"                                                 │   │       │                           ├─ name: NOXN3\n" +
			"                                                 │   │       │                           └─ columns: [id brqp2]\n" +
			"                                                 │   │       └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 │   └─ AND\n" +
			"                                                 │       ├─ AND\n" +
			"                                                 │       │   ├─ NOT\n" +
			"                                                 │       │   │   └─ MJR3D.TDEIU:6 IS NULL\n" +
			"                                                 │       │   └─ InSubquery\n" +
			"                                                 │       │       ├─ left: sn.id:10!null\n" +
			"                                                 │       │       └─ right: Subquery\n" +
			"                                                 │       │           ├─ cacheable: false\n" +
			"                                                 │       │           └─ Project\n" +
			"                                                 │       │               ├─ columns: [XMAFZ.id:20!null]\n" +
			"                                                 │       │               └─ Filter\n" +
			"                                                 │       │                   ├─ Eq\n" +
			"                                                 │       │                   │   ├─ XMAFZ.BRQP2:21!null\n" +
			"                                                 │       │                   │   └─ MJR3D.BJUF2:1\n" +
			"                                                 │       │                   └─ TableAlias(XMAFZ)\n" +
			"                                                 │       │                       └─ Table\n" +
			"                                                 │       │                           ├─ name: NOXN3\n" +
			"                                                 │       │                           └─ columns: [id brqp2]\n" +
			"                                                 │       └─ NOT\n" +
			"                                                 │           └─ MJR3D.BJUF2:1 IS NULL\n" +
			"                                                 ├─ LookupJoin\n" +
			"                                                 │   ├─ Eq\n" +
			"                                                 │   │   ├─ aac.id:7!null\n" +
			"                                                 │   │   └─ MJR3D.M22QN:2!null\n" +
			"                                                 │   ├─ SubqueryAlias\n" +
			"                                                 │   │   ├─ name: MJR3D\n" +
			"                                                 │   │   ├─ outerVisibility: false\n" +
			"                                                 │   │   ├─ cacheable: true\n" +
			"                                                 │   │   └─ Distinct\n" +
			"                                                 │   │       └─ Project\n" +
			"                                                 │   │           ├─ columns: [ism.FV24E:9!null as FJDP5, CPMFE.id:27 as BJUF2, ism.M22QN:11!null as M22QN, G3YXS.TUV25:5 as TUV25, G3YXS.ESFVY:1!null as ESFVY, YQIF4.id:44 as QNI57, YVHJZ.id:54 as TDEIU]\n" +
			"                                                 │   │           └─ Filter\n" +
			"                                                 │   │               ├─ Or\n" +
			"                                                 │   │               │   ├─ NOT\n" +
			"                                                 │   │               │   │   └─ YQIF4.id:44 IS NULL\n" +
			"                                                 │   │               │   └─ NOT\n" +
			"                                                 │   │               │       └─ YVHJZ.id:54 IS NULL\n" +
			"                                                 │   │               └─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   ├─ AND\n" +
			"                                                 │   │                   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   ├─ YVHJZ.BRQP2:55!null\n" +
			"                                                 │   │                   │   │   └─ ism.UJ6XY:10!null\n" +
			"                                                 │   │                   │   └─ Eq\n" +
			"                                                 │   │                   │       ├─ YVHJZ.FFTBJ:56!null\n" +
			"                                                 │   │                   │       └─ ism.FV24E:9!null\n" +
			"                                                 │   │                   ├─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   │   ├─ AND\n" +
			"                                                 │   │                   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   ├─ YQIF4.BRQP2:45!null\n" +
			"                                                 │   │                   │   │   │   └─ ism.FV24E:9!null\n" +
			"                                                 │   │                   │   │   └─ Eq\n" +
			"                                                 │   │                   │   │       ├─ YQIF4.FFTBJ:46!null\n" +
			"                                                 │   │                   │   │       └─ ism.UJ6XY:10!null\n" +
			"                                                 │   │                   │   ├─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   │   │   ├─ AND\n" +
			"                                                 │   │                   │   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   │   ├─ CPMFE.ZH72S:34\n" +
			"                                                 │   │                   │   │   │   │   └─ NHMXW.NOHHR:18\n" +
			"                                                 │   │                   │   │   │   └─ NOT\n" +
			"                                                 │   │                   │   │   │       └─ Eq\n" +
			"                                                 │   │                   │   │   │           ├─ CPMFE.id:27!null\n" +
			"                                                 │   │                   │   │   │           └─ ism.FV24E:9!null\n" +
			"                                                 │   │                   │   │   ├─ LeftOuterLookupJoin\n" +
			"                                                 │   │                   │   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   │   ├─ NHMXW.id:17!null\n" +
			"                                                 │   │                   │   │   │   │   └─ ism.PRUV2:14\n" +
			"                                                 │   │                   │   │   │   ├─ LookupJoin\n" +
			"                                                 │   │                   │   │   │   │   ├─ Eq\n" +
			"                                                 │   │                   │   │   │   │   │   ├─ G3YXS.id:0!null\n" +
			"                                                 │   │                   │   │   │   │   │   └─ ism.NZ4MQ:12!null\n" +
			"                                                 │   │                   │   │   │   │   ├─ Filter\n" +
			"                                                 │   │                   │   │   │   │   │   ├─ NOT\n" +
			"                                                 │   │                   │   │   │   │   │   │   └─ G3YXS.TUV25:5 IS NULL\n" +
			"                                                 │   │                   │   │   │   │   │   └─ TableAlias(G3YXS)\n" +
			"                                                 │   │                   │   │   │   │   │       └─ Table\n" +
			"                                                 │   │                   │   │   │   │   │           ├─ name: YYBCX\n" +
			"                                                 │   │                   │   │   │   │   │           └─ columns: [id esfvy sl76b ge5el f7a4q tuv25 ykssu fhcyt]\n" +
			"                                                 │   │                   │   │   │   │   └─ TableAlias(ism)\n" +
			"                                                 │   │                   │   │   │   │       └─ IndexedTableAccess(HDDVB)\n" +
			"                                                 │   │                   │   │   │   │           ├─ index: [HDDVB.NZ4MQ]\n" +
			"                                                 │   │                   │   │   │   │           └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"                                                 │   │                   │   │   │   └─ TableAlias(NHMXW)\n" +
			"                                                 │   │                   │   │   │       └─ IndexedTableAccess(WGSDC)\n" +
			"                                                 │   │                   │   │   │           ├─ index: [WGSDC.id]\n" +
			"                                                 │   │                   │   │   │           └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			"                                                 │   │                   │   │   └─ TableAlias(CPMFE)\n" +
			"                                                 │   │                   │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"                                                 │   │                   │   │           ├─ index: [E2I7U.ZH72S]\n" +
			"                                                 │   │                   │   │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"                                                 │   │                   │   └─ TableAlias(YQIF4)\n" +
			"                                                 │   │                   │       └─ IndexedTableAccess(NOXN3)\n" +
			"                                                 │   │                   │           ├─ index: [NOXN3.BRQP2]\n" +
			"                                                 │   │                   │           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"                                                 │   │                   └─ TableAlias(YVHJZ)\n" +
			"                                                 │   │                       └─ IndexedTableAccess(NOXN3)\n" +
			"                                                 │   │                           ├─ index: [NOXN3.BRQP2]\n" +
			"                                                 │   │                           └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"                                                 │   └─ TableAlias(aac)\n" +
			"                                                 │       └─ IndexedTableAccess(TPXBU)\n" +
			"                                                 │           ├─ index: [TPXBU.id]\n" +
			"                                                 │           └─ columns: [id btxc5 fhcyt]\n" +
			"                                                 └─ TableAlias(sn)\n" +
			"                                                     └─ Table\n" +
			"                                                         ├─ name: NOXN3\n" +
			"                                                         └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
SELECT
    TW55N
FROM 
    E2I7U 
ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [E2I7U.TW55N:1!null]\n" +
			" └─ IndexedTableAccess(E2I7U)\n" +
			"     ├─ index: [E2I7U.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
SELECT
    TW55N, FGG57
FROM 
    E2I7U 
ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [E2I7U.TW55N:1!null, E2I7U.FGG57:2]\n" +
			" └─ IndexedTableAccess(E2I7U)\n" +
			"     ├─ index: [E2I7U.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id tw55n fgg57]\n" +
			"",
	},
	{
		Query: `
SELECT COUNT(*) FROM E2I7U`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [COUNT(1):0!null as COUNT(*)]\n" +
			" └─ GroupBy\n" +
			"     ├─ select: COUNT(1 (bigint))\n" +
			"     ├─ group: \n" +
			"     └─ Table\n" +
			"         ├─ name: E2I7U\n" +
			"         └─ columns: []\n" +
			"",
	},
	{
		Query: `
SELECT
    ROW_NUMBER() OVER (ORDER BY id ASC) -1 DICQO,
    TW55N
FROM
    E2I7U`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [(row_number() over ( order by E2I7U.id ASC):0!null - 1 (tinyint)) as DICQO, E2I7U.TW55N:1!null]\n" +
			" └─ Window\n" +
			"     ├─ row_number() over ( order by E2I7U.id ASC)\n" +
			"     ├─ E2I7U.TW55N:1!null\n" +
			"     └─ Table\n" +
			"         ├─ name: E2I7U\n" +
			"         └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
SELECT 
    TUSAY.Y3IOU AS Q7H3X
FROM
    (SELECT 
        id AS Y46B2,
        HHVLX AS HHVLX, 
        HVHRZ AS HVHRZ 
    FROM 
        QYWQD) XJ2RD
INNER JOIN
    (SELECT 
        ROW_NUMBER() OVER (ORDER BY id ASC) Y3IOU, 
        id AS XLFIA
    FROM 
        NOXN3) TUSAY

    ON XJ2RD.HHVLX = TUSAY.XLFIA
ORDER BY Y46B2 ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [TUSAY.Y3IOU:0!null as Q7H3X]\n" +
			" └─ Sort(XJ2RD.Y46B2:2!null ASC nullsFirst)\n" +
			"     └─ HashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ XJ2RD.HHVLX:3!null\n" +
			"         │   └─ TUSAY.XLFIA:1!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: TUSAY\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Project\n" +
			"         │       ├─ columns: [row_number() over ( order by NOXN3.id ASC):0!null as Y3IOU, XLFIA:1!null]\n" +
			"         │       └─ Window\n" +
			"         │           ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"         │           ├─ NOXN3.id:0!null as XLFIA\n" +
			"         │           └─ Table\n" +
			"         │               ├─ name: NOXN3\n" +
			"         │               └─ columns: [id]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(TUSAY.XLFIA:1!null)\n" +
			"             ├─ target: TUPLE(XJ2RD.HHVLX:1!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ SubqueryAlias\n" +
			"                     ├─ name: XJ2RD\n" +
			"                     ├─ outerVisibility: false\n" +
			"                     ├─ cacheable: true\n" +
			"                     └─ Project\n" +
			"                         ├─ columns: [QYWQD.id:0!null as Y46B2, QYWQD.HHVLX:1!null as HHVLX, QYWQD.HVHRZ:2!null as HVHRZ]\n" +
			"                         └─ Table\n" +
			"                             ├─ name: QYWQD\n" +
			"                             └─ columns: [id hhvlx hvhrz]\n" +
			"",
	},
	{
		Query: `
SELECT 
    I2GJ5.R2SR7
FROM
    (SELECT
        id AS XLFIA,
        BRQP2
    FROM
        NOXN3
    ORDER BY id ASC) sn
    LEFT JOIN
    (SELECT
        nd.LUEVY,
    CASE
        WHEN nma.DZLIM = 'Q5I4E' THEN 1
        ELSE 0
        END AS R2SR7
    FROM
        (SELECT 
            id AS LUEVY, 
            HPCMS AS HPCMS
        FROM 
            E2I7U) nd 
        LEFT JOIN
        (SELECT 
            id AS MLECF, 
            DZLIM
        FROM 
            TNMXI) nma
        ON nd.HPCMS = nma.MLECF) I2GJ5
    ON sn.BRQP2 = I2GJ5.LUEVY
ORDER BY sn.XLFIA ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [I2GJ5.R2SR7:3]\n" +
			" └─ Sort(sn.XLFIA:0!null ASC nullsFirst)\n" +
			"     └─ LeftOuterHashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ sn.BRQP2:1!null\n" +
			"         │   └─ I2GJ5.LUEVY:2!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: sn\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Project\n" +
			"         │       ├─ columns: [NOXN3.id:0!null as XLFIA, NOXN3.BRQP2:1!null]\n" +
			"         │       └─ IndexedTableAccess(NOXN3)\n" +
			"         │           ├─ index: [NOXN3.id]\n" +
			"         │           ├─ static: [{[NULL, ∞)}]\n" +
			"         │           └─ columns: [id brqp2]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(sn.BRQP2:1!null)\n" +
			"             ├─ target: TUPLE(I2GJ5.LUEVY:0!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ SubqueryAlias\n" +
			"                     ├─ name: I2GJ5\n" +
			"                     ├─ outerVisibility: false\n" +
			"                     ├─ cacheable: true\n" +
			"                     └─ Project\n" +
			"                         ├─ columns: [nd.LUEVY:0!null, CASE  WHEN Eq\n" +
			"                         │   ├─ nma.DZLIM:3\n" +
			"                         │   └─ Q5I4E (longtext)\n" +
			"                         │   THEN 1 (tinyint) ELSE 0 (tinyint) END as R2SR7]\n" +
			"                         └─ LeftOuterHashJoin\n" +
			"                             ├─ Eq\n" +
			"                             │   ├─ nd.HPCMS:1!null\n" +
			"                             │   └─ nma.MLECF:2!null\n" +
			"                             ├─ SubqueryAlias\n" +
			"                             │   ├─ name: nd\n" +
			"                             │   ├─ outerVisibility: false\n" +
			"                             │   ├─ cacheable: true\n" +
			"                             │   └─ Project\n" +
			"                             │       ├─ columns: [E2I7U.id:0!null as LUEVY, E2I7U.HPCMS:1!null as HPCMS]\n" +
			"                             │       └─ Table\n" +
			"                             │           ├─ name: E2I7U\n" +
			"                             │           └─ columns: [id hpcms]\n" +
			"                             └─ HashLookup\n" +
			"                                 ├─ source: TUPLE(nd.HPCMS:1!null)\n" +
			"                                 ├─ target: TUPLE(nma.MLECF:0!null)\n" +
			"                                 └─ CachedResults\n" +
			"                                     └─ SubqueryAlias\n" +
			"                                         ├─ name: nma\n" +
			"                                         ├─ outerVisibility: false\n" +
			"                                         ├─ cacheable: true\n" +
			"                                         └─ Project\n" +
			"                                             ├─ columns: [TNMXI.id:0!null as MLECF, TNMXI.DZLIM:1!null]\n" +
			"                                             └─ Table\n" +
			"                                                 ├─ name: TNMXI\n" +
			"                                                 └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `
SELECT
    QI2IE.DICQO AS DICQO
FROM
    (SELECT 
        id AS XLFIA,
        BRQP2 AS AHMDT
    FROM
        NOXN3) GRRB6
LEFT JOIN
    (SELECT 
        ROW_NUMBER() OVER (ORDER BY id ASC) DICQO, 
        id AS VIBZI
    FROM 
        E2I7U) QI2IE
    ON QI2IE.VIBZI = GRRB6.AHMDT
ORDER BY GRRB6.XLFIA ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [QI2IE.DICQO:2 as DICQO]\n" +
			" └─ Sort(GRRB6.XLFIA:0!null ASC nullsFirst)\n" +
			"     └─ LeftOuterHashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ QI2IE.VIBZI:3!null\n" +
			"         │   └─ GRRB6.AHMDT:1!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: GRRB6\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Project\n" +
			"         │       ├─ columns: [NOXN3.id:0!null as XLFIA, NOXN3.BRQP2:1!null as AHMDT]\n" +
			"         │       └─ Table\n" +
			"         │           ├─ name: NOXN3\n" +
			"         │           └─ columns: [id brqp2]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(GRRB6.AHMDT:1!null)\n" +
			"             ├─ target: TUPLE(QI2IE.VIBZI:1!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ SubqueryAlias\n" +
			"                     ├─ name: QI2IE\n" +
			"                     ├─ outerVisibility: false\n" +
			"                     ├─ cacheable: true\n" +
			"                     └─ Project\n" +
			"                         ├─ columns: [row_number() over ( order by E2I7U.id ASC):0!null as DICQO, VIBZI:1!null]\n" +
			"                         └─ Window\n" +
			"                             ├─ row_number() over ( order by E2I7U.id ASC)\n" +
			"                             ├─ E2I7U.id:0!null as VIBZI\n" +
			"                             └─ Table\n" +
			"                                 ├─ name: E2I7U\n" +
			"                                 └─ columns: [id]\n" +
			"",
	},
	{
		Query: `
SELECT
    DISTINCT cla.FTQLQ
FROM
    YK2GW cla
WHERE
    cla.id IN (
        SELECT bs.IXUXU
        FROM THNTS bs
        WHERE
            bs.id IN (SELECT GXLUB FROM HGMQ6)
            AND bs.id IN (SELECT GXLUB FROM AMYXQ)
    )
ORDER BY cla.FTQLQ ASC`,
		ExpectedPlan: "Sort(cla.FTQLQ:0!null ASC nullsFirst)\n" +
			" └─ Distinct\n" +
			"     └─ Project\n" +
			"         ├─ columns: [cla.FTQLQ:1!null]\n" +
			"         └─ RightSemiLookupJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ cla.id:4!null\n" +
			"             │   └─ applySubq0.IXUXU:2\n" +
			"             ├─ Distinct\n" +
			"             │   └─ Filter\n" +
			"             │       ├─ AND\n" +
			"             │       │   ├─ InSubquery\n" +
			"             │       │   │   ├─ left: applySubq0.id:0!null\n" +
			"             │       │   │   └─ right: Subquery\n" +
			"             │       │   │       ├─ cacheable: true\n" +
			"             │       │   │       └─ Table\n" +
			"             │       │   │           ├─ name: HGMQ6\n" +
			"             │       │   │           └─ columns: [gxlub]\n" +
			"             │       │   └─ InSubquery\n" +
			"             │       │       ├─ left: applySubq0.id:0!null\n" +
			"             │       │       └─ right: Subquery\n" +
			"             │       │           ├─ cacheable: true\n" +
			"             │       │           └─ Table\n" +
			"             │       │               ├─ name: AMYXQ\n" +
			"             │       │               └─ columns: [gxlub]\n" +
			"             │       └─ TableAlias(applySubq0)\n" +
			"             │           └─ Table\n" +
			"             │               ├─ name: THNTS\n" +
			"             │               └─ columns: [id nfryn ixuxu fhcyt]\n" +
			"             └─ TableAlias(cla)\n" +
			"                 └─ IndexedTableAccess(YK2GW)\n" +
			"                     ├─ index: [YK2GW.id]\n" +
			"                     └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
SELECT
    DISTINCT cla.FTQLQ
FROM HGMQ6 mf
INNER JOIN THNTS bs
    ON mf.GXLUB = bs.id
INNER JOIN YK2GW cla
    ON bs.IXUXU = cla.id
ORDER BY cla.FTQLQ ASC`,
		ExpectedPlan: "Sort(cla.FTQLQ:0!null ASC nullsFirst)\n" +
			" └─ Distinct\n" +
			"     └─ Project\n" +
			"         ├─ columns: [cla.FTQLQ:22!null]\n" +
			"         └─ LookupJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ bs.IXUXU:2\n" +
			"             │   └─ cla.id:21!null\n" +
			"             ├─ LookupJoin\n" +
			"             │   ├─ Eq\n" +
			"             │   │   ├─ mf.GXLUB:5!null\n" +
			"             │   │   └─ bs.id:0!null\n" +
			"             │   ├─ TableAlias(bs)\n" +
			"             │   │   └─ Table\n" +
			"             │   │       ├─ name: THNTS\n" +
			"             │   │       └─ columns: [id nfryn ixuxu fhcyt]\n" +
			"             │   └─ TableAlias(mf)\n" +
			"             │       └─ IndexedTableAccess(HGMQ6)\n" +
			"             │           ├─ index: [HGMQ6.GXLUB]\n" +
			"             │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			"             └─ TableAlias(cla)\n" +
			"                 └─ IndexedTableAccess(YK2GW)\n" +
			"                     ├─ index: [YK2GW.id]\n" +
			"                     └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
SELECT
    DISTINCT cla.FTQLQ
FROM YK2GW cla
WHERE cla.id IN
    (SELECT IXUXU FROM THNTS bs
        WHERE bs.id IN (SELECT GXLUB FROM AMYXQ))
ORDER BY cla.FTQLQ ASC`,
		ExpectedPlan: "Sort(cla.FTQLQ:0!null ASC nullsFirst)\n" +
			" └─ Distinct\n" +
			"     └─ Project\n" +
			"         ├─ columns: [cla.FTQLQ:1!null]\n" +
			"         └─ RightSemiLookupJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ cla.id:4!null\n" +
			"             │   └─ applySubq0.IXUXU:2\n" +
			"             ├─ Distinct\n" +
			"             │   └─ SemiLookupJoin\n" +
			"             │       ├─ Eq\n" +
			"             │       │   ├─ applySubq0.id:0!null\n" +
			"             │       │   └─ applySubq1.GXLUB:4!null\n" +
			"             │       ├─ TableAlias(applySubq0)\n" +
			"             │       │   └─ Table\n" +
			"             │       │       ├─ name: THNTS\n" +
			"             │       │       └─ columns: [id nfryn ixuxu fhcyt]\n" +
			"             │       └─ TableAlias(applySubq1)\n" +
			"             │           └─ IndexedTableAccess(AMYXQ)\n" +
			"             │               ├─ index: [AMYXQ.GXLUB,AMYXQ.LUEVY]\n" +
			"             │               └─ columns: [gxlub]\n" +
			"             └─ TableAlias(cla)\n" +
			"                 └─ IndexedTableAccess(YK2GW)\n" +
			"                     ├─ index: [YK2GW.id]\n" +
			"                     └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
SELECT
    DISTINCT ci.FTQLQ
FROM FLQLP ct
INNER JOIN JDLNA ci
    ON ct.FZ2R5 = ci.id
ORDER BY ci.FTQLQ`,
		ExpectedPlan: "Sort(ci.FTQLQ:0!null ASC nullsFirst)\n" +
			" └─ Distinct\n" +
			"     └─ Project\n" +
			"         ├─ columns: [ci.FTQLQ:1!null]\n" +
			"         └─ LookupJoin\n" +
			"             ├─ Eq\n" +
			"             │   ├─ ct.FZ2R5:6!null\n" +
			"             │   └─ ci.id:0!null\n" +
			"             ├─ TableAlias(ci)\n" +
			"             │   └─ Table\n" +
			"             │       ├─ name: JDLNA\n" +
			"             │       └─ columns: [id ftqlq fwwiq o3qxw fhcyt]\n" +
			"             └─ TableAlias(ct)\n" +
			"                 └─ IndexedTableAccess(FLQLP)\n" +
			"                     ├─ index: [FLQLP.FZ2R5]\n" +
			"                     └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"",
	},
	{
		Query: `
SELECT
        YPGDA.LUEVY AS LUEVY,
        YPGDA.TW55N AS TW55N,
        YPGDA.IYDZV AS IYDZV,
        '' AS IIISV,
        YPGDA.QRQXW AS QRQXW,
        YPGDA.CAECS AS CAECS,
        YPGDA.CJLLY AS CJLLY,
        YPGDA.SHP7H AS SHP7H,
        YPGDA.HARAZ AS HARAZ,
        '' AS ECUWU,
        '' AS LDMO7,
        CASE
            WHEN YBBG5.DZLIM = 'HGUEM' THEN 's30'
            WHEN YBBG5.DZLIM = 'YUHMV' THEN 'r90'
            WHEN YBBG5.DZLIM = 'T3JIU' THEN 'r50'
            WHEN YBBG5.DZLIM = 's' THEN 's'
            WHEN YBBG5.DZLIM = 'AX25H' THEN 'r70'
            WHEN YBBG5.DZLIM IS NULL then ''
            ELSE YBBG5.DZLIM
        END AS UBUYI,
        YPGDA.FUG6J AS FUG6J,
        YPGDA.NF5AM AS NF5AM,
        YPGDA.FRCVC AS FRCVC
FROM
    (SELECT 
        nd.id AS LUEVY,
        nd.TW55N AS TW55N,
        nd.FGG57 AS IYDZV,
        nd.QRQXW AS QRQXW,
        nd.IWV2H AS CAECS,
        nd.ECXAJ AS CJLLY,
        nma.DZLIM AS SHP7H,
        nd.N5CC2 AS HARAZ,
        (SELECT
            XQDYT
            FROM AMYXQ
            WHERE LUEVY = nd.id 
            LIMIT 1) AS I3L5A,
        nd.ETAQ7 AS FUG6J,
        nd.A75X7 AS NF5AM,
        nd.FSK67 AS FRCVC
    FROM E2I7U nd
    LEFT JOIN TNMXI nma
        ON nma.id = nd.HPCMS) YPGDA
LEFT JOIN XGSJM YBBG5
    ON YPGDA.I3L5A = YBBG5.id
ORDER BY LUEVY`,
		ExpectedPlan: "Sort(LUEVY:0!null ASC nullsFirst)\n" +
			" └─ Project\n" +
			"     ├─ columns: [YPGDA.LUEVY:0!null as LUEVY, YPGDA.TW55N:1!null as TW55N, YPGDA.IYDZV:2 as IYDZV,  (longtext) as IIISV, YPGDA.QRQXW:3!null as QRQXW, YPGDA.CAECS:4 as CAECS, YPGDA.CJLLY:5!null as CJLLY, YPGDA.SHP7H:6 as SHP7H, YPGDA.HARAZ:7 as HARAZ,  (longtext) as ECUWU,  (longtext) as LDMO7, CASE  WHEN Eq\n" +
			"     │   ├─ YBBG5.DZLIM:13\n" +
			"     │   └─ HGUEM (longtext)\n" +
			"     │   THEN s30 (longtext) WHEN Eq\n" +
			"     │   ├─ YBBG5.DZLIM:13\n" +
			"     │   └─ YUHMV (longtext)\n" +
			"     │   THEN r90 (longtext) WHEN Eq\n" +
			"     │   ├─ YBBG5.DZLIM:13\n" +
			"     │   └─ T3JIU (longtext)\n" +
			"     │   THEN r50 (longtext) WHEN Eq\n" +
			"     │   ├─ YBBG5.DZLIM:13\n" +
			"     │   └─ s (longtext)\n" +
			"     │   THEN s (longtext) WHEN Eq\n" +
			"     │   ├─ YBBG5.DZLIM:13\n" +
			"     │   └─ AX25H (longtext)\n" +
			"     │   THEN r70 (longtext) WHEN YBBG5.DZLIM:13 IS NULL THEN  (longtext) ELSE YBBG5.DZLIM:13 END as UBUYI, YPGDA.FUG6J:9 as FUG6J, YPGDA.NF5AM:10 as NF5AM, YPGDA.FRCVC:11!null as FRCVC]\n" +
			"     └─ LeftOuterHashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ YPGDA.I3L5A:8\n" +
			"         │   └─ YBBG5.id:12!null\n" +
			"         ├─ SubqueryAlias\n" +
			"         │   ├─ name: YPGDA\n" +
			"         │   ├─ outerVisibility: false\n" +
			"         │   ├─ cacheable: true\n" +
			"         │   └─ Project\n" +
			"         │       ├─ columns: [nd.id:0!null as LUEVY, nd.TW55N:3!null as TW55N, nd.FGG57:6 as IYDZV, nd.QRQXW:4!null as QRQXW, nd.IWV2H:11 as CAECS, nd.ECXAJ:5!null as CJLLY, nma.DZLIM:18 as SHP7H, nd.N5CC2:13 as HARAZ, Subquery\n" +
			"         │       │   ├─ cacheable: false\n" +
			"         │       │   └─ Limit(1)\n" +
			"         │       │       └─ Project\n" +
			"         │       │           ├─ columns: [AMYXQ.XQDYT:21!null]\n" +
			"         │       │           └─ Filter\n" +
			"         │       │               ├─ Eq\n" +
			"         │       │               │   ├─ AMYXQ.LUEVY:20!null\n" +
			"         │       │               │   └─ nd.id:0!null\n" +
			"         │       │               └─ Table\n" +
			"         │       │                   ├─ name: AMYXQ\n" +
			"         │       │                   └─ columns: [luevy xqdyt]\n" +
			"         │       │   as I3L5A, nd.ETAQ7:15 as FUG6J, nd.A75X7:16 as NF5AM, nd.FSK67:8!null as FRCVC]\n" +
			"         │       └─ LeftOuterMergeJoin\n" +
			"         │           ├─ cmp: Eq\n" +
			"         │           │   ├─ nd.HPCMS:12!null\n" +
			"         │           │   └─ nma.id:17!null\n" +
			"         │           ├─ TableAlias(nd)\n" +
			"         │           │   └─ IndexedTableAccess(E2I7U)\n" +
			"         │           │       ├─ index: [E2I7U.HPCMS]\n" +
			"         │           │       ├─ static: [{[NULL, ∞)}]\n" +
			"         │           │       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"         │           └─ TableAlias(nma)\n" +
			"         │               └─ IndexedTableAccess(TNMXI)\n" +
			"         │                   ├─ index: [TNMXI.id]\n" +
			"         │                   ├─ static: [{[NULL, ∞)}]\n" +
			"         │                   └─ columns: [id dzlim f3yue]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(YPGDA.I3L5A:8)\n" +
			"             ├─ target: TUPLE(YBBG5.id:0!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ TableAlias(YBBG5)\n" +
			"                     └─ Table\n" +
			"                         ├─ name: XGSJM\n" +
			"                         └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `
SELECT LUEVY, F6NSZ FROM ARLV5`,
		ExpectedPlan: "Table\n" +
			" ├─ name: ARLV5\n" +
			" └─ columns: [luevy f6nsz]\n" +
			"",
	},
	{
		Query: `
SELECT id, DZLIM FROM IIISV`,
		ExpectedPlan: "Table\n" +
			" ├─ name: IIISV\n" +
			" └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `
SELECT
    TVQG4.TW55N
        AS FJVD7,
    LSM32.TW55N
        AS KBXXJ,
    sn.NUMK2
        AS NUMK2,
    CASE
        WHEN it.DZLIM IS NULL
        THEN "N/A"
        ELSE it.DZLIM
    END
        AS TP6BK,
    sn.ECDKM
        AS ECDKM,
    sn.KBO7R
        AS KBO7R,
    CASE
        WHEN sn.YKSSU IS NULL
        THEN "N/A"
        ELSE sn.YKSSU
    END
        AS RQI4M,
    CASE
        WHEN sn.FHCYT IS NULL
        THEN "N/A"
        ELSE sn.FHCYT
    END
        AS RNVLS,
    sn.LETOE
        AS LETOE
FROM
    NOXN3 sn
LEFT JOIN
    E2I7U TVQG4
    ON sn.BRQP2 = TVQG4.id
LEFT JOIN
    E2I7U LSM32
    ON sn.FFTBJ = LSM32.id
LEFT JOIN
    FEVH4 it
    ON sn.A7XO2 = it.id
ORDER BY sn.id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [TVQG4.TW55N:11 as FJVD7, LSM32.TW55N:13 as KBXXJ, sn.NUMK2:6!null as NUMK2, CASE  WHEN it.DZLIM:15 IS NULL THEN N/A (longtext) ELSE it.DZLIM:15 END as TP6BK, sn.ECDKM:5 as ECDKM, sn.KBO7R:4!null as KBO7R, CASE  WHEN sn.YKSSU:8 IS NULL THEN N/A (longtext) ELSE sn.YKSSU:8 END as RQI4M, CASE  WHEN sn.FHCYT:9 IS NULL THEN N/A (longtext) ELSE sn.FHCYT:9 END as RNVLS, sn.LETOE:7!null as LETOE]\n" +
			" └─ Sort(sn.id:0!null ASC nullsFirst)\n" +
			"     └─ LeftOuterHashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ sn.A7XO2:3\n" +
			"         │   └─ it.id:14!null\n" +
			"         ├─ LeftOuterHashJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ sn.FFTBJ:2!null\n" +
			"         │   │   └─ LSM32.id:12!null\n" +
			"         │   ├─ LeftOuterMergeJoin\n" +
			"         │   │   ├─ cmp: Eq\n" +
			"         │   │   │   ├─ sn.BRQP2:1!null\n" +
			"         │   │   │   └─ TVQG4.id:10!null\n" +
			"         │   │   ├─ TableAlias(sn)\n" +
			"         │   │   │   └─ IndexedTableAccess(NOXN3)\n" +
			"         │   │   │       ├─ index: [NOXN3.BRQP2]\n" +
			"         │   │   │       ├─ static: [{[NULL, ∞)}]\n" +
			"         │   │   │       └─ columns: [id brqp2 fftbj a7xo2 kbo7r ecdkm numk2 letoe ykssu fhcyt]\n" +
			"         │   │   └─ TableAlias(TVQG4)\n" +
			"         │   │       └─ IndexedTableAccess(E2I7U)\n" +
			"         │   │           ├─ index: [E2I7U.id]\n" +
			"         │   │           ├─ static: [{[NULL, ∞)}]\n" +
			"         │   │           └─ columns: [id tw55n]\n" +
			"         │   └─ HashLookup\n" +
			"         │       ├─ source: TUPLE(sn.FFTBJ:2!null)\n" +
			"         │       ├─ target: TUPLE(LSM32.id:0!null)\n" +
			"         │       └─ CachedResults\n" +
			"         │           └─ TableAlias(LSM32)\n" +
			"         │               └─ Table\n" +
			"         │                   ├─ name: E2I7U\n" +
			"         │                   └─ columns: [id tw55n]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(sn.A7XO2:3)\n" +
			"             ├─ target: TUPLE(it.id:0!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ TableAlias(it)\n" +
			"                     └─ Table\n" +
			"                         ├─ name: FEVH4\n" +
			"                         └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `
SELECT
    KBO7R 
FROM 
    NOXN3 
ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [NOXN3.KBO7R:1!null]\n" +
			" └─ IndexedTableAccess(NOXN3)\n" +
			"     ├─ index: [NOXN3.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id kbo7r]\n" +
			"",
	},
	{
		Query: `
SELECT
    SDLLR.TW55N
        AS FZX4Y,
    JGT2H.LETOE
        AS QWTOI,
    RIIW6.TW55N
        AS PDX5Y,
    AYFCD.NUMK2
        AS V45YB ,
    AYFCD.LETOE
        AS DAGQN,
    FA75Y.TW55N
        AS SFQTS,
    rn.HVHRZ
        AS HVHRZ,
    CASE
        WHEN rn.YKSSU IS NULL
        THEN "N/A"
        ELSE rn.YKSSU
    END
        AS RQI4M,
    CASE
        WHEN rn.FHCYT IS NULL
        THEN "N/A"
        ELSE rn.FHCYT
    END
        AS RNVLS
FROM
    QYWQD rn
LEFT JOIN
    NOXN3 JGT2H
    ON  rn.WNUNU = JGT2H.id
LEFT JOIN
    NOXN3 AYFCD
    ON  rn.HHVLX = AYFCD.id
LEFT JOIN
    E2I7U SDLLR
    ON JGT2H.BRQP2 = SDLLR.id
LEFT JOIN
    E2I7U RIIW6
    ON JGT2H.FFTBJ = RIIW6.id
LEFT JOIN
    E2I7U FA75Y
    ON AYFCD.FFTBJ = FA75Y.id
ORDER BY rn.id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [SDLLR.TW55N:15 as FZX4Y, JGT2H.LETOE:9 as QWTOI, RIIW6.TW55N:17 as PDX5Y, AYFCD.NUMK2:12 as V45YB, AYFCD.LETOE:13 as DAGQN, FA75Y.TW55N:19 as SFQTS, rn.HVHRZ:3!null as HVHRZ, CASE  WHEN rn.YKSSU:4 IS NULL THEN N/A (longtext) ELSE rn.YKSSU:4 END as RQI4M, CASE  WHEN rn.FHCYT:5 IS NULL THEN N/A (longtext) ELSE rn.FHCYT:5 END as RNVLS]\n" +
			" └─ Sort(rn.id:0!null ASC nullsFirst)\n" +
			"     └─ LeftOuterHashJoin\n" +
			"         ├─ Eq\n" +
			"         │   ├─ AYFCD.FFTBJ:11\n" +
			"         │   └─ FA75Y.id:18!null\n" +
			"         ├─ LeftOuterHashJoin\n" +
			"         │   ├─ Eq\n" +
			"         │   │   ├─ JGT2H.FFTBJ:8\n" +
			"         │   │   └─ RIIW6.id:16!null\n" +
			"         │   ├─ LeftOuterHashJoin\n" +
			"         │   │   ├─ Eq\n" +
			"         │   │   │   ├─ JGT2H.BRQP2:7\n" +
			"         │   │   │   └─ SDLLR.id:14!null\n" +
			"         │   │   ├─ LeftOuterHashJoin\n" +
			"         │   │   │   ├─ Eq\n" +
			"         │   │   │   │   ├─ rn.HHVLX:2!null\n" +
			"         │   │   │   │   └─ AYFCD.id:10!null\n" +
			"         │   │   │   ├─ LeftOuterMergeJoin\n" +
			"         │   │   │   │   ├─ cmp: Eq\n" +
			"         │   │   │   │   │   ├─ rn.WNUNU:1!null\n" +
			"         │   │   │   │   │   └─ JGT2H.id:6!null\n" +
			"         │   │   │   │   ├─ TableAlias(rn)\n" +
			"         │   │   │   │   │   └─ IndexedTableAccess(QYWQD)\n" +
			"         │   │   │   │   │       ├─ index: [QYWQD.WNUNU]\n" +
			"         │   │   │   │   │       ├─ static: [{[NULL, ∞)}]\n" +
			"         │   │   │   │   │       └─ columns: [id wnunu hhvlx hvhrz ykssu fhcyt]\n" +
			"         │   │   │   │   └─ TableAlias(JGT2H)\n" +
			"         │   │   │   │       └─ IndexedTableAccess(NOXN3)\n" +
			"         │   │   │   │           ├─ index: [NOXN3.id]\n" +
			"         │   │   │   │           ├─ static: [{[NULL, ∞)}]\n" +
			"         │   │   │   │           └─ columns: [id brqp2 fftbj letoe]\n" +
			"         │   │   │   └─ HashLookup\n" +
			"         │   │   │       ├─ source: TUPLE(rn.HHVLX:2!null)\n" +
			"         │   │   │       ├─ target: TUPLE(AYFCD.id:0!null)\n" +
			"         │   │   │       └─ CachedResults\n" +
			"         │   │   │           └─ TableAlias(AYFCD)\n" +
			"         │   │   │               └─ Table\n" +
			"         │   │   │                   ├─ name: NOXN3\n" +
			"         │   │   │                   └─ columns: [id fftbj numk2 letoe]\n" +
			"         │   │   └─ HashLookup\n" +
			"         │   │       ├─ source: TUPLE(JGT2H.BRQP2:7)\n" +
			"         │   │       ├─ target: TUPLE(SDLLR.id:0!null)\n" +
			"         │   │       └─ CachedResults\n" +
			"         │   │           └─ TableAlias(SDLLR)\n" +
			"         │   │               └─ Table\n" +
			"         │   │                   ├─ name: E2I7U\n" +
			"         │   │                   └─ columns: [id tw55n]\n" +
			"         │   └─ HashLookup\n" +
			"         │       ├─ source: TUPLE(JGT2H.FFTBJ:8)\n" +
			"         │       ├─ target: TUPLE(RIIW6.id:0!null)\n" +
			"         │       └─ CachedResults\n" +
			"         │           └─ TableAlias(RIIW6)\n" +
			"         │               └─ Table\n" +
			"         │                   ├─ name: E2I7U\n" +
			"         │                   └─ columns: [id tw55n]\n" +
			"         └─ HashLookup\n" +
			"             ├─ source: TUPLE(AYFCD.FFTBJ:11)\n" +
			"             ├─ target: TUPLE(FA75Y.id:0!null)\n" +
			"             └─ CachedResults\n" +
			"                 └─ TableAlias(FA75Y)\n" +
			"                     └─ Table\n" +
			"                         ├─ name: E2I7U\n" +
			"                         └─ columns: [id tw55n]\n" +
			"",
	},
	{
		Query: `
SELECT
    QRQXW 
FROM 
    E2I7U 
ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [E2I7U.QRQXW:1!null]\n" +
			" └─ IndexedTableAccess(E2I7U)\n" +
			"     ├─ index: [E2I7U.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id qrqxw]\n" +
			"",
	},
	{
		Query: `
SELECT 
    sn.Y3IOU,
    sn.ECDKM
FROM 
    (SELECT
        ROW_NUMBER() OVER (ORDER BY id ASC) Y3IOU, 
        id,
        NUMK2,
        ECDKM
    FROM
    NOXN3) sn
WHERE NUMK2 = 4
ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [sn.Y3IOU:0!null, sn.ECDKM:3]\n" +
			" └─ Sort(sn.id:1!null ASC nullsFirst)\n" +
			"     └─ SubqueryAlias\n" +
			"         ├─ name: sn\n" +
			"         ├─ outerVisibility: false\n" +
			"         ├─ cacheable: true\n" +
			"         └─ Filter\n" +
			"             ├─ Eq\n" +
			"             │   ├─ NOXN3.NUMK2:2!null\n" +
			"             │   └─ 4 (tinyint)\n" +
			"             └─ Project\n" +
			"                 ├─ columns: [row_number() over ( order by NOXN3.id ASC):0!null as Y3IOU, NOXN3.id:1!null, NOXN3.NUMK2:2!null, NOXN3.ECDKM:3]\n" +
			"                 └─ Window\n" +
			"                     ├─ row_number() over ( order by NOXN3.id ASC)\n" +
			"                     ├─ NOXN3.id:0!null\n" +
			"                     ├─ NOXN3.NUMK2:2!null\n" +
			"                     ├─ NOXN3.ECDKM:1\n" +
			"                     └─ Table\n" +
			"                         ├─ name: NOXN3\n" +
			"                         └─ columns: [id ecdkm numk2]\n" +
			"",
	},
	{
		Query: `
SELECT id, NUMK2, ECDKM
FROM NOXN3
ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [NOXN3.id:0!null, NOXN3.NUMK2:2!null, NOXN3.ECDKM:1]\n" +
			" └─ IndexedTableAccess(NOXN3)\n" +
			"     ├─ index: [NOXN3.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id ecdkm numk2]\n" +
			"",
	},
	{
		Query: `
SELECT
    CASE 
        WHEN NUMK2 = 2 THEN ECDKM
        ELSE 0
    END AS RGXLL
    FROM NOXN3
    ORDER BY id ASC`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [CASE  WHEN Eq\n" +
			" │   ├─ NOXN3.NUMK2:2!null\n" +
			" │   └─ 2 (tinyint)\n" +
			" │   THEN NOXN3.ECDKM:1 ELSE 0 (tinyint) END as RGXLL]\n" +
			" └─ IndexedTableAccess(NOXN3)\n" +
			"     ├─ index: [NOXN3.id]\n" +
			"     ├─ static: [{[NULL, ∞)}]\n" +
			"     └─ columns: [id ecdkm numk2]\n" +
			"",
	},
	{
		Query: `
SELECT
    pa.DZLIM as ECUWU,
    nd.TW55N
FROM JJGQT QNRBH
INNER JOIN E2I7U nd
    ON QNRBH.LUEVY = nd.id
INNER JOIN XOAOP pa
    ON QNRBH.CH3FR = pa.id`,
		ExpectedPlan: "Project\n" +
			" ├─ columns: [pa.DZLIM:5!null as ECUWU, nd.TW55N:3!null]\n" +
			" └─ LookupJoin\n" +
			"     ├─ Eq\n" +
			"     │   ├─ QNRBH.CH3FR:0!null\n" +
			"     │   └─ pa.id:4!null\n" +
			"     ├─ LookupJoin\n" +
			"     │   ├─ Eq\n" +
			"     │   │   ├─ QNRBH.LUEVY:1!null\n" +
			"     │   │   └─ nd.id:2!null\n" +
			"     │   ├─ TableAlias(QNRBH)\n" +
			"     │   │   └─ Table\n" +
			"     │   │       ├─ name: JJGQT\n" +
			"     │   │       └─ columns: [ch3fr luevy]\n" +
			"     │   └─ TableAlias(nd)\n" +
			"     │       └─ IndexedTableAccess(E2I7U)\n" +
			"     │           ├─ index: [E2I7U.id]\n" +
			"     │           └─ columns: [id tw55n]\n" +
			"     └─ TableAlias(pa)\n" +
			"         └─ IndexedTableAccess(XOAOP)\n" +
			"             ├─ index: [XOAOP.id]\n" +
			"             └─ columns: [id dzlim]\n" +
			"",
	},
	{
		Query: `-- deletes
DELETE FROM QYWQD
WHERE id IN ('1','2','3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ QYWQD.id:0!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(QYWQD)\n" +
			"             ├─ index: [QYWQD.id]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id wnunu hhvlx hvhrz ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM HDDVB
WHERE
    FV24E IN ('1', '2', '3') OR
    UJ6XY IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ Or\n" +
			"         │   ├─ HashIn\n" +
			"         │   │   ├─ HDDVB.FV24E:1!null\n" +
			"         │   │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         │   └─ HashIn\n" +
			"         │       ├─ HDDVB.UJ6XY:2!null\n" +
			"         │       └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ Table\n" +
			"             ├─ name: HDDVB\n" +
			"             └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM QYWQD
WHERE id IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ QYWQD.id:0!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(QYWQD)\n" +
			"             ├─ index: [QYWQD.id]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id wnunu hhvlx hvhrz ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM AMYXQ
WHERE LUEVY IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ AMYXQ.LUEVY:2!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(AMYXQ)\n" +
			"             ├─ index: [AMYXQ.LUEVY]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id gxlub luevy xqdyt amyxq oztqf z35gy kkgn5]\n" +
			"",
	},
	{
		Query: `
DELETE FROM HGMQ6
WHERE id IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ HGMQ6.id:0!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(HGMQ6)\n" +
			"             ├─ index: [HGMQ6.id]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM HDDVB
WHERE id IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ HDDVB.id:0!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(HDDVB)\n" +
			"             ├─ index: [HDDVB.id]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM FLQLP
WHERE LUEVY IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ FLQLP.LUEVY:2!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(FLQLP)\n" +
			"             ├─ index: [FLQLP.LUEVY]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM FLQLP
WHERE id IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ FLQLP.id:0!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(FLQLP)\n" +
			"             ├─ index: [FLQLP.id]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"",
	},
	{
		Query: `
DELETE FROM FLQLP
WHERE id IN ('1', '2', '3')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Delete\n" +
			"     └─ Filter\n" +
			"         ├─ HashIn\n" +
			"         │   ├─ FLQLP.id:0!null\n" +
			"         │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"         └─ IndexedTableAccess(FLQLP)\n" +
			"             ├─ index: [FLQLP.id]\n" +
			"             ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"",
	},
	{
		Query: `
-- updates
UPDATE E2I7U nd
SET nd.KNG7T = (SELECT gn.id FROM WE72E gn INNER JOIN TDRVG ltnm ON ltnm.SSHPJ = gn.SSHPJ WHERE ltnm.FGG57 = nd.FGG57)
WHERE nd.FGG57 IS NOT NULL AND nd.KNG7T IS NULL`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Update\n" +
			"     └─ UpdateSource(SET nd.KNG7T:2 = Subquery\n" +
			"         ├─ cacheable: false\n" +
			"         └─ Project\n" +
			"             ├─ columns: [gn.id:17!null]\n" +
			"             └─ Filter\n" +
			"                 ├─ Eq\n" +
			"                 │   ├─ ltnm.FGG57:19!null\n" +
			"                 │   └─ nd.FGG57:6\n" +
			"                 └─ LookupJoin\n" +
			"                     ├─ Eq\n" +
			"                     │   ├─ ltnm.SSHPJ:20!null\n" +
			"                     │   └─ gn.SSHPJ:18!null\n" +
			"                     ├─ TableAlias(gn)\n" +
			"                     │   └─ Table\n" +
			"                     │       ├─ name: WE72E\n" +
			"                     │       └─ columns: [id sshpj]\n" +
			"                     └─ TableAlias(ltnm)\n" +
			"                         └─ IndexedTableAccess(TDRVG)\n" +
			"                             ├─ index: [TDRVG.SSHPJ]\n" +
			"                             └─ columns: [fgg57 sshpj]\n" +
			"        )\n" +
			"         └─ Filter\n" +
			"             ├─ AND\n" +
			"             │   ├─ NOT\n" +
			"             │   │   └─ nd.FGG57:6 IS NULL\n" +
			"             │   └─ nd.KNG7T:2 IS NULL\n" +
			"             └─ TableAlias(nd)\n" +
			"                 └─ IndexedTableAccess(E2I7U)\n" +
			"                     ├─ index: [E2I7U.FGG57]\n" +
			"                     ├─ static: [{(NULL, ∞)}]\n" +
			"                     └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"",
	},
	{
		Query: `

UPDATE S3FQX SET ADWYM = 0, FPUYA = 0`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Update\n" +
			"         └─ Trigger(CREATE TRIGGER S3FQX_on_update BEFORE UPDATE ON S3FQX\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF NEW.ADWYM NOT IN (0, 1)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ADWYM field is an int boolean (0/1).';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ADWYM field is an int boolean (0/1).';\n" +
			"              END IF;\n" +
			"              IF NEW.FPUYA NOT IN (0, 1)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The FPUYA field is an int boolean (0/1).';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The FPUYA field is an int boolean (0/1).';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ UpdateSource(SET S3FQX.ADWYM:1!null = 0 (tinyint),SET S3FQX.FPUYA:2!null = 0 (tinyint))\n" +
			"             │   └─ Table\n" +
			"             │       ├─ name: S3FQX\n" +
			"             │       └─ columns: [id adwym fpuya]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(NOT\n" +
			"                 │       └─ IN\n" +
			"                 │           ├─ left: new.ADWYM:4!null\n" +
			"                 │           └─ right: TUPLE(0 (tinyint), 1 (tinyint))\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ADWYM field is an int boolean (0/1)., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.FPUYA:5!null\n" +
			"                             └─ right: TUPLE(0 (tinyint), 1 (tinyint))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The FPUYA field is an int boolean (0/1)., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
-- inserts
INSERT INTO THNTS
    (id, NFRYN, IXUXU, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT id FROM JMRQL WHERE DZLIM = 'T4IBQ') AS NFRYN,
    id AS IXUXU,
    NULL AS FHCYT
FROM
    YK2GW
WHERE
    id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, NFRYN, IXUXU, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: THNTS\n" +
			"         │       └─ columns: [id nfryn ixuxu fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER THNTS_on_insert BEFORE INSERT ON THNTS\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.IXUXU IS NULL\n" +
			"              THEN\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The IXUXU field is mandatory.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, NFRYN:1!null, IXUXU:2, FHCYT:3]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: true\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [JMRQL.id:30!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ JMRQL.DZLIM:31!null\n" +
			"             │       │           │   └─ T4IBQ (longtext)\n" +
			"             │       │           └─ IndexedTableAccess(JMRQL)\n" +
			"             │       │               ├─ index: [JMRQL.DZLIM]\n" +
			"             │       │               ├─ static: [{[T4IBQ, T4IBQ]}]\n" +
			"             │       │               └─ columns: [id dzlim]\n" +
			"             │       │   as NFRYN, YK2GW.id:0!null as IXUXU, NULL (null) as FHCYT]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ YK2GW.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ IndexedTableAccess(YK2GW)\n" +
			"             │               ├─ index: [YK2GW.id]\n" +
			"             │               ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │               └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(new.IXUXU:2 IS NULL)\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The IXUXU field is mandatory., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO QYWQD
    (id, WNUNU, HHVLX, HVHRZ, YKSSU, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    ITWML.DRIWM AS WNUNU,
    ITWML.JIEVY AS HHVLX,
    1.0 AS HVHRZ,
    NULL AS YKSSU,
    NULL AS FHCYT
FROM
    (
    SELECT
        sn.id AS DRIWM,
        SKPM6.id AS JIEVY,
        sn.ECDKM AS HVHRZ
    FROM
        NOXN3 sn -- Potential upstream VUMUY
    INNER JOIN
        NOXN3 SKPM6 -- We can find a potential downstream edge
    ON
        SKPM6.BRQP2 = sn.FFTBJ
    LEFT JOIN
        QYWQD rn -- Join existing regnet records and keep where no corresponding is found
    ON
            rn.WNUNU = sn.id
        AND
            rn.HHVLX = SKPM6.id
    WHERE
            sn.NUMK2 = 1 -- Potential upstream edge is activity TAFAX
        AND
            rn.WNUNU IS NULL AND rn.HHVLX IS NULL -- Keep only where no corresponding is found
    ) ITWML`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, WNUNU, HHVLX, HVHRZ, YKSSU, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: QYWQD\n" +
			"         │       └─ columns: [id wnunu hhvlx hvhrz ykssu fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER QYWQD_on_insert BEFORE INSERT ON QYWQD\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                (SELECT FFTBJ FROM NOXN3 WHERE id = NEW.WNUNU) <> (SELECT BRQP2 FROM NOXN3 WHERE id = NEW.HHVLX)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The target UWBAI of the upstream edge must be the same as the source UWBAI of the downstream edge (the enzyme UWBAI).';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The target UWBAI of the upstream edge must be the same as the source UWBAI of the downstream edge (the enzyme UWBAI).';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, WNUNU:1!null, HHVLX:2!null, HVHRZ:3!null, YKSSU:4, FHCYT:5]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, ITWML.DRIWM:0!null as WNUNU, ITWML.JIEVY:1!null as HHVLX, 1 (decimal(2,1)) as HVHRZ, NULL (null) as YKSSU, NULL (null) as FHCYT]\n" +
			"             │       └─ SubqueryAlias\n" +
			"             │           ├─ name: ITWML\n" +
			"             │           ├─ outerVisibility: false\n" +
			"             │           ├─ cacheable: true\n" +
			"             │           └─ Project\n" +
			"             │               ├─ columns: [sn.id:2!null as DRIWM, SKPM6.id:0!null as JIEVY, sn.ECDKM:4 as HVHRZ]\n" +
			"             │               └─ Filter\n" +
			"             │                   ├─ AND\n" +
			"             │                   │   ├─ rn.WNUNU:6 IS NULL\n" +
			"             │                   │   └─ rn.HHVLX:7 IS NULL\n" +
			"             │                   └─ LeftOuterHashJoin\n" +
			"             │                       ├─ AND\n" +
			"             │                       │   ├─ Eq\n" +
			"             │                       │   │   ├─ rn.WNUNU:6!null\n" +
			"             │                       │   │   └─ sn.id:2!null\n" +
			"             │                       │   └─ Eq\n" +
			"             │                       │       ├─ rn.HHVLX:7!null\n" +
			"             │                       │       └─ SKPM6.id:0!null\n" +
			"             │                       ├─ MergeJoin\n" +
			"             │                       │   ├─ cmp: Eq\n" +
			"             │                       │   │   ├─ SKPM6.BRQP2:1!null\n" +
			"             │                       │   │   └─ sn.FFTBJ:3!null\n" +
			"             │                       │   ├─ TableAlias(SKPM6)\n" +
			"             │                       │   │   └─ IndexedTableAccess(NOXN3)\n" +
			"             │                       │   │       ├─ index: [NOXN3.BRQP2]\n" +
			"             │                       │   │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │                       │   │       └─ columns: [id brqp2]\n" +
			"             │                       │   └─ Filter\n" +
			"             │                       │       ├─ Eq\n" +
			"             │                       │       │   ├─ sn.NUMK2:3!null\n" +
			"             │                       │       │   └─ 1 (tinyint)\n" +
			"             │                       │       └─ TableAlias(sn)\n" +
			"             │                       │           └─ IndexedTableAccess(NOXN3)\n" +
			"             │                       │               ├─ index: [NOXN3.FFTBJ]\n" +
			"             │                       │               ├─ static: [{[NULL, ∞)}]\n" +
			"             │                       │               └─ columns: [id fftbj ecdkm numk2]\n" +
			"             │                       └─ HashLookup\n" +
			"             │                           ├─ source: TUPLE(sn.id:2!null, SKPM6.id:0!null)\n" +
			"             │                           ├─ target: TUPLE(rn.WNUNU:0!null, rn.HHVLX:1!null)\n" +
			"             │                           └─ CachedResults\n" +
			"             │                               └─ TableAlias(rn)\n" +
			"             │                                   └─ Table\n" +
			"             │                                       ├─ name: QYWQD\n" +
			"             │                                       └─ columns: [wnunu hhvlx]\n" +
			"             └─ BEGIN .. END\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ Eq\n" +
			"                             ├─ Subquery\n" +
			"                             │   ├─ cacheable: false\n" +
			"                             │   └─ Project\n" +
			"                             │       ├─ columns: [NOXN3.FFTBJ:7!null]\n" +
			"                             │       └─ Filter\n" +
			"                             │           ├─ Eq\n" +
			"                             │           │   ├─ NOXN3.id:6!null\n" +
			"                             │           │   └─ new.WNUNU:1!null\n" +
			"                             │           └─ Table\n" +
			"                             │               ├─ name: NOXN3\n" +
			"                             │               └─ columns: [id fftbj]\n" +
			"                             └─ Subquery\n" +
			"                                 ├─ cacheable: false\n" +
			"                                 └─ Project\n" +
			"                                     ├─ columns: [NOXN3.BRQP2:7!null]\n" +
			"                                     └─ Filter\n" +
			"                                         ├─ Eq\n" +
			"                                         │   ├─ NOXN3.id:6!null\n" +
			"                                         │   └─ new.HHVLX:2!null\n" +
			"                                         └─ Table\n" +
			"                                             ├─ name: NOXN3\n" +
			"                                             └─ columns: [id brqp2]\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The target UWBAI of the upstream edge must be the same as the source UWBAI of the downstream edge (the enzyme UWBAI)., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO WE72E
    (id, QZ7E7, SSHPJ, FHCYT)
SELECT
    id,
    SFJ6L,
    SSHPJ,
    NULL AS FHCYT
FROM
    TDRVG
WHERE
    id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, QZ7E7, SSHPJ, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: WE72E\n" +
			"         │       └─ columns: [id qz7e7 sshpj fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER WE72E_on_insert BEFORE INSERT ON WE72E\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.QZ7E7 IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR\n" +
			"                NEW.SSHPJ IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, QZ7E7:1!null, SSHPJ:2!null, FHCYT:3]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [TDRVG.id:0!null, TDRVG.SFJ6L:2!null, TDRVG.SSHPJ:1!null, NULL (null) as FHCYT]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ TDRVG.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ IndexedTableAccess(TDRVG)\n" +
			"             │               ├─ index: [TDRVG.id]\n" +
			"             │               ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │               └─ columns: [id sshpj sfj6l]\n" +
			"             └─ BEGIN .. END\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(Or\n" +
			"                         ├─ InSubquery\n" +
			"                         │   ├─ left: new.QZ7E7:1!null\n" +
			"                         │   └─ right: Subquery\n" +
			"                         │       ├─ cacheable: false\n" +
			"                         │       └─ Table\n" +
			"                         │           ├─ name: TPXHZ\n" +
			"                         │           └─ columns: [svaz4]\n" +
			"                         └─ InSubquery\n" +
			"                             ├─ left: new.SSHPJ:2!null\n" +
			"                             └─ right: Subquery\n" +
			"                                 ├─ cacheable: false\n" +
			"                                 └─ Table\n" +
			"                                     ├─ name: TPXHZ\n" +
			"                                     └─ columns: [svaz4]\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO AMYXQ
    (id, GXLUB, LUEVY, XQDYT, AMYXQ, OZTQF, Z35GY, KKGN5)
SELECT /*+ JOIN_ORDER(ufc, nd, YBBG5) */
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT /*+ JOIN_ORDER(cla, bs) */ bs.id FROM THNTS bs INNER JOIN YK2GW cla ON cla.id = bs.IXUXU WHERE cla.FTQLQ = ufc.T4IBQ) AS GXLUB,
    nd.id AS LUEVY,
    nd.XQDYT AS XQDYT,
    ufc.AMYXQ + 0.0 AS AMYXQ,
    CASE
        WHEN
            YBBG5.DZLIM = 'KTNZ2'
        THEN ufc.KTNZ2 + 0.0
        WHEN
            YBBG5.DZLIM = 'HIID2'
        THEN ufc.HIID2 + 0.0
        WHEN
            YBBG5.DZLIM = 'SH7TP'
        THEN ufc.SH7TP + 0.0
        WHEN
            YBBG5.DZLIM = 'VVKNB'
        THEN ufc.VVKNB + 0.0
        WHEN
            YBBG5.DZLIM = 'DN3OQ'
        THEN ufc.DN3OQ + 0.0
        ELSE NULL
    END AS OZTQF,
    ufc.SRZZO + 0.0 AS Z35GY,
    ufc.id AS KKGN5
FROM
    SISUT ufc
INNER JOIN
    E2I7U nd
ON
    nd.ZH72S = ufc.ZH72S
INNER JOIN
    XGSJM YBBG5
ON
    YBBG5.id = nd.XQDYT
WHERE
    ufc.id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, GXLUB, LUEVY, XQDYT, AMYXQ, OZTQF, Z35GY, KKGN5)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: AMYXQ\n" +
			"         │       └─ columns: [id gxlub luevy xqdyt amyxq oztqf z35gy kkgn5]\n" +
			"         └─ Trigger(CREATE TRIGGER AMYXQ_on_insert BEFORE INSERT ON AMYXQ\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                (SELECT FGG57 FROM E2I7U WHERE id = NEW.LUEVY) IS NULL\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The given UWBAI can not be connected to a AMYXQ record as it does not have IYDZV.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The given UWBAI can not be connected to a AMYXQ record as it does not have IYDZV.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.AMYXQ < 0 OR NEW.OZTQF < 0 OR NEW.Z35GY < 0\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'All values in AMYXQ must ne non-negative.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'All values in AMYXQ must ne non-negative.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, GXLUB:1!null, LUEVY:2!null, XQDYT:3!null, AMYXQ:4!null, OZTQF:5!null, Z35GY:6!null, KKGN5:7]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [bs.id:33!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ cla.FTQLQ:32!null\n" +
			"             │       │           │   └─ ufc.T4IBQ:1\n" +
			"             │       │           └─ MergeJoin\n" +
			"             │       │               ├─ cmp: Eq\n" +
			"             │       │               │   ├─ cla.id:31!null\n" +
			"             │       │               │   └─ bs.IXUXU:34\n" +
			"             │       │               ├─ TableAlias(cla)\n" +
			"             │       │               │   └─ IndexedTableAccess(YK2GW)\n" +
			"             │       │               │       ├─ index: [YK2GW.id]\n" +
			"             │       │               │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │               │       └─ columns: [id ftqlq]\n" +
			"             │       │               └─ TableAlias(bs)\n" +
			"             │       │                   └─ IndexedTableAccess(THNTS)\n" +
			"             │       │                       ├─ index: [THNTS.IXUXU]\n" +
			"             │       │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │                       └─ columns: [id ixuxu]\n" +
			"             │       │   as GXLUB, nd.id:11!null as LUEVY, nd.XQDYT:20!null as XQDYT, (ufc.AMYXQ:3 + 0 (decimal(2,1))) as AMYXQ, CASE  WHEN Eq\n" +
			"             │       │   ├─ YBBG5.DZLIM:29!null\n" +
			"             │       │   └─ KTNZ2 (longtext)\n" +
			"             │       │   THEN (ufc.KTNZ2:4 + 0 (decimal(2,1))) WHEN Eq\n" +
			"             │       │   ├─ YBBG5.DZLIM:29!null\n" +
			"             │       │   └─ HIID2 (longtext)\n" +
			"             │       │   THEN (ufc.HIID2:5 + 0 (decimal(2,1))) WHEN Eq\n" +
			"             │       │   ├─ YBBG5.DZLIM:29!null\n" +
			"             │       │   └─ SH7TP (longtext)\n" +
			"             │       │   THEN (ufc.SH7TP:8 + 0 (decimal(2,1))) WHEN Eq\n" +
			"             │       │   ├─ YBBG5.DZLIM:29!null\n" +
			"             │       │   └─ VVKNB (longtext)\n" +
			"             │       │   THEN (ufc.VVKNB:7 + 0 (decimal(2,1))) WHEN Eq\n" +
			"             │       │   ├─ YBBG5.DZLIM:29!null\n" +
			"             │       │   └─ DN3OQ (longtext)\n" +
			"             │       │   THEN (ufc.DN3OQ:6 + 0 (decimal(2,1))) ELSE NULL (null) END as OZTQF, (ufc.SRZZO:9 + 0 (decimal(2,1))) as Z35GY, ufc.id:0!null as KKGN5]\n" +
			"             │       └─ HashJoin\n" +
			"             │           ├─ Eq\n" +
			"             │           │   ├─ nd.ZH72S:18\n" +
			"             │           │   └─ ufc.ZH72S:2\n" +
			"             │           ├─ Filter\n" +
			"             │           │   ├─ HashIn\n" +
			"             │           │   │   ├─ ufc.id:0!null\n" +
			"             │           │   │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           │   └─ TableAlias(ufc)\n" +
			"             │           │       └─ IndexedTableAccess(SISUT)\n" +
			"             │           │           ├─ index: [SISUT.id]\n" +
			"             │           │           ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │           │           └─ columns: [id t4ibq zh72s amyxq ktnz2 hiid2 dn3oq vvknb sh7tp srzzo qz6vt]\n" +
			"             │           └─ HashLookup\n" +
			"             │               ├─ source: TUPLE(ufc.ZH72S:2)\n" +
			"             │               ├─ target: TUPLE(nd.ZH72S:7)\n" +
			"             │               └─ CachedResults\n" +
			"             │                   └─ MergeJoin\n" +
			"             │                       ├─ cmp: Eq\n" +
			"             │                       │   ├─ nd.XQDYT:20!null\n" +
			"             │                       │   └─ YBBG5.id:28!null\n" +
			"             │                       ├─ TableAlias(nd)\n" +
			"             │                       │   └─ IndexedTableAccess(E2I7U)\n" +
			"             │                       │       ├─ index: [E2I7U.XQDYT]\n" +
			"             │                       │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │                       │       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"             │                       └─ TableAlias(YBBG5)\n" +
			"             │                           └─ IndexedTableAccess(XGSJM)\n" +
			"             │                               ├─ index: [XGSJM.id]\n" +
			"             │                               ├─ static: [{[NULL, ∞)}]\n" +
			"             │                               └─ columns: [id dzlim f3yue]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(Subquery\n" +
			"                 │       ├─ cacheable: false\n" +
			"                 │       └─ Project\n" +
			"                 │           ├─ columns: [E2I7U.FGG57:9]\n" +
			"                 │           └─ Filter\n" +
			"                 │               ├─ Eq\n" +
			"                 │               │   ├─ E2I7U.id:8!null\n" +
			"                 │               │   └─ new.LUEVY:2!null\n" +
			"                 │               └─ Table\n" +
			"                 │                   ├─ name: E2I7U\n" +
			"                 │                   └─ columns: [id fgg57]\n" +
			"                 │       IS NULL)\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The given UWBAI can not be connected to a AMYXQ record as it does not have IYDZV., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(Or\n" +
			"                         ├─ Or\n" +
			"                         │   ├─ LessThan\n" +
			"                         │   │   ├─ new.AMYXQ:4!null\n" +
			"                         │   │   └─ 0 (tinyint)\n" +
			"                         │   └─ LessThan\n" +
			"                         │       ├─ new.OZTQF:5!null\n" +
			"                         │       └─ 0 (tinyint)\n" +
			"                         └─ LessThan\n" +
			"                             ├─ new.Z35GY:6!null\n" +
			"                             └─ 0 (tinyint)\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = All values in AMYXQ must ne non-negative., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO SZQWJ
    (id, GXLUB, CH3FR, D237E, JOGI6)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT bs.id FROM THNTS bs INNER JOIN YK2GW cla ON cla.id = bs.IXUXU WHERE cla.FTQLQ = ums.T4IBQ) AS GXLUB,
    (SELECT id FROM XOAOP WHERE DZLIM = 'NER') AS CH3FR,
    CASE -- This ugly thing is because of Dolt's problematic conversion handling at insertions
        WHEN ums.ner > 0.5 THEN 1
        WHEN ums.ner < 0.5 THEN 0
        ELSE NULL
    END AS D237E,
    ums.id AS JOGI6
FROM
    FG26Y ums
WHERE
    ums.id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, GXLUB, CH3FR, D237E, JOGI6)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: SZQWJ\n" +
			"         │       └─ columns: [id gxlub ch3fr d237e jogi6]\n" +
			"         └─ Trigger(CREATE TRIGGER SZQWJ_on_insert BEFORE INSERT ON SZQWJ\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                (SELECT DZLIM FROM XOAOP WHERE id = NEW.CH3FR) NOT IN ('NER', 'BER', 'HR', 'MMR')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.D237E NOT IN (0, 1)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The D237E field must be either 0 or 1.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The D237E field must be either 0 or 1.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, GXLUB:1!null, CH3FR:2!null, D237E:3!null, JOGI6:4]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [bs.id:9!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ cla.FTQLQ:8!null\n" +
			"             │       │           │   └─ ums.T4IBQ:1\n" +
			"             │       │           └─ MergeJoin\n" +
			"             │       │               ├─ cmp: Eq\n" +
			"             │       │               │   ├─ cla.id:7!null\n" +
			"             │       │               │   └─ bs.IXUXU:10\n" +
			"             │       │               ├─ TableAlias(cla)\n" +
			"             │       │               │   └─ IndexedTableAccess(YK2GW)\n" +
			"             │       │               │       ├─ index: [YK2GW.id]\n" +
			"             │       │               │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │               │       └─ columns: [id ftqlq]\n" +
			"             │       │               └─ TableAlias(bs)\n" +
			"             │       │                   └─ IndexedTableAccess(THNTS)\n" +
			"             │       │                       ├─ index: [THNTS.IXUXU]\n" +
			"             │       │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │                       └─ columns: [id ixuxu]\n" +
			"             │       │   as GXLUB, Subquery\n" +
			"             │       │   ├─ cacheable: true\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [XOAOP.id:7!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ XOAOP.DZLIM:8!null\n" +
			"             │       │           │   └─ NER (longtext)\n" +
			"             │       │           └─ IndexedTableAccess(XOAOP)\n" +
			"             │       │               ├─ index: [XOAOP.DZLIM]\n" +
			"             │       │               ├─ static: [{[NER, NER]}]\n" +
			"             │       │               └─ columns: [id dzlim]\n" +
			"             │       │   as CH3FR, CASE  WHEN GreaterThan\n" +
			"             │       │   ├─ ums.ner:2\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 1 (tinyint) WHEN LessThan\n" +
			"             │       │   ├─ ums.ner:2\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 0 (tinyint) ELSE NULL (null) END as D237E, ums.id:0!null as JOGI6]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ ums.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ TableAlias(ums)\n" +
			"             │               └─ IndexedTableAccess(FG26Y)\n" +
			"             │                   ├─ index: [FG26Y.id]\n" +
			"             │                   ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │                   └─ columns: [id t4ibq ner ber hr mmr qz6vt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(NOT\n" +
			"                 │       └─ IN\n" +
			"                 │           ├─ left: Subquery\n" +
			"                 │           │   ├─ cacheable: false\n" +
			"                 │           │   └─ Project\n" +
			"                 │           │       ├─ columns: [XOAOP.DZLIM:6!null]\n" +
			"                 │           │       └─ Filter\n" +
			"                 │           │           ├─ Eq\n" +
			"                 │           │           │   ├─ XOAOP.id:5!null\n" +
			"                 │           │           │   └─ new.CH3FR:2!null\n" +
			"                 │           │           └─ Table\n" +
			"                 │           │               ├─ name: XOAOP\n" +
			"                 │           │               └─ columns: [id dzlim]\n" +
			"                 │           └─ right: TUPLE(NER (longtext), BER (longtext), HR (longtext), MMR (longtext))\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ECUWU must be one of the following: 'NER', 'BER', 'HR', 'MMR'., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.D237E:3!null\n" +
			"                             └─ right: TUPLE(0 (tinyint), 1 (tinyint))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The D237E field must be either 0 or 1., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO SZQWJ
    (id, GXLUB, CH3FR, D237E, JOGI6)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT bs.id FROM THNTS bs INNER JOIN YK2GW cla ON cla.id = bs.IXUXU WHERE cla.FTQLQ = ums.T4IBQ) AS GXLUB,
    (SELECT id FROM XOAOP WHERE DZLIM = 'BER') AS CH3FR,
    CASE -- This ugly thing is because of Dolt's problematic conversion handling at insertions
        WHEN ums.ber > 0.5 THEN 1
        WHEN ums.ber < 0.5 THEN 0
        ELSE NULL
    END AS D237E,
    ums.id AS JOGI6
FROM
    FG26Y ums
WHERE
    ums.id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, GXLUB, CH3FR, D237E, JOGI6)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: SZQWJ\n" +
			"         │       └─ columns: [id gxlub ch3fr d237e jogi6]\n" +
			"         └─ Trigger(CREATE TRIGGER SZQWJ_on_insert BEFORE INSERT ON SZQWJ\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                (SELECT DZLIM FROM XOAOP WHERE id = NEW.CH3FR) NOT IN ('NER', 'BER', 'HR', 'MMR')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.D237E NOT IN (0, 1)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The D237E field must be either 0 or 1.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The D237E field must be either 0 or 1.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, GXLUB:1!null, CH3FR:2!null, D237E:3!null, JOGI6:4]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [bs.id:9!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ cla.FTQLQ:8!null\n" +
			"             │       │           │   └─ ums.T4IBQ:1\n" +
			"             │       │           └─ MergeJoin\n" +
			"             │       │               ├─ cmp: Eq\n" +
			"             │       │               │   ├─ cla.id:7!null\n" +
			"             │       │               │   └─ bs.IXUXU:10\n" +
			"             │       │               ├─ TableAlias(cla)\n" +
			"             │       │               │   └─ IndexedTableAccess(YK2GW)\n" +
			"             │       │               │       ├─ index: [YK2GW.id]\n" +
			"             │       │               │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │               │       └─ columns: [id ftqlq]\n" +
			"             │       │               └─ TableAlias(bs)\n" +
			"             │       │                   └─ IndexedTableAccess(THNTS)\n" +
			"             │       │                       ├─ index: [THNTS.IXUXU]\n" +
			"             │       │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │                       └─ columns: [id ixuxu]\n" +
			"             │       │   as GXLUB, Subquery\n" +
			"             │       │   ├─ cacheable: true\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [XOAOP.id:7!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ XOAOP.DZLIM:8!null\n" +
			"             │       │           │   └─ BER (longtext)\n" +
			"             │       │           └─ IndexedTableAccess(XOAOP)\n" +
			"             │       │               ├─ index: [XOAOP.DZLIM]\n" +
			"             │       │               ├─ static: [{[BER, BER]}]\n" +
			"             │       │               └─ columns: [id dzlim]\n" +
			"             │       │   as CH3FR, CASE  WHEN GreaterThan\n" +
			"             │       │   ├─ ums.ber:3\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 1 (tinyint) WHEN LessThan\n" +
			"             │       │   ├─ ums.ber:3\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 0 (tinyint) ELSE NULL (null) END as D237E, ums.id:0!null as JOGI6]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ ums.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ TableAlias(ums)\n" +
			"             │               └─ IndexedTableAccess(FG26Y)\n" +
			"             │                   ├─ index: [FG26Y.id]\n" +
			"             │                   ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │                   └─ columns: [id t4ibq ner ber hr mmr qz6vt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(NOT\n" +
			"                 │       └─ IN\n" +
			"                 │           ├─ left: Subquery\n" +
			"                 │           │   ├─ cacheable: false\n" +
			"                 │           │   └─ Project\n" +
			"                 │           │       ├─ columns: [XOAOP.DZLIM:6!null]\n" +
			"                 │           │       └─ Filter\n" +
			"                 │           │           ├─ Eq\n" +
			"                 │           │           │   ├─ XOAOP.id:5!null\n" +
			"                 │           │           │   └─ new.CH3FR:2!null\n" +
			"                 │           │           └─ Table\n" +
			"                 │           │               ├─ name: XOAOP\n" +
			"                 │           │               └─ columns: [id dzlim]\n" +
			"                 │           └─ right: TUPLE(NER (longtext), BER (longtext), HR (longtext), MMR (longtext))\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ECUWU must be one of the following: 'NER', 'BER', 'HR', 'MMR'., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.D237E:3!null\n" +
			"                             └─ right: TUPLE(0 (tinyint), 1 (tinyint))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The D237E field must be either 0 or 1., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO SZQWJ
    (id, GXLUB, CH3FR, D237E, JOGI6)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT bs.id FROM THNTS bs INNER JOIN YK2GW cla ON cla.id = bs.IXUXU WHERE cla.FTQLQ = ums.T4IBQ) AS GXLUB,
    (SELECT id FROM XOAOP WHERE DZLIM = 'HR') AS CH3FR,
    CASE -- This ugly thing is because of Dolt's problematic conversion handling at insertions
        WHEN ums.hr > 0.5 THEN 1
        WHEN ums.hr < 0.5 THEN 0
        ELSE NULL
    END AS D237E,
    ums.id AS JOGI6
FROM
    FG26Y ums
WHERE
    ums.id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, GXLUB, CH3FR, D237E, JOGI6)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: SZQWJ\n" +
			"         │       └─ columns: [id gxlub ch3fr d237e jogi6]\n" +
			"         └─ Trigger(CREATE TRIGGER SZQWJ_on_insert BEFORE INSERT ON SZQWJ\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                (SELECT DZLIM FROM XOAOP WHERE id = NEW.CH3FR) NOT IN ('NER', 'BER', 'HR', 'MMR')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.D237E NOT IN (0, 1)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The D237E field must be either 0 or 1.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The D237E field must be either 0 or 1.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, GXLUB:1!null, CH3FR:2!null, D237E:3!null, JOGI6:4]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [bs.id:9!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ cla.FTQLQ:8!null\n" +
			"             │       │           │   └─ ums.T4IBQ:1\n" +
			"             │       │           └─ MergeJoin\n" +
			"             │       │               ├─ cmp: Eq\n" +
			"             │       │               │   ├─ cla.id:7!null\n" +
			"             │       │               │   └─ bs.IXUXU:10\n" +
			"             │       │               ├─ TableAlias(cla)\n" +
			"             │       │               │   └─ IndexedTableAccess(YK2GW)\n" +
			"             │       │               │       ├─ index: [YK2GW.id]\n" +
			"             │       │               │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │               │       └─ columns: [id ftqlq]\n" +
			"             │       │               └─ TableAlias(bs)\n" +
			"             │       │                   └─ IndexedTableAccess(THNTS)\n" +
			"             │       │                       ├─ index: [THNTS.IXUXU]\n" +
			"             │       │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │                       └─ columns: [id ixuxu]\n" +
			"             │       │   as GXLUB, Subquery\n" +
			"             │       │   ├─ cacheable: true\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [XOAOP.id:7!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ XOAOP.DZLIM:8!null\n" +
			"             │       │           │   └─ HR (longtext)\n" +
			"             │       │           └─ IndexedTableAccess(XOAOP)\n" +
			"             │       │               ├─ index: [XOAOP.DZLIM]\n" +
			"             │       │               ├─ static: [{[HR, HR]}]\n" +
			"             │       │               └─ columns: [id dzlim]\n" +
			"             │       │   as CH3FR, CASE  WHEN GreaterThan\n" +
			"             │       │   ├─ ums.hr:4\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 1 (tinyint) WHEN LessThan\n" +
			"             │       │   ├─ ums.hr:4\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 0 (tinyint) ELSE NULL (null) END as D237E, ums.id:0!null as JOGI6]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ ums.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ TableAlias(ums)\n" +
			"             │               └─ IndexedTableAccess(FG26Y)\n" +
			"             │                   ├─ index: [FG26Y.id]\n" +
			"             │                   ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │                   └─ columns: [id t4ibq ner ber hr mmr qz6vt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(NOT\n" +
			"                 │       └─ IN\n" +
			"                 │           ├─ left: Subquery\n" +
			"                 │           │   ├─ cacheable: false\n" +
			"                 │           │   └─ Project\n" +
			"                 │           │       ├─ columns: [XOAOP.DZLIM:6!null]\n" +
			"                 │           │       └─ Filter\n" +
			"                 │           │           ├─ Eq\n" +
			"                 │           │           │   ├─ XOAOP.id:5!null\n" +
			"                 │           │           │   └─ new.CH3FR:2!null\n" +
			"                 │           │           └─ Table\n" +
			"                 │           │               ├─ name: XOAOP\n" +
			"                 │           │               └─ columns: [id dzlim]\n" +
			"                 │           └─ right: TUPLE(NER (longtext), BER (longtext), HR (longtext), MMR (longtext))\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ECUWU must be one of the following: 'NER', 'BER', 'HR', 'MMR'., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.D237E:3!null\n" +
			"                             └─ right: TUPLE(0 (tinyint), 1 (tinyint))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The D237E field must be either 0 or 1., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO SZQWJ
    (id, GXLUB, CH3FR, D237E, JOGI6)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT bs.id FROM THNTS bs INNER JOIN YK2GW cla ON cla.id = bs.IXUXU WHERE cla.FTQLQ = ums.T4IBQ) AS GXLUB,
    (SELECT id FROM XOAOP WHERE DZLIM = 'MMR') AS CH3FR,
    CASE -- This ugly thing is because of Dolt's problematic conversion handling at insertions
        WHEN ums.mmr > 0.5 THEN 1
        WHEN ums.mmr < 0.5 THEN 0
        ELSE NULL
    END AS D237E,
    ums.id AS JOGI6
FROM
    FG26Y ums
WHERE
    ums.id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, GXLUB, CH3FR, D237E, JOGI6)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: SZQWJ\n" +
			"         │       └─ columns: [id gxlub ch3fr d237e jogi6]\n" +
			"         └─ Trigger(CREATE TRIGGER SZQWJ_on_insert BEFORE INSERT ON SZQWJ\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                (SELECT DZLIM FROM XOAOP WHERE id = NEW.CH3FR) NOT IN ('NER', 'BER', 'HR', 'MMR')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ECUWU must be one of the following: ''NER'', ''BER'', ''HR'', ''MMR''.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.D237E NOT IN (0, 1)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The D237E field must be either 0 or 1.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The D237E field must be either 0 or 1.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, GXLUB:1!null, CH3FR:2!null, D237E:3!null, JOGI6:4]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [bs.id:9!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ cla.FTQLQ:8!null\n" +
			"             │       │           │   └─ ums.T4IBQ:1\n" +
			"             │       │           └─ MergeJoin\n" +
			"             │       │               ├─ cmp: Eq\n" +
			"             │       │               │   ├─ cla.id:7!null\n" +
			"             │       │               │   └─ bs.IXUXU:10\n" +
			"             │       │               ├─ TableAlias(cla)\n" +
			"             │       │               │   └─ IndexedTableAccess(YK2GW)\n" +
			"             │       │               │       ├─ index: [YK2GW.id]\n" +
			"             │       │               │       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │               │       └─ columns: [id ftqlq]\n" +
			"             │       │               └─ TableAlias(bs)\n" +
			"             │       │                   └─ IndexedTableAccess(THNTS)\n" +
			"             │       │                       ├─ index: [THNTS.IXUXU]\n" +
			"             │       │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │       │                       └─ columns: [id ixuxu]\n" +
			"             │       │   as GXLUB, Subquery\n" +
			"             │       │   ├─ cacheable: true\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [XOAOP.id:7!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ XOAOP.DZLIM:8!null\n" +
			"             │       │           │   └─ MMR (longtext)\n" +
			"             │       │           └─ IndexedTableAccess(XOAOP)\n" +
			"             │       │               ├─ index: [XOAOP.DZLIM]\n" +
			"             │       │               ├─ static: [{[MMR, MMR]}]\n" +
			"             │       │               └─ columns: [id dzlim]\n" +
			"             │       │   as CH3FR, CASE  WHEN GreaterThan\n" +
			"             │       │   ├─ ums.mmr:5\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 1 (tinyint) WHEN LessThan\n" +
			"             │       │   ├─ ums.mmr:5\n" +
			"             │       │   └─ 0.500000 (double)\n" +
			"             │       │   THEN 0 (tinyint) ELSE NULL (null) END as D237E, ums.id:0!null as JOGI6]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ ums.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ TableAlias(ums)\n" +
			"             │               └─ IndexedTableAccess(FG26Y)\n" +
			"             │                   ├─ index: [FG26Y.id]\n" +
			"             │                   ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │                   └─ columns: [id t4ibq ner ber hr mmr qz6vt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(NOT\n" +
			"                 │       └─ IN\n" +
			"                 │           ├─ left: Subquery\n" +
			"                 │           │   ├─ cacheable: false\n" +
			"                 │           │   └─ Project\n" +
			"                 │           │       ├─ columns: [XOAOP.DZLIM:6!null]\n" +
			"                 │           │       └─ Filter\n" +
			"                 │           │           ├─ Eq\n" +
			"                 │           │           │   ├─ XOAOP.id:5!null\n" +
			"                 │           │           │   └─ new.CH3FR:2!null\n" +
			"                 │           │           └─ Table\n" +
			"                 │           │               ├─ name: XOAOP\n" +
			"                 │           │               └─ columns: [id dzlim]\n" +
			"                 │           └─ right: TUPLE(NER (longtext), BER (longtext), HR (longtext), MMR (longtext))\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ECUWU must be one of the following: 'NER', 'BER', 'HR', 'MMR'., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.D237E:3!null\n" +
			"                             └─ right: TUPLE(0 (tinyint), 1 (tinyint))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The D237E field must be either 0 or 1., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO TPXBU
    (id, BTXC5, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    NCVD2.BTXC5 AS BTXC5,
    NULL AS FHCYT
FROM
(
SELECT DISTINCT
    umf.SYPKF AS BTXC5
FROM
    NZKPM umf
WHERE
        umf.SYPKF NOT IN (SELECT BTXC5 FROM TPXBU WHERE BTXC5 IS NOT NULL)
    AND
        umf.SYPKF IS NOT NULL
    AND
        umf.SYPKF <> 'N/A'
    AND
        umf.id IN ('1','2','3')
) NCVD2`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, BTXC5, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: TPXBU\n" +
			"         │       └─ columns: [id btxc5 fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER TPXBU_on_insert BEFORE INSERT ON TPXBU\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.BTXC5 IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, BTXC5:1, FHCYT:2]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, NCVD2.BTXC5:0 as BTXC5, NULL (null) as FHCYT]\n" +
			"             │       └─ SubqueryAlias\n" +
			"             │           ├─ name: NCVD2\n" +
			"             │           ├─ outerVisibility: false\n" +
			"             │           ├─ cacheable: true\n" +
			"             │           └─ Distinct\n" +
			"             │               └─ Project\n" +
			"             │                   ├─ columns: [umf.SYPKF:8 as BTXC5]\n" +
			"             │                   └─ Filter\n" +
			"             │                       ├─ AND\n" +
			"             │                       │   ├─ AND\n" +
			"             │                       │   │   ├─ AND\n" +
			"             │                       │   │   │   ├─ NOT\n" +
			"             │                       │   │   │   │   └─ InSubquery\n" +
			"             │                       │   │   │   │       ├─ left: umf.SYPKF:8\n" +
			"             │                       │   │   │   │       └─ right: Subquery\n" +
			"             │                       │   │   │   │           ├─ cacheable: true\n" +
			"             │                       │   │   │   │           └─ Filter\n" +
			"             │                       │   │   │   │               ├─ NOT\n" +
			"             │                       │   │   │   │               │   └─ TPXBU.BTXC5:25 IS NULL\n" +
			"             │                       │   │   │   │               └─ IndexedTableAccess(TPXBU)\n" +
			"             │                       │   │   │   │                   ├─ index: [TPXBU.BTXC5]\n" +
			"             │                       │   │   │   │                   ├─ static: [{(NULL, ∞)}]\n" +
			"             │                       │   │   │   │                   └─ columns: [btxc5]\n" +
			"             │                       │   │   │   └─ NOT\n" +
			"             │                       │   │   │       └─ umf.SYPKF:8 IS NULL\n" +
			"             │                       │   │   └─ NOT\n" +
			"             │                       │   │       └─ Eq\n" +
			"             │                       │   │           ├─ umf.SYPKF:8\n" +
			"             │                       │   │           └─ N/A (longtext)\n" +
			"             │                       │   └─ HashIn\n" +
			"             │                       │       ├─ umf.id:0!null\n" +
			"             │                       │       └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │                       └─ TableAlias(umf)\n" +
			"             │                           └─ IndexedTableAccess(NZKPM)\n" +
			"             │                               ├─ index: [NZKPM.id]\n" +
			"             │                               ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │                               └─ columns: [id t4ibq fgg57 sshpj nla6o sfj6l tjpt7 arn5p sypkf ivfmk ide43 az6sp fsdy2 xosd4 hmw4h s76om vaf zroh6 qcgts lnfm6 tvawl hdlcl bhhw6 fhcyt qz6vt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(InSubquery\n" +
			"                         ├─ left: new.BTXC5:1\n" +
			"                         └─ right: Subquery\n" +
			"                             ├─ cacheable: false\n" +
			"                             └─ Table\n" +
			"                                 ├─ name: TPXHZ\n" +
			"                                 └─ columns: [svaz4]\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO HGMQ6
    (id, GXLUB, LUEVY, M22QN, TJPT7, ARN5P, XOSD4, IDE43, HMW4H, ZBT6R, FSDY2, LT7K6, SPPYD, QCGTS, TEUJA, QQV4M, FHCYT)
SELECT
    umf.id AS id,
    bs.id AS GXLUB,
    CASE
        WHEN TJ5D2.id IS NOT NULL THEN (SELECT nd_for_id_overridden.id FROM E2I7U nd_for_id_overridden WHERE nd_for_id_overridden.TW55N = TJ5D2.H4DMT)
        ELSE (SELECT nd_for_id.id FROM E2I7U nd_for_id WHERE nd_for_id.FGG57 IS NOT NULL AND nd_for_id.FGG57 = umf.FGG57)
    END AS LUEVY,
    CASE
        WHEN umf.SYPKF = 'N/A' THEN (SELECT id FROM TPXBU WHERE BTXC5 IS NULL)
        ELSE (SELECT aac.id FROM TPXBU aac WHERE aac.BTXC5 = umf.SYPKF)
    END AS M22QN,
    umf.TJPT7 AS TJPT7,
    umf.ARN5P AS ARN5P,
    umf.XOSD4 AS XOSD4,
    umf.IDE43 AS IDE43,
    CASE
        WHEN umf.HMW4H <> 'N/A' THEN umf.HMW4H
        ELSE NULL
    END AS HMW4H,
    CASE
        WHEN umf.S76OM <> 'N/A' THEN (umf.S76OM + 0)
        ELSE NULL
    END AS ZBT6R,
    CASE
        WHEN umf.FSDY2 <> 'N/A' THEN umf.FSDY2
        ELSE 'VUS'
    END AS FSDY2,
    CASE
        WHEN umf.vaf <> '' THEN (umf.vaf + 0.0)
        ELSE NULL
    END AS LT7K6,
    CASE
        WHEN umf.ZROH6 <> '' THEN (umf.ZROH6 + 0.0)
        ELSE NULL
    END AS SPPYD,
    CASE
        WHEN umf.QCGTS <> '' THEN (umf.QCGTS + 0.0)
        ELSE NULL
    END AS QCGTS,
    umf.id AS TEUJA,
    TJ5D2.id AS QQV4M,
    umf.FHCYT AS FHCYT
FROM
    (SELECT
        *
    FROM
        NZKPM
    WHERE
        id IN ('1','2','3')
        AND ARN5P <> 'N/A'
        AND T4IBQ IN (SELECT FTQLQ FROM YK2GW)
        AND FGG57 IN (SELECT FGG57 FROM E2I7U WHERE FGG57 IS NOT NULL)
    ) umf
LEFT JOIN
    SZW6V TJ5D2
ON
        TJ5D2.SWCQV = 0 -- Override is turned on
    AND
        TJ5D2.T4IBQ = umf.T4IBQ
    AND
        TJ5D2.V7UFH = umf.FGG57
    AND
        TJ5D2.SYPKF = umf.SYPKF
INNER JOIN YK2GW cla ON umf.T4IBQ = cla.FTQLQ
INNER JOIN THNTS bs ON cla.id = bs.IXUXU`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, GXLUB, LUEVY, M22QN, TJPT7, ARN5P, XOSD4, IDE43, HMW4H, ZBT6R, FSDY2, LT7K6, SPPYD, QCGTS, TEUJA, QQV4M, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: HGMQ6\n" +
			"         │       └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER HGMQ6_on_insert BEFORE INSERT ON HGMQ6\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.TJPT7 IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR\n" +
			"                NEW.ARN5P IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR\n" +
			"                NEW.XOSD4 IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR\n" +
			"                NEW.IDE43 IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR\n" +
			"                NEW.HMW4H IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.FSDY2 NOT IN ('benign', 'VUS', 'SRARY', 'UBQWG')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'FSDY2 must be either ''benign'', ''VUS'', ''SRARY'' or ''UBQWG''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'FSDY2 must be either ''benign'', ''VUS'', ''SRARY'' or ''UBQWG''.';\n" +
			"              END IF;\n" +
			"              IF NEW.LT7K6 IS NOT NULL AND NEW.SPPYD IS NOT NULL\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'If LT7K6 has value, SPPYD must be NULL.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'If LT7K6 has value, SPPYD must be NULL.';\n" +
			"              END IF;\n" +
			"              IF NEW.LT7K6 IS NULL AND (NEW.SPPYD IS NULL OR NEW.SPPYD <> 0.5)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'If LT7K6 does not have value, SPPYD must be 0.5.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'If LT7K6 does not have value, SPPYD must be 0.5.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, GXLUB:1!null, LUEVY:2!null, M22QN:3!null, TJPT7:4!null, ARN5P:5!null, XOSD4:6!null, IDE43:7, HMW4H:8, ZBT6R:9, FSDY2:10!null, LT7K6:11, SPPYD:12, QCGTS:13, TEUJA:14, QQV4M:15, FHCYT:16]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [umf.id:0!null as id, bs.id:63!null as GXLUB, CASE  WHEN NOT\n" +
			"             │       │   └─ TJ5D2.id:25 IS NULL\n" +
			"             │       │   THEN Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [nd_for_id_overridden.id:67!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ nd_for_id_overridden.TW55N:68!null\n" +
			"             │       │           │   └─ TJ5D2.H4DMT:29\n" +
			"             │       │           └─ TableAlias(nd_for_id_overridden)\n" +
			"             │       │               └─ IndexedTableAccess(E2I7U)\n" +
			"             │       │                   ├─ index: [E2I7U.TW55N]\n" +
			"             │       │                   └─ columns: [id tw55n]\n" +
			"             │       │   ELSE Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [nd_for_id.id:67!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ AND\n" +
			"             │       │           │   ├─ NOT\n" +
			"             │       │           │   │   └─ nd_for_id.FGG57:68 IS NULL\n" +
			"             │       │           │   └─ Eq\n" +
			"             │       │           │       ├─ nd_for_id.FGG57:68\n" +
			"             │       │           │       └─ umf.FGG57:2\n" +
			"             │       │           └─ TableAlias(nd_for_id)\n" +
			"             │       │               └─ IndexedTableAccess(E2I7U)\n" +
			"             │       │                   ├─ index: [E2I7U.FGG57]\n" +
			"             │       │                   ├─ static: [{(NULL, ∞)}]\n" +
			"             │       │                   └─ columns: [id fgg57]\n" +
			"             │       │   END as LUEVY, CASE  WHEN Eq\n" +
			"             │       │   ├─ umf.SYPKF:8\n" +
			"             │       │   └─ N/A (longtext)\n" +
			"             │       │   THEN Subquery\n" +
			"             │       │   ├─ cacheable: true\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [TPXBU.id:67!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ TPXBU.BTXC5:68 IS NULL\n" +
			"             │       │           └─ IndexedTableAccess(TPXBU)\n" +
			"             │       │               ├─ index: [TPXBU.BTXC5]\n" +
			"             │       │               ├─ static: [{[NULL, NULL]}]\n" +
			"             │       │               └─ columns: [id btxc5]\n" +
			"             │       │   ELSE Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [aac.id:67!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ aac.BTXC5:68\n" +
			"             │       │           │   └─ umf.SYPKF:8\n" +
			"             │       │           └─ TableAlias(aac)\n" +
			"             │       │               └─ IndexedTableAccess(TPXBU)\n" +
			"             │       │                   ├─ index: [TPXBU.BTXC5]\n" +
			"             │       │                   └─ columns: [id btxc5]\n" +
			"             │       │   END as M22QN, umf.TJPT7:6 as TJPT7, umf.ARN5P:7 as ARN5P, umf.XOSD4:13 as XOSD4, umf.IDE43:10 as IDE43, CASE  WHEN NOT\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ umf.HMW4H:14\n" +
			"             │       │       └─ N/A (longtext)\n" +
			"             │       │   THEN umf.HMW4H:14 ELSE NULL (null) END as HMW4H, CASE  WHEN NOT\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ umf.S76OM:15\n" +
			"             │       │       └─ N/A (longtext)\n" +
			"             │       │   THEN (umf.S76OM:15 + 0 (tinyint)) ELSE NULL (null) END as ZBT6R, CASE  WHEN NOT\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ umf.FSDY2:12\n" +
			"             │       │       └─ N/A (longtext)\n" +
			"             │       │   THEN umf.FSDY2:12 ELSE VUS (longtext) END as FSDY2, CASE  WHEN NOT\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ umf.vaf:16\n" +
			"             │       │       └─  (longtext)\n" +
			"             │       │   THEN (umf.vaf:16 + 0 (decimal(2,1))) ELSE NULL (null) END as LT7K6, CASE  WHEN NOT\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ umf.ZROH6:17\n" +
			"             │       │       └─  (longtext)\n" +
			"             │       │   THEN (umf.ZROH6:17 + 0 (decimal(2,1))) ELSE NULL (null) END as SPPYD, CASE  WHEN NOT\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ umf.QCGTS:18\n" +
			"             │       │       └─  (longtext)\n" +
			"             │       │   THEN (umf.QCGTS:18 + 0 (decimal(2,1))) ELSE NULL (null) END as QCGTS, umf.id:0!null as TEUJA, TJ5D2.id:25 as QQV4M, umf.FHCYT:23 as FHCYT]\n" +
			"             │       └─ LookupJoin\n" +
			"             │           ├─ Eq\n" +
			"             │           │   ├─ cla.id:33!null\n" +
			"             │           │   └─ bs.IXUXU:65\n" +
			"             │           ├─ LookupJoin\n" +
			"             │           │   ├─ Eq\n" +
			"             │           │   │   ├─ umf.T4IBQ:1\n" +
			"             │           │   │   └─ cla.FTQLQ:34!null\n" +
			"             │           │   ├─ LeftOuterJoin\n" +
			"             │           │   │   ├─ AND\n" +
			"             │           │   │   │   ├─ AND\n" +
			"             │           │   │   │   │   ├─ AND\n" +
			"             │           │   │   │   │   │   ├─ Eq\n" +
			"             │           │   │   │   │   │   │   ├─ TJ5D2.SWCQV:30!null\n" +
			"             │           │   │   │   │   │   │   └─ 0 (tinyint)\n" +
			"             │           │   │   │   │   │   └─ Eq\n" +
			"             │           │   │   │   │   │       ├─ TJ5D2.T4IBQ:26!null\n" +
			"             │           │   │   │   │   │       └─ umf.T4IBQ:1\n" +
			"             │           │   │   │   │   └─ Eq\n" +
			"             │           │   │   │   │       ├─ TJ5D2.V7UFH:27!null\n" +
			"             │           │   │   │   │       └─ umf.FGG57:2\n" +
			"             │           │   │   │   └─ Eq\n" +
			"             │           │   │   │       ├─ TJ5D2.SYPKF:28!null\n" +
			"             │           │   │   │       └─ umf.SYPKF:8\n" +
			"             │           │   │   ├─ SubqueryAlias\n" +
			"             │           │   │   │   ├─ name: umf\n" +
			"             │           │   │   │   ├─ outerVisibility: false\n" +
			"             │           │   │   │   ├─ cacheable: true\n" +
			"             │           │   │   │   └─ Filter\n" +
			"             │           │   │   │       ├─ AND\n" +
			"             │           │   │   │       │   ├─ AND\n" +
			"             │           │   │   │       │   │   ├─ AND\n" +
			"             │           │   │   │       │   │   │   ├─ HashIn\n" +
			"             │           │   │   │       │   │   │   │   ├─ NZKPM.id:0!null\n" +
			"             │           │   │   │       │   │   │   │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           │   │   │       │   │   │   └─ NOT\n" +
			"             │           │   │   │       │   │   │       └─ Eq\n" +
			"             │           │   │   │       │   │   │           ├─ NZKPM.ARN5P:7\n" +
			"             │           │   │   │       │   │   │           └─ N/A (longtext)\n" +
			"             │           │   │   │       │   │   └─ InSubquery\n" +
			"             │           │   │   │       │   │       ├─ left: NZKPM.T4IBQ:1\n" +
			"             │           │   │   │       │   │       └─ right: Subquery\n" +
			"             │           │   │   │       │   │           ├─ cacheable: true\n" +
			"             │           │   │   │       │   │           └─ Table\n" +
			"             │           │   │   │       │   │               ├─ name: YK2GW\n" +
			"             │           │   │   │       │   │               └─ columns: [ftqlq]\n" +
			"             │           │   │   │       │   └─ InSubquery\n" +
			"             │           │   │   │       │       ├─ left: NZKPM.FGG57:2\n" +
			"             │           │   │   │       │       └─ right: Subquery\n" +
			"             │           │   │   │       │           ├─ cacheable: true\n" +
			"             │           │   │   │       │           └─ Filter\n" +
			"             │           │   │   │       │               ├─ NOT\n" +
			"             │           │   │   │       │               │   └─ E2I7U.FGG57:25 IS NULL\n" +
			"             │           │   │   │       │               └─ IndexedTableAccess(E2I7U)\n" +
			"             │           │   │   │       │                   ├─ index: [E2I7U.FGG57]\n" +
			"             │           │   │   │       │                   ├─ static: [{(NULL, ∞)}]\n" +
			"             │           │   │   │       │                   └─ columns: [fgg57]\n" +
			"             │           │   │   │       └─ IndexedTableAccess(NZKPM)\n" +
			"             │           │   │   │           ├─ index: [NZKPM.id]\n" +
			"             │           │   │   │           ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │           │   │   │           └─ columns: [id t4ibq fgg57 sshpj nla6o sfj6l tjpt7 arn5p sypkf ivfmk ide43 az6sp fsdy2 xosd4 hmw4h s76om vaf zroh6 qcgts lnfm6 tvawl hdlcl bhhw6 fhcyt qz6vt]\n" +
			"             │           │   │   └─ TableAlias(TJ5D2)\n" +
			"             │           │   │       └─ Table\n" +
			"             │           │   │           ├─ name: SZW6V\n" +
			"             │           │   │           └─ columns: [id t4ibq v7ufh sypkf h4dmt swcqv ykssu fhcyt]\n" +
			"             │           │   └─ TableAlias(cla)\n" +
			"             │           │       └─ IndexedTableAccess(YK2GW)\n" +
			"             │           │           ├─ index: [YK2GW.FTQLQ]\n" +
			"             │           │           └─ columns: [id ftqlq tuxml paef5 rucy4 tpnj6 lbl53 nb3qs eo7iv muhjf fm34l ty5rf zhtlh npb7w sx3hh isbnf ya7yb c5ykb qk7kt ffge6 fiigj sh3nc ntena m4aub x5air sab6m g5qi5 zvqvd ykssu fhcyt]\n" +
			"             │           └─ TableAlias(bs)\n" +
			"             │               └─ IndexedTableAccess(THNTS)\n" +
			"             │                   ├─ index: [THNTS.IXUXU]\n" +
			"             │                   └─ columns: [id nfryn ixuxu fhcyt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(Or\n" +
			"                 │       ├─ Or\n" +
			"                 │       │   ├─ Or\n" +
			"                 │       │   │   ├─ Or\n" +
			"                 │       │   │   │   ├─ InSubquery\n" +
			"                 │       │   │   │   │   ├─ left: new.TJPT7:4!null\n" +
			"                 │       │   │   │   │   └─ right: Subquery\n" +
			"                 │       │   │   │   │       ├─ cacheable: false\n" +
			"                 │       │   │   │   │       └─ Table\n" +
			"                 │       │   │   │   │           ├─ name: TPXHZ\n" +
			"                 │       │   │   │   │           └─ columns: [svaz4]\n" +
			"                 │       │   │   │   └─ InSubquery\n" +
			"                 │       │   │   │       ├─ left: new.ARN5P:5!null\n" +
			"                 │       │   │   │       └─ right: Subquery\n" +
			"                 │       │   │   │           ├─ cacheable: false\n" +
			"                 │       │   │   │           └─ Table\n" +
			"                 │       │   │   │               ├─ name: TPXHZ\n" +
			"                 │       │   │   │               └─ columns: [svaz4]\n" +
			"                 │       │   │   └─ InSubquery\n" +
			"                 │       │   │       ├─ left: new.XOSD4:6!null\n" +
			"                 │       │   │       └─ right: Subquery\n" +
			"                 │       │   │           ├─ cacheable: false\n" +
			"                 │       │   │           └─ Table\n" +
			"                 │       │   │               ├─ name: TPXHZ\n" +
			"                 │       │   │               └─ columns: [svaz4]\n" +
			"                 │       │   └─ InSubquery\n" +
			"                 │       │       ├─ left: new.IDE43:7\n" +
			"                 │       │       └─ right: Subquery\n" +
			"                 │       │           ├─ cacheable: false\n" +
			"                 │       │           └─ Table\n" +
			"                 │       │               ├─ name: TPXHZ\n" +
			"                 │       │               └─ columns: [svaz4]\n" +
			"                 │       └─ InSubquery\n" +
			"                 │           ├─ left: new.HMW4H:8\n" +
			"                 │           └─ right: Subquery\n" +
			"                 │               ├─ cacheable: false\n" +
			"                 │               └─ Table\n" +
			"                 │                   ├─ name: TPXHZ\n" +
			"                 │                   └─ columns: [svaz4]\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(NOT\n" +
			"                 │       └─ IN\n" +
			"                 │           ├─ left: new.FSDY2:10!null\n" +
			"                 │           └─ right: TUPLE(benign (longtext), VUS (longtext), SRARY (longtext), UBQWG (longtext))\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = FSDY2 must be either 'benign', 'VUS', 'SRARY' or 'UBQWG'., MYSQL_ERRNO = 1644\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(AND\n" +
			"                 │       ├─ NOT\n" +
			"                 │       │   └─ new.LT7K6:11 IS NULL\n" +
			"                 │       └─ NOT\n" +
			"                 │           └─ new.SPPYD:12 IS NULL\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = If LT7K6 has value, SPPYD must be NULL., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(AND\n" +
			"                         ├─ new.LT7K6:11 IS NULL\n" +
			"                         └─ Or\n" +
			"                             ├─ new.SPPYD:12 IS NULL\n" +
			"                             └─ NOT\n" +
			"                                 └─ Eq\n" +
			"                                     ├─ new.SPPYD:12\n" +
			"                                     └─ 0.500000 (double)\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = If LT7K6 does not have value, SPPYD must be 0.5., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO SEQS3
    (id, Z7CP5, YH4XB)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    C6PUD.id AS Z7CP5,
    vc.id AS YH4XB
FROM (
    SELECT
        mf.id AS id,
        umf.AZ6SP AS AZ6SP
    FROM
        HGMQ6 mf
    INNER JOIN NZKPM umf ON umf.id = mf.TEUJA
    WHERE
        umf.id IN ('1','2','3')
) C6PUD
INNER JOIN D34QP vc ON C6PUD.AZ6SP LIKE CONCAT(CONCAT('%', vc.TWMSR), '%')`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Insert(id, Z7CP5, YH4XB)\n" +
			"     ├─ InsertDestination\n" +
			"     │   └─ Table\n" +
			"     │       ├─ name: SEQS3\n" +
			"     │       └─ columns: [id z7cp5 yh4xb]\n" +
			"     └─ Project\n" +
			"         ├─ columns: [id:0!null, Z7CP5:1!null, YH4XB:2!null]\n" +
			"         └─ Project\n" +
			"             ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, C6PUD.id:0!null as Z7CP5, vc.id:2!null as YH4XB]\n" +
			"             └─ InnerJoin\n" +
			"                 ├─ C6PUD.AZ6SP LIKE concat(concat('%',vc.TWMSR),'%')\n" +
			"                 ├─ SubqueryAlias\n" +
			"                 │   ├─ name: C6PUD\n" +
			"                 │   ├─ outerVisibility: false\n" +
			"                 │   ├─ cacheable: true\n" +
			"                 │   └─ Project\n" +
			"                 │       ├─ columns: [mf.id:0!null as id, umf.AZ6SP:3 as AZ6SP]\n" +
			"                 │       └─ LookupJoin\n" +
			"                 │           ├─ Eq\n" +
			"                 │           │   ├─ umf.id:2!null\n" +
			"                 │           │   └─ mf.TEUJA:1\n" +
			"                 │           ├─ TableAlias(mf)\n" +
			"                 │           │   └─ Table\n" +
			"                 │           │       ├─ name: HGMQ6\n" +
			"                 │           │       └─ columns: [id teuja]\n" +
			"                 │           └─ Filter\n" +
			"                 │               ├─ HashIn\n" +
			"                 │               │   ├─ umf.id:0!null\n" +
			"                 │               │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"                 │               └─ TableAlias(umf)\n" +
			"                 │                   └─ IndexedTableAccess(NZKPM)\n" +
			"                 │                       ├─ index: [NZKPM.id]\n" +
			"                 │                       └─ columns: [id az6sp]\n" +
			"                 └─ TableAlias(vc)\n" +
			"                     └─ Table\n" +
			"                         ├─ name: D34QP\n" +
			"                         └─ columns: [id twmsr]\n" +
			"",
	},
	{
		Query: `
INSERT INTO HDDVB(id, FV24E, UJ6XY, M22QN, NZ4MQ, ETPQV, PRUV2, YKSSU, FHCYT)
-- The ones without overrides - mutfunc check is necessary
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    BPNW2.FV24E AS FV24E,
    BPNW2.UJ6XY AS UJ6XY,
    BPNW2.M22QN AS M22QN,
    BPNW2.NZ4MQ AS NZ4MQ,
    BPNW2.MU3KG AS ETPQV,
    NULL AS PRUV2,
    BPNW2.YKSSU AS YKSSU,
    BPNW2.FHCYT AS FHCYT
FROM
    (
    SELECT DISTINCT
        TIZHK.id AS MU3KG,
        J4JYP.id AS FV24E,
        RHUZN.id AS UJ6XY,
        aac.id AS M22QN,
        (SELECT G3YXS.id FROM YYBCX G3YXS WHERE CONCAT(G3YXS.ESFVY, '(MI:', G3YXS.SL76B, ')') = TIZHK.IDUT2) AS NZ4MQ,
        NULL AS FHCYT,
        NULL AS YKSSU
    FROM
        WRZVO TIZHK
    LEFT JOIN
        WGSDC NHMXW
    ON
            NHMXW.SWCQV = 0 -- Override is turned on
        AND
            NHMXW.NOHHR = TIZHK.TVNW2
        AND
            NHMXW.AVPYF = TIZHK.ZHITY
        AND
            NHMXW.SYPKF = TIZHK.SYPKF
        AND
            NHMXW.IDUT2 = TIZHK.IDUT2
    INNER JOIN
        E2I7U J4JYP ON J4JYP.ZH72S = TIZHK.TVNW2
    INNER JOIN
        E2I7U RHUZN ON RHUZN.ZH72S = TIZHK.ZHITY
    INNER JOIN
        HGMQ6 mf ON mf.LUEVY = J4JYP.id
    INNER JOIN
        TPXBU aac ON aac.id = mf.M22QN
    WHERE
            TIZHK.id IN ('1','2','3')
        AND
            aac.BTXC5 = TIZHK.SYPKF
        AND
            NHMXW.id IS NULL -- No overrides here
    ) BPNW2
UNION
-- The ones with overrides - no mutfunc check is necessary
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    BPNW2.FV24E AS FV24E,
    BPNW2.UJ6XY AS UJ6XY,
    (SELECT aac.id FROM TPXBU aac WHERE aac.BTXC5 = BPNW2.SYPKF) AS M22QN,
    BPNW2.NZ4MQ AS NZ4MQ,
    BPNW2.MU3KG AS ETPQV,
    BPNW2.I4NDZ AS PRUV2,
    BPNW2.YKSSU AS YKSSU,
    BPNW2.FHCYT AS FHCYT
FROM
    (
    SELECT DISTINCT
        TIZHK.id AS MU3KG,
        CASE
            WHEN NHMXW.FZXV5 IS NOT NULL
                THEN (SELECT overridden_nd_mutant.id FROM E2I7U overridden_nd_mutant WHERE overridden_nd_mutant.TW55N = NHMXW.FZXV5)
            ELSE J4JYP.id
        END AS FV24E,
        CASE
            WHEN NHMXW.DQYGV IS NOT NULL
                THEN (SELECT overridden_QI2IEner.id FROM E2I7U overridden_QI2IEner WHERE overridden_QI2IEner.TW55N = NHMXW.DQYGV)
            ELSE RHUZN.id
        END AS UJ6XY,
        TIZHK.SYPKF AS SYPKF,
        (SELECT G3YXS.id FROM YYBCX G3YXS WHERE CONCAT(G3YXS.ESFVY, '(MI:', G3YXS.SL76B, ')') = TIZHK.IDUT2) AS NZ4MQ,
        NULL AS FHCYT,
        NULL AS YKSSU,
        NHMXW.id AS I4NDZ
    FROM
        WRZVO TIZHK
    LEFT JOIN
        WGSDC NHMXW
    ON
            NHMXW.SWCQV = 0 -- Override is turned on
        AND
            NHMXW.NOHHR = TIZHK.TVNW2
        AND
            NHMXW.AVPYF = TIZHK.ZHITY
        AND
            NHMXW.SYPKF = TIZHK.SYPKF
        AND
            NHMXW.IDUT2 = TIZHK.IDUT2
    LEFT JOIN
        E2I7U J4JYP ON J4JYP.ZH72S = TIZHK.TVNW2
    LEFT JOIN
        E2I7U RHUZN ON RHUZN.ZH72S = TIZHK.ZHITY
    WHERE
            TIZHK.id IN ('1','2','3')
        AND
            NHMXW.id IS NOT NULL -- Only overrides here
    ) BPNW2`,
		ExpectedPlan: "RowUpdateAccumulator\n" +
			" └─ Insert(id, FV24E, UJ6XY, M22QN, NZ4MQ, ETPQV, PRUV2, YKSSU, FHCYT)\n" +
			"     ├─ InsertDestination\n" +
			"     │   └─ Table\n" +
			"     │       ├─ name: HDDVB\n" +
			"     │       └─ columns: [id fv24e uj6xy m22qn nz4mq etpqv pruv2 ykssu fhcyt]\n" +
			"     └─ Project\n" +
			"         ├─ columns: [id:0!null, FV24E:1!null, UJ6XY:2!null, M22QN:3!null, NZ4MQ:4!null, ETPQV:5, PRUV2:6, YKSSU:7, FHCYT:8]\n" +
			"         └─ Union distinct\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, convert\n" +
			"             │   │   ├─ type: char\n" +
			"             │   │   └─ FV24E:1!null\n" +
			"             │   │   as FV24E, convert\n" +
			"             │   │   ├─ type: char\n" +
			"             │   │   └─ UJ6XY:2!null\n" +
			"             │   │   as UJ6XY, M22QN:3!null, NZ4MQ:4, ETPQV:5!null, convert\n" +
			"             │   │   ├─ type: char\n" +
			"             │   │   └─ PRUV2:6\n" +
			"             │   │   as PRUV2, YKSSU:7, FHCYT:8]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, BPNW2.FV24E:1!null as FV24E, BPNW2.UJ6XY:2!null as UJ6XY, BPNW2.M22QN:3!null as M22QN, BPNW2.NZ4MQ:4 as NZ4MQ, BPNW2.MU3KG:0!null as ETPQV, NULL (null) as PRUV2, BPNW2.YKSSU:6 as YKSSU, BPNW2.FHCYT:5 as FHCYT]\n" +
			"             │       └─ SubqueryAlias\n" +
			"             │           ├─ name: BPNW2\n" +
			"             │           ├─ outerVisibility: false\n" +
			"             │           ├─ cacheable: true\n" +
			"             │           └─ Distinct\n" +
			"             │               └─ Project\n" +
			"             │                   ├─ columns: [TIZHK.id:37!null as MU3KG, J4JYP.id:0!null as FV24E, RHUZN.id:47!null as UJ6XY, aac.id:34!null as M22QN, Subquery\n" +
			"             │                   │   ├─ cacheable: false\n" +
			"             │                   │   └─ Project\n" +
			"             │                   │       ├─ columns: [G3YXS.id:74!null]\n" +
			"             │                   │       └─ Filter\n" +
			"             │                   │           ├─ Eq\n" +
			"             │                   │           │   ├─ concat(G3YXS.ESFVY:75!null,(MI: (longtext),G3YXS.SL76B:76!null,) (longtext))\n" +
			"             │                   │           │   └─ TIZHK.IDUT2:41\n" +
			"             │                   │           └─ TableAlias(G3YXS)\n" +
			"             │                   │               └─ Table\n" +
			"             │                   │                   ├─ name: YYBCX\n" +
			"             │                   │                   └─ columns: [id esfvy sl76b]\n" +
			"             │                   │   as NZ4MQ, NULL (null) as FHCYT, NULL (null) as YKSSU]\n" +
			"             │                   └─ Filter\n" +
			"             │                       ├─ AND\n" +
			"             │                       │   ├─ Eq\n" +
			"             │                       │   │   ├─ aac.BTXC5:35\n" +
			"             │                       │   │   └─ TIZHK.SYPKF:40\n" +
			"             │                       │   └─ NHMXW.id:64 IS NULL\n" +
			"             │                       └─ LeftOuterLookupJoin\n" +
			"             │                           ├─ AND\n" +
			"             │                           │   ├─ AND\n" +
			"             │                           │   │   ├─ AND\n" +
			"             │                           │   │   │   ├─ AND\n" +
			"             │                           │   │   │   │   ├─ Eq\n" +
			"             │                           │   │   │   │   │   ├─ NHMXW.SWCQV:71!null\n" +
			"             │                           │   │   │   │   │   └─ 0 (tinyint)\n" +
			"             │                           │   │   │   │   └─ Eq\n" +
			"             │                           │   │   │   │       ├─ NHMXW.NOHHR:65!null\n" +
			"             │                           │   │   │   │       └─ TIZHK.TVNW2:38\n" +
			"             │                           │   │   │   └─ Eq\n" +
			"             │                           │   │   │       ├─ NHMXW.AVPYF:66!null\n" +
			"             │                           │   │   │       └─ TIZHK.ZHITY:39\n" +
			"             │                           │   │   └─ Eq\n" +
			"             │                           │   │       ├─ NHMXW.SYPKF:67!null\n" +
			"             │                           │   │       └─ TIZHK.SYPKF:40\n" +
			"             │                           │   └─ Eq\n" +
			"             │                           │       ├─ NHMXW.IDUT2:68!null\n" +
			"             │                           │       └─ TIZHK.IDUT2:41\n" +
			"             │                           ├─ LookupJoin\n" +
			"             │                           │   ├─ Eq\n" +
			"             │                           │   │   ├─ RHUZN.ZH72S:54\n" +
			"             │                           │   │   └─ TIZHK.ZHITY:39\n" +
			"             │                           │   ├─ LookupJoin\n" +
			"             │                           │   │   ├─ Eq\n" +
			"             │                           │   │   │   ├─ J4JYP.ZH72S:7\n" +
			"             │                           │   │   │   └─ TIZHK.TVNW2:38\n" +
			"             │                           │   │   ├─ LookupJoin\n" +
			"             │                           │   │   │   ├─ Eq\n" +
			"             │                           │   │   │   │   ├─ aac.id:34!null\n" +
			"             │                           │   │   │   │   └─ mf.M22QN:20!null\n" +
			"             │                           │   │   │   ├─ LookupJoin\n" +
			"             │                           │   │   │   │   ├─ Eq\n" +
			"             │                           │   │   │   │   │   ├─ mf.LUEVY:19!null\n" +
			"             │                           │   │   │   │   │   └─ J4JYP.id:0!null\n" +
			"             │                           │   │   │   │   ├─ TableAlias(J4JYP)\n" +
			"             │                           │   │   │   │   │   └─ Table\n" +
			"             │                           │   │   │   │   │       ├─ name: E2I7U\n" +
			"             │                           │   │   │   │   │       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"             │                           │   │   │   │   └─ TableAlias(mf)\n" +
			"             │                           │   │   │   │       └─ IndexedTableAccess(HGMQ6)\n" +
			"             │                           │   │   │   │           ├─ index: [HGMQ6.LUEVY]\n" +
			"             │                           │   │   │   │           └─ columns: [id gxlub luevy m22qn tjpt7 arn5p xosd4 ide43 hmw4h zbt6r fsdy2 lt7k6 sppyd qcgts teuja qqv4m fhcyt]\n" +
			"             │                           │   │   │   └─ TableAlias(aac)\n" +
			"             │                           │   │   │       └─ IndexedTableAccess(TPXBU)\n" +
			"             │                           │   │   │           ├─ index: [TPXBU.id]\n" +
			"             │                           │   │   │           └─ columns: [id btxc5 fhcyt]\n" +
			"             │                           │   │   └─ Filter\n" +
			"             │                           │   │       ├─ HashIn\n" +
			"             │                           │   │       │   ├─ TIZHK.id:0!null\n" +
			"             │                           │   │       │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │                           │   │       └─ TableAlias(TIZHK)\n" +
			"             │                           │   │           └─ IndexedTableAccess(WRZVO)\n" +
			"             │                           │   │               ├─ index: [WRZVO.TVNW2]\n" +
			"             │                           │   │               └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			"             │                           │   └─ TableAlias(RHUZN)\n" +
			"             │                           │       └─ IndexedTableAccess(E2I7U)\n" +
			"             │                           │           ├─ index: [E2I7U.ZH72S]\n" +
			"             │                           │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"             │                           └─ TableAlias(NHMXW)\n" +
			"             │                               └─ IndexedTableAccess(WGSDC)\n" +
			"             │                                   ├─ index: [WGSDC.AVPYF]\n" +
			"             │                                   └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			"             └─ Project\n" +
			"                 ├─ columns: [id:0!null, FV24E:1 as FV24E, UJ6XY:2 as UJ6XY, M22QN:3, NZ4MQ:4, ETPQV:5!null, convert\n" +
			"                 │   ├─ type: char\n" +
			"                 │   └─ PRUV2:6\n" +
			"                 │   as PRUV2, YKSSU:7, FHCYT:8]\n" +
			"                 └─ Project\n" +
			"                     ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, BPNW2.FV24E:1 as FV24E, BPNW2.UJ6XY:2 as UJ6XY, Subquery\n" +
			"                     │   ├─ cacheable: false\n" +
			"                     │   └─ Project\n" +
			"                     │       ├─ columns: [aac.id:8!null]\n" +
			"                     │       └─ Filter\n" +
			"                     │           ├─ Eq\n" +
			"                     │           │   ├─ aac.BTXC5:9\n" +
			"                     │           │   └─ BPNW2.SYPKF:3\n" +
			"                     │           └─ TableAlias(aac)\n" +
			"                     │               └─ IndexedTableAccess(TPXBU)\n" +
			"                     │                   ├─ index: [TPXBU.BTXC5]\n" +
			"                     │                   └─ columns: [id btxc5]\n" +
			"                     │   as M22QN, BPNW2.NZ4MQ:4 as NZ4MQ, BPNW2.MU3KG:0!null as ETPQV, BPNW2.I4NDZ:7 as PRUV2, BPNW2.YKSSU:6 as YKSSU, BPNW2.FHCYT:5 as FHCYT]\n" +
			"                     └─ SubqueryAlias\n" +
			"                         ├─ name: BPNW2\n" +
			"                         ├─ outerVisibility: false\n" +
			"                         ├─ cacheable: true\n" +
			"                         └─ Distinct\n" +
			"                             └─ Project\n" +
			"                                 ├─ columns: [TIZHK.id:0!null as MU3KG, CASE  WHEN NOT\n" +
			"                                 │   └─ NHMXW.FZXV5:15 IS NULL\n" +
			"                                 │   THEN Subquery\n" +
			"                                 │   ├─ cacheable: false\n" +
			"                                 │   └─ Project\n" +
			"                                 │       ├─ columns: [overridden_nd_mutant.id:54!null]\n" +
			"                                 │       └─ Filter\n" +
			"                                 │           ├─ Eq\n" +
			"                                 │           │   ├─ overridden_nd_mutant.TW55N:55!null\n" +
			"                                 │           │   └─ NHMXW.FZXV5:15\n" +
			"                                 │           └─ TableAlias(overridden_nd_mutant)\n" +
			"                                 │               └─ IndexedTableAccess(E2I7U)\n" +
			"                                 │                   ├─ index: [E2I7U.TW55N]\n" +
			"                                 │                   └─ columns: [id tw55n]\n" +
			"                                 │   ELSE J4JYP.id:20 END as FV24E, CASE  WHEN NOT\n" +
			"                                 │   └─ NHMXW.DQYGV:16 IS NULL\n" +
			"                                 │   THEN Subquery\n" +
			"                                 │   ├─ cacheable: false\n" +
			"                                 │   └─ Project\n" +
			"                                 │       ├─ columns: [overridden_QI2IEner.id:54!null]\n" +
			"                                 │       └─ Filter\n" +
			"                                 │           ├─ Eq\n" +
			"                                 │           │   ├─ overridden_QI2IEner.TW55N:55!null\n" +
			"                                 │           │   └─ NHMXW.DQYGV:16\n" +
			"                                 │           └─ TableAlias(overridden_QI2IEner)\n" +
			"                                 │               └─ Table\n" +
			"                                 │                   ├─ name: E2I7U\n" +
			"                                 │                   └─ columns: [id tw55n]\n" +
			"                                 │   ELSE RHUZN.id:37 END as UJ6XY, TIZHK.SYPKF:3 as SYPKF, Subquery\n" +
			"                                 │   ├─ cacheable: false\n" +
			"                                 │   └─ Project\n" +
			"                                 │       ├─ columns: [G3YXS.id:54!null]\n" +
			"                                 │       └─ Filter\n" +
			"                                 │           ├─ Eq\n" +
			"                                 │           │   ├─ concat(G3YXS.ESFVY:55!null,(MI: (longtext),G3YXS.SL76B:56!null,) (longtext))\n" +
			"                                 │           │   └─ TIZHK.IDUT2:4\n" +
			"                                 │           └─ TableAlias(G3YXS)\n" +
			"                                 │               └─ Table\n" +
			"                                 │                   ├─ name: YYBCX\n" +
			"                                 │                   └─ columns: [id esfvy sl76b]\n" +
			"                                 │   as NZ4MQ, NULL (null) as FHCYT, NULL (null) as YKSSU, NHMXW.id:10 as I4NDZ]\n" +
			"                                 └─ Filter\n" +
			"                                     ├─ NOT\n" +
			"                                     │   └─ NHMXW.id:10 IS NULL\n" +
			"                                     └─ LeftOuterHashJoin\n" +
			"                                         ├─ Eq\n" +
			"                                         │   ├─ RHUZN.ZH72S:44\n" +
			"                                         │   └─ TIZHK.ZHITY:2\n" +
			"                                         ├─ LeftOuterHashJoin\n" +
			"                                         │   ├─ Eq\n" +
			"                                         │   │   ├─ J4JYP.ZH72S:27\n" +
			"                                         │   │   └─ TIZHK.TVNW2:1\n" +
			"                                         │   ├─ LeftOuterMergeJoin\n" +
			"                                         │   │   ├─ cmp: Eq\n" +
			"                                         │   │   │   ├─ TIZHK.TVNW2:1\n" +
			"                                         │   │   │   └─ NHMXW.NOHHR:11!null\n" +
			"                                         │   │   ├─ sel: AND\n" +
			"                                         │   │   │   ├─ AND\n" +
			"                                         │   │   │   │   ├─ AND\n" +
			"                                         │   │   │   │   │   ├─ Eq\n" +
			"                                         │   │   │   │   │   │   ├─ NHMXW.SWCQV:17!null\n" +
			"                                         │   │   │   │   │   │   └─ 0 (tinyint)\n" +
			"                                         │   │   │   │   │   └─ Eq\n" +
			"                                         │   │   │   │   │       ├─ NHMXW.AVPYF:12!null\n" +
			"                                         │   │   │   │   │       └─ TIZHK.ZHITY:2\n" +
			"                                         │   │   │   │   └─ Eq\n" +
			"                                         │   │   │   │       ├─ NHMXW.SYPKF:13!null\n" +
			"                                         │   │   │   │       └─ TIZHK.SYPKF:3\n" +
			"                                         │   │   │   └─ Eq\n" +
			"                                         │   │   │       ├─ NHMXW.IDUT2:14!null\n" +
			"                                         │   │   │       └─ TIZHK.IDUT2:4\n" +
			"                                         │   │   ├─ Filter\n" +
			"                                         │   │   │   ├─ HashIn\n" +
			"                                         │   │   │   │   ├─ TIZHK.id:0!null\n" +
			"                                         │   │   │   │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"                                         │   │   │   └─ TableAlias(TIZHK)\n" +
			"                                         │   │   │       └─ IndexedTableAccess(WRZVO)\n" +
			"                                         │   │   │           ├─ index: [WRZVO.TVNW2]\n" +
			"                                         │   │   │           ├─ static: [{[NULL, ∞)}]\n" +
			"                                         │   │   │           └─ columns: [id tvnw2 zhity sypkf idut2 o6qj3 no2ja ykssu fhcyt qz6vt]\n" +
			"                                         │   │   └─ TableAlias(NHMXW)\n" +
			"                                         │   │       └─ IndexedTableAccess(WGSDC)\n" +
			"                                         │   │           ├─ index: [WGSDC.NOHHR]\n" +
			"                                         │   │           ├─ static: [{[NULL, ∞)}]\n" +
			"                                         │   │           └─ columns: [id nohhr avpyf sypkf idut2 fzxv5 dqygv swcqv ykssu fhcyt]\n" +
			"                                         │   └─ HashLookup\n" +
			"                                         │       ├─ source: TUPLE(TIZHK.TVNW2:1)\n" +
			"                                         │       ├─ target: TUPLE(J4JYP.ZH72S:7)\n" +
			"                                         │       └─ CachedResults\n" +
			"                                         │           └─ TableAlias(J4JYP)\n" +
			"                                         │               └─ Table\n" +
			"                                         │                   ├─ name: E2I7U\n" +
			"                                         │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"                                         └─ HashLookup\n" +
			"                                             ├─ source: TUPLE(TIZHK.ZHITY:2)\n" +
			"                                             ├─ target: TUPLE(RHUZN.ZH72S:7)\n" +
			"                                             └─ CachedResults\n" +
			"                                                 └─ TableAlias(RHUZN)\n" +
			"                                                     └─ Table\n" +
			"                                                         ├─ name: E2I7U\n" +
			"                                                         └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"",
	},
	{
		Query: `
INSERT INTO
    SFEGG(id, NO52D, VYO5E, DKCAJ, ADURZ, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    rs.NO52D AS NO52D,
    rs.VYO5E AS VYO5E,
    rs.DKCAJ AS DKCAJ,
    CASE
        WHEN rs.NO52D = 'FZB3D' AND rs.F35MI = 'SUZTA' THEN 1
        WHEN rs.NO52D = 'FZB3D' AND rs.F35MI <> 'SUZTA' THEN 3
        WHEN rs.NO52D LIKE 'AC%' OR rs.NO52D LIKE 'EC%' THEN 3
        WHEN rs.NO52D LIKE 'IC%' AND rs.VYO5E IS NULL THEN 2
        WHEN rs.NO52D LIKE 'IC%' AND rs.VYO5E = 'CF' THEN 1
        WHEN rs.NO52D LIKE 'IC%' AND rs.VYO5E IS NOT NULL AND NOT(rs.VYO5E = 'CF') THEN 4
        WHEN rs.NO52D = 'Ki' THEN 1
        WHEN rs.NO52D = 'Kd' THEN 2
        ELSE NULL
    END AS ADURZ,
    NULL AS FHCYT
FROM
    (
    SELECT DISTINCT
        NK7FP.NO52D AS NO52D,
        CASE
            WHEN NK7FP.VYO5E = 'N/A' THEN NULL
            ELSE NK7FP.VYO5E
        END AS VYO5E,
        nt.id AS DKCAJ,
        nt.DZLIM AS F35MI
    FROM
        (
        SELECT DISTINCT
            uct.NO52D,
            uct.VYO5E,
            uct.ZH72S,
            I7HCR.FVUCX
        FROM
            OUBDL uct
        LEFT JOIN -- Joining overrides, we need the overridden UWBAI TAFAX in this case
            EPZU6 I7HCR
        ON
                I7HCR.SWCQV = 0 -- Override is turned on
            AND
                I7HCR.TOFPN = uct.FTQLQ
            AND
                I7HCR.SJYN2 = uct.ZH72S
            AND
                I7HCR.BTXC5 = uct.LJLUM
        WHERE
            uct.id IN ('1','2','3')
        ) NK7FP
    INNER JOIN
        E2I7U nd
    ON
            (
                NK7FP.FVUCX IS NULL
            AND
                nd.ZH72S = NK7FP.ZH72S
            )
        OR
            (
                NK7FP.FVUCX IS NOT NULL
            AND
                nd.TW55N = NK7FP.FVUCX
            )
    INNER JOIN
        F35MI nt ON nt.id = nd.DKCAJ
    ) rs
WHERE
        (
            rs.VYO5E IS NOT NULL
        AND
            (rs.NO52D, rs.VYO5E, rs.DKCAJ) NOT IN (SELECT DISTINCT NO52D, VYO5E, DKCAJ FROM SFEGG WHERE VYO5E IS NOT NULL)
        )
    OR
        (
            rs.VYO5E IS NULL
        AND
            (rs.NO52D, rs.DKCAJ) NOT IN (SELECT DISTINCT NO52D, DKCAJ FROM SFEGG WHERE VYO5E IS NULL)
        )`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, NO52D, VYO5E, DKCAJ, ADURZ, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: SFEGG\n" +
			"         │       └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER SFEGG_on_insert BEFORE INSERT ON SFEGG\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.NO52D IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR NEW.VYO5E IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.ADURZ <= 0\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'ADURZ must be positive.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'ADURZ must be positive.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, NO52D:1!null, VYO5E:2, DKCAJ:3!null, ADURZ:4!null, FHCYT:5]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, rs.NO52D:0 as NO52D, rs.VYO5E:1 as VYO5E, rs.DKCAJ:2!null as DKCAJ, CASE  WHEN AND\n" +
			"             │       │   ├─ Eq\n" +
			"             │       │   │   ├─ rs.NO52D:0\n" +
			"             │       │   │   └─ FZB3D (longtext)\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ rs.F35MI:3!null\n" +
			"             │       │       └─ SUZTA (longtext)\n" +
			"             │       │   THEN 1 (tinyint) WHEN AND\n" +
			"             │       │   ├─ Eq\n" +
			"             │       │   │   ├─ rs.NO52D:0\n" +
			"             │       │   │   └─ FZB3D (longtext)\n" +
			"             │       │   └─ NOT\n" +
			"             │       │       └─ Eq\n" +
			"             │       │           ├─ rs.F35MI:3!null\n" +
			"             │       │           └─ SUZTA (longtext)\n" +
			"             │       │   THEN 3 (tinyint) WHEN Or\n" +
			"             │       │   ├─ rs.NO52D LIKE 'AC%'\n" +
			"             │       │   └─ rs.NO52D LIKE 'EC%'\n" +
			"             │       │   THEN 3 (tinyint) WHEN AND\n" +
			"             │       │   ├─ rs.NO52D LIKE 'IC%'\n" +
			"             │       │   └─ rs.VYO5E:1 IS NULL\n" +
			"             │       │   THEN 2 (tinyint) WHEN AND\n" +
			"             │       │   ├─ rs.NO52D LIKE 'IC%'\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ rs.VYO5E:1\n" +
			"             │       │       └─ CF (longtext)\n" +
			"             │       │   THEN 1 (tinyint) WHEN AND\n" +
			"             │       │   ├─ AND\n" +
			"             │       │   │   ├─ rs.NO52D LIKE 'IC%'\n" +
			"             │       │   │   └─ NOT\n" +
			"             │       │   │       └─ rs.VYO5E:1 IS NULL\n" +
			"             │       │   └─ NOT\n" +
			"             │       │       └─ Eq\n" +
			"             │       │           ├─ rs.VYO5E:1\n" +
			"             │       │           └─ CF (longtext)\n" +
			"             │       │   THEN 4 (tinyint) WHEN Eq\n" +
			"             │       │   ├─ rs.NO52D:0\n" +
			"             │       │   └─ Ki (longtext)\n" +
			"             │       │   THEN 1 (tinyint) WHEN Eq\n" +
			"             │       │   ├─ rs.NO52D:0\n" +
			"             │       │   └─ Kd (longtext)\n" +
			"             │       │   THEN 2 (tinyint) ELSE NULL (null) END as ADURZ, NULL (null) as FHCYT]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ Or\n" +
			"             │           │   ├─ AND\n" +
			"             │           │   │   ├─ NOT\n" +
			"             │           │   │   │   └─ rs.VYO5E:1 IS NULL\n" +
			"             │           │   │   └─ NOT\n" +
			"             │           │   │       └─ InSubquery\n" +
			"             │           │   │           ├─ left: TUPLE(rs.NO52D:0, rs.VYO5E:1, rs.DKCAJ:2!null)\n" +
			"             │           │   │           └─ right: Subquery\n" +
			"             │           │   │               ├─ cacheable: true\n" +
			"             │           │   │               └─ Distinct\n" +
			"             │           │   │                   └─ Project\n" +
			"             │           │   │                       ├─ columns: [SFEGG.NO52D:5!null, SFEGG.VYO5E:6, SFEGG.DKCAJ:7!null]\n" +
			"             │           │   │                       └─ Filter\n" +
			"             │           │   │                           ├─ NOT\n" +
			"             │           │   │                           │   └─ SFEGG.VYO5E:6 IS NULL\n" +
			"             │           │   │                           └─ Table\n" +
			"             │           │   │                               ├─ name: SFEGG\n" +
			"             │           │   │                               └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"             │           │   └─ AND\n" +
			"             │           │       ├─ rs.VYO5E:1 IS NULL\n" +
			"             │           │       └─ NOT\n" +
			"             │           │           └─ InSubquery\n" +
			"             │           │               ├─ left: TUPLE(rs.NO52D:0, rs.DKCAJ:2!null)\n" +
			"             │           │               └─ right: Subquery\n" +
			"             │           │                   ├─ cacheable: true\n" +
			"             │           │                   └─ Distinct\n" +
			"             │           │                       └─ Project\n" +
			"             │           │                           ├─ columns: [SFEGG.NO52D:5!null, SFEGG.DKCAJ:7!null]\n" +
			"             │           │                           └─ Filter\n" +
			"             │           │                               ├─ SFEGG.VYO5E:6 IS NULL\n" +
			"             │           │                               └─ Table\n" +
			"             │           │                                   ├─ name: SFEGG\n" +
			"             │           │                                   └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"             │           └─ SubqueryAlias\n" +
			"             │               ├─ name: rs\n" +
			"             │               ├─ outerVisibility: false\n" +
			"             │               ├─ cacheable: true\n" +
			"             │               └─ Distinct\n" +
			"             │                   └─ Project\n" +
			"             │                       ├─ columns: [NK7FP.NO52D:0 as NO52D, CASE  WHEN Eq\n" +
			"             │                       │   ├─ NK7FP.VYO5E:1\n" +
			"             │                       │   └─ N/A (longtext)\n" +
			"             │                       │   THEN NULL (null) ELSE NK7FP.VYO5E:1 END as VYO5E, nt.id:4!null as DKCAJ, nt.DZLIM:5!null as F35MI]\n" +
			"             │                       └─ InnerJoin\n" +
			"             │                           ├─ Or\n" +
			"             │                           │   ├─ AND\n" +
			"             │                           │   │   ├─ NK7FP.FVUCX:3 IS NULL\n" +
			"             │                           │   │   └─ Eq\n" +
			"             │                           │   │       ├─ nd.ZH72S:14\n" +
			"             │                           │   │       └─ NK7FP.ZH72S:2\n" +
			"             │                           │   └─ AND\n" +
			"             │                           │       ├─ NOT\n" +
			"             │                           │       │   └─ NK7FP.FVUCX:3 IS NULL\n" +
			"             │                           │       └─ Eq\n" +
			"             │                           │           ├─ nd.TW55N:10!null\n" +
			"             │                           │           └─ NK7FP.FVUCX:3\n" +
			"             │                           ├─ SubqueryAlias\n" +
			"             │                           │   ├─ name: NK7FP\n" +
			"             │                           │   ├─ outerVisibility: false\n" +
			"             │                           │   ├─ cacheable: true\n" +
			"             │                           │   └─ Distinct\n" +
			"             │                           │       └─ Project\n" +
			"             │                           │           ├─ columns: [uct.NO52D:7, uct.VYO5E:9, uct.ZH72S:2, I7HCR.FVUCX:17]\n" +
			"             │                           │           └─ LeftOuterMergeJoin\n" +
			"             │                           │               ├─ cmp: Eq\n" +
			"             │                           │               │   ├─ uct.FTQLQ:1\n" +
			"             │                           │               │   └─ I7HCR.TOFPN:14!null\n" +
			"             │                           │               ├─ sel: AND\n" +
			"             │                           │               │   ├─ AND\n" +
			"             │                           │               │   │   ├─ Eq\n" +
			"             │                           │               │   │   │   ├─ I7HCR.SWCQV:18!null\n" +
			"             │                           │               │   │   │   └─ 0 (tinyint)\n" +
			"             │                           │               │   │   └─ Eq\n" +
			"             │                           │               │   │       ├─ I7HCR.SJYN2:15!null\n" +
			"             │                           │               │   │       └─ uct.ZH72S:2\n" +
			"             │                           │               │   └─ Eq\n" +
			"             │                           │               │       ├─ I7HCR.BTXC5:16!null\n" +
			"             │                           │               │       └─ uct.LJLUM:5\n" +
			"             │                           │               ├─ Filter\n" +
			"             │                           │               │   ├─ HashIn\n" +
			"             │                           │               │   │   ├─ uct.id:0!null\n" +
			"             │                           │               │   │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │                           │               │   └─ TableAlias(uct)\n" +
			"             │                           │               │       └─ IndexedTableAccess(OUBDL)\n" +
			"             │                           │               │           ├─ index: [OUBDL.FTQLQ]\n" +
			"             │                           │               │           ├─ static: [{[NULL, ∞)}]\n" +
			"             │                           │               │           └─ columns: [id ftqlq zh72s sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e ykssu fhcyt qz6vt]\n" +
			"             │                           │               └─ TableAlias(I7HCR)\n" +
			"             │                           │                   └─ IndexedTableAccess(EPZU6)\n" +
			"             │                           │                       ├─ index: [EPZU6.TOFPN]\n" +
			"             │                           │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │                           │                       └─ columns: [id tofpn sjyn2 btxc5 fvucx swcqv ykssu fhcyt]\n" +
			"             │                           └─ LookupJoin\n" +
			"             │                               ├─ Eq\n" +
			"             │                               │   ├─ nt.id:4!null\n" +
			"             │                               │   └─ nd.DKCAJ:8!null\n" +
			"             │                               ├─ TableAlias(nt)\n" +
			"             │                               │   └─ Table\n" +
			"             │                               │       ├─ name: F35MI\n" +
			"             │                               │       └─ columns: [id dzlim f3yue]\n" +
			"             │                               └─ TableAlias(nd)\n" +
			"             │                                   └─ IndexedTableAccess(E2I7U)\n" +
			"             │                                       ├─ index: [E2I7U.DKCAJ]\n" +
			"             │                                       └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(Or\n" +
			"                 │       ├─ InSubquery\n" +
			"                 │       │   ├─ left: new.NO52D:1!null\n" +
			"                 │       │   └─ right: Subquery\n" +
			"                 │       │       ├─ cacheable: false\n" +
			"                 │       │       └─ Table\n" +
			"                 │       │           ├─ name: TPXHZ\n" +
			"                 │       │           └─ columns: [svaz4]\n" +
			"                 │       └─ InSubquery\n" +
			"                 │           ├─ left: new.VYO5E:2\n" +
			"                 │           └─ right: Subquery\n" +
			"                 │               ├─ cacheable: false\n" +
			"                 │               └─ Table\n" +
			"                 │                   ├─ name: TPXHZ\n" +
			"                 │                   └─ columns: [svaz4]\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(LessThanOrEqual\n" +
			"                         ├─ new.ADURZ:4!null\n" +
			"                         └─ 0 (tinyint)\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = ADURZ must be positive., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO FLQLP
    (id, FZ2R5, LUEVY, M22QN, OVE3E, NRURT, OCA7E, XMM6Q, V5DPX, S3Q3Y, ZRV3B, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    PQSXB.FZ2R5 AS FZ2R5,
    nd.id AS LUEVY,
    (SELECT aac.id FROM TPXBU aac WHERE aac.BTXC5 = PQSXB.BTXC5) AS M22QN,
    PQSXB.OVE3E AS OVE3E,
    PQSXB.NRURT AS NRURT,
    PQSXB.OCA7E AS OCA7E,
    PQSXB.XMM6Q AS XMM6Q,
    PQSXB.V5DPX AS V5DPX,
    PQSXB.S3Q3Y AS S3Q3Y,
    PQSXB.ZRV3B AS ZRV3B,
    PQSXB.FHCYT AS FHCYT
FROM
    (
    SELECT
        -- Base fields to insert to FLQLP
        (SELECT id FROM JDLNA WHERE JDLNA.FTQLQ = uct.FTQLQ) AS FZ2R5,
        (SELECT id FROM SFEGG WHERE
            SFEGG.NO52D = uct.NO52D AND
            (
                SFEGG.VYO5E = uct.VYO5E OR
                (SFEGG.VYO5E IS NULL AND (uct.VYO5E IS NULL OR uct.VYO5E = 'N/A' OR uct.VYO5E = 'NA'))
            ) AND
            SFEGG.DKCAJ = (
                SELECT
                    CASE
                        WHEN I7HCR.FVUCX IS NULL
                            THEN (SELECT nd.DKCAJ FROM E2I7U nd WHERE nd.ZH72S = uct.ZH72S LIMIT 1)
                        ELSE
                            (SELECT nd.DKCAJ FROM E2I7U nd WHERE nd.TW55N = I7HCR.FVUCX)
                    END
            )
        ) AS OVE3E,
        uct.id AS NRURT,
        I7HCR.id AS OCA7E,
        NULL AS XMM6Q, -- Here we do not care with additionals
        uct.V5DPX AS V5DPX,
        uct.IDPK7 + 0.0 AS S3Q3Y,
        uct.ZRV3B AS ZRV3B,
        CASE
            WHEN uct.FHCYT <> 'N/A' THEN uct.FHCYT
            ELSE NULL
        END AS FHCYT,
        -- Extra fields to use
        uct.ZH72S AS K3B6V,
        uct.LJLUM AS BTXC5,
        I7HCR.FVUCX AS H4DMT
    FROM
        OUBDL uct
    LEFT JOIN -- Joining overrides
        EPZU6 I7HCR
    ON
            I7HCR.SWCQV = 0 -- Override is turned on
        AND
            I7HCR.TOFPN = uct.FTQLQ
        AND
            I7HCR.SJYN2 = uct.ZH72S
        AND
            I7HCR.BTXC5 = uct.LJLUM
    WHERE
        uct.id IN ('1','2','3')
    ) PQSXB
INNER JOIN
    E2I7U nd
ON
    (
            PQSXB.H4DMT IS NOT NULL
        AND
            nd.TW55N = PQSXB.H4DMT
    )
    OR
    (
            PQSXB.H4DMT IS NULL
        AND
            nd.ZH72S = PQSXB.K3B6V
    )
WHERE
        -- In the case we could not build-in evidence class for some
        PQSXB.OVE3E IS NOT NULL`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, FZ2R5, LUEVY, M22QN, OVE3E, NRURT, OCA7E, XMM6Q, V5DPX, S3Q3Y, ZRV3B, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: FLQLP\n" +
			"         │       └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER FLQLP_on_insert BEFORE INSERT ON FLQLP\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.V5DPX IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.ZRV3B NOT IN ('=', '<=', '>=', '<', '>')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ZRV3B must be on of the following: ''='', ''<='', ''>='', ''<'', ''>''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ZRV3B must be on of the following: ''='', ''<='', ''>='', ''<'', ''>''.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, FZ2R5:1!null, LUEVY:2!null, M22QN:3!null, OVE3E:4!null, NRURT:5, OCA7E:6, XMM6Q:7, V5DPX:8!null, S3Q3Y:9!null, ZRV3B:10!null, FHCYT:11]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, PQSXB.FZ2R5:0 as FZ2R5, nd.id:12!null as LUEVY, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [aac.id:29!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ aac.BTXC5:30\n" +
			"             │       │           │   └─ PQSXB.BTXC5:10\n" +
			"             │       │           └─ TableAlias(aac)\n" +
			"             │       │               └─ IndexedTableAccess(TPXBU)\n" +
			"             │       │                   ├─ index: [TPXBU.BTXC5]\n" +
			"             │       │                   └─ columns: [id btxc5]\n" +
			"             │       │   as M22QN, PQSXB.OVE3E:1 as OVE3E, PQSXB.NRURT:2!null as NRURT, PQSXB.OCA7E:3 as OCA7E, PQSXB.XMM6Q:4 as XMM6Q, PQSXB.V5DPX:5 as V5DPX, PQSXB.S3Q3Y:6 as S3Q3Y, PQSXB.ZRV3B:7 as ZRV3B, PQSXB.FHCYT:8 as FHCYT]\n" +
			"             │       └─ InnerJoin\n" +
			"             │           ├─ Or\n" +
			"             │           │   ├─ AND\n" +
			"             │           │   │   ├─ NOT\n" +
			"             │           │   │   │   └─ PQSXB.H4DMT:11 IS NULL\n" +
			"             │           │   │   └─ Eq\n" +
			"             │           │   │       ├─ nd.TW55N:15!null\n" +
			"             │           │   │       └─ PQSXB.H4DMT:11\n" +
			"             │           │   └─ AND\n" +
			"             │           │       ├─ PQSXB.H4DMT:11 IS NULL\n" +
			"             │           │       └─ Eq\n" +
			"             │           │           ├─ nd.ZH72S:19\n" +
			"             │           │           └─ PQSXB.K3B6V:9\n" +
			"             │           ├─ SubqueryAlias\n" +
			"             │           │   ├─ name: PQSXB\n" +
			"             │           │   ├─ outerVisibility: false\n" +
			"             │           │   ├─ cacheable: true\n" +
			"             │           │   └─ Filter\n" +
			"             │           │       ├─ NOT\n" +
			"             │           │       │   └─ OVE3E:1 IS NULL\n" +
			"             │           │       └─ Project\n" +
			"             │           │           ├─ columns: [Subquery\n" +
			"             │           │           │   ├─ cacheable: false\n" +
			"             │           │           │   └─ Project\n" +
			"             │           │           │       ├─ columns: [JDLNA.id:21!null]\n" +
			"             │           │           │       └─ Filter\n" +
			"             │           │           │           ├─ Eq\n" +
			"             │           │           │           │   ├─ JDLNA.FTQLQ:22!null\n" +
			"             │           │           │           │   └─ uct.FTQLQ:1\n" +
			"             │           │           │           └─ Table\n" +
			"             │           │           │               ├─ name: JDLNA\n" +
			"             │           │           │               └─ columns: [id ftqlq]\n" +
			"             │           │           │   as FZ2R5, Subquery\n" +
			"             │           │           │   ├─ cacheable: false\n" +
			"             │           │           │   └─ Project\n" +
			"             │           │           │       ├─ columns: [SFEGG.id:21!null]\n" +
			"             │           │           │       └─ Filter\n" +
			"             │           │           │           ├─ AND\n" +
			"             │           │           │           │   ├─ AND\n" +
			"             │           │           │           │   │   ├─ Eq\n" +
			"             │           │           │           │   │   │   ├─ SFEGG.NO52D:22!null\n" +
			"             │           │           │           │   │   │   └─ uct.NO52D:7\n" +
			"             │           │           │           │   │   └─ Or\n" +
			"             │           │           │           │   │       ├─ Eq\n" +
			"             │           │           │           │   │       │   ├─ SFEGG.VYO5E:23\n" +
			"             │           │           │           │   │       │   └─ uct.VYO5E:9\n" +
			"             │           │           │           │   │       └─ AND\n" +
			"             │           │           │           │   │           ├─ SFEGG.VYO5E:23 IS NULL\n" +
			"             │           │           │           │   │           └─ Or\n" +
			"             │           │           │           │   │               ├─ Or\n" +
			"             │           │           │           │   │               │   ├─ uct.VYO5E:9 IS NULL\n" +
			"             │           │           │           │   │               │   └─ Eq\n" +
			"             │           │           │           │   │               │       ├─ uct.VYO5E:9\n" +
			"             │           │           │           │   │               │       └─ N/A (longtext)\n" +
			"             │           │           │           │   │               └─ Eq\n" +
			"             │           │           │           │   │                   ├─ uct.VYO5E:9\n" +
			"             │           │           │           │   │                   └─ NA (longtext)\n" +
			"             │           │           │           │   └─ Eq\n" +
			"             │           │           │           │       ├─ SFEGG.DKCAJ:24!null\n" +
			"             │           │           │           │       └─ Subquery\n" +
			"             │           │           │           │           ├─ cacheable: false\n" +
			"             │           │           │           │           └─ Project\n" +
			"             │           │           │           │               ├─ columns: [CASE  WHEN I7HCR.FVUCX:17 IS NULL THEN Subquery\n" +
			"             │           │           │           │               │   ├─ cacheable: false\n" +
			"             │           │           │           │               │   └─ Limit(1)\n" +
			"             │           │           │           │               │       └─ Project\n" +
			"             │           │           │           │               │           ├─ columns: [nd.DKCAJ:28!null]\n" +
			"             │           │           │           │               │           └─ Filter\n" +
			"             │           │           │           │               │               ├─ Eq\n" +
			"             │           │           │           │               │               │   ├─ nd.ZH72S:29\n" +
			"             │           │           │           │               │               │   └─ uct.ZH72S:2\n" +
			"             │           │           │           │               │               └─ TableAlias(nd)\n" +
			"             │           │           │           │               │                   └─ IndexedTableAccess(E2I7U)\n" +
			"             │           │           │           │               │                       ├─ index: [E2I7U.ZH72S]\n" +
			"             │           │           │           │               │                       └─ columns: [dkcaj zh72s]\n" +
			"             │           │           │           │               │   ELSE Subquery\n" +
			"             │           │           │           │               │   ├─ cacheable: false\n" +
			"             │           │           │           │               │   └─ Project\n" +
			"             │           │           │           │               │       ├─ columns: [nd.DKCAJ:28!null]\n" +
			"             │           │           │           │               │       └─ Filter\n" +
			"             │           │           │           │               │           ├─ Eq\n" +
			"             │           │           │           │               │           │   ├─ nd.TW55N:29!null\n" +
			"             │           │           │           │               │           │   └─ I7HCR.FVUCX:17\n" +
			"             │           │           │           │               │           └─ TableAlias(nd)\n" +
			"             │           │           │           │               │               └─ IndexedTableAccess(E2I7U)\n" +
			"             │           │           │           │               │                   ├─ index: [E2I7U.TW55N]\n" +
			"             │           │           │           │               │                   └─ columns: [dkcaj tw55n]\n" +
			"             │           │           │           │               │   END]\n" +
			"             │           │           │           │               └─ Table\n" +
			"             │           │           │           │                   ├─ name: \n" +
			"             │           │           │           │                   └─ columns: []\n" +
			"             │           │           │           └─ Table\n" +
			"             │           │           │               ├─ name: SFEGG\n" +
			"             │           │           │               └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"             │           │           │   as OVE3E, uct.id:0!null as NRURT, I7HCR.id:13 as OCA7E, NULL (null) as XMM6Q, uct.V5DPX:4 as V5DPX, (uct.IDPK7:6 + 0 (decimal(2,1))) as S3Q3Y, uct.ZRV3B:8 as ZRV3B, CASE  WHEN NOT\n" +
			"             │           │           │   └─ Eq\n" +
			"             │           │           │       ├─ uct.FHCYT:11\n" +
			"             │           │           │       └─ N/A (longtext)\n" +
			"             │           │           │   THEN uct.FHCYT:11 ELSE NULL (null) END as FHCYT, uct.ZH72S:2 as K3B6V, uct.LJLUM:5 as BTXC5, I7HCR.FVUCX:17 as H4DMT]\n" +
			"             │           │           └─ LeftOuterMergeJoin\n" +
			"             │           │               ├─ cmp: Eq\n" +
			"             │           │               │   ├─ uct.FTQLQ:1\n" +
			"             │           │               │   └─ I7HCR.TOFPN:14!null\n" +
			"             │           │               ├─ sel: AND\n" +
			"             │           │               │   ├─ AND\n" +
			"             │           │               │   │   ├─ Eq\n" +
			"             │           │               │   │   │   ├─ I7HCR.SWCQV:18!null\n" +
			"             │           │               │   │   │   └─ 0 (tinyint)\n" +
			"             │           │               │   │   └─ Eq\n" +
			"             │           │               │   │       ├─ I7HCR.SJYN2:15!null\n" +
			"             │           │               │   │       └─ uct.ZH72S:2\n" +
			"             │           │               │   └─ Eq\n" +
			"             │           │               │       ├─ I7HCR.BTXC5:16!null\n" +
			"             │           │               │       └─ uct.LJLUM:5\n" +
			"             │           │               ├─ Filter\n" +
			"             │           │               │   ├─ HashIn\n" +
			"             │           │               │   │   ├─ uct.id:0!null\n" +
			"             │           │               │   │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           │               │   └─ TableAlias(uct)\n" +
			"             │           │               │       └─ IndexedTableAccess(OUBDL)\n" +
			"             │           │               │           ├─ index: [OUBDL.FTQLQ]\n" +
			"             │           │               │           ├─ static: [{[NULL, ∞)}]\n" +
			"             │           │               │           └─ columns: [id ftqlq zh72s sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e ykssu fhcyt qz6vt]\n" +
			"             │           │               └─ TableAlias(I7HCR)\n" +
			"             │           │                   └─ IndexedTableAccess(EPZU6)\n" +
			"             │           │                       ├─ index: [EPZU6.TOFPN]\n" +
			"             │           │                       ├─ static: [{[NULL, ∞)}]\n" +
			"             │           │                       └─ columns: [id tofpn sjyn2 btxc5 fvucx swcqv ykssu fhcyt]\n" +
			"             │           └─ TableAlias(nd)\n" +
			"             │               └─ Table\n" +
			"             │                   ├─ name: E2I7U\n" +
			"             │                   └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(InSubquery\n" +
			"                 │       ├─ left: new.V5DPX:8!null\n" +
			"                 │       └─ right: Subquery\n" +
			"                 │           ├─ cacheable: false\n" +
			"                 │           └─ Table\n" +
			"                 │               ├─ name: TPXHZ\n" +
			"                 │               └─ columns: [svaz4]\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.ZRV3B:10!null\n" +
			"                             └─ right: TUPLE(= (longtext), <= (longtext), >= (longtext), < (longtext), > (longtext))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ZRV3B must be on of the following: '=', '<=', '>=', '<', '>'., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO
    SFEGG(id, NO52D, VYO5E, DKCAJ, ADURZ, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    rs.NO52D AS NO52D,
    rs.VYO5E AS VYO5E,
    rs.DKCAJ AS DKCAJ,
    CASE
        WHEN rs.NO52D = 'FZB3D' AND rs.F35MI = 'SUZTA' THEN 1
        WHEN rs.NO52D = 'FZB3D' AND rs.F35MI <> 'SUZTA' THEN 3
        WHEN rs.NO52D LIKE 'AC%' OR rs.NO52D LIKE 'EC%' THEN 3
        WHEN rs.NO52D LIKE 'IC%' AND rs.VYO5E IS NULL THEN 2
        WHEN rs.NO52D LIKE 'IC%' AND rs.VYO5E = 'CF' THEN 1
        WHEN rs.NO52D LIKE 'IC%' AND rs.VYO5E IS NOT NULL AND NOT(rs.VYO5E = 'CF') THEN 4
        WHEN rs.NO52D = 'Ki' THEN 1
        WHEN rs.NO52D = 'Kd' THEN 2
        ELSE NULL
    END AS ADURZ,
    NULL AS FHCYT
FROM
    (
    SELECT DISTINCT
        TVTJS.NO52D AS NO52D,
        TVTJS.VYO5E AS VYO5E,
        nt.id AS DKCAJ,
        nt.DZLIM AS F35MI
    FROM
        HU5A5 TVTJS
    INNER JOIN
        E2I7U nd ON nd.TW55N = TVTJS.I3VTA
    INNER JOIN
        F35MI nt ON nt.id = nd.DKCAJ
    WHERE
        TVTJS.id IN ('1','2','3')
    ) rs
WHERE
        (
            rs.VYO5E IS NOT NULL
        AND
            (rs.NO52D, rs.VYO5E, rs.DKCAJ) NOT IN (SELECT DISTINCT NO52D, VYO5E, DKCAJ FROM SFEGG WHERE VYO5E IS NOT NULL)
        )
    OR
        (
            rs.VYO5E IS NULL
        AND
            (rs.NO52D, rs.DKCAJ) NOT IN (SELECT DISTINCT NO52D, DKCAJ FROM SFEGG WHERE VYO5E IS NULL)
        )`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, NO52D, VYO5E, DKCAJ, ADURZ, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: SFEGG\n" +
			"         │       └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER SFEGG_on_insert BEFORE INSERT ON SFEGG\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.NO52D IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"                OR NEW.VYO5E IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.ADURZ <= 0\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'ADURZ must be positive.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'ADURZ must be positive.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, NO52D:1!null, VYO5E:2, DKCAJ:3!null, ADURZ:4!null, FHCYT:5]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, rs.NO52D:0!null as NO52D, rs.VYO5E:1 as VYO5E, rs.DKCAJ:2!null as DKCAJ, CASE  WHEN AND\n" +
			"             │       │   ├─ Eq\n" +
			"             │       │   │   ├─ rs.NO52D:0!null\n" +
			"             │       │   │   └─ FZB3D (longtext)\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ rs.F35MI:3!null\n" +
			"             │       │       └─ SUZTA (longtext)\n" +
			"             │       │   THEN 1 (tinyint) WHEN AND\n" +
			"             │       │   ├─ Eq\n" +
			"             │       │   │   ├─ rs.NO52D:0!null\n" +
			"             │       │   │   └─ FZB3D (longtext)\n" +
			"             │       │   └─ NOT\n" +
			"             │       │       └─ Eq\n" +
			"             │       │           ├─ rs.F35MI:3!null\n" +
			"             │       │           └─ SUZTA (longtext)\n" +
			"             │       │   THEN 3 (tinyint) WHEN Or\n" +
			"             │       │   ├─ rs.NO52D LIKE 'AC%'\n" +
			"             │       │   └─ rs.NO52D LIKE 'EC%'\n" +
			"             │       │   THEN 3 (tinyint) WHEN AND\n" +
			"             │       │   ├─ rs.NO52D LIKE 'IC%'\n" +
			"             │       │   └─ rs.VYO5E:1 IS NULL\n" +
			"             │       │   THEN 2 (tinyint) WHEN AND\n" +
			"             │       │   ├─ rs.NO52D LIKE 'IC%'\n" +
			"             │       │   └─ Eq\n" +
			"             │       │       ├─ rs.VYO5E:1\n" +
			"             │       │       └─ CF (longtext)\n" +
			"             │       │   THEN 1 (tinyint) WHEN AND\n" +
			"             │       │   ├─ AND\n" +
			"             │       │   │   ├─ rs.NO52D LIKE 'IC%'\n" +
			"             │       │   │   └─ NOT\n" +
			"             │       │   │       └─ rs.VYO5E:1 IS NULL\n" +
			"             │       │   └─ NOT\n" +
			"             │       │       └─ Eq\n" +
			"             │       │           ├─ rs.VYO5E:1\n" +
			"             │       │           └─ CF (longtext)\n" +
			"             │       │   THEN 4 (tinyint) WHEN Eq\n" +
			"             │       │   ├─ rs.NO52D:0!null\n" +
			"             │       │   └─ Ki (longtext)\n" +
			"             │       │   THEN 1 (tinyint) WHEN Eq\n" +
			"             │       │   ├─ rs.NO52D:0!null\n" +
			"             │       │   └─ Kd (longtext)\n" +
			"             │       │   THEN 2 (tinyint) ELSE NULL (null) END as ADURZ, NULL (null) as FHCYT]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ Or\n" +
			"             │           │   ├─ AND\n" +
			"             │           │   │   ├─ NOT\n" +
			"             │           │   │   │   └─ rs.VYO5E:1 IS NULL\n" +
			"             │           │   │   └─ NOT\n" +
			"             │           │   │       └─ InSubquery\n" +
			"             │           │   │           ├─ left: TUPLE(rs.NO52D:0!null, rs.VYO5E:1, rs.DKCAJ:2!null)\n" +
			"             │           │   │           └─ right: Subquery\n" +
			"             │           │   │               ├─ cacheable: true\n" +
			"             │           │   │               └─ Distinct\n" +
			"             │           │   │                   └─ Project\n" +
			"             │           │   │                       ├─ columns: [SFEGG.NO52D:5!null, SFEGG.VYO5E:6, SFEGG.DKCAJ:7!null]\n" +
			"             │           │   │                       └─ Filter\n" +
			"             │           │   │                           ├─ NOT\n" +
			"             │           │   │                           │   └─ SFEGG.VYO5E:6 IS NULL\n" +
			"             │           │   │                           └─ Table\n" +
			"             │           │   │                               ├─ name: SFEGG\n" +
			"             │           │   │                               └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"             │           │   └─ AND\n" +
			"             │           │       ├─ rs.VYO5E:1 IS NULL\n" +
			"             │           │       └─ NOT\n" +
			"             │           │           └─ InSubquery\n" +
			"             │           │               ├─ left: TUPLE(rs.NO52D:0!null, rs.DKCAJ:2!null)\n" +
			"             │           │               └─ right: Subquery\n" +
			"             │           │                   ├─ cacheable: true\n" +
			"             │           │                   └─ Distinct\n" +
			"             │           │                       └─ Project\n" +
			"             │           │                           ├─ columns: [SFEGG.NO52D:5!null, SFEGG.DKCAJ:7!null]\n" +
			"             │           │                           └─ Filter\n" +
			"             │           │                               ├─ SFEGG.VYO5E:6 IS NULL\n" +
			"             │           │                               └─ Table\n" +
			"             │           │                                   ├─ name: SFEGG\n" +
			"             │           │                                   └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"             │           └─ SubqueryAlias\n" +
			"             │               ├─ name: rs\n" +
			"             │               ├─ outerVisibility: false\n" +
			"             │               ├─ cacheable: true\n" +
			"             │               └─ Distinct\n" +
			"             │                   └─ Project\n" +
			"             │                       ├─ columns: [TVTJS.NO52D:27!null as NO52D, TVTJS.VYO5E:29 as VYO5E, nt.id:0!null as DKCAJ, nt.DZLIM:1!null as F35MI]\n" +
			"             │                       └─ LookupJoin\n" +
			"             │                           ├─ Eq\n" +
			"             │                           │   ├─ nd.TW55N:6!null\n" +
			"             │                           │   └─ TVTJS.I3VTA:22!null\n" +
			"             │                           ├─ LookupJoin\n" +
			"             │                           │   ├─ Eq\n" +
			"             │                           │   │   ├─ nt.id:0!null\n" +
			"             │                           │   │   └─ nd.DKCAJ:4!null\n" +
			"             │                           │   ├─ TableAlias(nt)\n" +
			"             │                           │   │   └─ Table\n" +
			"             │                           │   │       ├─ name: F35MI\n" +
			"             │                           │   │       └─ columns: [id dzlim f3yue]\n" +
			"             │                           │   └─ TableAlias(nd)\n" +
			"             │                           │       └─ IndexedTableAccess(E2I7U)\n" +
			"             │                           │           ├─ index: [E2I7U.DKCAJ]\n" +
			"             │                           │           └─ columns: [id dkcaj kng7t tw55n qrqxw ecxaj fgg57 zh72s fsk67 xqdyt tce7a iwv2h hpcms n5cc2 fhcyt etaq7 a75x7]\n" +
			"             │                           └─ Filter\n" +
			"             │                               ├─ HashIn\n" +
			"             │                               │   ├─ TVTJS.id:0!null\n" +
			"             │                               │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │                               └─ TableAlias(TVTJS)\n" +
			"             │                                   └─ IndexedTableAccess(HU5A5)\n" +
			"             │                                       ├─ index: [HU5A5.I3VTA]\n" +
			"             │                                       └─ columns: [id tofpn i3vta sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e swcqv ykssu fhcyt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(Or\n" +
			"                 │       ├─ InSubquery\n" +
			"                 │       │   ├─ left: new.NO52D:1!null\n" +
			"                 │       │   └─ right: Subquery\n" +
			"                 │       │       ├─ cacheable: false\n" +
			"                 │       │       └─ Table\n" +
			"                 │       │           ├─ name: TPXHZ\n" +
			"                 │       │           └─ columns: [svaz4]\n" +
			"                 │       └─ InSubquery\n" +
			"                 │           ├─ left: new.VYO5E:2\n" +
			"                 │           └─ right: Subquery\n" +
			"                 │               ├─ cacheable: false\n" +
			"                 │               └─ Table\n" +
			"                 │                   ├─ name: TPXHZ\n" +
			"                 │                   └─ columns: [svaz4]\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(LessThanOrEqual\n" +
			"                         ├─ new.ADURZ:4!null\n" +
			"                         └─ 0 (tinyint)\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = ADURZ must be positive., MYSQL_ERRNO = 1644\n" +
			"",
	},
	{
		Query: `
INSERT INTO FLQLP
    (id, FZ2R5, LUEVY, M22QN, OVE3E, NRURT, OCA7E, XMM6Q, V5DPX, S3Q3Y, ZRV3B, FHCYT)
SELECT
    LPAD(LOWER(CONCAT(CONCAT(HEX(RAND()*4294967296),LOWER(HEX(RAND()*4294967296)),LOWER(HEX(RAND()*4294967296))))), 24, '0') AS id,
    (SELECT id FROM JDLNA WHERE JDLNA.FTQLQ = TVTJS.TOFPN) AS FZ2R5,
    (SELECT id FROM E2I7U WHERE TW55N = TVTJS.I3VTA) AS LUEVY,
    (SELECT id FROM TPXBU WHERE BTXC5 = TVTJS.LJLUM) AS M22QN,
    (SELECT id FROM SFEGG WHERE
        SFEGG.NO52D = TVTJS.NO52D AND
        (
            SFEGG.VYO5E = TVTJS.VYO5E OR
            (SFEGG.VYO5E IS NULL AND (TVTJS.VYO5E IS NULL OR TVTJS.VYO5E = 'N/A' OR TVTJS.VYO5E = 'NA'))
        ) AND
        SFEGG.DKCAJ = (
            SELECT nd.DKCAJ FROM E2I7U nd WHERE nd.TW55N = TVTJS.I3VTA
        )
    ) AS OVE3E,
    NULL AS NRURT, -- Not coming from unprocessed
    NULL AS OCA7E, -- Can not be overridden
    TVTJS.id AS XMM6Q, -- It is an additional
    TVTJS.V5DPX AS V5DPX,
    TVTJS.IDPK7 + 0.0 AS S3Q3Y,
    TVTJS.ZRV3B AS ZRV3B,
    TVTJS.FHCYT AS FHCYT
FROM
    HU5A5 TVTJS
WHERE
    TVTJS.id IN ('1','2','3')`,
		ExpectedPlan: "TriggerRollback\n" +
			" └─ RowUpdateAccumulator\n" +
			"     └─ Insert(id, FZ2R5, LUEVY, M22QN, OVE3E, NRURT, OCA7E, XMM6Q, V5DPX, S3Q3Y, ZRV3B, FHCYT)\n" +
			"         ├─ InsertDestination\n" +
			"         │   └─ Table\n" +
			"         │       ├─ name: FLQLP\n" +
			"         │       └─ columns: [id fz2r5 luevy m22qn ove3e nrurt oca7e xmm6q v5dpx s3q3y zrv3b fhcyt]\n" +
			"         └─ Trigger(CREATE TRIGGER FLQLP_on_insert BEFORE INSERT ON FLQLP\n" +
			"            FOR EACH ROW\n" +
			"            BEGIN\n" +
			"              IF\n" +
			"                NEW.V5DPX IN (SELECT SVAZ4 FROM TPXHZ)\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = (SELECT error_message FROM trigger_helper_error_message WHERE DZLIM = 'SVAZ4');\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.';\n" +
			"              END IF;\n" +
			"              IF\n" +
			"                NEW.ZRV3B NOT IN ('=', '<=', '>=', '<', '>')\n" +
			"              THEN\n" +
			"                -- SET @custom_error_message = 'The ZRV3B must be on of the following: ''='', ''<='', ''>='', ''<'', ''>''.';\n" +
			"                -- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @custom_error_message;\n" +
			"                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The ZRV3B must be on of the following: ''='', ''<='', ''>='', ''<'', ''>''.';\n" +
			"              END IF;\n" +
			"            END//)\n" +
			"             ├─ Project\n" +
			"             │   ├─ columns: [id:0!null, FZ2R5:1!null, LUEVY:2!null, M22QN:3!null, OVE3E:4!null, NRURT:5, OCA7E:6, XMM6Q:7, V5DPX:8!null, S3Q3Y:9!null, ZRV3B:10!null, FHCYT:11]\n" +
			"             │   └─ Project\n" +
			"             │       ├─ columns: [lpad(lower(concat(concat(hex((rand() * 4294967296)),lower(hex((rand() * 4294967296))),lower(hex((rand() * 4294967296)))))), 24, '0') as id, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [JDLNA.id:13!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ JDLNA.FTQLQ:14!null\n" +
			"             │       │           │   └─ TVTJS.TOFPN:1!null\n" +
			"             │       │           └─ Table\n" +
			"             │       │               ├─ name: JDLNA\n" +
			"             │       │               └─ columns: [id ftqlq]\n" +
			"             │       │   as FZ2R5, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [E2I7U.id:13!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ E2I7U.TW55N:14!null\n" +
			"             │       │           │   └─ TVTJS.I3VTA:2!null\n" +
			"             │       │           └─ Table\n" +
			"             │       │               ├─ name: E2I7U\n" +
			"             │       │               └─ columns: [id tw55n]\n" +
			"             │       │   as LUEVY, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [TPXBU.id:13!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ Eq\n" +
			"             │       │           │   ├─ TPXBU.BTXC5:14\n" +
			"             │       │           │   └─ TVTJS.LJLUM:5!null\n" +
			"             │       │           └─ Table\n" +
			"             │       │               ├─ name: TPXBU\n" +
			"             │       │               └─ columns: [id btxc5]\n" +
			"             │       │   as M22QN, Subquery\n" +
			"             │       │   ├─ cacheable: false\n" +
			"             │       │   └─ Project\n" +
			"             │       │       ├─ columns: [SFEGG.id:13!null]\n" +
			"             │       │       └─ Filter\n" +
			"             │       │           ├─ AND\n" +
			"             │       │           │   ├─ AND\n" +
			"             │       │           │   │   ├─ Eq\n" +
			"             │       │           │   │   │   ├─ SFEGG.NO52D:14!null\n" +
			"             │       │           │   │   │   └─ TVTJS.NO52D:7!null\n" +
			"             │       │           │   │   └─ Or\n" +
			"             │       │           │   │       ├─ Eq\n" +
			"             │       │           │   │       │   ├─ SFEGG.VYO5E:15\n" +
			"             │       │           │   │       │   └─ TVTJS.VYO5E:9\n" +
			"             │       │           │   │       └─ AND\n" +
			"             │       │           │   │           ├─ SFEGG.VYO5E:15 IS NULL\n" +
			"             │       │           │   │           └─ Or\n" +
			"             │       │           │   │               ├─ Or\n" +
			"             │       │           │   │               │   ├─ TVTJS.VYO5E:9 IS NULL\n" +
			"             │       │           │   │               │   └─ Eq\n" +
			"             │       │           │   │               │       ├─ TVTJS.VYO5E:9\n" +
			"             │       │           │   │               │       └─ N/A (longtext)\n" +
			"             │       │           │   │               └─ Eq\n" +
			"             │       │           │   │                   ├─ TVTJS.VYO5E:9\n" +
			"             │       │           │   │                   └─ NA (longtext)\n" +
			"             │       │           │   └─ Eq\n" +
			"             │       │           │       ├─ SFEGG.DKCAJ:16!null\n" +
			"             │       │           │       └─ Subquery\n" +
			"             │       │           │           ├─ cacheable: false\n" +
			"             │       │           │           └─ Project\n" +
			"             │       │           │               ├─ columns: [nd.DKCAJ:19!null]\n" +
			"             │       │           │               └─ Filter\n" +
			"             │       │           │                   ├─ Eq\n" +
			"             │       │           │                   │   ├─ nd.TW55N:20!null\n" +
			"             │       │           │                   │   └─ TVTJS.I3VTA:2!null\n" +
			"             │       │           │                   └─ TableAlias(nd)\n" +
			"             │       │           │                       └─ IndexedTableAccess(E2I7U)\n" +
			"             │       │           │                           ├─ index: [E2I7U.TW55N]\n" +
			"             │       │           │                           └─ columns: [dkcaj tw55n]\n" +
			"             │       │           └─ Table\n" +
			"             │       │               ├─ name: SFEGG\n" +
			"             │       │               └─ columns: [id no52d vyo5e dkcaj adurz fhcyt]\n" +
			"             │       │   as OVE3E, NULL (null) as NRURT, NULL (null) as OCA7E, TVTJS.id:0!null as XMM6Q, TVTJS.V5DPX:4!null as V5DPX, (TVTJS.IDPK7:6!null + 0 (decimal(2,1))) as S3Q3Y, TVTJS.ZRV3B:8!null as ZRV3B, TVTJS.FHCYT:12 as FHCYT]\n" +
			"             │       └─ Filter\n" +
			"             │           ├─ HashIn\n" +
			"             │           │   ├─ TVTJS.id:0!null\n" +
			"             │           │   └─ TUPLE(1 (longtext), 2 (longtext), 3 (longtext))\n" +
			"             │           └─ TableAlias(TVTJS)\n" +
			"             │               └─ IndexedTableAccess(HU5A5)\n" +
			"             │                   ├─ index: [HU5A5.id]\n" +
			"             │                   ├─ static: [{[2, 2]}, {[3, 3]}, {[1, 1]}]\n" +
			"             │                   └─ columns: [id tofpn i3vta sfj6l v5dpx ljlum idpk7 no52d zrv3b vyo5e swcqv ykssu fhcyt]\n" +
			"             └─ BEGIN .. END\n" +
			"                 ├─ IF BLOCK\n" +
			"                 │   └─ IF(InSubquery\n" +
			"                 │       ├─ left: new.V5DPX:8!null\n" +
			"                 │       └─ right: Subquery\n" +
			"                 │           ├─ cacheable: false\n" +
			"                 │           └─ Table\n" +
			"                 │               ├─ name: TPXHZ\n" +
			"                 │               └─ columns: [svaz4]\n" +
			"                 │      )\n" +
			"                 │       └─ BLOCK\n" +
			"                 │           └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = String field contains invalid value, like empty string, 'none', 'null', 'n/a', 'nan' etc., MYSQL_ERRNO = 1644\n" +
			"                 └─ IF BLOCK\n" +
			"                     └─ IF(NOT\n" +
			"                         └─ IN\n" +
			"                             ├─ left: new.ZRV3B:10!null\n" +
			"                             └─ right: TUPLE(= (longtext), <= (longtext), >= (longtext), < (longtext), > (longtext))\n" +
			"                        )\n" +
			"                         └─ BLOCK\n" +
			"                             └─ SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = The ZRV3B must be on of the following: '=', '<=', '>=', '<', '>'., MYSQL_ERRNO = 1644\n" +
			"",
	},
}

IntegrationPlanTests is a test of generating the right query plans for more complex queries that closely represent real use cases by customers. Like other query plan tests, these tests are fragile because they rely on string representations of query plans, but they're much easier to construct this way. To regenerate these plans after analyzer changes, use the TestWriteIntegrationQueryPlans function in testgen_test.go.

View Source
var JSONTableQueryTests = []QueryTest{
	{
		Query:    "SELECT * FROM JSON_TABLE(NULL,'$[*]' COLUMNS(x int path '$.a')) as t;",
		Expected: []sql.Row{},
	},
	{
		Query: "SELECT * FROM JSON_TABLE('[{\"a\":1},{\"a\":2}]','$[*]' COLUMNS(x varchar(100) path '$.a')) as tt;",
		Expected: []sql.Row{
			{"1"},
			{"2"},
		},
	},
	{
		Query: "SELECT * FROM JSON_TABLE('[{\"a\":1, \"b\":2},{\"a\":3, \"b\":4}]',\"$[*]\" COLUMNS(x int path '$.a', y int path '$.b')) as tt;",
		Expected: []sql.Row{
			{1, 2},
			{3, 4},
		},
	},
	{
		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;",
		Expected: []sql.Row{
			{1.5, 2.25},
			{3.125, 4.0625},
		},
	},
	{
		Query: "SELECT * FROM JSON_TABLE(concat('[{},','{}]'),'$[*]' COLUMNS(x varchar(100) path '$.a',y varchar(100) path '$.b')) as t;",
		Expected: []sql.Row{
			{nil, nil},
			{nil, nil},
		},
	},
	{
		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;",
		Expected: []sql.Row{
			{1, 1},
			{1, 2},
			{2, 1},
			{2, 2},
		},
	},
	{
		Query: "select * from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t1 join one_pk order by x, pk;",
		Expected: []sql.Row{
			{1, 0, 0, 1, 2, 3, 4},
			{1, 1, 10, 11, 12, 13, 14},
			{1, 2, 20, 21, 22, 23, 24},
			{1, 3, 30, 31, 32, 33, 34},
			{2, 0, 0, 1, 2, 3, 4},
			{2, 1, 10, 11, 12, 13, 14},
			{2, 2, 20, 21, 22, 23, 24},
			{2, 3, 30, 31, 32, 33, 34},
		},
	},
	{
		Query: "select * from one_pk join JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t1 order by x, pk;",
		Expected: []sql.Row{
			{0, 0, 1, 2, 3, 4, 1},
			{1, 10, 11, 12, 13, 14, 1},
			{2, 20, 21, 22, 23, 24, 1},
			{3, 30, 31, 32, 33, 34, 1},
			{0, 0, 1, 2, 3, 4, 2},
			{1, 10, 11, 12, 13, 14, 2},
			{2, 20, 21, 22, 23, 24, 2},
			{3, 30, 31, 32, 33, 34, 2},
		},
	},
	{
		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",
		Expected: []sql.Row{
			{1},
			{2},
			{3},
			{4},
		},
	},
	{
		Query: "select * from one_pk where pk in (select x from JSON_TABLE('[{\"a\":1},{\"a\":2}]', '$[*]' COLUMNS(x int path '$.a')) as t)",
		Expected: []sql.Row{
			{1, 10, 11, 12, 13, 14},
			{2, 20, 21, 22, 23, 24},
		},
	},
	{
		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)",
		Expected: []sql.Row{
			{1},
		},
	},
	{
		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",
		Expected: []sql.Row{
			{1},
			{4},
			{7},
		},
	},
	{
		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;",
		Expected: []sql.Row{
			{1},
			{4},
			{7},
			{2},
			{5},
			{8},
			{3},
			{6},
			{9},
		},
	},
}
View Source
var JSONTableScriptTests = []ScriptTest{
	{
		Name: "create table from json column not qualified simple",
		SetUpScript: []string{
			"create table organizations (organization varchar(10), members json)",
			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
		},
		Query: "select names from organizations, JSON_TABLE(organizations.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
		Expected: []sql.Row{
			{"bob"},
			{"john"},
			{"alice"},
			{"mary"},
		},
	},
	{
		Name: "create table from json column not qualified complex",
		SetUpScript: []string{
			"create table organizations(organization varchar(10), members json);",
			`insert into organizations values("orgA", '["bob", "john"]'), ("orgB", '["alice", "mary"]'), ('orgC', '["kevin", "john"]'), ('orgD', '["alice", "alice"]')`,
		},
		Query: "SELECT names, COUNT(names) AS count FROM organizations, JSON_TABLE(organizations.members, '$[*]' COLUMNS (names varchar(100) path '$')) AS jt GROUP BY names ORDER BY names asc;",
		Expected: []sql.Row{
			{"alice", 3},
			{"bob", 1},
			{"john", 2},
			{"kevin", 1},
			{"mary", 1},
		},
	},
	{
		Name: "create table from json column qualified complex",
		SetUpScript: []string{
			"create table organizations(organization varchar(10), members json);",
			`insert into organizations values("orgA", '["bob", "john"]'), ("orgB", '["alice", "mary"]'), ('orgC', '["kevin", "john"]'), ('orgD', '["alice", "alice"]')`,
		},
		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;",
		Expected: []sql.Row{
			{"alice", 3},
			{"bob", 1},
			{"john", 2},
			{"kevin", 1},
			{"mary", 1},
		},
	},
	{
		Name: "create table from json column aliased",
		SetUpScript: []string{
			"create table organizations (organization varchar(10), members json)",
			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
		},
		Query: "select names from organizations o, JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
		Expected: []sql.Row{
			{"bob"},
			{"john"},
			{"alice"},
			{"mary"},
		},
	},
	{
		Name: "create table from json column aliased column",
		SetUpScript: []string{
			"create table organizations (organization varchar(10), members json)",
			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
		},
		Query: "select o.organization, jt.names from organizations o, JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
		Expected: []sql.Row{
			{"orgA", "bob"},
			{"orgA", "john"},
			{"orgB", "alice"},
			{"orgB", "mary"},
		},
	},
	{
		Name: "cross join json table",
		SetUpScript: []string{
			"create table organizations (organization varchar(10), members json)",
			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
		},
		Query: "select o.organization, jt.names from organizations o CROSS JOIN JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
		Expected: []sql.Row{
			{"orgA", "bob"},
			{"orgA", "john"},
			{"orgB", "alice"},
			{"orgB", "mary"},
		},
	},
	{
		Name: "natural join json table",
		SetUpScript: []string{
			"create table organizations (organization varchar(10), members json)",
			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
		},
		Query: "select o.organization, jt.names from organizations o NATURAL JOIN JSON_TABLE(o.members, '$[*]' columns (names varchar(100) path '$')) as jt;",
		Expected: []sql.Row{
			{"orgA", "bob"},
			{"orgA", "john"},
			{"orgB", "alice"},
			{"orgB", "mary"},
		},
	},
	{
		Name: "inner join json table with condition",
		SetUpScript: []string{
			"create table organizations (organization varchar(10), members json)",
			`insert into organizations values ("orgA", '["bob","john"]'), ("orgB", '["alice","mary"]')`,
		},
		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';",
		Expected: []sql.Row{
			{"orgA", "bob"},
			{"orgA", "john"},
		},
	},
	{
		Name: "inner join json table with condition in subquery",
		SetUpScript: []string{
			`create table p (i int primary key)`,
			`insert into p values (1),(2),(3)`,
		},
		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);`,
		Expected: []sql.Row{
			{1},
		},
	},
	{
		Name: "left join json table with condition",
		SetUpScript: []string{
			`create table p (i int primary key)`,
			`insert into p values (1),(2),(3)`,
		},
		Query: `select * from p left join JSON_TABLE('[1,2,3]', '$[*]' columns (i int path '$')) as jt on p.i > jt.i;`,
		Expected: []sql.Row{
			{1, nil},
			{2, 1},
			{3, 1},
			{3, 2},
		},
	},
	{
		Name: "right join json table with condition",
		SetUpScript: []string{
			`create table p (i int primary key)`,
			`insert into p values (1),(2),(3)`,
		},
		Query: `select * from p right join JSON_TABLE('[1,2,3]', '$[*]' columns (i int path '$')) as jt on p.i > jt.i;`,
		Expected: []sql.Row{
			{2, 1},
			{3, 1},
			{3, 2},
			{nil, 3},
		},
	},
	{
		Name: "json table in subquery references parent data",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query: "select i, (select names from JSON_Table(t.j, '$[*]' columns (names varchar(100) path '$')) jt) from t;",
		Expected: []sql.Row{
			{1, "test"},
		},
	},
	{
		Name: "json table in subquery qualified with parent",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query: "select (select names from JSON_Table(t.j, '$[*]' columns (names varchar(100) path '$')) jt) from t;",
		Expected: []sql.Row{
			{"test"},
		},
	},
	{
		Name: "json table in cte",
		SetUpScript: []string{
			`create table tbl (i int primary key, j json)`,
			`insert into tbl values (0, '[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]')`,
		},
		Query: "with c as (select jt.a from tbl, json_table(tbl.j, '$[*]' columns (a int path '$.a')) as jt) select * from c",
		Expected: []sql.Row{
			{1},
			{4},
			{7},
		},
	},
	{
		Name: "json table join with cte",
		SetUpScript: []string{
			`create table t (i int primary key)`,
			`insert into t values (1), (2)`,
		},
		Query: "with tt as (select * from t) select * from tt, json_table('[{\"a\":3}]', '$[*]' columns (a int path '$.a')) as jt",
		Expected: []sql.Row{
			{1, 3},
			{2, 3},
		},
	},
	{
		Name: "join table, json_table, json_table",
		SetUpScript: []string{
			`create table tbl (i int primary key, j json)`,
			`insert into tbl values (0, '[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]')`,
		},
		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;",
		Expected: []sql.Row{
			{1, 2, 3},
			{1, 2, 6},
			{1, 2, 9},
			{1, 5, 3},
			{1, 5, 6},
			{1, 5, 9},
			{1, 8, 3},
			{1, 8, 6},
			{1, 8, 9},
			{4, 2, 3},
			{4, 2, 6},
			{4, 2, 9},
			{4, 5, 3},
			{4, 5, 6},
			{4, 5, 9},
			{4, 8, 3},
			{4, 8, 6},
			{4, 8, 9},
			{7, 2, 3},
			{7, 2, 6},
			{7, 2, 9},
			{7, 5, 3},
			{7, 5, 6},
			{7, 5, 9},
			{7, 8, 3},
			{7, 8, 6},
			{7, 8, 9},
		},
	},
	{
		Name: "join table, table, json_table",
		SetUpScript: []string{
			`create table t1 (x int primary key)`,
			`insert into t1 values (1), (2)`,
			`create table t2 (y int primary key)`,
			`insert into t2 values (3), (4)`,
			`create table tbl (j json)`,
			`insert into tbl values ('[{"a":5},{"a":6}]')`,
		},
		Query: "select t1.x, t2.y, jt.a from t1, t2, tbl, json_table(tbl.j, '$[*]' columns (a int path '$.a')) as jt",
		Expected: []sql.Row{
			{1, 3, 5},
			{1, 3, 6},
			{1, 4, 5},
			{1, 4, 6},
			{2, 3, 5},
			{2, 3, 6},
			{2, 4, 5},
			{2, 4, 6},
		},
	},
	{
		Name: "join table, table, json_table two references past one node",
		SetUpScript: []string{
			`create table t1 (i int, x json)`,
			`insert into t1 values (1, '[{"a":5},{"a":6}]')`,
			`create table t2 (y int primary key)`,
			`insert into t2 values (3), (4)`,
			`create table tbl (j json)`,
			`insert into tbl values ('[{"a":5},{"a":6}]')`,
		},
		Query: "select t1.i, t2.y, jt.a from t1, t2, tbl, json_table(t1.x, '$[*]' columns (a int path '$.a')) as jt",
		Expected: []sql.Row{
			{1, 3, 5},
			{1, 3, 6},
			{1, 4, 5},
			{1, 4, 6},
		},
	},
	{
		Name: "table union cross join with json table",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query: "select t.j from t union select a from t, json_table(t.j, '$[*]' columns (a varchar(10) path '$')) as jt;",
		Expected: []sql.Row{
			{"[\"test\"]"},
			{"test"},
		},
	},

	{
		Name: "non existent unqualified column",
		SetUpScript: []string{
			"create table t (i int, j json)",
		},
		Query:       "select j.a from t, json_table(k, '$[*]' columns (a INT path '$.a')) AS j",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Name: "non existent qualified column",
		SetUpScript: []string{
			"create table t (i int, j json)",
		},
		Query:       "select t.a from t, json_table(t.k, '$[*]' columns (a INT path '$.a')) AS j",
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Name: "select from non existent json table column",
		SetUpScript: []string{
			"create table t (i int, j json)",
		},
		Query:       "select j.b from t, json_table(t.j, '$[*]' columns (a INT path '$.a')) AS j",
		ExpectedErr: sql.ErrTableColumnNotFound,
	},
	{
		Name: "subquery argument to json_table not allowed",
		SetUpScript: []string{
			"create table t (i int, j json)",
			`insert into t values (1, '["test"]')`,
		},
		Query:       "select * from json_table((select j from t), '$[*]' columns (a varchar(10) path '$')) as jt;",
		ExpectedErr: sql.ErrInvalidArgument,
	},
}
View Source
var JoinQueryTests = []QueryTest{
	{
		Query: "select ab.* from ab join pq on a = p where b = (select y from xy where y in (select v from uv where v = b)) order by a;",
		Expected: []sql.Row{
			{0, 2},
			{1, 2},
			{2, 2},
			{3, 1},
		},
	},
	{
		Query: "select * from ab where b in (select y from xy where y in (select v from uv where v = b));",
		Expected: []sql.Row{
			{0, 2},
			{1, 2},
			{2, 2},
			{3, 1},
		},
	},
	{
		Query: "select * from ab where a in (select y from xy where y in (select v from uv where v = a));",
		Expected: []sql.Row{
			{1, 2},
			{2, 2},
		},
	},
	{
		Query: "select * from ab where a in (select x from xy where x in (select u from uv where u = a));",
		Expected: []sql.Row{
			{1, 2},
			{2, 2},
			{0, 2},
			{3, 1},
		},
	},
	{

		Query: `select y, (select 1 from uv where y = 1 and u = x) is_one from xy join uv on x = v order by y;`,
		Expected: []sql.Row{
			{0, nil},
			{0, nil},
			{1, 1},
			{1, 1},
		},
	},
	{
		Query: `select y, (select 1 where y = 1) is_one from xy join uv on x = v order by y`,
		Expected: []sql.Row{
			{0, nil},
			{0, nil},
			{1, 1},
			{1, 1},
		},
	},
	{
		Query: `select * from (select y, (select 1 where y = 1) is_one from xy join uv on x = v) sq order by y`,
		Expected: []sql.Row{
			{0, nil},
			{0, nil},
			{1, 1},
			{1, 1},
		},
	},
	{
		Query:    `with cte1 as (select u, v from cte2 join ab on cte2.u = b), cte2 as (select u,v from uv join ab on u = b where u in (2,3)) select * from xy where (x) not in (select u from cte1) order by 1`,
		Expected: []sql.Row{{0, 2}, {1, 0}, {3, 3}},
	},
	{
		Query:    `SELECT (SELECT 1 FROM (SELECT x FROM xy INNER JOIN uv ON (x = u OR y = v) LIMIT 1) r) AS s FROM xy`,
		Expected: []sql.Row{{1}, {1}, {1}, {1}},
	},
	{
		Query:    `select a from ab where exists (select 1 from xy where a =x)`,
		Expected: []sql.Row{{0}, {1}, {2}, {3}},
	},
	{
		Query:    "select a from ab where exists (select 1 from xy where a = x and b = 2 and y = 2);",
		Expected: []sql.Row{{0}},
	},
	{
		Query:    "select * from uv where exists (select 1, count(a) from ab where u = a group by a)",
		Expected: []sql.Row{{0, 1}, {1, 1}, {2, 2}, {3, 2}},
	},
	{
		Query: `
select * from
(
  select * from ab
  left join uv on a = u
  where exists (select * from pq where u = p)
) alias2
inner join xy on a = x;`,
		Expected: []sql.Row{
			{0, 2, 0, 1, 0, 2},
			{1, 2, 1, 1, 1, 0},
			{2, 2, 2, 2, 2, 1},
			{3, 1, 3, 2, 3, 3},
		},
	},
	{
		Query: `
select * from ab
where exists
(
  select * from uv
  left join pq on u = p
  where a = u
);`,
		Expected: []sql.Row{
			{0, 2},
			{1, 2},
			{2, 2},
			{3, 1},
		},
	},
	{
		Query: `
select * from
(
  select * from ab
  where not exists (select * from uv where a = v)
) alias1
where exists (select * from xy where a = x);`,
		Expected: []sql.Row{
			{0, 2},
			{3, 1},
		}},
	{
		Query: `
select * from
(
  select * from ab
  inner join xy on true
) alias1
inner join uv on true
inner join pq on true order by 1,2,3,4,5,6,7,8 limit 5;`,
		Expected: []sql.Row{
			{0, 2, 0, 2, 0, 1, 0, 0},
			{0, 2, 0, 2, 0, 1, 1, 1},
			{0, 2, 0, 2, 0, 1, 2, 2},
			{0, 2, 0, 2, 0, 1, 3, 3},
			{0, 2, 0, 2, 1, 1, 0, 0},
		},
	},
	{
		Query: `
	select * from
	(
	 select * from ab
	 where not exists (select * from xy where a = y+1)
	) alias1
	left join pq on alias1.a = p
	where exists (select * from uv where a = u);`,
		Expected: []sql.Row{
			{0, 2, 0, 0},
		}},
	{

		Query: "SELECT mytable.i " +
			"FROM mytable " +
			"INNER JOIN othertable ON (mytable.i = othertable.i2) " +
			"LEFT JOIN othertable T4 ON (mytable.i = T4.i2) " +
			"ORDER BY othertable.i2, T4.s2",
		Expected: []sql.Row{{1}, {2}, {3}},
	},
	{

		Query:    "select 1 as exprAlias, 2, 3, (select exprAlias + count(*) from one_pk_three_idx a cross join one_pk_three_idx b);",
		Expected: []sql.Row{{1, 2, 3, 65}},
	},
	{

		Query:    "select pk, v1, v2 from one_pk_three_idx where v1 in (select max(a.v1) from one_pk_three_idx a cross join (select 'foo' from dual) b);",
		Expected: []sql.Row{{7, 4, 4}},
	},
	{

		Query: "select * from (select a.v1, b.v2 from one_pk_three_idx a cross join one_pk_three_idx b) dt order by 1 desc, 2 desc limit 5;",
		Expected: []sql.Row{
			{4, 4},
			{4, 3},
			{4, 2},
			{4, 1},
			{4, 0},
		},
	},
	{
		Query: "select a.pk, c.v2 from one_pk_three_idx a cross join one_pk_three_idx b left join one_pk_three_idx c on b.pk = c.v2 where b.pk = 0 and a.v2 = 1;",
		Expected: []sql.Row{
			{2, 0},
			{2, 0},
			{2, 0},
			{2, 0},
		},
	},
	{
		Query: "select a.pk, c.v2 from one_pk_three_idx a cross join one_pk_three_idx b right join one_pk_three_idx c on b.pk = c.v3 where b.pk = 0 and c.v2 = 0 order by a.pk;",
		Expected: []sql.Row{
			{0, 0},
			{0, 0},
			{1, 0},
			{1, 0},
			{2, 0},
			{2, 0},
			{3, 0},
			{3, 0},
			{4, 0},
			{4, 0},
			{5, 0},
			{5, 0},
			{6, 0},
			{6, 0},
			{7, 0},
			{7, 0},
		},
	},
	{
		Query: "select a.pk, c.v2 from one_pk_three_idx a cross join one_pk_three_idx b inner join (select * from one_pk_three_idx where v2 = 0) c on b.pk = c.v3 where b.pk = 0 and c.v2 = 0 order by a.pk;",
		Expected: []sql.Row{
			{0, 0},
			{0, 0},
			{1, 0},
			{1, 0},
			{2, 0},
			{2, 0},
			{3, 0},
			{3, 0},
			{4, 0},
			{4, 0},
			{5, 0},
			{5, 0},
			{6, 0},
			{6, 0},
			{7, 0},
			{7, 0},
		},
	},
	{
		Query: "select a.pk, c.v2 from one_pk_three_idx a cross join one_pk_three_idx b left join one_pk_three_idx c on b.pk = c.v1+1 where b.pk = 0 order by a.pk;",
		Expected: []sql.Row{
			{0, nil},
			{1, nil},
			{2, nil},
			{3, nil},
			{4, nil},
			{5, nil},
			{6, nil},
			{7, nil},
		},
	},
	{
		Query: "select a.pk, c.v2 from one_pk_three_idx a cross join one_pk_three_idx b right join one_pk_three_idx c on b.pk = c.v1 where b.pk = 0 and c.v2 = 0 order by a.pk;",
		Expected: []sql.Row{
			{0, 0},
			{0, 0},
			{1, 0},
			{1, 0},
			{2, 0},
			{2, 0},
			{3, 0},
			{3, 0},
			{4, 0},
			{4, 0},
			{5, 0},
			{5, 0},
			{6, 0},
			{6, 0},
			{7, 0},
			{7, 0},
		},
	},
	{
		Query: "select * from mytable a CROSS JOIN mytable b RIGHT JOIN mytable c ON b.i = c.i + 1 order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{nil, nil, nil, nil, 3, "third row"},
			{1, "first row", 2, "second row", 1, "first row"},
			{1, "first row", 3, "third row", 2, "second row"},
			{2, "second row", 2, "second row", 1, "first row"},
			{2, "second row", 3, "third row", 2, "second row"},
			{3, "third row", 2, "second row", 1, "first row"},
			{3, "third row", 3, "third row", 2, "second row"},
		},
	},
	{
		Query: "select * from mytable a CROSS JOIN mytable b LEFT JOIN mytable c ON b.i = c.i + 1 order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{1, "first row", 1, "first row", nil, nil},
			{1, "first row", 2, "second row", 1, "first row"},
			{1, "first row", 3, "third row", 2, "second row"},
			{2, "second row", 1, "first row", nil, nil},
			{2, "second row", 2, "second row", 1, "first row"},
			{2, "second row", 3, "third row", 2, "second row"},
			{3, "third row", 1, "first row", nil, nil},
			{3, "third row", 2, "second row", 1, "first row"},
			{3, "third row", 3, "third row", 2, "second row"},
		},
	},
	{
		Query: "select a.i, b.i, c.i from mytable a CROSS JOIN mytable b LEFT JOIN mytable c ON b.i+1 = c.i order by 1,2,3;",
		Expected: []sql.Row{
			{1, 1, 2},
			{1, 2, 3},
			{1, 3, nil},
			{2, 1, 2},
			{2, 2, 3},
			{2, 3, nil},
			{3, 1, 2},
			{3, 2, 3},
			{3, 3, nil},
		}},
	{
		Query: "select * from mytable a LEFT JOIN mytable b on a.i = b.i LEFT JOIN mytable c ON b.i = c.i + 1 order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{1, "first row", 1, "first row", nil, nil},
			{2, "second row", 2, "second row", 1, "first row"},
			{3, "third row", 3, "third row", 2, "second row"},
		},
	},
	{
		Query: "select * from mytable a LEFT JOIN  mytable b on a.i = b.i RIGHT JOIN mytable c ON b.i = c.i + 1 order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{nil, nil, nil, nil, 3, "third row"},
			{2, "second row", 2, "second row", 1, "first row"},
			{3, "third row", 3, "third row", 2, "second row"},
		},
	},
	{
		Query: "select * from mytable a RIGHT JOIN mytable b on a.i = b.i RIGHT JOIN mytable c ON b.i = c.i + 1 order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{nil, nil, nil, nil, 3, "third row"},
			{2, "second row", 2, "second row", 1, "first row"},
			{3, "third row", 3, "third row", 2, "second row"},
		},
	},
	{
		Query: "select * from mytable a RIGHT JOIN mytable b on a.i = b.i LEFT JOIN mytable c ON b.i = c.i + 1;",
		Expected: []sql.Row{
			{1, "first row", 1, "first row", nil, nil},
			{2, "second row", 2, "second row", 1, "first row"},
			{3, "third row", 3, "third row", 2, "second row"},
		},
	},
	{
		Query: "select * from mytable a LEFT JOIN mytable b on a.i = b.i LEFT JOIN mytable c ON b.i+1 = c.i;",
		Expected: []sql.Row{
			{1, "first row", 1, "first row", 2, "second row"},
			{2, "second row", 2, "second row", 3, "third row"},
			{3, "third row", 3, "third row", nil, nil},
		}},
	{
		Query: "select * from mytable a LEFT JOIN  mytable b on a.i = b.i RIGHT JOIN mytable c ON b.i+1 = c.i order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{nil, nil, nil, nil, 1, "first row"},
			{1, "first row", 1, "first row", 2, "second row"},
			{2, "second row", 2, "second row", 3, "third row"},
		}},
	{
		Query: "select * from mytable a RIGHT JOIN mytable b on a.i = b.i RIGHT JOIN mytable c ON b.i+1= c.i order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{nil, nil, nil, nil, 1, "first row"},
			{1, "first row", 1, "first row", 2, "second row"},
			{2, "second row", 2, "second row", 3, "third row"},
		}},
	{
		Query: "select * from mytable a RIGHT JOIN mytable b on a.i = b.i LEFT JOIN mytable c ON b.i+1 = c.i order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{1, "first row", 1, "first row", 2, "second row"},
			{2, "second row", 2, "second row", 3, "third row"},
			{3, "third row", 3, "third row", nil, nil},
		},
	},
	{
		Query: "select * from mytable a CROSS JOIN mytable b RIGHT JOIN mytable c ON b.i+1 = c.i order by 1,2,3,4,5,6;",
		Expected: []sql.Row{
			{nil, nil, nil, nil, 1, "first row"},
			{1, "first row", 1, "first row", 2, "second row"},
			{1, "first row", 2, "second row", 3, "third row"},
			{2, "second row", 1, "first row", 2, "second row"},
			{2, "second row", 2, "second row", 3, "third row"},
			{3, "third row", 1, "first row", 2, "second row"},
			{3, "third row", 2, "second row", 3, "third row"},
		},
	},
	{
		Query: "with a as (select a.i, a.s from mytable a CROSS JOIN mytable b) select * from a RIGHT JOIN mytable c on a.i+1 = c.i-1;",
		Expected: []sql.Row{
			{nil, nil, 1, "first row"},
			{nil, nil, 2, "second row"},
			{1, "first row", 3, "third row"},
			{1, "first row", 3, "third row"},
			{1, "first row", 3, "third row"},
		},
	},
	{
		Query: "select a.* from mytable a RIGHT JOIN mytable b on a.i = b.i+1 LEFT JOIN mytable c on a.i = c.i-1 RIGHT JOIN mytable d on b.i = d.i;",
		Expected: []sql.Row{
			{2, "second row"},
			{3, "third row"},
			{nil, nil},
		},
	},
	{
		Query: "select a.*,b.* from mytable a RIGHT JOIN othertable b on a.i = b.i2+1 LEFT JOIN mytable c on a.i = c.i-1 LEFT JOIN othertable d on b.i2 = d.i2;",
		Expected: []sql.Row{
			{2, "second row", "third", 1},
			{3, "third row", "second", 2},
			{nil, nil, "first", 3},
		},
	},
	{
		Query: "select a.*,b.* from mytable a RIGHT JOIN othertable b on a.i = b.i2+1 RIGHT JOIN mytable c on a.i = c.i-1 LEFT JOIN othertable d on b.i2 = d.i2;",
		Expected: []sql.Row{
			{nil, nil, nil, nil},
			{nil, nil, nil, nil},
			{2, "second row", "third", 1},
		},
	},
	{
		Query:    "select i.pk, j.v3 from one_pk_two_idx i JOIN one_pk_three_idx j on i.v1 = j.pk;",
		Expected: []sql.Row{{0, 0}, {1, 1}, {2, 0}, {3, 2}, {4, 0}, {5, 3}, {6, 0}, {7, 4}},
	},
	{
		Query:    "select i.pk, j.v3, k.c1 from one_pk_two_idx i JOIN one_pk_three_idx j on i.v1 = j.pk JOIN one_pk k on j.v3 = k.pk;",
		Expected: []sql.Row{{0, 0, 0}, {1, 1, 10}, {2, 0, 0}, {3, 2, 20}, {4, 0, 0}, {5, 3, 30}, {6, 0, 0}},
	},
	{
		Query:    "select i.pk, j.v3 from (one_pk_two_idx i JOIN one_pk_three_idx j on((i.v1 = j.pk)));",
		Expected: []sql.Row{{0, 0}, {1, 1}, {2, 0}, {3, 2}, {4, 0}, {5, 3}, {6, 0}, {7, 4}},
	},
	{
		Query:    "select i.pk, j.v3, k.c1 from ((one_pk_two_idx i JOIN one_pk_three_idx j on ((i.v1 = j.pk))) JOIN one_pk k on((j.v3 = k.pk)));",
		Expected: []sql.Row{{0, 0, 0}, {1, 1, 10}, {2, 0, 0}, {3, 2, 20}, {4, 0, 0}, {5, 3, 30}, {6, 0, 0}},
	},
	{
		Query:    "select i.pk, j.v3, k.c1 from (one_pk_two_idx i JOIN one_pk_three_idx j on ((i.v1 = j.pk)) JOIN one_pk k on((j.v3 = k.pk)));",
		Expected: []sql.Row{{0, 0, 0}, {1, 1, 10}, {2, 0, 0}, {3, 2, 20}, {4, 0, 0}, {5, 3, 30}, {6, 0, 0}},
	},
	{
		Query: "select a.* from one_pk_two_idx a RIGHT JOIN (one_pk_two_idx i JOIN one_pk_three_idx j on i.v1 = j.pk) on a.pk = i.v1 LEFT JOIN (one_pk_two_idx k JOIN one_pk_three_idx l on k.v1 = l.pk) on a.pk = l.v2;",
		Expected: []sql.Row{{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{1, 1, 1},
			{2, 2, 2},
			{3, 3, 3},
			{4, 4, 4},
			{5, 5, 5},
			{6, 6, 6},
			{7, 7, 7}},
	},
	{
		Query: "select a.* from one_pk_two_idx a LEFT JOIN (one_pk_two_idx i JOIN one_pk_three_idx j on i.pk = j.v3) on a.pk = i.pk RIGHT JOIN (one_pk_two_idx k JOIN one_pk_three_idx l on k.v2 = l.v3) on a.v1 = l.v2;",
		Expected: []sql.Row{{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{1, 1, 1},
			{2, 2, 2},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{0, 0, 0},
			{3, 3, 3},
			{4, 4, 4},
		},
	},
	{
		Query: "select a.* from mytable a join mytable b on a.i = b.i and a.i > 2",
		Expected: []sql.Row{
			{3, "third row"},
		},
	},
	{
		Query: "select a.* from mytable a join mytable b on a.i = b.i and now() >= coalesce(NULL, NULL, now())",
		Expected: []sql.Row{
			{1, "first row"},
			{2, "second row"},
			{3, "third row"}},
	},
	{
		Query: "select * from mytable a join niltable  b on a.i = b.i and b <=> NULL",
		Expected: []sql.Row{
			{1, "first row", 1, nil, nil, nil},
		},
	},
	{
		Query: "select * from mytable a join niltable  b on a.i = b.i and s IS NOT NULL",
		Expected: []sql.Row{
			{1, "first row", 1, nil, nil, nil},
			{2, "second row", 2, 2, 1, nil},
			{3, "third row", 3, nil, 0, nil},
		},
	},
	{
		Query: "select * from mytable a join niltable  b on a.i = b.i and b IS NOT NULL",
		Expected: []sql.Row{
			{2, "second row", 2, 2, 1, nil},
			{3, "third row", 3, nil, 0, nil},
		},
	},
	{
		Query: "select * from mytable a join niltable  b on a.i = b.i and b != 0",
		Expected: []sql.Row{
			{2, "second row", 2, 2, 1, nil},
		},
	},
	{
		Query: "select * from mytable a join niltable  b on a.i <> b.i and b != 0;",
		Expected: []sql.Row{
			{3, "third row", 2, 2, 1, nil},
			{1, "first row", 2, 2, 1, nil},
			{3, "third row", 5, nil, 1, float64(5)},
			{2, "second row", 5, nil, 1, float64(5)},
			{1, "first row", 5, nil, 1, float64(5)},
		},
	},
	{
		Query: "select * from mytable a join niltable  b on a.i <> b.i;",
		Expected: []sql.Row{
			{3, "third row", 1, nil, nil, nil},
			{2, "second row", 1, nil, nil, nil},
			{3, "third row", 2, 2, 1, nil},
			{1, "first row", 2, 2, 1, nil},
			{2, "second row", 3, nil, 0, nil},
			{1, "first row", 3, nil, 0, nil},
			{3, "third row", 5, nil, 1, float64(5)},
			{2, "second row", 5, nil, 1, float64(5)},
			{1, "first row", 5, nil, 1, float64(5)},
			{3, "third row", 4, 4, nil, float64(4)},
			{2, "second row", 4, 4, nil, float64(4)},
			{1, "first row", 4, 4, nil, float64(4)},
			{3, "third row", 6, 6, 0, float64(6)},
			{2, "second row", 6, 6, 0, float64(6)},
			{1, "first row", 6, 6, 0, float64(6)},
		},
	},
	{
		Query: "select * from ab full join pq on a = p order by 1,2,3,4;",
		Expected: []sql.Row{
			{0, 2, 0, 0},
			{1, 2, 1, 1},
			{2, 2, 2, 2},
			{3, 1, 3, 3},
		},
	},
	{
		Query: `
	select * from ab
	inner join uv on a = u
	full join pq on a = p order by 1,2,3,4,5,6;`,
		Expected: []sql.Row{
			{0, 2, 0, 1, 0, 0},
			{1, 2, 1, 1, 1, 1},
			{2, 2, 2, 2, 2, 2},
			{3, 1, 3, 2, 3, 3},
		},
	},
	{
		Query: `
	select * from ab
	full join pq on a = p
	left join xy on a = x order by 1,2,3,4,5,6;`,
		Expected: []sql.Row{
			{0, 2, 0, 0, 0, 2},
			{1, 2, 1, 1, 1, 0},
			{2, 2, 2, 2, 2, 1},
			{3, 1, 3, 3, 3, 3},
		},
	},
	{
		Query: `select * from (select a,v from ab join uv on a=u) av join (select x,q from xy join pq on x = p) xq on av.v = xq.x`,
		Expected: []sql.Row{
			{0, 1, 1, 1},
			{1, 1, 1, 1},
			{2, 2, 2, 2},
			{3, 2, 2, 2},
		},
	},
	{
		Query:    "select x from xy join uv on y = v join ab on y = b and u = -1",
		Expected: []sql.Row{},
	},
	{
		Query: "select a.* from one_pk_two_idx a LEFT JOIN (one_pk_two_idx i JOIN one_pk_three_idx j on i.pk = j.v3) on a.pk = i.pk LEFT JOIN (one_pk_two_idx k JOIN one_pk_three_idx l on k.v2 = l.v3) on a.v1 = l.v2;",
		Expected: []sql.Row{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
			{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {1, 1, 1}, {2, 2, 2}, {3, 3, 3}, {4, 4, 4}, {5, 5, 5}, {6, 6, 6}, {7, 7, 7},
		},
	},
	{
		Query:    "with recursive a(x,y) as (select i,i from mytable where i < 4 union select a.x, mytable.i from a join mytable on a.x+1 = mytable.i limit 2) select * from a;",
		Expected: []sql.Row{{1, 1}, {2, 2}},
	},
	{
		Query: `
select * from (
    (ab JOIN pq ON (1 = p))
	LEFT OUTER JOIN uv on (2 = u)
);`,
		Expected: []sql.Row{
			{0, 2, 1, 1, 2, 2},
			{1, 2, 1, 1, 2, 2},
			{2, 2, 1, 1, 2, 2},
			{3, 1, 1, 1, 2, 2},
		},
	},
	{
		Query: "select * from (ab JOIN pq ON (a = 1)) where a in (1,2,3)",
		Expected: []sql.Row{
			{1, 2, 0, 0},
			{1, 2, 1, 1},
			{1, 2, 2, 2},
			{1, 2, 3, 3}},
	},
	{
		Query: "select * from (ab JOIN pq ON (a = p)) where a in (select a from ab)",
		Expected: []sql.Row{
			{0, 2, 0, 0},
			{1, 2, 1, 1},
			{2, 2, 2, 2},
			{3, 1, 3, 3}},
	},
	{
		Query: "select * from (ab JOIN pq ON (a = 1)) where a in (select a from ab)",
		Expected: []sql.Row{
			{1, 2, 0, 0},
			{1, 2, 1, 1},
			{1, 2, 2, 2},
			{1, 2, 3, 3}},
	},
	{
		Query: "select * from (ab JOIN pq) where a in (select a from ab)",
		Expected: []sql.Row{
			{0, 2, 0, 0},
			{0, 2, 1, 1},
			{0, 2, 2, 2},
			{0, 2, 3, 3},
			{1, 2, 0, 0},
			{1, 2, 1, 1},
			{1, 2, 2, 2},
			{1, 2, 3, 3},
			{2, 2, 0, 0},
			{2, 2, 1, 1},
			{2, 2, 2, 2},
			{2, 2, 3, 3},
			{3, 1, 0, 0},
			{3, 1, 1, 1},
			{3, 1, 2, 2},
			{3, 1, 3, 3}},
	},
	{
		Query: "select * from (ab JOIN pq ON (a = 1)) where a in (1,2,3)",
		Expected: []sql.Row{
			{1, 2, 0, 0},
			{1, 2, 1, 1},
			{1, 2, 2, 2},
			{1, 2, 3, 3}},
	},
	{
		Query: "select * from (ab JOIN pq ON (a = 1)) where a in (select a from ab)",
		Expected: []sql.Row{
			{1, 2, 0, 0},
			{1, 2, 1, 1},
			{1, 2, 2, 2},
			{1, 2, 3, 3}},
	},
	{

		Query: `SELECT count(*)
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 t1
join
JSON_TABLE(
	'[{"c":2, "d":3},{"c":4, "d":5}]',
	'$[*]' COLUMNS(z float path '$.c', w float path '$.d')
) as t2
on w = 0;`,
		Expected: []sql.Row{{0}},
	},
}
View Source
var JoinScriptTests = []ScriptTest{
	{
		Name: "Complex join query with foreign key constraints",
		SetUpScript: []string{
			"CREATE TABLE `users` (`id` int NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, PRIMARY KEY (`id`));",
			"CREATE TABLE `tweet` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `content` text NOT NULL, `timestamp` bigint NOT NULL, PRIMARY KEY (`id`), KEY `tweet_user_id` (`user_id`), CONSTRAINT `0qpfesgd` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`));",
			"INSERT INTO `users` (`id`,`username`) VALUES (1,'huey'), (2,'zaizee'), (3,'mickey')",
			"INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (1,1,'meow',1647463727), (2,1,'purr',1647463727), (3,2,'hiss',1647463727), (4,3,'woof',1647463727)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    " SELECT `t1`.`username`, COUNT(`t1`.`id`) AS `ct` FROM ((SELECT `t2`.`id`, `t2`.`content`, `t3`.`username` FROM `tweet` AS `t2` INNER JOIN `users` AS `t3` ON (`t2`.`user_id` = `t3`.`id`) WHERE (`t3`.`username` = 'u3')) UNION (SELECT `t4`.`id`, `t4`.`content`, `t5`.`username` FROM `tweet` AS `t4` INNER JOIN `users` AS `t5` ON (`t4`.`user_id` = `t5`.`id`) WHERE (`t5`.`username` IN ('u2', 'u4')))) AS `t1` GROUP BY `t1`.`username` ORDER BY COUNT(`t1`.`id`) DESC;",
				Expected: []sql.Row{},
			},
		},
	},
}
View Source
var JsonScripts = []ScriptTest{
	{
		Name: "JSON_ARRAYAGG on one column",
		SetUpScript: []string{
			"create table t (o_id int primary key)",
			"INSERT INTO t VALUES (1),(2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT JSON_ARRAYAGG(o_id) FROM (SELECT * FROM t ORDER BY o_id) as sub",
				Expected: []sql.Row{
					{
						types.MustJSON(`[1,2]`),
					},
				},
			},
		},
	},
	{
		Name: "Simple JSON_ARRAYAGG on two columns",
		SetUpScript: []string{
			"create table t (o_id int primary key, attribute longtext)",
			"INSERT INTO t VALUES (1, 'color'), (2, 'fabric')",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT JSON_ARRAYAGG(o_id), JSON_ARRAYAGG(`attribute`) FROM (SELECT * FROM t ORDER BY o_id) as sub;",
				Expected: []sql.Row{
					{
						types.MustJSON(`[1,2]`),
						types.MustJSON(`["color","fabric"]`),
					},
				},
			},
		},
	},
	{
		Name: "JSON_ARRAYAGG on column with string values w/ groupby",
		SetUpScript: []string{
			"create table t (o_id int primary key, c0 int, attribute longtext, value longtext)",
			"INSERT INTO t VALUES (1, 2, 'color', 'red'), (2, 2, 'fabric', 'silk')",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT c0, JSON_ARRAYAGG(`attribute`) FROM (SELECT * FROM t ORDER BY o_id) as sub GROUP BY c0",
				Expected: []sql.Row{
					{
						2,
						types.MustJSON(`["color","fabric"]`),
					},
				},
			},
			{
				Query: "SELECT c0, JSON_ARRAYAGG(value) FROM (SELECT * FROM t ORDER BY o_id) as sub GROUP BY c0",
				Expected: []sql.Row{
					{
						2,
						types.MustJSON(`["red","silk"]`),
					},
				},
			},
		},
	},
	{
		Name: "JSON_ARRAYAGG on column with int values w/ groupby",
		SetUpScript: []string{
			"create table t2 (o_id int primary key, val int)",
			"INSERT INTO t2 VALUES (1,1), (2,1), (3,1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT val, JSON_ARRAYAGG(o_id) FROM (SELECT * FROM t2 ORDER BY o_id) AS sub GROUP BY val",
				Expected: []sql.Row{
					{
						1,
						types.MustJSON(`[1,2,3]`),
					},
				},
			},
		},
	},
	{
		Name: "JSON_ARRAYAGG on unknown column throws error",
		SetUpScript: []string{
			"create table t2 (o_id int primary key, val int)",
			"INSERT INTO t2 VALUES (1,1), (2,2), (3,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "SELECT o_id, JSON_ARRAYAGG(val2) FROM t2 GROUP BY o_id",
				ExpectedErr: sql.ErrColumnNotFound,
			},
		},
	},
	{
		Name: "JSON_ARRAYAGG on column with no rows returns NULL",
		SetUpScript: []string{
			"create table t2 (o_id int primary key)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT JSON_ARRAYAGG(o_id) FROM t2",
				Expected: []sql.Row{
					{
						types.MustJSON(`[]`),
					},
				},
			},
		},
	},
	{
		Name: "JSON_ARRAYAGG on row with 1 value, 1 null is fine",
		SetUpScript: []string{
			"create table x(pk int primary key, c1 int)",
			"INSERT INTO x VALUES (1,NULL)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT pk, JSON_ARRAYAGG(c1) FROM x GROUP BY pk",
				Expected: []sql.Row{
					{1, types.MustJSON(`[null]`)},
				},
			},
			{
				Query: "SELECT JSON_ARRAYAGG(c1) FROM x",
				Expected: []sql.Row{
					{types.MustJSON(`[null]`)},
				},
			},
		},
	},
	{
		Name: "JSON_ARRAYAGG and group by use the same field.",
		SetUpScript: []string{
			"create table x(pk int primary key, c1 int)",
			"INSERT INTO x VALUES (1, 1)",
			"INSERT INTO x VALUES (2, 1)",
			"INSERT INTO x VALUES (3, 3)",
			"INSERT INTO x VALUES (4, 3)",
			"INSERT INTO x VALUES (5, 5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT JSON_ARRAYAGG(pk) FROM (SELECT * FROM x ORDER BY pk) as sub GROUP BY c1",
				Expected: []sql.Row{
					{types.MustJSON(`[1,2]`)},
					{types.MustJSON(`[3,4]`)},
					{types.MustJSON(`[5]`)},
				},
			},
		},
	},
	{
		Name: "JSON_ARRAGG with simple and nested json objects.",
		SetUpScript: []string{
			"create table j(pk int primary key, field JSON)",
			`INSERT INTO j VALUES(1, '{"key1": {"key": "value"}}')`,
			`INSERT INTO j VALUES(2, '{"key1": "value1", "key2": "value2"}')`,
			`INSERT INTO j VALUES(3, '{"key1": {"key": [2,3]}}')`,
			`INSERT INTO j VALUES(4, '["a", 1]')`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT pk, JSON_ARRAYAGG(field) FROM (SELECT * FROM j ORDER BY pk) as sub GROUP BY field ORDER BY pk",
				Expected: []sql.Row{
					{1, types.MustJSON(`[{"key1": {"key": "value"}}]`)},
					{2, types.MustJSON(`[{"key1": "value1", "key2": "value2"}]`)},
					{3, types.MustJSON(`[{"key1":{"key":[2,3]}}]`)},
					{4, types.MustJSON(`[["a",1]]`)},
				},
			},
		},
	},
	{
		Name: "Simple JSON_OBJECTAGG with GROUP BY",
		SetUpScript: []string{
			"create table t2 (o_id int primary key, val int)",
			"INSERT INTO t2 VALUES (1,1), (2,1), (3,1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT JSON_OBJECTAGG(val, o_id) FROM (SELECT * FROM t2 ORDER BY o_id) as sub GROUP BY val",
				Expected: []sql.Row{
					{types.MustJSON(`{"1": 3}`)},
				},
			},
		},
	},
	{
		Name: "More complex JSON_OBJECTAGG WITH GROUP BY",
		SetUpScript: []string{
			"create table t (o_id int primary key, c0 int, attribute longtext, value longtext)",
			"INSERT INTO t VALUES (1, 2, 'color', 'red'), (2, 2, 'fabric', 'silk')",
			"INSERT INTO t VALUES (3, 3, 'color', 'green'), (4, 3, 'shape', 'square')",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT c0, JSON_OBJECTAGG(`attribute`, value) FROM (SELECT * FROM t ORDER BY o_id) as sub GROUP BY c0",
				Expected: []sql.Row{
					{2, types.MustJSON(`{"color": "red", "fabric": "silk"}`)},
					{3, types.MustJSON(`{"color": "green", "shape": "square"}`)},
				},
			},
			{
				Query: `SELECT c0, JSON_OBJECTAGG(c0, value) FROM (SELECT * FROM t ORDER BY o_id) as sub GROUP BY c0`,
				Expected: []sql.Row{
					{2, types.MustJSON(`{"2": "silk"}`)},
					{3, types.MustJSON(`{"3": "square"}`)},
				},
			},
		},
	},
	{
		Name: "3 column table that uses JSON_OBJECTAGG without groupby",
		SetUpScript: []string{
			"create table t (o_id int primary key, c0 int, attribute longtext, value longtext)",
			"INSERT INTO t VALUES (1, 2, 'color', 'red'), (2, 2, 'fabric', 'silk')",
			"INSERT INTO t VALUES (3, 3, 'color', 'green'), (4, 3, 'shape', 'square')",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `select JSON_OBJECTAGG(c0, value) from (SELECT * FROM t ORDER BY o_id) as sub`,
				Expected: []sql.Row{
					{types.MustJSON(`{"2": "silk", "3": "square"}`)},
				},
			},
			{
				Query: "select JSON_OBJECTAGG(`attribute`, value) from (SELECT * FROM t ORDER BY o_id) as sub",
				Expected: []sql.Row{
					{types.MustJSON(`{"color": "green", "fabric": "silk", "shape": "square"}`)},
				},
			},
		},
	},
	{
		Name: "JSON_OBJECTAGG and null values",
		SetUpScript: []string{
			`create table test (pk int primary key, val longtext)`,
			`insert into test values (1, NULL)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT JSON_OBJECTAGG(pk, val) from test`,
				Expected: []sql.Row{
					{types.MustJSON(`{"1": null}`)},
				},
			},
		},
	},
	{
		Name: "JSON_OBJECTAGG and nested json values",
		SetUpScript: []string{
			"create table j(pk int primary key, c0 int, val JSON)",
			`INSERT INTO j VALUES(1, 1, '{"key1": "value1", "key2": "value2"}')`,
			`INSERT INTO j VALUES(2, 1, '{"key1": {"key": [2,3]}}')`,
			`INSERT INTO j VALUES(3, 2, '["a", 1]')`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT JSON_OBJECTAGG(c0, val) from (SELECT * FROM j ORDER BY pk) as sub`,
				Expected: []sql.Row{
					{types.MustJSON(`{"1": {"key1": {"key": [2, 3]}}, "2": ["a", 1]}`)},
				},
			},
		},
	},
	{
		Name: "JSON_OBJECTAGG correctly returns null when no rows are present",
		SetUpScript: []string{
			`create table test (pk int primary key, val longtext)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT JSON_OBJECTAGG(pk, val) from test`,
				Expected: []sql.Row{
					{nil},
				},
			},
		},
	},
	{
		Name: "JSON_OBJECTAGG handles errors appropriately",
		SetUpScript: []string{
			`create table test (pk int primary key, c0 int, val longtext)`,
			`insert into test values (1, 1, NULL)`,
			`insert into test values (2, NULL, 1)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       `SELECT JSON_OBJECTAGG(c0, notval) from test`,
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{
				Query:       `SELECT JSON_OBJECTAGG(notpk, val) from test`,
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{
				Query:       `SELECT JSON_OBJECTAGG(c0, val) from nottest`,
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:       `SELECT JSON_OBJECTAGG(c0, val, badarg) from test`,
				ExpectedErr: sql.ErrInvalidArgumentNumber,
			},
			{
				Query:       `SELECT JSON_OBJECTAGG(c0) from test`,
				ExpectedErr: sql.ErrInvalidArgumentNumber,
			},
			{
				Query:       `SELECT JSON_OBJECTAGG(c0, val) from test`,
				ExpectedErr: sql.ErrJSONObjectAggNullKey,
			},
		},
	},

	{
		Name: "json is ordered correctly",
		SetUpScript: []string{
			"create table t (pk int primary key, col1 json);",
			"insert into t values (1, null);",
			"insert into t values (2, '{}');",
			"insert into t values (3, (select json_extract('{\"a\": null}', '$.a')));",
			"insert into t values (4, 0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from t order by col1 asc;",
				Expected: []sql.Row{
					{1, nil},
					{3, types.MustJSON("null")},
					{4, types.MustJSON("0")},
					{2, types.MustJSON("{}")},
				},
			},
			{
				Query: "select * from t order by col1 desc;",
				Expected: []sql.Row{
					{2, types.MustJSON("{}")},
					{4, types.MustJSON("0")},
					{3, types.MustJSON("null")},
					{1, nil},
				},
			},
		},
	},
	{
		Name: "json_extract returns missing keys as sql null and handles json null literals correctly",
		SetUpScript: []string{
			"create table t (pk int primary key, col1 json);",
			"insert into t values (1, '{\"items\": {\"1\": 1, \"2\": 2}}');",
			"insert into t values (2, null);",
			"insert into t values (3, '{}');",
			"insert into t values (4, '{\"items\": null}');",
			"insert into t values (5, (select json_extract('{\"a\": null}', '$.a')));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select pk, json_extract(col1, '$.items') from t order by pk;",
				Expected: []sql.Row{
					{1, types.MustJSON("{\"1\":1,\"2\":2}")},
					{2, nil},
					{3, nil},
					{4, types.MustJSON("null")},
					{5, nil},
				},
			},
			{
				Query: "select pk, json_extract(col1, '$') from t order by pk;",
				Expected: []sql.Row{
					{1, types.MustJSON("{\"items\": {\"1\": 1, \"2\": 2}}")},
					{2, nil},
					{3, types.MustJSON("{}")},
					{4, types.MustJSON("{\"items\": null}")},
					{5, types.MustJSON("null")},
				},
			},
			{
				Query: "select pk, json_extract(col1, '$.items') is null from t order by pk;",
				Expected: []sql.Row{
					{1, false},
					{2, true},
					{3, true},
					{4, false},
					{5, true},
				},
			},
			{
				Query: "select pk, json_extract(col1, '$.items') <> null from t order by pk;",
				Expected: []sql.Row{
					{1, nil},
					{2, nil},
					{3, nil},
					{4, nil},
					{5, nil},
				},
			},
			{
				Query:    "select pk from t where json_extract(col1, '$.items') is null;",
				Expected: []sql.Row{{2}, {3}, {5}},
			},
			{
				Query:    "select pk from t where json_extract(col1, '$.items') <> null;",
				Expected: []sql.Row{},
			},
		},
	},
}
View Source
var KeylessQueries = []QueryTest{
	{
		Query: "SELECT * FROM keyless ORDER BY c0",
		Expected: []sql.Row{
			{0, 0},
			{1, 1},
			{1, 1},
			{2, 2},
		},
	},
	{
		Query: "SELECT * FROM keyless ORDER BY c1 DESC",
		Expected: []sql.Row{
			{2, 2},
			{1, 1},
			{1, 1},
			{0, 0},
		},
	},
	{
		Query: "SELECT * FROM keyless JOIN myTable where c0 = i",
		Expected: []sql.Row{
			{1, 1, 1, "first row"},
			{1, 1, 1, "first row"},
			{2, 2, 2, "second row"},
		},
	},
	{
		Query: "SELECT * FROM myTable JOIN keyless WHERE i = c0 ORDER BY i",
		Expected: []sql.Row{
			{1, "first row", 1, 1},
			{1, "first row", 1, 1},
			{2, "second row", 2, 2},
		},
	},
	{
		Query: "DESCRIBE keyless",
		Expected: []sql.Row{
			{"c0", "bigint", "YES", "", "NULL", ""},
			{"c1", "bigint", "YES", "", "NULL", ""},
		},
	},
	{
		Query: "SHOW COLUMNS FROM keyless",
		Expected: []sql.Row{
			{"c0", "bigint", "YES", "", "NULL", ""},
			{"c1", "bigint", "YES", "", "NULL", ""},
		},
	},
	{
		Query: "SHOW FULL COLUMNS FROM keyless",
		Expected: []sql.Row{
			{"c0", "bigint", nil, "YES", "", "NULL", "", "", ""},
			{"c1", "bigint", nil, "YES", "", "NULL", "", "", ""},
		},
	},
	{
		Query: "SHOW CREATE TABLE keyless",
		Expected: []sql.Row{
			{"keyless", "CREATE TABLE `keyless` (\n  `c0` bigint,\n  `c1` bigint\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
		},
	},
}
View Source
var LoadDataErrorScripts = []ScriptTest{
	{
		Name:        "Load data into table that doesn't exist throws error.",
		Query:       "LOAD DATA INFILE 'test1.txt' INTO TABLE loadtable",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Name: "Load data with unknown files throws an error.",
		SetUpScript: []string{
			"create table loadtable(pk longtext, c1 int)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "LOAD DATA INFILE '/x/ytx' INTO TABLE loadtable",
				ExpectedErr: sql.ErrLoadDataCannotOpen,
			},
		},
	},
	{
		Name: "Load data with unknown columns throws an error",
		SetUpScript: []string{
			"create table loadtable(pk int primary key)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (bad)",
				ExpectedErr: plan.ErrInsertIntoNonexistentColumn,
			},
		},
	},
	{
		Name: "Load data escaped by terms longer than 1 character throws an error",
		SetUpScript: []string{
			"create table loadtable(pk int primary key)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ESCAPED BY 'xx' (pk)",
				ExpectedErr: sql.ErrLoadDataCharacterLength,
			},
		},
	},
	{
		Name: "Load data enclosed by term longer than 1 character throws an error",
		SetUpScript: []string{
			"create table loadtable(pk int primary key)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY 'xx' (pk)",
				ExpectedErr: sql.ErrLoadDataCharacterLength,
			},
		},
	},
}
View Source
var LoadDataFailingScripts = []ScriptTest{
	{
		Name: "Escaped values are correctly parsed.",
		SetUpScript: []string{
			"create table loadtable(pk longtext)",
			"LOAD DATA INFILE 'test5.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' IGNORE 1 LINES",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{"hi"}, {"hello"}, {nil}, {"TryN"}, {fmt.Sprintf("%c", 26)}, {fmt.Sprintf("%c", 0)}, {"new\n"}},
			},
		},
	},
	{
		Name: "Load and terminate have the same values.",
		SetUpScript: []string{
			"create table loadtable(pk int primary key)",
			"LOAD DATA INFILE 'test1.txt' INTO TABLE loadtable FIELDS TERMINATED BY '\"' ENCLOSED BY '\"'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{int8(1)}, {int8(2)}, {int8(3)}, {int8(4)}},
			},
		},
	},
	{
		Name: "Loading value into different column type results in default value.",
		SetUpScript: []string{
			"create table loadtable(pk longtext, c1 int)",
			"LOAD DATA INFILE 'test4.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (c1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{nil, 0}, {nil, 0}},
			},
		},
	},
	{
		Name: "LOAD DATA handles nulls",
		SetUpScript: []string{
			"create table loadtable(pk longtext, c1 int)",
			"LOAD DATA INFILE 'test4.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{"hi", 1}, {"hello", nil}},
			},
		},
	},
	{
		Name: "LOAD DATA can handle a differing column order",
		SetUpScript: []string{
			"create table loadtable(pk int, c1 string) ",
			"LOAD DATA INFILE 'test4.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"' (c1, pk)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{1, "hi"}, {nil, "hello"}},
			},
		},
	},
}
View Source
var LoadDataScripts = []ScriptTest{
	{
		Name: "Basic load data with enclosed values.",
		SetUpScript: []string{
			"create table loadtable(pk int primary key)",
			"LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{int8(1)}, {int8(2)}, {int8(3)}, {int8(4)}},
			},
		},
	},
	{
		Name: "Load data with csv",
		SetUpScript: []string{
			"create table loadtable(pk int primary key, c1 longtext)",
			"LOAD DATA INFILE './testdata/test2.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 LINES",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{int8(1), "hi"}, {int8(2), "hello"}},
			},
		},
	},
	{
		Name: "Load data with csv but use IGNORE ROWS syntax",
		SetUpScript: []string{
			"create table loadtable(pk int primary key, c1 longtext)",
			"LOAD DATA INFILE './testdata/test2.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' IGNORE 1 ROWS",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{int8(1), "hi"}, {int8(2), "hello"}},
			},
		},
	},
	{
		Name: "Load data with csv with prefix.",
		SetUpScript: []string{
			"create table loadtable(pk longtext, c1 int)",
			"LOAD DATA INFILE './testdata/test3.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' LINES STARTING BY 'xxx' IGNORE 1 LINES (`pk`, `c1`)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{"\"abc\"", int8(1)}, {"\"def\"", int8(2)}, {"\"hello\"", nil}},
			},
		},
	},
	{
		Name: "LOAD DATA with all columns reordered in projection",
		SetUpScript: []string{
			"create table loadtable(pk longtext, c1 int)",
			"LOAD DATA INFILE './testdata/test3backwards.csv' INTO TABLE loadtable FIELDS TERMINATED BY ',' LINES STARTING BY 'xxx' IGNORE 1 LINES (`c1`, `pk`)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable",
				Expected: []sql.Row{{"\"abc\"", int8(1)}, {"\"def\"", int8(2)}, {"\"hello\"", nil}},
			},
		},
	},
	{
		Name: "Table has more columns than import.",
		SetUpScript: []string{
			"create table loadtable(pk int primary key, c1 int)",
			"LOAD DATA INFILE './testdata/test1.txt' INTO TABLE loadtable FIELDS ENCLOSED BY '\"'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from loadtable ORDER BY pk",
				Expected: []sql.Row{{1, nil}, {2, nil}, {3, nil}, {4, nil}},
			},
		},
	},
	{
		Name: "LOAD DATA handles Windows line-endings and a subset of columns that are not in order",
		SetUpScript: []string{
			"CREATE TABLE inmate_population_snapshots (id char(21) NOT NULL, snapshot_date date NOT NULL, total int," +
				"total_off_site int, male int, female int, other_gender int, white int, black int, hispanic int," +
				"asian int, american_indian int, mexican_american int, multi_racial int, other_race int," +
				"on_probation int, on_parole int, felony int, misdemeanor int, other_offense int," +
				"convicted_or_sentenced int, detained_or_awaiting_trial int, first_time_incarcerated int, employed int," +
				"unemployed int, citizen int, noncitizen int, juvenile int, juvenile_male int, juvenile_female int," +
				"death_row_condemned int, solitary_confinement int, technical_parole_violators int," +
				"source_url varchar(2043) NOT NULL, source_url_2 varchar(2043), civil_offense int, federal_offense int," +
				"PRIMARY KEY (id,snapshot_date), KEY id (id));",
			"LOAD DATA INFILE './testdata/test6.csv' INTO TABLE inmate_population_snapshots " +
				"FIELDS TERMINATED BY ',' " +
				"LINES TERMINATED BY '\r\n' " +
				"IGNORE 1 LINES " +
				"(federal_offense, misdemeanor, total, detained_or_awaiting_trial, felony, snapshot_date, id, source_url, source_url_2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM inmate_population_snapshots",
				Expected: []sql.Row{
					{"8946", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, nil, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, nil},
					{"8976", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 196, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, 73, nil, nil, 123, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, 0},
					{"8978", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 0, nil, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, nil},
					{"8979", time.Date(2020, 5, 1, 0, 0, 0, 0, time.UTC), 71, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 5, 3, nil, nil, 63, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, "https://www.website.gov", "https://www.website.gov/other.html", nil, 0},
				},
			},
		},
	},
	{
		Name: "LOAD DATA handles non-nil default values",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (v2 * 10), v2 BIGINT DEFAULT 5);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (v2 * 10), v2 BIGINT DEFAULT 5);",
			"CREATE TABLE test3 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (pk * 10), v2 BIGINT DEFAULT (v1 - 1));",
			"CREATE TABLE test4 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (pk * 10), v2 BIGINT DEFAULT (v1 - 1));",
			"LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test1;",
			"LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test2 (pk);",
			"LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test3;",
			"LOAD DATA INFILE './testdata/test7.txt' INTO TABLE test4 (pk);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM test1",
				Expected: []sql.Row{
					{1, 50, 5},
					{2, 50, 5},
					{3, 50, 5},
				},
			},
			{
				Query: "SELECT * FROM test2",
				Expected: []sql.Row{
					{1, 50, 5},
					{2, 50, 5},
					{3, 50, 5},
				},
			},
			{
				Query: "SELECT * FROM test3",
				Expected: []sql.Row{
					{1, 10, 9},
					{2, 20, 19},
					{3, 30, 29},
				},
			},
			{
				Query: "SELECT * FROM test4",
				Expected: []sql.Row{
					{1, 10, 9},
					{2, 20, 19},
					{3, 30, 29},
				},
			},
		},
	},
	{
		Name: "LOAD DATA handles non-nil default values with varying field counts per row",
		SetUpScript: []string{
			"CREATE TABLE test1 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (v2 * 10), v2 BIGINT DEFAULT 5);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 BIGINT DEFAULT (pk * 10), v2 BIGINT DEFAULT (v1 - 1));",
			"LOAD DATA INFILE './testdata/test8.txt' INTO TABLE test1 FIELDS TERMINATED BY ',';",
			"LOAD DATA INFILE './testdata/test8.txt' INTO TABLE test2 FIELDS TERMINATED BY ',';",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM test1",
				Expected: []sql.Row{
					{1, 50, 5},
					{2, 100, 5},
					{3, 50, 5},
				},
			},
			{
				Query: "SELECT * FROM test2",
				Expected: []sql.Row{
					{1, 10, 9},
					{2, 100, 99},
					{3, 30, 29},
				},
			},
		},
	},
}
View Source
var NoDbProcedureTests = []ScriptTestAssertion{
	{
		Query:    "SHOW databases;",
		Expected: []sql.Row{{"information_schema"}, {"mydb"}, {"mysql"}},
	},
	{
		Query:    "SELECT database();",
		Expected: []sql.Row{{nil}},
	},
	{
		Query:    "CREATE PROCEDURE mydb.p5() SELECT 42;",
		Expected: []sql.Row{{types.NewOkResult(0)}},
	},
	{
		Query:            "SHOW CREATE PROCEDURE mydb.p5;",
		SkipResultsCheck: true,
	},
	{
		Query:       "SHOW CREATE PROCEDURE p5;",
		ExpectedErr: sql.ErrNoDatabaseSelected,
	},
}
View Source
var NullRangeTests = []QueryTest{
	{
		Query: "select * from null_ranges where y IS NULL or y < 1",
		Expected: []sql.Row{
			{0, 0},
			{3, nil},
			{4, nil},
		},
	},
	{
		Query:    "select * from null_ranges where y IS NULL and y < 1",
		Expected: []sql.Row{},
	},
	{
		Query: "select * from null_ranges where y IS NULL or y IS NOT NULL",
		Expected: []sql.Row{
			{0, 0},
			{1, 1},
			{2, 2},
			{3, nil},
			{4, nil},
		},
	},
	{
		Query: "select * from null_ranges where y IS NOT NULL",
		Expected: []sql.Row{
			{0, 0},
			{1, 1},
			{2, 2},
		},
	},
	{
		Query: "select * from null_ranges where y IS NULL or y = 0 or y = 1",
		Expected: []sql.Row{
			{0, 0},
			{1, 1},
			{3, nil},
			{4, nil},
		},
	},
	{
		Query: "select * from null_ranges where y IS NULL or y < 1 or y > 1",
		Expected: []sql.Row{
			{0, 0},
			{2, 2},
			{3, nil},
			{4, nil},
		},
	},
	{
		Query: "select * from null_ranges where y IS NOT NULL and x > 1",
		Expected: []sql.Row{
			{2, 2},
		},
	}, {
		Query: "select * from null_ranges where y IS NULL and x = 4",
		Expected: []sql.Row{
			{4, nil},
		},
	}, {
		Query: "select * from null_ranges where y IS NULL and x > 1",
		Expected: []sql.Row{
			{3, nil},
			{4, nil},
		},
	},
	{
		Query:    "select * from null_ranges where y IS NULL and y IS NOT NULL",
		Expected: []sql.Row{},
	},
	{
		Query:    "select * from null_ranges where y is NULL and y > -1 and y > -2",
		Expected: []sql.Row{},
	},
	{
		Query:    "select * from null_ranges where y > -1 and y < 7 and y IS NULL",
		Expected: []sql.Row{},
	},
	{
		Query: "select * from null_ranges where y > -1 and y > -2 and y IS NOT NULL",
		Expected: []sql.Row{
			{0, 0},
			{1, 1},
			{2, 2},
		},
	},
	{
		Query: "select * from null_ranges where y > -1 and y > 1 and y IS NOT NULL",
		Expected: []sql.Row{
			{2, 2},
		},
	},
	{
		Query: "select * from null_ranges where y < 6 and y > -1 and y IS NOT NULL",
		Expected: []sql.Row{
			{0, 0},
			{1, 1},
			{2, 2},
		},
	},
}
View Source
var OrderByGroupByScriptTests = []ScriptTest{
	{
		Name: "Basic order by/group by cases",
		SetUpScript: []string{
			"use mydb;",
			"create table members (id bigint primary key, team text);",
			"insert into members values (3,'red'), (4,'red'),(5,'orange'),(6,'orange'),(7,'orange'),(8,'purple');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select team as f from members order by id, f",
				Expected: []sql.Row{{"red"}, {"red"}, {"orange"}, {"orange"}, {"orange"}, {"purple"}},
			},
			{
				Query: "SELECT team, COUNT(*) FROM members GROUP BY team ORDER BY 2",
				Expected: []sql.Row{
					{"purple", int64(1)},
					{"red", int64(2)},
					{"orange", int64(3)},
				},
			},
			{
				Query: "SELECT team, COUNT(*) FROM members GROUP BY 1 ORDER BY 2",
				Expected: []sql.Row{
					{"purple", int64(1)},
					{"red", int64(2)},
					{"orange", int64(3)},
				},
			},
			{
				Query:       "SELECT team, COUNT(*) FROM members GROUP BY team ORDER BY columndoesnotexist",
				ExpectedErr: sql.ErrColumnNotFound,
			},
			{
				Query:    "SELECT DISTINCT BINARY t1.id as id FROM members AS t1 JOIN members AS t2 ON t1.id = t2.id WHERE t1.id > 0 ORDER BY BINARY t1.id",
				Expected: []sql.Row{{[]uint8{0x33}}, {[]uint8{0x34}}, {[]uint8{0x35}}, {[]uint8{0x36}}, {[]uint8{0x37}}, {[]uint8{0x38}}},
			},
			{
				Query:    "SELECT DISTINCT BINARY t1.id as id FROM members AS t1 JOIN members AS t2 ON t1.id = t2.id WHERE t1.id > 0 ORDER BY t1.id",
				Expected: []sql.Row{{[]uint8{0x33}}, {[]uint8{0x34}}, {[]uint8{0x35}}, {[]uint8{0x36}}, {[]uint8{0x37}}, {[]uint8{0x38}}},
			},
			{
				Query:    "SELECT DISTINCT t1.id as id FROM members AS t1 JOIN members AS t2 ON t1.id = t2.id WHERE t2.id > 0 ORDER BY t1.id",
				Expected: []sql.Row{{3}, {4}, {5}, {6}, {7}, {8}},
			},
			{

				Query:    "SELECT id as alias1, (SELECT alias1+1 group by alias1 having alias1 > 0) FROM members where id < 6;",
				Expected: []sql.Row{{3, 4}, {4, 5}, {5, 6}},
			},
			{

				Query:    "SELECT id, (SELECT UPPER(team) having id > 3) as upper_team FROM members where id < 6;",
				Expected: []sql.Row{{3, nil}, {4, "RED"}, {5, "ORANGE"}},
			},
			{

				Query:    "SELECT id, (SELECT -1 as id having id < 10) as upper_team FROM members where id < 6;",
				Expected: []sql.Row{{3, -1}, {4, -1}, {5, -1}},
			},
		},
	},
	{
		Name: "https://github.com/dolthub/dolt/issues/3016",
		SetUpScript: []string{
			"CREATE TABLE `users` (`id` int NOT NULL AUTO_INCREMENT,  `username` varchar(255) NOT NULL,  PRIMARY KEY (`id`));",
			"INSERT INTO `users` (`id`,`username`) VALUES (1,'u2');",
			"INSERT INTO `users` (`id`,`username`) VALUES (2,'u3');",
			"INSERT INTO `users` (`id`,`username`) VALUES (3,'u4');",
			"CREATE TABLE `tweet` (`id` int NOT NULL AUTO_INCREMENT,  `user_id` int NOT NULL,  `content` text NOT NULL,  `timestamp` bigint NOT NULL,  PRIMARY KEY (`id`),  KEY `tweet_user_id` (`user_id`));",
			"INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (1,1,'meow',1647463727);",
			"INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (2,1,'purr',1647463727);",
			"INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (3,2,'hiss',1647463727);",
			"INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (4,3,'woof',1647463727);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT t1.username, COUNT(t1.id) FROM ((SELECT t2.id, t2.content, t3.username FROM tweet AS t2 INNER JOIN users AS t3 ON (-t2.user_id = -t3.id) WHERE (t3.username = 'u3')) UNION (SELECT t4.id, t4.content, `t5`.`username` FROM `tweet` AS t4 INNER JOIN users AS t5 ON (-t4.user_id = -t5.id) WHERE (t5.username IN ('u2', 'u4')))) AS t1 GROUP BY `t1`.`username` ORDER BY 1,2 DESC;",
				Expected: []sql.Row{{"u2", 2}, {"u3", 1}, {"u4", 1}},
			},
			{
				Query:    "SELECT t1.username, COUNT(t1.id) AS ct FROM ((SELECT t2.id, t2.content, t3.username FROM tweet AS t2 INNER JOIN users AS t3 ON (-t2.user_id = -t3.id) WHERE (t3.username = 'u3')) UNION (SELECT t4.id, t4.content, `t5`.`username` FROM `tweet` AS t4 INNER JOIN users AS t5 ON (-t4.user_id = -t5.id) WHERE (t5.username IN ('u2', 'u4')))) AS t1 GROUP BY `t1`.`username` ORDER BY 1,2 DESC;",
				Expected: []sql.Row{{"u2", 2}, {"u3", 1}, {"u4", 1}},
			},
			{
				Query:    "SELECT COUNT(id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id ORDER BY COUNT(id), user_id;",
				Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}},
			},
			{
				Query:    "SELECT COUNT(tweet.id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id ORDER BY COUNT(id), user_id;",
				Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}},
			},
			{
				Query:    "SELECT COUNT(id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id ORDER BY COUNT(tweet.id), user_id;",
				Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}},
			},
			{
				Query:    "SELECT COUNT(id) as ct, user_id as uid FROM tweet GROUP BY tweet.user_id HAVING COUNT(tweet.id) > 0 ORDER BY COUNT(tweet.id), user_id;",
				Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}},
			},
			{
				Query:    "SELECT COUNT(id) as ct, user_id as uid FROM tweet WHERE tweet.id is NOT NULL GROUP BY tweet.user_id ORDER BY COUNT(tweet.id), user_id;",
				Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}},
			},
			{
				Query:    "SELECT COUNT(id) as ct, user_id as uid FROM tweet WHERE tweet.id is NOT NULL GROUP BY tweet.user_id HAVING COUNT(tweet.id) > 0 ORDER BY COUNT(tweet.id), user_id;",
				Expected: []sql.Row{{1, 2}, {1, 3}, {2, 1}},
			},
			{
				Query:    "SELECT COUNT(id) as ct, user_id as uid FROM tweet WHERE tweet.id is NOT NULL GROUP BY tweet.user_id HAVING COUNT(tweet.id) > 0 ORDER BY COUNT(tweet.id), user_id LIMIT 1;",
				Expected: []sql.Row{{1, 2}},
			},
		},
	},
	{
		Name: "Group by with decimal columns",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT column_0, sum(column_1) FROM (values row(1.00,1), row(1.00,3), row(2,2), row(2,5), row(3,9)) a group by 1 order by 1;",
				Expected: []sql.Row{{"1.00", float64(4)}, {"2.00", float64(7)}, {"3.00", float64(9)}},
			},
		},
	},
	{

		Name: "Validation for use of non-aggregated columns with implicit grouping of all rows",
		SetUpScript: []string{
			"CREATE TABLE t (num INTEGER, val DOUBLE);",
			"INSERT INTO t VALUES (1, 0.01), (2,0.5);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "SELECT AVG(val), LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
			{
				Query:       "SELECT 1 + AVG(val) + 1, LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
			{
				Query:       "SELECT AVG(1), 1 + LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
			{

				Skip:        true,
				Query:       "select AVG(val), val from t;",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
			{

				Query:       "select * from (SELECT AVG(val), LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) as dt;",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
			{

				Query:       "select 1, 1 union SELECT AVG(val), LAST_VALUE(val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING);",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
			{

				Query:       "select * from (with recursive a as (select 1 as c1, 1 as c2 union SELECT AVG(t.val), LAST_VALUE(t.val) OVER w FROM t WINDOW w AS (ORDER BY num RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) select * from a union select * from a limit 1) as dt;",
				ExpectedErr: sql.ErrNonAggregatedColumnWithoutGroupBy,
			},
		},
	},
	{
		Name: "group by with any_value()",
		SetUpScript: []string{
			"use mydb;",
			"create table members (id bigint primary key, team text);",
			"insert into members values (3,'red'), (4,'red'),(5,'orange'),(6,'orange'),(7,'orange'),(8,'purple');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select @@global.sql_mode",
				Expected: []sql.Row{
					{"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY"},
				},
			},
			{
				Query: "select @@session.sql_mode",
				Expected: []sql.Row{
					{"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY"},
				},
			},
			{
				Query: "select any_value(id), any_value(team) from members order by id",
				Expected: []sql.Row{
					{3, "red"},
					{4, "red"},
					{5, "orange"},
					{6, "orange"},
					{7, "orange"},
					{8, "purple"},
				},
			},
		},
	},
	{
		Name: "group by with strict errors",
		SetUpScript: []string{
			"use mydb;",
			"create table members (id bigint primary key, team text);",
			"insert into members values (3,'red'), (4,'red'),(5,'orange'),(6,'orange'),(7,'orange'),(8,'purple');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select @@global.sql_mode",
				Expected: []sql.Row{
					{"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY"},
				},
			},
			{
				Query: "select @@session.sql_mode",
				Expected: []sql.Row{
					{"STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY"},
				},
			},
			{
				Query:       "select id, team from members group by team",
				ExpectedErr: analyzer.ErrValidationGroupBy,
			},
		},
	},
	{
		Name: "Group by null handling",

		SetUpScript: []string{
			"create table t (pk int primary key, c1 varchar(10));",
			"insert into t values (1, 'foo'), (2, 'foo'), (3, NULL);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select c1, count(pk) from t group by c1;",
				Expected: []sql.Row{
					{"foo", 2},
					{nil, 1},
				},
			},
			{
				Query: "select c1, count(c1) from t group by c1;",
				Expected: []sql.Row{
					{"foo", 2},
					{nil, 0},
				},
			},
		},
	},
}
View Source
var OrdinalDDLQueries = []QueryTest{
	{
		Query: "show keys from short_ord_pk",
		Expected: []sql.Row{
			{"short_ord_pk", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"short_ord_pk", 0, "PRIMARY", 2, "x", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		Query: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'short_ord_pk'",
		Expected: []sql.Row{
			{"x", uint(1)},
			{"y", uint(2)},
		},
	},
	{
		Query: "show keys from long_ord_pk1",
		Expected: []sql.Row{
			{"long_ord_pk1", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk1", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		Query: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk1' and column_key = 'PRI'",
		Expected: []sql.Row{
			{"v", uint(2)},
			{"y", uint(5)},
		},
	},
	{
		Query: "show keys from long_ord_pk2",
		Expected: []sql.Row{
			{"long_ord_pk2", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 3, "x", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 4, "z", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 5, "u", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		Query: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk2' and column_key = 'PRI'",
		Expected: []sql.Row{
			{"u", uint(1)},
			{"v", uint(2)},
			{"x", uint(4)},
			{"y", uint(5)},
			{"z", uint(6)},
		},
	},
	{
		Query: "show keys from long_ord_pk3",
		Expected: []sql.Row{
			{"long_ord_pk3", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 3, "x", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 4, "z", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 5, "u", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		Query: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk3' and column_key = 'PRI'",
		Expected: []sql.Row{
			{"u", uint(1)},
			{"v", uint(2)},
			{"x", uint(5)},
			{"y", uint(6)},
			{"z", uint(7)},
		},
	},
	{
		Query:    "show keys from ord_kl",
		Expected: []sql.Row{},
	},
	{
		Query:    "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'ord_kl' and column_key = 'PRI'",
		Expected: []sql.Row{},
	},
}
View Source
var OrdinalDDLWriteQueries = []WriteQueryTest{
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 ADD COLUMN ww int AFTER v",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk1' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"v", uint(2)},
			{"y", uint(6)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 MODIFY COLUMN w int AFTER y",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk1' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"v", uint(2)},
			{"y", uint(4)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 DROP PRIMARY KEY",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery:    "show keys from ord_kl",
		ExpectedSelect: []sql.Row{},
	},
	{
		WriteQuery: "ALTER TABLE ord_kl ADD PRIMARY KEY (y,v)",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "show keys from ord_kl",
		ExpectedSelect: []sql.Row{
			{"ord_kl", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"ord_kl", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		WriteQuery: "ALTER TABLE ord_kl ADD PRIMARY KEY (y,v)",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'ord_kl' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"v", uint(2)},
			{"y", uint(5)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 MODIFY COLUMN y int AFTER u",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: `SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS 
				WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk1' and column_key = 'PRI' order by 2`,
		ExpectedSelect: []sql.Row{
			{"y", uint(2)},
			{"v", uint(3)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 MODIFY COLUMN y int AFTER u",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "show keys from long_ord_pk1",
		ExpectedSelect: []sql.Row{
			{"long_ord_pk1", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk1", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 RENAME COLUMN y to yy",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk1' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"v", uint(2)},
			{"yy", uint(5)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk1 RENAME COLUMN y to yy",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "show keys from long_ord_pk1",
		ExpectedSelect: []sql.Row{
			{"long_ord_pk1", 0, "PRIMARY", 1, "yy", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk1", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk2 ADD COLUMN ww int AFTER w",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk2' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"u", uint(1)},
			{"v", uint(2)},
			{"x", uint(5)},
			{"y", uint(6)},
			{"z", uint(7)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk2 ADD COLUMN ww int AFTER w",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "show keys from long_ord_pk2",
		ExpectedSelect: []sql.Row{
			{"long_ord_pk2", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 3, "x", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 4, "z", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 5, "u", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk3 DROP COLUMN ww",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk3' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"u", uint(1)},
			{"v", uint(2)},
			{"x", uint(4)},
			{"y", uint(5)},
			{"z", uint(6)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk3 DROP COLUMN ww",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "show keys from long_ord_pk3",
		ExpectedSelect: []sql.Row{
			{"long_ord_pk3", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 3, "x", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 4, "z", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk3", 0, "PRIMARY", 5, "u", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk2 MODIFY COLUMN y int AFTER u",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "SELECT column_name, ordinal_position FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'long_ord_pk2' and column_key = 'PRI'",
		ExpectedSelect: []sql.Row{
			{"u", uint(1)},
			{"y", uint(2)},
			{"v", uint(3)},
			{"x", uint(5)},
			{"z", uint(6)},
		},
	},
	{
		WriteQuery: "ALTER TABLE long_ord_pk2 MODIFY COLUMN y int AFTER u",
		ExpectedWriteResult: []sql.Row{
			{types.OkResult{RowsAffected: 0}},
		},
		SelectQuery: "show keys from long_ord_pk2",
		ExpectedSelect: []sql.Row{
			{"long_ord_pk2", 0, "PRIMARY", 1, "y", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 2, "v", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 3, "x", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 4, "z", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
			{"long_ord_pk2", 0, "PRIMARY", 5, "u", nil, 0, nil, nil, "", "BTREE", "", "", "YES", nil},
		},
	},
}
View Source
var PlanTests = []QueryPlanTest{}/* 306 elements not displayed */

PlanTests is a test of generating the right query plans for different queries in the presence of indexes and other features. These tests are fragile because they rely on string representations of query plans, but they're much easier to construct this way. To regenerate these plans after analyzer changes, use the TestWriteQueryPlans function in testgen_test.go.

View Source
var PreparedScriptTests = []ScriptTest{
	{
		Name:        "bad prepare",
		SetUpScript: []string{},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "prepare s from 'prepare t from ?'",
				ExpectedErrStr: "syntax error at position 17 near ':v1'",
			},
			{
				Query:          "prepare s from 'a very real query'",
				ExpectedErrStr: "syntax error at position 2 near 'a'",
			},
			{
				Query:       "deallocate prepare idontexist",
				ExpectedErr: sql.ErrUnknownPreparedStatement,
			},
		},
	},
	{
		Name:        "simple select case no bindings",
		SetUpScript: []string{},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "execute s",
				ExpectedErr: sql.ErrUnknownPreparedStatement,
			},
			{
				Query: "prepare s from 'select 1'",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query: "execute s",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query: "deallocate prepare s",
				Expected: []sql.Row{
					{types.OkResult{}},
				},
			},
			{
				Query:       "execute s",
				ExpectedErr: sql.ErrUnknownPreparedStatement,
			},
		},
	},
	{
		Name: "simple select case one binding",
		SetUpScript: []string{
			"set @a = 1",
			"set @b = 100",
			"set @c = 'abc'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "prepare s from 'select ?'",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query:       "execute s",
				ExpectedErr: sql.ErrInvalidArgument,
			},
			{
				Query: "execute s using @abc",
				Expected: []sql.Row{
					{nil},
				},
			},
			{
				Query:       "execute s using @a, @b, @c, @abc",
				ExpectedErr: sql.ErrInvalidArgument,
			},
			{
				Query: "execute s using @a",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query: "execute s using @b",
				Expected: []sql.Row{
					{100},
				},
			},
			{
				Query: "execute s using @c",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "deallocate prepare s",
				Expected: []sql.Row{
					{types.OkResult{}},
				},
			},
			{
				Query:       "execute s using @a",
				ExpectedErr: sql.ErrUnknownPreparedStatement,
			},
		},
	},
	{
		Name: "prepare insert",
		SetUpScript: []string{
			"set @a = 123",
			"set @b = 'abc'",
			"create table t (i int, j varchar(100))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "prepare s from 'insert into t values (?,?)'",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query:       "execute s using @a",
				ExpectedErr: sql.ErrInvalidArgument,
			},
			{
				Query: "execute s using @a, @b",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query: "select * from t order by i",
				Expected: []sql.Row{
					{123, "abc"},
				},
			},
			{
				Query: "deallocate prepare s",
				Expected: []sql.Row{
					{types.OkResult{}},
				},
			},
			{
				Query:       "execute s using @a",
				ExpectedErr: sql.ErrUnknownPreparedStatement,
			},
		},
	},
	{
		Name: "prepare using user vars",
		SetUpScript: []string{
			"create table t (i int primary key);",
			"insert into t values (0), (1), (2);",
			"set @num = 123",
			"set @bad = 'bad'",
			"set @a = 'select * from t order by i'",
			"set @b = concat('select 1',' + 1')",
			"set @c = 'select 1 from dual limit ?'",
			"set @d = 'select @num'",
		},
		Assertions: []ScriptTestAssertion{
			{

				Query:          "prepare stmt from @asdf",
				ExpectedErrStr: "syntax error at position 5 near 'NULL'",
			},
			{
				Query:          "prepare stmt from @num",
				ExpectedErrStr: "syntax error at position 4 near '123'",
			},
			{
				Query:          "prepare stmt from @bad",
				ExpectedErrStr: "syntax error at position 4 near 'bad'",
			},
			{
				Query: "prepare stmt from @a",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query: "execute stmt",
				Expected: []sql.Row{
					{0},
					{1},
					{2},
				},
			},
			{
				Query: "prepare stmt from @b",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query: "execute stmt",
				Expected: []sql.Row{
					{2},
				},
			},
			{
				Query: "prepare stmt from @c",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query: "execute stmt using @num",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query: "prepare stmt from @d",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query: "execute stmt",
				Expected: []sql.Row{
					{123},
				},
			},
		},
	},
	{
		Name: "Complex join query with foreign key constraints",
		SetUpScript: []string{
			"CREATE TABLE `users` (`id` int NOT NULL AUTO_INCREMENT, `username` varchar(255) NOT NULL, PRIMARY KEY (`id`));",
			"CREATE TABLE `tweet` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL, `content` text NOT NULL, `timestamp` bigint NOT NULL, PRIMARY KEY (`id`), KEY `tweet_user_id` (`user_id`), CONSTRAINT `0qpfesgd` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`));",
			"INSERT INTO `users` (`id`,`username`) VALUES (1,'huey'), (2,'zaizee'), (3,'mickey');",
			"INSERT INTO `tweet` (`id`,`user_id`,`content`,`timestamp`) VALUES (1,1,'meow',1647463727), (2,1,'purr',1647463727), (3,2,'hiss',1647463727), (4,3,'woof',1647463727);",
			"set @u2 = 'u2';",
			"set @u3 = 'u3';",
			"set @u4 = 'u4';",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "prepare s from 'SELECT `t1`.`username`, COUNT(`t1`.`id`) AS `ct` FROM ((SELECT `t2`.`id`, `t2`.`content`, `t3`.`username` FROM `tweet` AS `t2` INNER JOIN `users` AS `t3` ON (`t2`.`user_id` = `t3`.`id`) WHERE (`t3`.`username` = ?)) UNION (SELECT `t4`.`id`, `t4`.`content`, `t5`.`username` FROM `tweet` AS `t4` INNER JOIN `users` AS `t5` ON (`t4`.`user_id` = `t5`.`id`) WHERE (`t5`.`username` IN (?, ?)))) AS `t1` GROUP BY `t1`.`username` ORDER BY COUNT(`t1`.`id`) DESC'",
				Expected: []sql.Row{
					{types.OkResult{Info: plan.PrepareInfo{}}},
				},
			},
			{
				Query:    "execute s using @u3, @u2, @u4",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "Drop column with check constraint, no other columns",
		SetUpScript: []string{
			"create table mytable (pk int primary key);",
			"ALTER TABLE mytable ADD COLUMN col2 text NOT NULL;",
			"ALTER TABLE mytable ADD CONSTRAINT constraint_check CHECK (col2 LIKE '%myregex%');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE mytable DROP COLUMN col2",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Drop column with check constraint, other column referenced first",
		SetUpScript: []string{
			"create table mytable (pk int primary key);",
			"ALTER TABLE mytable ADD COLUMN col2 text NOT NULL;",
			"ALTER TABLE mytable ADD COLUMN col3 text NOT NULL;",
			"ALTER TABLE mytable ADD CONSTRAINT constraint_check CHECK (col3 LIKE col2);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE mytable DROP COLUMN col2",
				ExpectedErr: sql.ErrCheckConstraintInvalidatedByColumnAlter,
			},
		},
	},
	{
		Name: "Drop column with check constraint, other column referenced second",
		SetUpScript: []string{
			"create table mytable (pk int primary key);",
			"ALTER TABLE mytable ADD COLUMN col2 text NOT NULL;",
			"ALTER TABLE mytable ADD COLUMN col3 text NOT NULL;",
			"ALTER TABLE mytable ADD CONSTRAINT constraint_check CHECK (col2 LIKE col3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE mytable DROP COLUMN col2",
				ExpectedErr: sql.ErrCheckConstraintInvalidatedByColumnAlter,
			},
		},
	},
	{
		Name: "Drop column with check constraint, multiple constraints",
		SetUpScript: []string{
			"create table mytable (pk int primary key);",
			"ALTER TABLE mytable ADD COLUMN col2 text NOT NULL;",
			"ALTER TABLE mytable ADD COLUMN col3 text NOT NULL;",
			"ALTER TABLE mytable ADD CONSTRAINT ok_check CHECK (col2 LIKE '%myregex%');",
			"ALTER TABLE mytable ADD CONSTRAINT bad_check CHECK (col2 LIKE col3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE mytable DROP COLUMN col2",
				ExpectedErr: sql.ErrCheckConstraintInvalidatedByColumnAlter,
			},
		},
	},
}
View Source
var ProcedureCallTests = []ScriptTest{
	{
		Name: "OUT param with SET",
		SetUpScript: []string{
			"SET @outparam = 5",
			"CREATE PROCEDURE testabc(OUT x BIGINT) SET x = 9",
			"CALL testabc(@outparam)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						int64(9),
					},
				},
			},
		},
	},
	{
		Name: "OUT param without SET",
		SetUpScript: []string{
			"SET @outparam = 5",
			"CREATE PROCEDURE testabc(OUT x BIGINT) SELECT x",
			"CALL testabc(@outparam)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						nil,
					},
				},
			},
		},
	},
	{
		Name: "INOUT param with SET",
		SetUpScript: []string{
			"SET @outparam = 5",
			"CREATE PROCEDURE testabc(INOUT x BIGINT) BEGIN SET x = x + 1; SET x = x + 3; END;",
			"CALL testabc(@outparam)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						int64(9),
					},
				},
			},
		},
	},
	{
		Name: "INOUT param without SET",
		SetUpScript: []string{
			"SET @outparam = 5",
			"CREATE PROCEDURE testabc(INOUT x BIGINT) SELECT x",
			"CALL testabc(@outparam)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						int64(5),
					},
				},
			},
		},
	},
	{
		Name: "Nested CALL with INOUT param",
		SetUpScript: []string{
			"SET @outparam = 5",
			"CREATE PROCEDURE p3(INOUT z INT) BEGIN SET z = z * 111; END;",
			"CREATE PROCEDURE p2(INOUT y DOUBLE) BEGIN SET y = y + 4; CALL p3(y); END;",
			"CREATE PROCEDURE p1(INOUT x BIGINT) BEGIN SET x = 3; CALL p2(x); END;",
			"CALL p1(@outparam)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						int64(777),
					},
				},
			},
		},
	},
	{
		Name: "OUT param without SET",
		SetUpScript: []string{
			"SET @outparam = 5",
			"CREATE PROCEDURE testabc(OUT x BIGINT) SELECT x",
			"CALL testabc(@outparam)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						nil,
					},
				},
			},
		},
	},
	{
		Name: "Incompatible type for parameter",
		SetUpScript: []string{
			"CREATE PROCEDURE p1(x DATETIME) SELECT x",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL p1('hi')",
				ExpectedErr: types.ErrConvertingToTime,
			},
		},
	},
	{
		Name: "Incorrect parameter count",
		SetUpScript: []string{
			"CREATE PROCEDURE p1(x BIGINT, y BIGINT) SELECT x + y",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL p1(1)",
				ExpectedErr: sql.ErrCallIncorrectParameterCount,
			},
			{
				Query:       "CALL p1(1, 2, 3)",
				ExpectedErr: sql.ErrCallIncorrectParameterCount,
			},
		},
	},
	{
		Name: "use procedure parameter in filter expressions and multiple statements",
		SetUpScript: []string{
			"CREATE TABLE inventory (store_id int, product varchar(5))",
			"INSERT INTO inventory VALUES (1, 'a'), (1, 'b'), (1, 'c'), (1, 'd'), (2, 'e'), (2, 'f'), (1, 'g'), (1, 'h'), (3, 'i')",
			"CREATE PROCEDURE proc1 (IN p_store_id INT) SELECT COUNT(*) FROM inventory WHERE store_id = p_store_id;",
			"CREATE PROCEDURE proc2 (IN p_store_id INT, OUT p_film_count INT) READS SQL DATA BEGIN SELECT COUNT(*) as counted FROM inventory WHERE store_id = p_store_id; SET p_film_count = 44; END ;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL proc1(1)",
				Expected: []sql.Row{
					{
						int64(6),
					},
				},
			},
			{
				Query: "CALL proc1(2)",
				Expected: []sql.Row{
					{
						int64(2),
					},
				},
			}, {
				Query: "CALL proc1(4)",
				Expected: []sql.Row{
					{
						int64(0),
					},
				},
			}, {
				Query: "CALL proc2(3, @foo)",
				Expected: []sql.Row{
					{
						int64(1),
					},
				},
			}, {
				Query: "SELECT @foo",
				Expected: []sql.Row{
					{
						int64(44),
					},
				},
			},
		},
	},
	{
		Name: "Call procedures by their qualified name",
		SetUpScript: []string{
			"CREATE DATABASE otherdb",
			"CREATE PROCEDURE mydb.p1() SELECT 42",
			"CREATE PROCEDURE otherdb.p1() SELECT 43",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL p1()",
				Expected: []sql.Row{{42}},
			},
			{
				Query:    "CALL mydb.p1()",
				Expected: []sql.Row{{42}},
			},
			{
				Query:    "CALL otherdb.p1()",
				Expected: []sql.Row{{43}},
			},
			{
				Query:    "USE otherdb",
				Expected: []sql.Row{},
			},
			{
				Query:    "CALL p1()",
				Expected: []sql.Row{{43}},
			},
		},
	},

	{
		Name: "String literals with escaped chars",
		SetUpScript: []string{
			`CREATE PROCEDURE joe(IN str VARCHAR(15)) SELECT CONCAT('joe''s bar:', str);`,
			`CREATE PROCEDURE jill(IN str VARCHAR(15)) SELECT CONCAT('jill\'s bar:', str);`,
			`CREATE PROCEDURE stan(IN str VARCHAR(15)) SELECT CONCAT("stan\'s bar:", str);`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL joe('open')",
				Expected: []sql.Row{{"joe's bar:open"}},
			},
			{
				Query:    "CALL jill('closed')",
				Expected: []sql.Row{{"jill's bar:closed"}},
			},
			{
				Query:    "CALL stan('quarantined')",
				Expected: []sql.Row{{"stan's bar:quarantined"}},
			},
		},
	},
}
View Source
var ProcedureDropTests = []ScriptTest{
	{
		Name: "DROP procedures",
		SetUpScript: []string{
			"CREATE PROCEDURE p1() SELECT 5",
			"CREATE PROCEDURE p2() SELECT 6",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1",
				Expected: []sql.Row{
					{
						int64(5),
					},
				},
			},
			{
				Query: "CALL p2",
				Expected: []sql.Row{
					{
						int64(6),
					},
				},
			},
			{
				Query:    "DROP PROCEDURE p1",
				Expected: []sql.Row{},
			},
			{
				Query:       "CALL p1",
				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
			},
			{
				Query:    "DROP PROCEDURE IF EXISTS p2",
				Expected: []sql.Row{},
			},
			{
				Query:       "CALL p2",
				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
			},
			{
				Query:       "DROP PROCEDURE p3",
				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
			},
			{
				Query:    "DROP PROCEDURE IF EXISTS p4",
				Expected: []sql.Row{},
			},
		},
	},
}
View Source
var ProcedureLogicTests = []ScriptTest{
	{
		Name: "Simple SELECT",
		SetUpScript: []string{
			"CREATE PROCEDURE testabc(x DOUBLE, y DOUBLE) SELECT x*y",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL testabc(2, 3)",
				Expected: []sql.Row{
					{
						"6",
					},
				},
			},
			{
				Query: "CALL testabc(9, 9.5)",
				Expected: []sql.Row{
					{
						"85.5",
					},
				},
			},
		},
	},
	{
		Name: "Multiple SELECTs",
		SetUpScript: []string{
			"CREATE TABLE t1(pk VARCHAR(20) PRIMARY KEY)",
			"INSERT INTO t1 VALUES (3), (4), (50)",
			`CREATE PROCEDURE p1()
BEGIN
	SELECT * FROM t1;
	UPDATE t1 SET pk = CONCAT(pk, '0');
	SELECT * FROM t1;
	INSERT INTO t1 VALUES (1), (2);
	SELECT * FROM t1;
	REPLACE INTO t1 VALUES (1), (30);
	DELETE FROM t1 WHERE pk LIKE '%00';
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1()",
				Expected: []sql.Row{
					{"1"},
					{"2"},
					{"30"},
					{"40"},
					{"500"},
				},
			},
			{
				Query: "SELECT * FROM t1 ORDER BY 1",
				Expected: []sql.Row{
					{"1"},
					{"2"},
					{"30"},
					{"40"},
				},
			},
		},
	},
	{
		Name: "IF/ELSE with 1 SELECT at end",
		SetUpScript: []string{
			"SET @outparam = ''",
			`CREATE PROCEDURE p1(OUT s VARCHAR(200), N DOUBLE, m DOUBLE)
BEGIN
	SET s = '';
	IF n = m THEN SET s = 'equals';
	ELSE
		IF n > m THEN SET s = 'greater';
		ELSE SET s = 'less';
		END IF;
		SET s = CONCAT('is ', s, ' than');
	END IF;
	SET s = CONCAT(n, ' ', s, ' ', m, '.');
	SELECT s;
END;`,
			`CREATE PROCEDURE p2(s VARCHAR(200), N DOUBLE, m DOUBLE)
BEGIN
	SET s = '';
	IF n = m THEN SET s = 'equals';
	ELSE
		IF n > m THEN SET s = 'greater';
		ELSE SET s = 'less';
		END IF;
		SET s = CONCAT('is ', s, ' than');
	END IF;
	SET s = CONCAT(n, ' ', s, ' ', m, '.');
	SELECT s;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(@outparam, 1, 2)",
				Expected: []sql.Row{
					{
						"1 is less than 2.",
					},
				},
			},
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						"1 is less than 2.",
					},
				},
			},
			{
				Query: "CALL p1(@outparam, null, 2)",
				Expected: []sql.Row{
					{
						nil,
					},
				},
			},
			{
				Query: "CALL p1(@outparam, 7, 4)",
				Expected: []sql.Row{
					{
						"7 is greater than 4.",
					},
				},
			},
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						"7 is greater than 4.",
					},
				},
			},
			{
				Query: "CALL p1(@outparam, 5, 5)",
				Expected: []sql.Row{
					{
						"5 equals 5.",
					},
				},
			},
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						"5 equals 5.",
					},
				},
			},
			{
				Query: "CALL p2(@outparam, 9, 3)",
				Expected: []sql.Row{
					{
						"9 is greater than 3.",
					},
				},
			},
			{
				Query: "SELECT @outparam",
				Expected: []sql.Row{
					{
						"5 equals 5.",
					},
				},
			},
		},
	},
	{
		Name: "IF/ELSE with nested SELECT in branches",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
			`CREATE PROCEDURE p1(x BIGINT)
BEGIN
	DELETE FROM t1;
	IF x < 10 THEN
		IF x = 0 THEN
			SELECT 1000;
		ELSEIF x = 1 THEN
			SELECT 1001;
		ELSE
			INSERT INTO t1 VALUES (3), (4), (5);
		END IF;
	ELSEIF x < 20 THEN
		IF x = 10 THEN
			INSERT INTO t1 VALUES (1), (2), (6), (7);
		ELSEIF x = 11 THEN
			INSERT INTO t1 VALUES (8), (9), (10), (11), (12);
			SELECT * FROM t1;
		ELSE
			SELECT 2002;
			SELECT 2003;
		END IF;
	END IF;
	INSERT INTO t1 VALUES (1), (2);
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(0)",
				Expected: []sql.Row{
					{
						int64(1000),
					},
				},
			},
			{
				Query: "CALL p1(1)",
				Expected: []sql.Row{
					{
						int64(1001),
					},
				},
			},
			{
				Query: "CALL p1(2)",
				Expected: []sql.Row{
					{
						types.NewOkResult(2),
					},
				},
			},
			{
				Query:       "CALL p1(10)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "CALL p1(11)",
				Expected: []sql.Row{
					{int64(8)},
					{int64(9)},
					{int64(10)},
					{int64(11)},
					{int64(12)},
				},
			},
			{
				Query: "CALL p1(12)",
				Expected: []sql.Row{
					{
						int64(2003),
					},
				},
			},
		},
	},
	{
		Name: "REPEAT loop over user variable",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(p1 INT)
BEGIN
	SET @x = 0;
	REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT;
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL p1(0)",
				Expected: []sql.Row{},
			},
			{
				Query:    "CALL p1(1)",
				Expected: []sql.Row{{}, {}},
			},
			{
				Query:    "CALL p1(2)",
				Expected: []sql.Row{{}, {}, {}},
			},
		},
	},
	{
		Name: "WHILE loop over user variable",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(p1 INT)
BEGIN
	SET @x = 0;
	WHILE @x <= p1 DO
		SET @x = @x + 1;
	END WHILE;
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL p1(0)",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "CALL p1(1)",
				Expected: []sql.Row{{}, {}},
			},
			{
				Query:    "CALL p1(2)",
				Expected: []sql.Row{{}, {}, {}},
			},
		},
	},
	{
		Name: "CASE statements",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(IN a BIGINT)
BEGIN
	DECLARE b VARCHAR(200) DEFAULT "";
	tloop: LOOP
		CASE
			WHEN a < 4 THEN
				SET b = CONCAT(b, "a");
				SET a = a + 1;
			WHEN a < 8 THEN
				SET b = CONCAT(b, "b");
				SET a = a + 1;
			ELSE
				LEAVE tloop;
		END CASE;
	END LOOP;
	SELECT b;
END;`,
			`CREATE PROCEDURE p2(IN a BIGINT)
BEGIN
	DECLARE b VARCHAR(200) DEFAULT "";
	tloop: LOOP
		CASE a
			WHEN 1 THEN
				SET b = CONCAT(b, "a");
				SET a = a + 1;
			WHEN 2 THEN
				SET b = CONCAT(b, "b");
				SET a = a + 1;
			WHEN 3 THEN
				SET b = CONCAT(b, "c");
				SET a = a + 1;
			ELSE
				LEAVE tloop;
		END CASE;
	END LOOP;
	SELECT b;
END;`,
			`CREATE PROCEDURE p3(IN a BIGINT)
BEGIN
	DECLARE b VARCHAR(200) DEFAULT "";
	tloop: LOOP
		CASE a
			WHEN 1 THEN
				SET b = CONCAT(b, "a");
				SET a = a + 1;
		END CASE;
	END LOOP;
	SELECT b;
END;`,
			`CREATE PROCEDURE p4(IN a BIGINT)
BEGIN
	DECLARE b VARCHAR(200) DEFAULT "";
	tloop: LOOP
		CASE
			WHEN a = 1 THEN
				SET b = CONCAT(b, "a");
				SET a = a + 1;
		END CASE;
	END LOOP;
	SELECT b;
END;`,
			`CREATE PROCEDURE p5(IN a BIGINT)
BEGIN
	DECLARE b VARCHAR(200) DEFAULT "";
	REPEAT
		CASE
			WHEN a <= 1 THEN
				SET b = CONCAT(b, "a");
				SET a = a + 1;
		END CASE;
	UNTIL a > 1
	END REPEAT;
	SELECT b;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(0)",
				Expected: []sql.Row{
					{"aaaabbbb"},
				},
			},
			{
				Query: "CALL p1(3)",
				Expected: []sql.Row{
					{"abbbb"},
				},
			},
			{
				Query: "CALL p1(6)",
				Expected: []sql.Row{
					{"bb"},
				},
			},
			{
				Query: "CALL p1(9)",
				Expected: []sql.Row{
					{""},
				},
			},
			{
				Query: "CALL p2(1)",
				Expected: []sql.Row{
					{"abc"},
				},
			},
			{
				Query: "CALL p2(2)",
				Expected: []sql.Row{
					{"bc"},
				},
			},
			{
				Query: "CALL p2(3)",
				Expected: []sql.Row{
					{"c"},
				},
			},
			{
				Query: "CALL p2(4)",
				Expected: []sql.Row{
					{""},
				},
			},
			{
				Query:          "CALL p3(1)",
				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
			},
			{
				Query:          "CALL p3(2)",
				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
			},
			{
				Query:          "CALL p4(1)",
				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
			},
			{
				Query:          "CALL p4(-1)",
				ExpectedErrStr: "Case not found for CASE statement (errno 1339) (sqlstate 20000)",
			},
			{
				Query: "CALL p5(0)",
				Expected: []sql.Row{
					{"aa"},
				},
			},
			{
				Query: "CALL p5(1)",
				Expected: []sql.Row{
					{"a"},
				},
			},
		},
	},
	{
		Name: "SELECT with JOIN and table aliases",
		SetUpScript: []string{
			"CREATE TABLE foo(a BIGINT PRIMARY KEY, b VARCHAR(20))",
			"INSERT INTO foo VALUES (1, 'd'), (2, 'e'), (3, 'f')",
			"CREATE TABLE bar(b VARCHAR(30) PRIMARY KEY, c BIGINT)",
			"INSERT INTO bar VALUES ('x', 3), ('y', 2), ('z', 1)",

			"CREATE PROCEDURE p1() SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1",

			"CREATE PROCEDURE p2() BEGIN SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END;",

			"CREATE PROCEDURE p3() IF 0 = 0 THEN SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END IF;",

			"CREATE PROCEDURE p4() BEGIN SELECT 7; SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END;",

			"CREATE PROCEDURE p5() IF 0 = 0 THEN SELECT 7; SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1; END IF;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT f.a, bar.b, f.b FROM foo f INNER JOIN bar ON f.a = bar.c ORDER BY 1",
				Expected: []sql.Row{
					{int64(1), "z", "d"},
					{int64(2), "y", "e"},
					{int64(3), "x", "f"},
				},
			},
			{
				Query: "CALL p1()",
				Expected: []sql.Row{
					{int64(1), "z", "d"},
					{int64(2), "y", "e"},
					{int64(3), "x", "f"},
				},
			},
			{
				Query: "CALL p2()",
				Expected: []sql.Row{
					{int64(1), "z", "d"},
					{int64(2), "y", "e"},
					{int64(3), "x", "f"},
				},
			},
			{
				Query: "CALL p3()",
				Expected: []sql.Row{
					{int64(1), "z", "d"},
					{int64(2), "y", "e"},
					{int64(3), "x", "f"},
				},
			},
			{
				Query: "CALL p4()",
				Expected: []sql.Row{
					{int64(1), "z", "d"},
					{int64(2), "y", "e"},
					{int64(3), "x", "f"},
				},
			},
			{
				Query: "CALL p5()",
				Expected: []sql.Row{
					{int64(1), "z", "d"},
					{int64(2), "y", "e"},
					{int64(3), "x", "f"},
				},
			},
		},
	},
	{
		Name: "Nested CALL in IF/ELSE branch",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
			"INSERT INTO t1 VALUES (2), (3)",
			"CREATE PROCEDURE p1(INOUT x BIGINT) BEGIN IF X = 1 THEN CALL p2(10); ELSEIF x = 2 THEN CALL p2(100); ELSE CALL p2(X); END IF; END;",
			"CREATE PROCEDURE p2(INOUT y BIGINT) BEGIN SELECT pk * y FROM t1 ORDER BY 1; END;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(1)",
				Expected: []sql.Row{
					{int64(20)},
					{int64(30)},
				},
			},
			{
				Query: "CALL p1(2)",
				Expected: []sql.Row{
					{int64(200)},
					{int64(300)},
				},
			},
			{
				Query: "CALL p1(5)",
				Expected: []sql.Row{
					{int64(10)},
					{int64(15)},
				},
			},
		},
	},
	{
		Name: "INSERT INTO SELECT doesn't override SELECT",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
			"CREATE TABLE t2(pk BIGINT PRIMARY KEY)",
			"INSERT INTO t1 VALUES (2), (3)",
			"INSERT INTO t2 VALUES (1)",
			`CREATE PROCEDURE p1(x BIGINT)
BEGIN
	DELETE FROM t2 WHERE pk > 1;
	INSERT INTO t2 SELECT pk FROM t1;
	SELECT * FROM t2;
	INSERT INTO t2 SELECT pk + 10 FROM t1;
	IF x = 1 THEN
		SELECT * FROM t2;
	END IF;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(0)",
				Expected: []sql.Row{
					{int64(1)},
					{int64(2)},
					{int64(3)},
				},
			},
			{
				Query: "CALL p1(1)",
				Expected: []sql.Row{
					{int64(1)},
					{int64(2)},
					{int64(3)},
					{int64(12)},
					{int64(13)},
				},
			},
		},
	},
	{
		Name: "Parameters resolve inside of INSERT",
		SetUpScript: []string{
			`CREATE TABLE items (
	id INT PRIMARY KEY AUTO_INCREMENT,
	item TEXT NOT NULL
);`,
			`CREATE PROCEDURE add_item (IN txt TEXT) MODIFIES SQL DATA
INSERT INTO items (item) VALUES (txt)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL add_item('A test item');",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1, InsertID: 1}},
				},
			},
			{
				Query: "SELECT * FROM items;",
				Expected: []sql.Row{
					{1, "A test item"},
				},
			},
		},
	},
	{
		Name: "Parameters resolve inside of SELECT UNION",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY, v1 BIGINT)",
			"INSERT INTO t1 VALUES (1, 2)",
			"SELECT pk, v1 FROM t1 UNION SELECT 1, 2;",
			`CREATE PROCEDURE p1(x BIGINT, y BIGINT)
BEGIN
	SELECT pk+x, v1+y FROM t1 UNION SELECT x, y;
END;`,
			`CREATE PROCEDURE p2(u BIGINT, v BIGINT) SELECT pk+u, v1+v FROM t1 UNION SELECT u, v;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(3, 4)",
				Expected: []sql.Row{
					{"4", "6"},
					{"3", "4"},
				},
			},
			{
				Query: "CALL p2(5, 6)",
				Expected: []sql.Row{
					{"6", "8"},
					{"5", "6"},
				},
			},
		},
	},
	{
		Name: "Parameters resolve inside of REPLACE",
		SetUpScript: []string{
			`CREATE TABLE items (
	id INT PRIMARY KEY AUTO_INCREMENT,
	item INT NOT NULL
);`,
			`CREATE PROCEDURE add_item (IN num INT) MODIFIES SQL DATA
BEGIN
	REPLACE INTO items (item) VALUES (5), (num), (num+1);
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL add_item(6);",
				Expected: []sql.Row{
					{types.NewOkResult(3)},
				},
			},
			{
				Query: "SELECT * FROM items ORDER BY 1;",
				Expected: []sql.Row{
					{1, 5},
					{2, 6},
					{3, 7},
				},
			},
		},
	},
	{
		Name: "Parameters resolve inside of INSERT INTO SELECT",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
			"CREATE TABLE t2(pk BIGINT PRIMARY KEY)",
			"INSERT INTO t1 VALUES (1), (2)",
			`CREATE PROCEDURE p1(x BIGINT)
BEGIN
	TRUNCATE t2;
	INSERT INTO t2 SELECT pk+x FROM t1;
	SELECT * FROM t2;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(0)",
				Expected: []sql.Row{
					{int64(1)},
					{int64(2)},
				},
			},
			{
				Query: "CALL p1(5)",
				Expected: []sql.Row{
					{int64(6)},
					{int64(7)},
				},
			},
		},
	},
	{
		Name: "Subquery on SET user variable captures parameter",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(x VARCHAR(20))
BEGIN
	SET @randomvar = (SELECT LENGTH(x));
	SELECT @randomvar;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1('hi')",
				Expected: []sql.Row{
					{int64(2)},
				},
			},
			{
				Query: "CALL p1('hello')",
				Expected: []sql.Row{
					{int64(5)},
				},
			},
		},
	},
	{
		Name: "Simple SELECT INTO",
		SetUpScript: []string{
			"CREATE PROCEDURE testabc(IN x DOUBLE, IN y DOUBLE, OUT abc DOUBLE) SELECT x*y INTO abc",
			"CALL testabc(2, 3, @res1)",
			"CALL testabc(9, 9.5, @res2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @res1",
				Expected: []sql.Row{{float64(6)}},
			},
			{
				Query:    "SELECT @res2",
				Expected: []sql.Row{{float64(85.5)}},
			},
		},
	},
	{
		Name: "Multiple variables in SELECT INTO",
		SetUpScript: []string{
			"CREATE PROCEDURE new_proc(IN x DOUBLE, IN y DOUBLE, OUT abc DOUBLE, OUT def DOUBLE) SELECT x*y, x+y INTO abc, def",
			"CALL new_proc(2, 3, @res1, @res2)",
			"CALL new_proc(9, 9.5, @res3, @res4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @res1, @res2",
				Expected: []sql.Row{{float64(6), float64(5)}},
			},
			{
				Query:    "SELECT @res3, @res4",
				Expected: []sql.Row{{float64(85.5), float64(18.5)}},
			},
		},
	},
	{
		Name: "SELECT INTO with condition",
		SetUpScript: []string{
			"CREATE TABLE inventory (item_id int primary key, shelf_id int, items varchar(100))",
			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
			"CREATE PROCEDURE in_stock (IN p_id INT, OUT p_count INT) SELECT COUNT(*) FROM inventory WHERE shelf_id = p_id INTO p_count",
			"CALL in_stock(1, @shelf1)",
			"CALL in_stock(2, @shelf2)",
			"CALL in_stock(3, @shelf3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @shelf1, @shelf2, @shelf3",
				Expected: []sql.Row{{3, 1, 0}},
			},
		},
	},
	{
		Name: "SELECT INTO with group by, order by and limit",
		SetUpScript: []string{
			"CREATE TABLE inventory (item_id int primary key, shelf_id int, item varchar(10))",
			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
			"CREATE PROCEDURE first_shelf (OUT p_count INT) SELECT COUNT(*) FROM inventory GROUP BY shelf_id ORDER BY shelf_id ASC LIMIT 1 INTO p_count",
			"CREATE PROCEDURE last_shelf (OUT p_count INT) SELECT COUNT(*) FROM inventory GROUP BY shelf_id ORDER BY shelf_id DESC LIMIT 1 INTO p_count",
			"CALL first_shelf(@result1)",
			"CALL last_shelf(@result2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @result1",
				Expected: []sql.Row{{3}},
			},
			{
				Query:    "SELECT @result2",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "multiple SELECT INTO in begin end block",
		SetUpScript: []string{
			"CREATE TABLE inventory (item_id int primary key, shelf_id int, item varchar(10))",
			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
			"CREATE PROCEDURE random_info(OUT p_count1 INT, OUT p_count2 VARCHAR(10)) BEGIN " +
				"SELECT COUNT(*) FROM inventory GROUP BY shelf_id ORDER BY shelf_id ASC LIMIT 1 INTO p_count1;" +
				"SELECT item INTO p_count2 FROM inventory WHERE shelf_id = 1 ORDER BY item DESC LIMIT 1; " +
				"END",
			"CALL random_info(@s1, @s2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @s1, @s2",
				Expected: []sql.Row{{3, "d"}},
			},
		},
	},
	{
		Name: "multiple statement with single SELECT INTO in begin end block",
		SetUpScript: []string{
			"CREATE TABLE inventory (item_id int primary key, shelf_id int, item varchar(10))",
			"INSERT INTO inventory VALUES (1, 1, 'a'), (2, 1, 'b'), (3, 2, 'c'), (4, 1, 'd'), (5, 4, 'e')",
			`CREATE PROCEDURE count_and_print(IN p_shelf_id INT, OUT p_count INT) BEGIN
SELECT item FROM inventory WHERE shelf_id = p_shelf_id ORDER BY item ASC;
SELECT COUNT(*) INTO p_count FROM inventory WHERE shelf_id = p_shelf_id;
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL count_and_print(1, @total)",
				Expected: []sql.Row{{"a"}, {"b"}, {"d"}},
			},
			{
				Query:    "SELECT @total",
				Expected: []sql.Row{{3}},
			},
		},
	},
	{
		Name: "DECLARE variables, proper nesting support",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(OUT x BIGINT)
BEGIN
	DECLARE a INT;
	DECLARE b MEDIUMINT;
	DECLARE c VARCHAR(20);
	SELECT 1, 2, 'a' INTO a, b, c;
	BEGIN
		DECLARE b MEDIUMINT;
		SET a = 4;
		SET b = 5;
	END;
	SET x = a + b;
	SELECT a, b, c;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(@x);",
				Expected: []sql.Row{
					{4, 2, "a"},
				},
			},
			{
				Query: "SELECT @x;",
				Expected: []sql.Row{
					{6},
				},
			},
		},
	},
	{
		Name: "DECLARE multiple variables, same statement",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b, c INT;
	SELECT 2, 3, 4 INTO a, b, c;
	SELECT a + b + c;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{9},
				},
			},
		},
	},
	{
		Name: "DECLARE variable shadows parameter",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(INOUT x INT)
BEGIN
	DECLARE x INT;
	SET x = 5;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SET @x = 2;",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "CALL p1(@x);",
				Expected: []sql.Row{{}},
			},
			{
				Query: "SELECT @x;",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
	{
		Name: "DECLARE CONDITION",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(x INT)
BEGIN
	DECLARE specialty CONDITION FOR SQLSTATE '45000';
	DECLARE specialty2 CONDITION FOR SQLSTATE '02000';
	IF x = 0 THEN
		SIGNAL SQLSTATE '01000';
	ELSEIF x = 1 THEN
		SIGNAL SQLSTATE '45000'
			SET MESSAGE_TEXT = 'A custom error occurred 1';
	ELSEIF x = 2 THEN
		SIGNAL specialty
			SET MESSAGE_TEXT = 'A custom error occurred 2', MYSQL_ERRNO = 1002;
	ELSEIF x = 3 THEN
		SIGNAL specialty;
	ELSEIF x = 4 THEN
		SIGNAL specialty2;
	ELSE
		SIGNAL SQLSTATE '01000'
			SET MESSAGE_TEXT = 'A warning occurred', MYSQL_ERRNO = 1000;
		SIGNAL SQLSTATE '45000'
			SET MESSAGE_TEXT = 'An error occurred', MYSQL_ERRNO = 1001;
	END IF;
	BEGIN
		DECLARE specialty3 CONDITION FOR SQLSTATE '45000';
	END;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "CALL p1(0)",
				ExpectedErrStr: "warnings not yet implemented",
			},
			{
				Query:          "CALL p1(1)",
				ExpectedErrStr: "A custom error occurred 1 (errno 1644) (sqlstate 45000)",
			},
			{
				Query:          "CALL p1(2)",
				ExpectedErrStr: "A custom error occurred 2 (errno 1002) (sqlstate 45000)",
			},
			{
				Query:          "CALL p1(3)",
				ExpectedErrStr: "Unhandled user-defined exception condition (errno 1644) (sqlstate 45000)",
			},
			{
				Query:          "CALL p1(4)",
				ExpectedErrStr: "Unhandled user-defined not found condition (errno 1643) (sqlstate 02000)",
			},
		},
	},
	{
		Name: "DECLARE CONDITION nesting priority",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(x INT)
BEGIN
	DECLARE cond_name CONDITION FOR SQLSTATE '02000';
	BEGIN
		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
		IF x = 0 THEN
			SIGNAL cond_name;
		END IF;
	END;
	SIGNAL cond_name;
END;`,
			`CREATE PROCEDURE p2(x INT)
BEGIN
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	BEGIN
		DECLARE cond_name CONDITION FOR SQLSTATE '02000';
		IF x = 0 THEN
			SIGNAL cond_name;
		END IF;
	END;
	SIGNAL cond_name;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "CALL p1(0)",
				ExpectedErrStr: "Unhandled user-defined exception condition (errno 1644) (sqlstate 45000)",
			},
			{
				Query:          "CALL p1(1)",
				ExpectedErrStr: "Unhandled user-defined not found condition (errno 1643) (sqlstate 02000)",
			},
			{
				Query:          "CALL p2(0)",
				ExpectedErrStr: "Unhandled user-defined not found condition (errno 1643) (sqlstate 02000)",
			},
			{
				Query:          "CALL p2(1)",
				ExpectedErrStr: "Unhandled user-defined exception condition (errno 1644) (sqlstate 45000)",
			},
		},
	},
	{
		Name: "FETCH multiple rows",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b INT;
	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
	DELETE FROM t1;
    INSERT INTO t1 VALUES (1), (2);
    OPEN cur1;
    FETCH cur1 INTO a;
    FETCH cur1 INTO b;
    CLOSE cur1;
    SELECT a, b;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{1, 2},
				},
			},
		},
	},
	{
		Name: "FETCH with multiple opens and closes",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b INT;
	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
	DELETE FROM t1;
    INSERT INTO t1 VALUES (1);
    OPEN cur1;
    FETCH cur1 INTO a;
    CLOSE cur1;
	UPDATE t1 SET pk = 2;
    OPEN cur1;
    FETCH cur1 INTO b;
    CLOSE cur1;
    SELECT a, b;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{1, 2},
				},
			},
		},
	},
	{
		Name: "FETCH captures state at OPEN",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b INT;
	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
	DELETE FROM t1;
    INSERT INTO t1 VALUES (1);
    OPEN cur1;
	UPDATE t1 SET pk = 2;
    FETCH cur1 INTO a;
    CLOSE cur1;
    OPEN cur1;
    FETCH cur1 INTO b;
    CLOSE cur1;
    SELECT a, b;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{1, 2},
				},
			},
		},
	},
	{
		Name: "FETCH implicitly closes",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a INT;
	DECLARE cur1 CURSOR FOR SELECT pk FROM t1;
	DELETE FROM t1;
    INSERT INTO t1 VALUES (4);
    OPEN cur1;
    FETCH cur1 INTO a;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{4},
				},
			},
		},
	},
	{
		Name: "DECLARE HANDLERs exit according to the block they were declared in",
		SetUpScript: []string{
			`DROP TABLE IF EXISTS t1;`,
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`CREATE PROCEDURE outer_declare()
BEGIN
	DECLARE a, b INT DEFAULT 1;
    DECLARE cur1 CURSOR FOR SELECT * FROM t1;
	DECLARE EXIT HANDLER FOR NOT FOUND SET a = 1001;
    OPEN cur1;
    BEGIN
		tloop: LOOP
			FETCH cur1 INTO b;
            IF a > 1000 THEN
				LEAVE tloop;
            END IF;
		END LOOP;
    END;
    CLOSE cur1;
    SELECT a;
END;`,
			`CREATE PROCEDURE inner_declare()
BEGIN
	DECLARE a, b INT DEFAULT 1;
    DECLARE cur1 CURSOR FOR SELECT * FROM t1;
	DECLARE EXIT HANDLER FOR NOT FOUND SET a = a + 1;
    OPEN cur1;
    BEGIN
		DECLARE EXIT HANDLER FOR NOT FOUND SET a = 1001;
		tloop: LOOP
			FETCH cur1 INTO b;
            IF a > 1000 THEN
				LEAVE tloop;
            END IF;
		END LOOP;
    END;
    CLOSE cur1;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL outer_declare();",
				Expected: []sql.Row{},
			},
			{
				Query: "CALL inner_declare();",
				Expected: []sql.Row{
					{1001},
				},
			},
		},
	},
	{
		Name: "Labeled BEGIN...END",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a INT DEFAULT 1;
	tblock: BEGIN
		LOOP
			SET a = a + 3;
			LEAVE tblock;
		END LOOP;
	END;
	SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{4},
				},
			},
			{
				Query:       `CREATE PROCEDURE p2() BEGIN tblock: BEGIN ITERATE tblock; END; END;`,
				ExpectedErr: sql.ErrLoopLabelNotFound,
			},
		},
	},
	{
		Name: "REPEAT runs loop before first evaluation",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a INT DEFAULT 10;
	REPEAT
		SET a = a * 5;
	UNTIL a > 0
	END REPEAT;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{50},
				},
			},
		},
	},
	{
		Name: "WHILE runs evaluation before first loop",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a INT DEFAULT 10;
	WHILE a < 10 DO
		SET a = a * 10;
	END WHILE;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{10},
				},
			},
		},
	},
	{
		Name: "ITERATE and LEAVE LOOP",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b INT DEFAULT 1;
    DECLARE cur1 CURSOR FOR SELECT * FROM t1;
	DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
    OPEN cur1;
    BEGIN
		tloop: LOOP
			FETCH cur1 INTO b;
			SET a = (a + b) * 10;
            IF a < 1000 THEN
				ITERATE tloop;
			ELSE
				LEAVE tloop;
            END IF;
		END LOOP;
    END;
    CLOSE cur1;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{2230},
				},
			},
		},
	},
	{
		Name: "ITERATE and LEAVE REPEAT",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b INT DEFAULT 1;
    DECLARE cur1 CURSOR FOR SELECT * FROM t1;
	DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
    OPEN cur1;
    BEGIN
		tloop: REPEAT
			FETCH cur1 INTO b;
			SET a = (a + b) * 10;
            IF a < 1000 THEN
				ITERATE tloop;
			ELSE
				LEAVE tloop;
            END IF;
		UNTIL false
		END REPEAT;
    END;
    CLOSE cur1;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{2230},
				},
			},
		},
	},
	{
		Name: "ITERATE and LEAVE WHILE",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`INSERT INTO t1 VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE a, b INT DEFAULT 1;
    DECLARE cur1 CURSOR FOR SELECT * FROM t1;
	DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
    OPEN cur1;
    BEGIN
		tloop: WHILE true DO
			FETCH cur1 INTO b;
			SET a = (a + b) * 10;
            IF a < 1000 THEN
				ITERATE tloop;
			ELSE
				LEAVE tloop;
            END IF;
		END WHILE;
    END;
    CLOSE cur1;
    SELECT a;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{2230},
				},
			},
		},
	},
	{
		Name: "Handle setting an uninitialized user variable",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(INOUT param VARCHAR(10))
BEGIN
	SELECT param;
	SET param = '5';
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(@uservar4);",
				Expected: []sql.Row{
					{nil},
				},
			},
			{
				Query: "SELECT @uservar4;",
				Expected: []sql.Row{
					{"5"},
				},
			},
		},
	},
	{
		Name: "Dolt Issue #4980",
		SetUpScript: []string{
			`CREATE TABLE person_cal_entries (id VARCHAR(36) PRIMARY KEY, cal_entry_id_fk VARCHAR(36), person_id_fk VARCHAR(36));`,
			`CREATE TABLE personnel (id VARCHAR(36) PRIMARY KEY, event_id VARCHAR(36));`,
			`CREATE TABLE season_participants (person_id_fk VARCHAR(36), season_id_fk VARCHAR(36));`,
			`CREATE TABLE cal_entries (id VARCHAR(36) PRIMARY KEY, season_id_fk VARCHAR(36));`,
			`INSERT INTO personnel VALUES ('6140e23e-7b9b-11ed-a1eb-0242ac120002', 'c546abc4-7b9b-11ed-a1eb-0242ac120002');`,
			`INSERT INTO season_participants VALUES ('6140e23e-7b9b-11ed-a1eb-0242ac120002', '46d7041e-7b9b-11ed-a1eb-0242ac120002');`,
			`INSERT INTO cal_entries VALUES ('cb8ba301-6c27-4bf8-b99b-617082d72621', '46d7041e-7b9b-11ed-a1eb-0242ac120002');`,
			`CREATE PROCEDURE create_cal_entries_for_event(IN event_id VARCHAR(36))
BEGIN
    INSERT INTO person_cal_entries (id, cal_entry_id_fk, person_id_fk)
    SELECT 'd17cb898-7b9b-11ed-a1eb-0242ac120002' as id, event_id as cal_entry_id_fk, id as person_id_fk
    FROM personnel
    WHERE id IN (
        SELECT person_id_fk
        FROM season_participants
        WHERE season_id_fk = (
            SELECT season_id_fk
            FROM cal_entries
            WHERE id = event_id
        )
    );
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "call create_cal_entries_for_event('cb8ba301-6c27-4bf8-b99b-617082d72621');",
				Expected: []sql.Row{
					{types.NewOkResult(1)},
				},
			},
			{
				Query: "SELECT * FROM person_cal_entries;",
				Expected: []sql.Row{
					{"d17cb898-7b9b-11ed-a1eb-0242ac120002", "cb8ba301-6c27-4bf8-b99b-617082d72621", "6140e23e-7b9b-11ed-a1eb-0242ac120002"},
				},
			},
		},
	},
	{
		Name: "HANDLERs ignore variables declared after them",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk BIGINT PRIMARY KEY);`,
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE dvar BIGINT DEFAULT 1;
	DECLARE cur1 CURSOR FOR SELECT * FROM t1;
    OPEN cur1;
	BEGIN
		DECLARE EXIT HANDLER FOR NOT FOUND SET dvar = 10;
		BEGIN
			DECLARE dvar BIGINT DEFAULT 2;
			BEGIN
				DECLARE dvar BIGINT DEFAULT 3;
				LOOP
					FETCH cur1 INTO dvar; # Handler is triggered here, but should only set the first "dvar"
				END LOOP;
            END;
		END;
    END;
    SELECT dvar;
END`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{10},
				},
			},
		},
	},
	{
		Name:        "Duplicate parameter names",
		Query:       "CREATE PROCEDURE p1(abc DATETIME, abc DOUBLE) SELECT abc",
		ExpectedErr: sql.ErrDeclareVariableDuplicate,
	},
	{
		Name:        "Duplicate parameter names mixed casing",
		Query:       "CREATE PROCEDURE p1(abc DATETIME, ABC DOUBLE) SELECT abc",
		ExpectedErr: sql.ErrDeclareVariableDuplicate,
	},
	{
		Name:        "Invalid parameter type",
		Query:       "CREATE PROCEDURE p1(x FAKETYPE) SELECT x",
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Name:        "Invalid USE statement",
		Query:       `CREATE PROCEDURE p1() USE mydb`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Name: "Invalid LOCK/UNLOCK statements",
		SetUpScript: []string{
			"CREATE TABLE t1(pk BIGINT PRIMARY KEY)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CREATE PROCEDURE p1(x BIGINT) LOCK TABLES t1 READ",
				ExpectedErr: sql.ErrSyntaxError,
			},
			{
				Query:       "CREATE PROCEDURE p1(x BIGINT) UNLOCK TABLES",
				ExpectedErr: sql.ErrSyntaxError,
			},
		},
	},
	{
		Name: "DECLARE CONDITION wrong positions",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1(x INT)
BEGIN
	SELECT x;
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
END;`,
				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
			},
			{
				Query: `CREATE PROCEDURE p1(x INT)
BEGIN
	BEGIN
		SELECT x;
		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	END;
END;`,
				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
			},
			{
				Query: `CREATE PROCEDURE p1(x INT)
BEGIN
	IF x = 0 THEN
		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	END IF;
END;`,
				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
			},
			{
				Query: `CREATE PROCEDURE p1(x INT)
BEGIN
	IF x = 0 THEN
		SELECT x;
	ELSE
		DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	END IF;
END;`,
				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
			},
		},
	},
	{
		Name: "DECLARE CONDITION duplicate name",
		Query: `CREATE PROCEDURE p1()
BEGIN
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
END;`,
		ExpectedErr: sql.ErrDeclareConditionDuplicate,
	},
	{
		Name: "SIGNAL references condition name for MySQL error code",
		Query: `CREATE PROCEDURE p1(x INT)
BEGIN
	DECLARE mysql_err_code CONDITION FOR 1000;
	SIGNAL mysql_err_code;
END;`,
		ExpectedErr: sql.ErrUnsupportedSyntax,
	},
	{
		Name: "SIGNAL non-existent condition name",
		Query: `CREATE PROCEDURE p1(x INT)
BEGIN
	DECLARE abcdefg CONDITION FOR SQLSTATE '45000';
	SIGNAL abcdef;
END;`,
		ExpectedErr: sql.ErrDeclareConditionNotFound,
	},
	{
		Name: "Duplicate procedure name",
		SetUpScript: []string{
			"CREATE PROCEDURE test_proc(x DOUBLE, y DOUBLE) SELECT x*y",
		},
		Query:       "CREATE PROCEDURE test_proc(z VARCHAR(20)) SELECT z",
		ExpectedErr: sql.ErrStoredProcedureAlreadyExists,
	},
	{
		Name: "Broken procedure shouldn't break other procedures",
		SetUpScript: []string{
			"CREATE TABLE t (pk INT PRIMARY KEY, other INT);",
			"INSERT INTO t VALUES (1, 1), (2, 2), (3, 3);",
			"CREATE PROCEDURE fragile() select other from t;",
			"CREATE PROCEDURE stable() select pk from t;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CALL stable();",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:    "CALL fragile();",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:            "SHOW PROCEDURE STATUS LIKE 'stable'",
				SkipResultsCheck: true,
			},
			{
				Query:            "SHOW PROCEDURE STATUS LIKE 'fragile'",
				SkipResultsCheck: true,
			},
			{
				Query:    "alter table t drop other;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "CALL stable();",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:          "CALL fragile();",
				ExpectedErrStr: "column \"other\" could not be found in any table in scope",
			},
			{
				Query:            "SHOW PROCEDURE STATUS LIKE 'stable'",
				SkipResultsCheck: true,
			},
			{
				Query:            "SHOW PROCEDURE STATUS LIKE 'fragile'",
				SkipResultsCheck: true,
			},
			{
				Query:    "ALTER TABLE t ADD COLUMN other INT",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "CALL stable();",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:    "CALL fragile();",
				Expected: []sql.Row{{nil}, {nil}, {nil}},
			},
			{
				Query:    "INSERT INTO t VALUES (4, 4), (5, 5), (6, 6);",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
			{
				Query:    "CALL stable();",
				Expected: []sql.Row{{1}, {2}, {3}, {4}, {5}, {6}},
			},
			{
				Query:    "CALL fragile();",
				Expected: []sql.Row{{nil}, {nil}, {nil}, {4}, {5}, {6}},
			},
		},
	},
	{
		Name: "DECLARE name duplicate same type",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1()
BEGIN
	DECLARE x INT;
	DECLARE x INT;
	SELECT 1;
END;`,
				ExpectedErr: sql.ErrDeclareVariableDuplicate,
			},
		},
	},
	{
		Name: "DECLARE name duplicate different type",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1()
BEGIN
	DECLARE x INT;
	DECLARE x VARCHAR(20);
	SELECT 1;
END;`,
				ExpectedErr: sql.ErrDeclareVariableDuplicate,
			},
		},
	},
	{
		Name: "Variable, condition, and cursor in invalid order",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1()
BEGIN
	DECLARE var_name INT;
	DECLARE cur_name CURSOR FOR SELECT 1;
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	SELECT 1;
END;`,
				ExpectedErr: sql.ErrDeclareConditionOrderInvalid,
			},
			{
				Query: `CREATE PROCEDURE p2()
BEGIN
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	DECLARE cur_name CURSOR FOR SELECT 1;
	DECLARE var_name INT;
	SELECT 1;
END;`,
				ExpectedErr: sql.ErrDeclareVariableOrderInvalid,
			},
			{
				Query: `CREATE PROCEDURE p3()
BEGIN
	DECLARE cond_name CONDITION FOR SQLSTATE '45000';
	DECLARE var_name INT;
	SELECT 1;
	DECLARE cur_name CURSOR FOR SELECT 1;
END;`,
				ExpectedErr: sql.ErrDeclareCursorOrderInvalid,
			},
		},
	},
	{
		Name: "FETCH non-existent cursor",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1()
BEGIN
	DECLARE a INT;
	FETCH no_cursor INTO a;
END;`,
				ExpectedErr: sql.ErrCursorNotFound,
			},
		},
	},
	{
		Name: "OPEN non-existent cursor",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1()
BEGIN
	OPEN no_cursor;
END;`,
				ExpectedErr: sql.ErrCursorNotFound,
			},
		},
	},
	{
		Name: "CLOSE non-existent cursor",
		Assertions: []ScriptTestAssertion{
			{
				Query: `CREATE PROCEDURE p1()
BEGIN
	CLOSE no_cursor;
END;`,
				ExpectedErr: sql.ErrCursorNotFound,
			},
		},
	},
	{
		Name: "CLOSE without OPEN",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE cur1 CURSOR FOR SELECT 1;
    CLOSE cur1;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL p1();",
				ExpectedErr: sql.ErrCursorNotOpen,
			},
		},
	},
	{
		Name: "OPEN repeatedly",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE cur1 CURSOR FOR SELECT 1;
    OPEN cur1;
    OPEN cur1;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL p1();",
				ExpectedErr: sql.ErrCursorAlreadyOpen,
			},
		},
	},
	{
		Name: "CLOSE repeatedly",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE cur1 CURSOR FOR SELECT 1;
    OPEN cur1;
    CLOSE cur1;
    CLOSE cur1;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "CALL p1();",
				ExpectedErr: sql.ErrCursorNotOpen,
			},
		},
	},
	{
		Name: "With CTE using variable",
		SetUpScript: []string{
			`CREATE PROCEDURE p1()
BEGIN
	DECLARE v1 INT DEFAULT 1234;
	WITH cte as (SELECT v1)
	SELECT * FROM cte;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1();",
				Expected: []sql.Row{
					{1234},
				},
			},
		},
	},
	{
		Name: "With CTE using parameter",
		SetUpScript: []string{
			`CREATE PROCEDURE p1(v1 int)
BEGIN
	WITH cte as (SELECT v1)
	SELECT * FROM cte;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL p1(1234);",
				Expected: []sql.Row{
					{1234},
				},
			},
		},
	},
	{
		Name: "Dolt Issue #4480",
		SetUpScript: []string{
			"create table p1 (row_id int primary key, pred int, actual int)",
			"create table p2 (row_id int primary key, pred int, actual int)",
			"insert into p1 values (0, 0, 0), (1, 0, 1), (2, 1, 0), (3, 1, 1)",
			"insert into p2 values (0, 0, 0), (1, 0, 1), (2, 1, 0), (3, 1, 1)",
			`CREATE PROCEDURE computeSummary(c VARCHAR(200)) 
BEGIN
	with t as (
		select
			case
				when p1.pred = p2.actual then 1
			else 0
			end as correct,
			p1.actual
			from p1
			join p2
			on p1.row_id = p2.row_id
	)
	select
		sum(correct)/count(*),
		count(*) as row_num
		from t;
END;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CALL computeSummary('i am not used');",
				Expected: []sql.Row{
					{"0.5000", 4},
				},
			},
		},
	},
}
View Source
var ProcedureShowCreate = []ScriptTest{
	{
		Name: "SHOW procedures",
		SetUpScript: []string{
			"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6",
			"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7",
			"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SHOW CREATE PROCEDURE p1",
				Expected: []sql.Row{
					{
						"p1",
						"",
						"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE PROCEDURE p2",
				Expected: []sql.Row{
					{
						"p2",
						"",
						"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW CREATE PROCEDURE p21",
				Expected: []sql.Row{
					{
						"p21",
						"",
						"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
		},
	},
	{
		Name:        "SHOW non-existent procedures",
		SetUpScript: []string{},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "SHOW CREATE PROCEDURE p1",
				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
			},
		},
	},
}
View Source
var ProcedureShowStatus = []ScriptTest{
	{
		Name: "SHOW procedures",
		SetUpScript: []string{
			"CREATE PROCEDURE p1() COMMENT 'hi' DETERMINISTIC SELECT 6",
			"CREATE definer=`user` PROCEDURE p2() SQL SECURITY INVOKER SELECT 7",
			"CREATE PROCEDURE p21() SQL SECURITY DEFINER SELECT 8",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SHOW PROCEDURE STATUS",
				Expected: []sql.Row{
					{
						"mydb",
						"p1",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"hi",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
					{
						"mydb",
						"p2",
						"PROCEDURE",
						"user@%",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"INVOKER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
					{
						"mydb",
						"p21",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW PROCEDURE STATUS LIKE 'p2%'",
				Expected: []sql.Row{
					{
						"mydb",
						"p2",
						"PROCEDURE",
						"user@%",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"INVOKER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
					{
						"mydb",
						"p21",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
			{
				Query:    "SHOW PROCEDURE STATUS LIKE 'p4'",
				Expected: []sql.Row{},
			},
			{
				Query: "SHOW PROCEDURE STATUS WHERE Db = 'mydb'",
				Expected: []sql.Row{
					{
						"mydb",
						"p1",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"hi",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
					{
						"mydb",
						"p2",
						"PROCEDURE",
						"user@%",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"INVOKER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
					{
						"mydb",
						"p21",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW PROCEDURE STATUS WHERE Name LIKE '%1'",
				Expected: []sql.Row{
					{
						"mydb",
						"p1",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"hi",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
					{
						"mydb",
						"p21",
						"PROCEDURE",
						"",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"DEFINER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
			{
				Query: "SHOW PROCEDURE STATUS WHERE Security_type = 'INVOKER'",
				Expected: []sql.Row{
					{
						"mydb",
						"p2",
						"PROCEDURE",
						"user@%",
						time.Unix(0, 0).UTC(),
						time.Unix(0, 0).UTC(),
						"INVOKER",
						"",
						"utf8mb4",
						"utf8mb4_0900_bin",
						"utf8mb4_0900_bin",
					},
				},
			},
		},
	},
}
View Source
var QueryPlanTODOs = []QueryPlanTest{
	{

		Query: `SELECT pk,i,f FROM one_pk RIGHT JOIN niltable ON pk=i and pk > 0 ORDER BY 2,3`,
		ExpectedPlan: "Sort(niltable.i ASC, niltable.f ASC)\n" +
			" └─ Project(one_pk.pk, niltable.i, niltable.f)\n" +
			"     └─ RightJoin((one_pk.pk = niltable.i) AND (one_pk.pk > 0))\n" +
			"         ├─ Projected table access on [pk]\n" +
			"         │   └─ Table(one_pk)\n" +
			"         └─ Projected table access on [i f]\n" +
			"             └─ Table(niltable)\n" +
			"",
	},
}

QueryPlanTODOs are queries where the query planner produces a correct (results) but suboptimal plan.

View Source
var QueryTests = []QueryTest{}/* 1110 elements not displayed */
View Source
var QuickPrivTests = []QuickPrivilegeTest{
	{
		Queries: []string{
			"GRANT SELECT ON *.* TO tester@localhost",
			"SELECT * FROM mydb.test",
		},
		Expected: []sql.Row{{0, 0}, {1, 1}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.* TO tester@localhost",
			"SELECT * FROM mydb.test",
		},
		Expected: []sql.Row{{0, 0}, {1, 1}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.* TO tester@localhost",
			"SELECT * FROM mydb.test2",
		},
		Expected: []sql.Row{{0, 1}, {1, 2}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.test TO tester@localhost",
			"SELECT * FROM mydb.test",
		},
		Expected: []sql.Row{{0, 0}, {1, 1}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.test TO tester@localhost",
			"SELECT * FROM mydb.test2",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT SELECT ON otherdb.* TO tester@localhost",
			"SELECT * FROM mydb.test",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT SELECT ON otherdb.test TO tester@localhost",
			"SELECT * FROM mydb.test",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT SELECT ON otherdb.test TO tester@localhost",
			"SELECT * FROM mydb.test",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT SELECT ON *.* TO tester@localhost",
			"USE mydb;",
			"SHOW TABLES;",
		},
		Expected: []sql.Row{{"test"}, {"test2"}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.* TO tester@localhost",
			"USE mydb;",
			"SHOW TABLES;",
		},
		Expected: []sql.Row{{"test"}, {"test2"}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.test TO tester@localhost",
			"USE mydb;",
			"SHOW TABLES;",
		},
		Expected: []sql.Row{{"test"}},
	},
	{
		Queries: []string{
			"GRANT SELECT ON mydb.non_exist TO tester@localhost",
			"USE mydb;",
			"SHOW TABLES;",
		},
		Expected: []sql.Row{},
	},
	{
		Queries: []string{
			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER ON *.* TO tester@localhost",
			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT",
		},
	},
	{
		Queries: []string{
			"GRANT ALTER ON mydb.* TO tester@localhost",
			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;",
		},
	},
	{
		Queries: []string{
			"GRANT ALTER ON mydb.test TO tester@localhost",
			"ALTER TABLE mydb.test ADD COLUMN new_column BIGINT;",
		},
	},
	{
		Queries: []string{
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER ON *.* TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER, CREATE, DROP, INSERT ON *.* TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
	},
	{
		Queries: []string{
			"GRANT ALTER, CREATE, DROP, INSERT ON mydb.* TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
	},
	{
		Queries: []string{
			"GRANT ALTER, CREATE, DROP, INSERT ON mydb.test TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER, DROP ON mydb.test TO tester@localhost",
			"GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
	},
	{
		Queries: []string{
			"GRANT ALTER ON mydb.test TO tester@localhost",
			"GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.test TO tester@localhost",
			"GRANT CREATE, INSERT ON mydb.new_test TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER, DROP ON mydb.test TO tester@localhost",
			"GRANT CREATE ON mydb.new_test TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER, DROP ON mydb.test TO tester@localhost",
			"GRANT INSERT ON mydb.new_test TO tester@localhost",
			"ALTER TABLE mydb.test RENAME TO mydb.new_test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"USE mydb;",
			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
			"DROP PROCEDURE new_proc;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT ALTER ROUTINE ON *.* TO tester@localhost",
			"USE mydb;",
			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
			"DROP PROCEDURE new_proc;",
		},
	},
	{
		Queries: []string{
			"GRANT ALTER ROUTINE ON mydb.* TO tester@localhost",
			"USE mydb;",
			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
			"DROP PROCEDURE new_proc;",
		},
	},
	{
		Queries: []string{
			"CREATE DATABASE new_db;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT CREATE ON *.* TO tester@localhost",
			"CREATE DATABASE new_db2;",
			"GRANT DROP ON *.* TO tester@localhost",
			"drop database new_db2",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE ON *.* TO tester@localhost",
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE ON mydb.* TO tester@localhost",
			"CREATE DATABASE new_db3;",
			"GRANT DROP ON *.* TO tester@localhost",
			"drop database new_db3",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE ON mydb.* TO tester@localhost",
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
		},
	},
	{
		Queries: []string{
			"CREATE ROLE new_role;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT CREATE ROLE ON *.* TO tester@localhost",
			"CREATE ROLE new_role;",
		},
	},
	{
		Queries: []string{
			"USE mydb;",
			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT CREATE ROUTINE ON *.* TO tester@localhost",
			"USE mydb;",
			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE ROUTINE ON mydb.* TO tester@localhost",
			"USE mydb;",
			"CREATE PROCEDURE new_proc (x DOUBLE, y DOUBLE) SELECT x*y;",
		},
	},
	{
		Queries: []string{
			"CREATE USER new_user;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"CREATE USER new_user;",
			"DROP USER new_user;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT CREATE USER ON *.* TO tester@localhost",
			"CREATE USER new_user;",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE USER ON *.* TO tester@localhost",
			"CREATE USER new_user;",
			"DROP USER new_user;",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE USER ON *.* TO tester@localhost",
			"CREATE ROLE new_role;",
		},
	},
	{
		Queries: []string{
			"GRANT CREATE USER ON *.* TO tester@localhost",
			"CREATE ROLE new_role;",
			"DROP ROLE new_role;",
		},
	},
	{
		Queries: []string{
			"CREATE VIEW new_view AS SELECT 1;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT CREATE VIEW ON *.* TO tester@localhost",
			"CREATE VIEW new_view AS SELECT 1;",
		},
	},
	{
		Queries: []string{
			"DELETE FROM mydb.test WHERE pk >= 0;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DELETE ON *.* TO tester@localhost",
			"DELETE FROM mydb.test WHERE pk >= 0;",
		},
	},
	{
		Queries: []string{
			"GRANT DELETE ON mydb.* TO tester@localhost",
			"DELETE FROM mydb.test WHERE pk >= 0;",
		},
	},
	{
		Queries: []string{
			"GRANT DELETE ON mydb.test TO tester@localhost",
			"DELETE FROM mydb.test WHERE pk >= 0;",
		},
	},
	{
		Queries: []string{
			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DELETE ON mydb.test TO tester@localhost",
			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DELETE ON mydb.test2 TO tester@localhost",
			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DELETE ON mydb.test TO tester@localhost",
			"GRANT DELETE ON mydb.test2 TO tester@localhost",
			"DELETE test, test2 FROM mydb.test join mydb.test2 where test.pk=test2.pk",
		},
	},
	{
		Queries: []string{
			"CREATE DATABASE new_db4;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"CREATE VIEW new_view AS SELECT 1;",
			"DROP VIEW new_view;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DROP ON *.* TO tester@localhost",
			"CREATE DATABASE new_db5;",
			"GRANT DROP ON *.* TO tester@localhost",
			"DROP DATABASE new_db5;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON *.* TO tester@localhost",
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON *.* TO tester@localhost",
			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table1, mydb.new_table2;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON *.* TO tester@localhost",
			"CREATE VIEW new_view AS SELECT 1;",
			"DROP VIEW new_view;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.* TO tester@localhost",
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.* TO tester@localhost",
			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table1, mydb.new_table2;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.new_table TO tester@localhost",
			"CREATE TABLE mydb.new_table (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table;",
		},
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.new_table1 TO tester@localhost",
			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table1, mydb.new_table2;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.new_table2 TO tester@localhost",
			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table1, mydb.new_table2;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DROP ON mydb.new_table1 TO tester@localhost",
			"GRANT DROP ON mydb.new_table2 TO tester@localhost",
			"CREATE TABLE mydb.new_table1 (pk BIGINT PRIMARY KEY);",
			"CREATE TABLE mydb.new_table2 (pk BIGINT PRIMARY KEY);",
			"DROP TABLE mydb.new_table1, mydb.new_table2;",
		},
	},
	{
		Queries: []string{
			"CREATE ROLE new_role;",
			"DROP ROLE new_role;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT DROP ROLE ON *.* TO tester@localhost",
			"CREATE ROLE new_role;",
			"DROP ROLE new_role;",
		},
	},
	{
		Queries: []string{
			"CREATE INDEX new_idx ON mydb.test (v1);",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"CREATE INDEX new_idx ON mydb.test (v1);",
			"DROP INDEX new_idx ON mydb.test;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT INDEX ON *.* TO tester@localhost",
			"CREATE INDEX new_idx ON mydb.test (v1);",
		},
	},
	{
		Queries: []string{
			"GRANT INDEX ON *.* TO tester@localhost",
			"CREATE INDEX new_idx ON mydb.test (v1);",
			"DROP INDEX new_idx ON mydb.test;",
		},
	},
	{
		Queries: []string{
			"GRANT INDEX ON mydb.* TO tester@localhost",
			"CREATE INDEX new_idx ON mydb.test (v1);",
		},
	},
	{
		Queries: []string{
			"GRANT INDEX ON mydb.* TO tester@localhost",
			"CREATE INDEX new_idx ON mydb.test (v1);",
			"DROP INDEX new_idx ON mydb.test;",
		},
	},
	{
		Queries: []string{
			"GRANT INDEX ON mydb.test TO tester@localhost",
			"CREATE INDEX new_idx ON mydb.test (v1);",
		},
	},
	{
		Queries: []string{
			"GRANT INDEX ON mydb.test TO tester@localhost",
			"CREATE INDEX new_idx ON mydb.test (v1);",
			"DROP INDEX new_idx ON mydb.test;",
		},
	},
	{
		Queries: []string{
			"INSERT INTO mydb.test VALUES (9, 9);",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT INSERT ON *.* TO tester@localhost",
			"INSERT INTO mydb.test VALUES (9, 9);",
		},
	},
	{
		Queries: []string{
			"GRANT INSERT ON mydb.* TO tester@localhost",
			"INSERT INTO mydb.test VALUES (9, 9);",
		},
	},
	{
		Queries: []string{
			"GRANT INSERT ON mydb.test TO tester@localhost",
			"INSERT INTO mydb.test VALUES (9, 9);",
		},
	},
	{
		Queries: []string{
			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
			"DROP TRIGGER new_trig;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT TRIGGER ON *.* TO tester@localhost",
			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
		},
	},
	{
		Queries: []string{
			"GRANT TRIGGER ON *.* TO tester@localhost",
			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
			"DROP TRIGGER new_trig;",
		},
	},
	{
		Queries: []string{
			"GRANT TRIGGER ON mydb.* TO tester@localhost",
			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
		},
	},
	{
		Queries: []string{
			"GRANT TRIGGER ON mydb.* TO tester@localhost",
			"CREATE TRIGGER new_trig BEFORE INSERT ON mydb.test2 FOR EACH ROW SET NEW.v1 = NEW.pk * NEW.v1;",
			"DROP TRIGGER new_trig;",
		},
	},
	{
		Queries: []string{
			"UPDATE mydb.test SET v1 = 0;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT UPDATE ON *.* TO tester@localhost",
			"UPDATE mydb.test SET v1 = 0;",
		},
	},
	{
		Queries: []string{
			"GRANT UPDATE ON mydb.* TO tester@localhost",
			"UPDATE mydb.test SET v1 = 0;",
		},
	},
	{
		Queries: []string{
			"GRANT UPDATE ON mydb.test TO tester@localhost",
			"UPDATE mydb.test SET v1 = 0;",
		},
	},
	{
		Queries: []string{
			"FLUSH PRIVILEGES;",
		},
		ExpectingErr: true,
	},
	{
		Queries: []string{
			"GRANT RELOAD ON *.* TO tester@localhost",
			"FLUSH PRIVILEGES;",
		},
	},
}

QuickPrivTests are test that specifically attempt to test as many privileges against as many statements as possible, while being as succinct as possible. All tests here could be fully represented as a UserPrivilegeTest, however each equivalent test would comparatively take up many more lines. This is intended to have as many tests as possible that are as quick to write as possible.

View Source
var ReplaceErrorTests = []GenericErrorQueryTest{
	{
		Name:  "too few values",
		Query: "REPLACE INTO mytable (s, i) VALUES ('x');",
	},
	{
		Name:  "too many values one column",
		Query: "REPLACE INTO mytable (s) VALUES ('x', 999);",
	},
	{
		Name:  "too many values two columns",
		Query: "REPLACE INTO mytable (i, s) VALUES (999, 'x', 'y');",
	},
	{
		Name:  "too few values no columns specified",
		Query: "REPLACE INTO mytable VALUES (999);",
	},
	{
		Name:  "too many values no columns specified",
		Query: "REPLACE INTO mytable VALUES (999, 'x', 'y');",
	},
	{
		Name:  "non-existent column values",
		Query: "REPLACE INTO mytable (i, s, z) VALUES (999, 'x', 999);",
	},
	{
		Name:  "non-existent column set",
		Query: "REPLACE INTO mytable SET i = 999, s = 'x', z = 999;",
	},
	{
		Name:  "duplicate column values",
		Query: "REPLACE INTO mytable (i, s, s) VALUES (999, 'x', 'x');",
	},
	{
		Name:  "duplicate column set",
		Query: "REPLACE INTO mytable SET i = 999, s = 'y', s = 'y';",
	},
	{
		Name:  "null given to non-nullable values",
		Query: "INSERT INTO mytable (i, s) VALUES (null, 'y');",
	},
	{
		Name:  "null given to non-nullable set",
		Query: "INSERT INTO mytable SET i = null, s = 'y';",
	},
}
View Source
var ReplaceQueries = []WriteQueryTest{
	{
		WriteQuery:          "REPLACE INTO mytable VALUES (1, 'first row');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT s FROM mytable WHERE i = 1;",
		ExpectedSelect:      []sql.Row{{"first row"}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable SET i = 1, s = 'first row';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT s FROM mytable WHERE i = 1;",
		ExpectedSelect:      []sql.Row{{"first row"}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable VALUES (1, 'new row same i');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT s FROM mytable WHERE i = 1;",
		ExpectedSelect:      []sql.Row{{"new row same i"}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable SET i = 1, s = 'new row same i';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT s FROM mytable WHERE i = 1;",
		ExpectedSelect:      []sql.Row{{"new row same i"}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable (s, i) VALUES ('x', 999);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable SET s = 'x', i = 999;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable VALUES (999, 'x');",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery:          "REPLACE INTO mytable SET i = 999, s = 'x';",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT i FROM mytable WHERE s = 'x';",
		ExpectedSelect:      []sql.Row{{int64(999)}},
	},
	{
		WriteQuery: `REPLACE INTO typestable VALUES (
			999, 127, 32767, 2147483647, 9223372036854775807,
			255, 65535, 4294967295, 18446744073709551615,
			3.40282346638528859811704183484516925440e+38, 1.797693134862315708145274237317043567981e+308,
			'2037-04-05 12:51:36', '2231-11-07',
			'random text', true, '{"key":"value"}', 'blobdata', 'v1', 'v2'
			);`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(math.MaxInt8), int16(math.MaxInt16), int32(math.MaxInt32), int64(math.MaxInt64),
			uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64),
			float32(math.MaxFloat32), float64(math.MaxFloat64),
			sql.MustConvert(types.Timestamp.Convert("2037-04-05 12:51:36")), sql.MustConvert(types.Date.Convert("2231-11-07")),
			"random text", sql.True, types.MustJSON(`{"key":"value"}`), []byte("blobdata"), uint(2), uint(4),
		}},
	},
	{
		WriteQuery: `REPLACE INTO typestable SET
			id = 999, i8 = 127, i16 = 32767, i32 = 2147483647, i64 = 9223372036854775807,
			u8 = 255, u16 = 65535, u32 = 4294967295, u64 = 18446744073709551615,
			f32 = 3.40282346638528859811704183484516925440e+38, f64 = 1.797693134862315708145274237317043567981e+308,
			ti = '2037-04-05 12:51:36', da = '2231-11-07',
			te = 'random text', bo = true, js = '{"key":"value"}', bl = 'blobdata', e1 = 'v1', s1 = 'v2'
			;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(math.MaxInt8), int16(math.MaxInt16), int32(math.MaxInt32), int64(math.MaxInt64),
			uint8(math.MaxUint8), uint16(math.MaxUint16), uint32(math.MaxUint32), uint64(math.MaxUint64),
			float32(math.MaxFloat32), float64(math.MaxFloat64),
			sql.MustConvert(types.Timestamp.Convert("2037-04-05 12:51:36")), sql.MustConvert(types.Date.Convert("2231-11-07")),
			"random text", sql.True, types.MustJSON(`{"key":"value"}`), []byte("blobdata"), uint(2), uint(4),
		}},
	},
	{
		WriteQuery: `REPLACE INTO typestable VALUES (
			999, -128, -32768, -2147483648, -9223372036854775808,
			0, 0, 0, 0,
			1.401298464324817070923729583289916131280e-45, 4.940656458412465441765687928682213723651e-324,
			'0000-00-00 00:00:00', '0000-00-00',
			'', false, '""', '', '', ''
			);`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(-math.MaxInt8 - 1), int16(-math.MaxInt16 - 1), int32(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
			uint8(0), uint16(0), uint32(0), uint64(0),
			float32(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
			types.Timestamp.Zero(), types.Date.Zero(),
			"", sql.False, types.MustJSON(`""`), []byte(""), uint(1), uint(0),
		}},
	},
	{
		WriteQuery: `REPLACE INTO typestable SET
			id = 999, i8 = -128, i16 = -32768, i32 = -2147483648, i64 = -9223372036854775808,
			u8 = 0, u16 = 0, u32 = 0, u64 = 0,
			f32 = 1.401298464324817070923729583289916131280e-45, f64 = 4.940656458412465441765687928682213723651e-324,
			ti = '0000-00-00 00:00:00', da = '0000-00-00',
			te = '', bo = false, js = '""', bl = '', e1 = '', s1 = ''
			;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect: []sql.Row{{
			int64(999), int8(-math.MaxInt8 - 1), int16(-math.MaxInt16 - 1), int32(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
			uint8(0), uint16(0), uint32(0), uint64(0),
			float32(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
			types.Timestamp.Zero(), types.Date.Zero(),
			"", sql.False, types.MustJSON(`""`), []byte(""), uint(1), uint(0),
		}},
	},
	{
		WriteQuery: `REPLACE INTO typestable VALUES (999, null, null, null, null, null, null, null, null,
			null, null, null, null, null, null, null, null, null, null);`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect:      []sql.Row{{int64(999), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}},
	},
	{
		WriteQuery: `REPLACE INTO typestable SET id=999, i8=null, i16=null, i32=null, i64=null, u8=null, u16=null, u32=null, u64=null,
			f32=null, f64=null, ti=null, da=null, te=null, bo=null, js=null, bl=null, e1=null, s1=null;`,
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM typestable WHERE id = 999;",
		ExpectedSelect:      []sql.Row{{int64(999), nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil}},
	},
}

TODO: none of these tests insert into tables without primary key columns, which have different semantics for REPLACE INTO queries. Add some tables / data without primary keys.

View Source
var RollbackTriggerTests = []ScriptTest{

	{
		Name: "trigger before insert, reverts insert when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"create trigger trig before insert on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select x from b order by x",
				Expected: []sql.Row{
					{1}, {2},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1}, {2},
				},
			},
		},
	},
	{
		Name: "trigger after insert, reverts insert when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"create trigger trig after insert on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select x from b order by x",
				Expected: []sql.Row{
					{1}, {2},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1}, {2},
				},
			},
		},
	},
	{
		Name: "trigger before insert, reverts update when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into b values (0)",
			"create trigger trig before insert on a for each row update b set x = x + 1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{2},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
	{
		Name: "trigger after insert, reverts update when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into b values (0)",
			"create trigger trig after insert on a for each row update b set x = x + 1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{2},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
	{
		Name: "trigger before insert, reverts delete when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (1)",
			"insert into b values (1), (2)",
			"create trigger trig before insert on a for each row delete from b where x = new.i;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query: "select x from b order by x",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
	{
		Name: "trigger after insert, reverts delete when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (1)",
			"insert into b values (1), (2)",
			"create trigger trig after insert on a for each row delete from b where x = new.i;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query: "select x from b order by x",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
	{
		Name: "trigger before insert, reverts multiple inserts when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"create trigger trig before insert on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "insert into a values (1), (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query:    "select * from a",
				Expected: []sql.Row{},
			},
			{
				Query:    "select * from b",
				Expected: []sql.Row{},
			},
			{
				Query: "insert into a values (0)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query:       "insert into a values (1), (2), (0)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{0},
				},
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{0},
				},
			},
		},
	},
	{
		Name: "trigger after insert, reverts multiple inserts when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"create trigger trig after insert on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "insert into a values (1), (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query:    "select * from a",
				Expected: []sql.Row{},
			},
			{
				Query:    "select * from b",
				Expected: []sql.Row{},
			},
			{
				Query: "insert into a values (0)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
			{
				Query:       "insert into a values (1), (2), (0)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from a",
				Expected: []sql.Row{
					{0},
				},
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{0},
				},
			},
		},
	},

	{
		Name: "trigger before update, reverts insert when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"create trigger trig before update on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
	{
		Name: "trigger after update, reverts insert when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"create trigger trig after update on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
	{
		Name: "trigger before update, reverts update when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"insert into b values (0)",
			"create trigger trig before update on a for each row update b set x = x + new.i;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
	{
		Name: "trigger after update, reverts update when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"insert into b values (0)",
			"create trigger trig after update on a for each row update b set x = x + new.i;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
	{
		Name: "trigger before update, reverts delete when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"insert into b values (1), (2)",
			"create trigger trig before update on a for each row delete from b where x = new.i;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{2},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
	{
		Name: "trigger after update, reverts delete when query fails",
		SetUpScript: []string{
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"insert into b values (1), (2)",
			"create trigger trig after update on a for each row delete from b where x = new.i;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{2},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},

	{
		Name: "triggers before and after insert fails, rollback",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before insert on a for each row insert into b values (NEW.x * 7)",
			"create trigger a2 after insert on a for each row insert into b values (New.x * 11)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (2), (3), (5)",
				Expected: []sql.Row{
					{types.NewOkResult(3)},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{2}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {33}, {35}, {55},
				},
			},
			{
				Query:       "insert into a values (2), (3), (5)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{2}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {33}, {35}, {55},
				},
			},
		},
	},

	{
		Name: "autocommit off, trigger before insert, reverts insert when query fails",
		SetUpScript: []string{
			"set @@autocommit = off",
			"create table a (i int primary key)",
			"create table b (x int)",
			"create trigger trig before insert on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (2)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select x from b order by x",
				Expected: []sql.Row{
					{1}, {2},
				},
			},
			{
				Query:       "insert into a values (1)",
				ExpectedErr: sql.ErrPrimaryKeyViolation,
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1}, {2},
				},
			},
		},
	},
	{
		Name: "trigger before update, reverts insert when query fails",
		SetUpScript: []string{
			"set @@autocommit = off",
			"create table a (i int primary key)",
			"create table b (x int)",
			"insert into a values (0)",
			"create trigger trig before update on a for each row insert into b values (new.i);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set i = 1",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:          "update a set i = 'not int'",
				ExpectedErrStr: "error: 'not int' is not a valid value for 'int'",
			},
			{
				Query: "select * from b",
				Expected: []sql.Row{
					{1},
				},
			},
		},
	},
}

RollbackTriggerTests are trigger tests that require rollback logic to work correctly

View Source
var ScriptTests = []ScriptTest{
	{
		Name: "enums with default, case-sensitive collation (utf8mb4_0900_bin)",
		SetUpScript: []string{
			"CREATE TABLE enumtest1 (pk int primary key, e enum('abc', 'XYZ'));",
			"CREATE TABLE enumtest2 (pk int PRIMARY KEY, e enum('x ', 'X ', 'y', 'Y'));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO enumtest1 VALUES (1, 'abc'), (2, 'abc'), (3, 'XYZ');",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
			{

				Query:    "SELECT * FROM enumtest1;",
				Expected: []sql.Row{{1, uint64(1)}, {2, uint64(1)}, {3, uint64(2)}},
			},
			{

				Query:          "INSERT INTO enumtest1 VALUES (10, 'ABC'), (11, 'aBc'), (12, 'xyz');",
				ExpectedErrStr: "value ABC is not valid for this Enum",
			},
			{
				Query: "SHOW CREATE TABLE enumtest1;",
				Expected: []sql.Row{{
					"enumtest1",
					"CREATE TABLE `enumtest1` (\n  `pk` int NOT NULL,\n  `e` enum('abc','XYZ'),\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{

				Query: "SHOW CREATE TABLE enumtest2;",
				Expected: []sql.Row{{
					"enumtest2",
					"CREATE TABLE `enumtest2` (\n  `pk` int NOT NULL,\n  `e` enum('x','X','y','Y'),\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query: "DESCRIBE enumtest1;",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"e", "enum('abc','XYZ')", "YES", "", "NULL", ""}},
			},
			{
				Query: "DESCRIBE enumtest2;",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"e", "enum('x','X','y','Y')", "YES", "", "NULL", ""}},
			},
			{
				Query:    "select data_type, column_type from information_schema.columns where table_name='enumtest1' and column_name='e';",
				Expected: []sql.Row{{"enum", "enum('abc','XYZ')"}},
			},
			{
				Query:    "select data_type, column_type from information_schema.columns where table_name='enumtest2' and column_name='e';",
				Expected: []sql.Row{{"enum", "enum('x','X','y','Y')"}},
			},
		},
	},
	{
		Name: "enums with case-insensitive collation (utf8mb4_0900_ai_ci)",
		SetUpScript: []string{
			"CREATE TABLE enumtest1 (pk int primary key, e enum('abc', 'XYZ') collate utf8mb4_0900_ai_ci);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO enumtest1 VALUES (1, 'abc'), (2, 'abc'), (3, 'XYZ');",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
			{
				Query: "SHOW CREATE TABLE enumtest1;",
				Expected: []sql.Row{{
					"enumtest1",
					"CREATE TABLE `enumtest1` (\n  `pk` int NOT NULL,\n  `e` enum('abc','XYZ') COLLATE utf8mb4_0900_ai_ci,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query: "DESCRIBE enumtest1;",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"e", "enum('abc','XYZ') COLLATE utf8mb4_0900_ai_ci", "YES", "", "NULL", ""}},
			},
			{
				Query:    "select data_type, column_type from information_schema.columns where table_name='enumtest1' and column_name='e';",
				Expected: []sql.Row{{"enum", "enum('abc','XYZ')"}},
			},
			{
				Query:    "CREATE TABLE enumtest2 (pk int PRIMARY KEY, e enum('x ', 'X ', 'y', 'Y'));",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO enumtest1 VALUES (10, 'ABC'), (11, 'aBc'), (12, 'xyz');",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
		},
	},
	{
		Name: "failed statements data validation for INSERT, UPDATE",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT, INDEX (v1));",
			"INSERT INTO test VALUES (1,1), (4,4), (5,5);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "INSERT INTO test VALUES (2,2), (3,3), (1,1);",
				ExpectedErrStr: "duplicate primary key given: [1]",
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 1}, {4, 4}, {5, 5}},
			},
			{
				Query:          "UPDATE test SET pk = pk + 1 ORDER BY pk;",
				ExpectedErrStr: "duplicate primary key given: [5]",
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 1}, {4, 4}, {5, 5}},
			},
		},
	},
	{
		Name: "failed statements data validation for DELETE, REPLACE",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT, INDEX (v1));",
			"INSERT INTO test VALUES (1,1), (4,4), (5,5);",
			"CREATE TABLE test2 (pk BIGINT PRIMARY KEY, CONSTRAINT fk_test FOREIGN KEY (pk) REFERENCES test (v1));",
			"INSERT INTO test2 VALUES (4);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DELETE FROM test WHERE pk > 0;",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 1}, {4, 4}, {5, 5}},
			},
			{
				Query:    "SELECT * FROM test2;",
				Expected: []sql.Row{{4}},
			},
			{
				Query:       "REPLACE INTO test VALUES (1,7), (4,8), (5,9);",
				ExpectedErr: sql.ErrForeignKeyParentViolation,
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 1}, {4, 4}, {5, 5}},
			},
			{
				Query:    "SELECT * FROM test2;",
				Expected: []sql.Row{{4}},
			},
		},
	},
	{
		Name: "delete with in clause",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"insert into a values (1), (3), (5)",
			"delete from a where x in (1, 3)",
		},
		Query: "select x from a order by 1",
		Expected: []sql.Row{
			{5},
		},
	},
	{
		Name: "sqllogictest evidence/slt_lang_aggfunc.test",
		SetUpScript: []string{
			"CREATE TABLE t1( x INTEGER, y VARCHAR(8) )",
			"INSERT INTO t1 VALUES(1,'true')",
			"INSERT INTO t1 VALUES(0,'false')",
			"INSERT INTO t1 VALUES(NULL,'NULL')",
		},
		Query: "SELECT count(DISTINCT x) FROM t1",
		Expected: []sql.Row{
			{2},
		},
	},
	{
		Name: "sqllogictest index/commute/10/slt_good_1.test",
		SetUpScript: []string{
			"CREATE TABLE tab0(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT)",
			"INSERT INTO tab0 VALUES(0,42,58.92,'fnbtk',54,68.41,'xmttf')",
			"INSERT INTO tab0 VALUES(1,31,46.55,'sksjf',46,53.20,'wiuva')",
			"INSERT INTO tab0 VALUES(2,30,31.11,'oldqn',41,5.26,'ulaay')",
			"INSERT INTO tab0 VALUES(3,77,44.90,'pmsir',70,84.14,'vcmyo')",
			"INSERT INTO tab0 VALUES(4,23,95.26,'qcwxh',32,48.53,'rvtbr')",
			"INSERT INTO tab0 VALUES(5,43,6.75,'snvwg',3,14.38,'gnfxz')",
			"INSERT INTO tab0 VALUES(6,47,98.26,'bzzva',60,15.2,'imzeq')",
			"INSERT INTO tab0 VALUES(7,98,40.9,'lsrpi',78,66.30,'ephwy')",
			"INSERT INTO tab0 VALUES(8,19,15.16,'ycvjz',55,38.70,'dnkkz')",
			"INSERT INTO tab0 VALUES(9,7,84.4,'ptovf',17,2.46,'hrxsf')",
			"CREATE TABLE tab1(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT)",
			"CREATE INDEX idx_tab1_0 on tab1 (col0)",
			"CREATE INDEX idx_tab1_1 on tab1 (col1)",
			"CREATE INDEX idx_tab1_3 on tab1 (col3)",
			"CREATE INDEX idx_tab1_4 on tab1 (col4)",
			"INSERT INTO tab1 SELECT * FROM tab0",
			"CREATE TABLE tab2(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT)",
			"CREATE UNIQUE INDEX idx_tab2_1 ON tab2 (col4 DESC,col3)",
			"CREATE UNIQUE INDEX idx_tab2_2 ON tab2 (col3 DESC,col0)",
			"CREATE UNIQUE INDEX idx_tab2_3 ON tab2 (col3 DESC,col1)",
			"INSERT INTO tab2 SELECT * FROM tab0",
			"CREATE TABLE tab3(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT)",
			"CREATE INDEX idx_tab3_0 ON tab3 (col3 DESC)",
			"INSERT INTO tab3 SELECT * FROM tab0",
			"CREATE TABLE tab4(pk INTEGER PRIMARY KEY, col0 INTEGER, col1 FLOAT, col2 TEXT, col3 INTEGER, col4 FLOAT, col5 TEXT)",
			"CREATE INDEX idx_tab4_0 ON tab4 (col0 DESC)",
			"CREATE UNIQUE INDEX idx_tab4_2 ON tab4 (col4 DESC,col3)",
			"CREATE INDEX idx_tab4_3 ON tab4 (col3 DESC)",
			"INSERT INTO tab4 SELECT * FROM tab0",
		},
		Query: "SELECT pk FROM tab2 WHERE 78 < col0 AND 19 < col3",
		Expected: []sql.Row{
			{7},
		},
	},
	{
		Name: "3 tables, linear join",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select ya from a join b on ya - 1= xb join c on xc = zb - 2",
				Expected: []sql.Row{{2}},
			},
		},
	},
	{
		Name: "3 tables, v join",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select za from a join b on ya - 1 = xb join c on xa = xc",
				Expected: []sql.Row{{3}},
			},
		},
	},
	{
		Name: "3 tables, linear join, indexes on A,C",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from a join b on xa = yb - 1 join c on yb - 1 = xc",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "4 tables, linear join",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from a join b on ya - 1 = xb join c on xb = xc join d on xc = xd",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "4 tables, linear join, index on D",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from a join b on ya = yb join c on yb = yc join d on yc - 1 = xd",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "4 tables, left join, indexes on all tables",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from a left join b on ya = yb left join c on yb = yc left join d on yc - 1 = xd",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "4 tables, linear join, index on B, D",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from a join b on ya - 1 = xb join c on yc = za - 1 join d on yc - 1 = xd",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "4 tables, all joined to A",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from a join b on xa = xb join c on ya - 1 = xc join d on za - 2 = xd",
				Expected: []sql.Row{{1}},
			},
		},
	},

	{
		Name: "4 tables, all joined to D",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select xa from d join a on yd - 1 = xa join c on zd - 2 = xc join b on xb = zd - 2",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "5 tables, complex join conditions",
		SetUpScript: []string{
			"create table a (xa int primary key, ya int, za int)",
			"create table b (xb int primary key, yb int, zb int)",
			"create table c (xc int primary key, yc int, zc int)",
			"create table d (xd int primary key, yd int, zd int)",
			"create table e (xe int, ye int, ze int, primary key(xe, ye))",
			"insert into a values (1,2,3)",
			"insert into b values (1,2,3)",
			"insert into c values (1,2,3)",
			"insert into d values (1,2,3)",
			"insert into e values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `select xa from a
									join b on ya - 1 = xb
									join c on xc = za - 2
									join d on xd = yb - 1
									join e on xe = zb - 2 and ye = yc`,
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "UUIDs used in the wild.",
		SetUpScript: []string{
			"SET @uuid = '6ccd780c-baba-1026-9564-5b8c656024db'",
			"SET @binuuid = '0011223344556677'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    `SELECT IS_UUID(UUID())`,
				Expected: []sql.Row{{int8(1)}},
			},
			{
				Query:    `SELECT IS_UUID(@uuid)`,
				Expected: []sql.Row{{int8(1)}},
			},
			{
				Query:    `SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid))`,
				Expected: []sql.Row{{"6ccd780c-baba-1026-9564-5b8c656024db"}},
			},
			{
				Query:    `SELECT BIN_TO_UUID(UUID_TO_BIN(@uuid, 1), 1)`,
				Expected: []sql.Row{{"6ccd780c-baba-1026-9564-5b8c656024db"}},
			},
			{
				Query:    `SELECT UUID_TO_BIN(NULL)`,
				Expected: []sql.Row{{nil}},
			},
			{
				Query:    `SELECT HEX(UUID_TO_BIN(@uuid))`,
				Expected: []sql.Row{{"6CCD780CBABA102695645B8C656024DB"}},
			},
			{
				Query:       `SELECT UUID_TO_BIN(123)`,
				ExpectedErr: sql.ErrUuidUnableToParse,
			},
			{
				Query:       `SELECT BIN_TO_UUID(123)`,
				ExpectedErr: sql.ErrUuidUnableToParse,
			},
			{
				Query:    `SELECT BIN_TO_UUID(X'00112233445566778899aabbccddeeff')`,
				Expected: []sql.Row{{"00112233-4455-6677-8899-aabbccddeeff"}},
			},
			{
				Query:    `SELECT BIN_TO_UUID('0011223344556677')`,
				Expected: []sql.Row{{"30303131-3232-3333-3434-353536363737"}},
			},
			{
				Query:    `SELECT BIN_TO_UUID(@binuuid)`,
				Expected: []sql.Row{{"30303131-3232-3333-3434-353536363737"}},
			},
		},
	},
	{
		Name: "Test cases on select into statement",
		SetUpScript: []string{
			"SELECT 1 INTO @abc",
			"SELECT * FROM (VALUES ROW(22,44,88)) AS t INTO @x,@y,@z",
			"CREATE TABLE tab1 (id int primary key, v1 int)",
			"INSERT INTO tab1 VALUES (1, 1), (2, 3), (3, 6)",
			"SELECT id FROM tab1 ORDER BY id DESC LIMIT 1 INTO @myVar",
			"CREATE TABLE tab2 (i2 int primary key, s text)",
			"INSERT INTO tab2 VALUES (1, 'b'), (2, 'm'), (3, 'g')",
			"SELECT m.id, t.s FROM tab1 m JOIN tab2 t on m.id = t.i2 ORDER BY t.s DESC LIMIT 1 INTO @myId, @myText",

			"SELECT id FROM tab1 WHERE id > 3 UNION select s FROM tab2 WHERE s < 'f' INTO @mustSingleVar",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    `SELECT @abc`,
				Expected: []sql.Row{{int8(1)}},
			},
			{
				Query:    `SELECT @z, @x, @y`,
				Expected: []sql.Row{{88, 22, 44}},
			},
			{
				Query:    `SELECT @myVar, @mustSingleVar`,
				Expected: []sql.Row{{3, "b"}},
			},
			{
				Query:    `SELECT @myId, @myText, @myUnion`,
				Expected: []sql.Row{{2, "m", nil}},
			},
			{
				Query:       `SELECT id FROM tab1 ORDER BY id DESC INTO @myvar`,
				ExpectedErr: sql.ErrMoreThanOneRow,
			},
			{
				Query:       `SELECT 1 INTO OUTFILE 'x.txt'`,
				ExpectedErr: sql.ErrUnsupportedSyntax,
			},
			{
				Query:       `SELECT id INTO DUMPFILE 'dump.txt' FROM tab1 ORDER BY id DESC LIMIT 15`,
				ExpectedErr: sql.ErrUnsupportedSyntax,
			},
			{
				Query:       `select 1, 2, 3 into @my1, @my2`,
				ExpectedErr: sql.ErrColumnNumberDoesNotMatch,
			},
			{
				Query:          `SELECT id, v1 INTO @myFirstVar FROM tab1 ORDER BY id DESC LIMIT 1 INTO @mySecondVar`,
				ExpectedErrStr: "Multiple INTO clauses in one query block at position 84 near '@mySecondVar'",
			},
			{
				Query:          `SELECT id FROM tab1 WHERE id > 3 UNION select s INTO @mustSingleVar FROM tab2 WHERE s < 'f' ORDER BY s DESC`,
				ExpectedErrStr: "INTO clause is not allowed at position 98 near 'ORDER'",
			},
		},
	},
	{
		Name: "CrossDB Queries",
		SetUpScript: []string{
			"CREATE DATABASE test",
			"CREATE TABLE test.x (pk int primary key)",
			"insert into test.x values (1),(2),(3)",
			"DELETE FROM test.x WHERE pk=2",
			"UPDATE test.x set pk=300 where pk=3",
			"create table a (xa int primary key, ya int, za int)",
			"insert into a values (1,2,3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT pk from test.x",
				Expected: []sql.Row{{1}, {300}},
			},
			{
				Query:    "SELECT * from a",
				Expected: []sql.Row{{1, 2, 3}},
			},
		},
	},
	{

		Name: "Top-level DECLARE statements",
		Assertions: []ScriptTestAssertion{
			{
				Query:       "DECLARE no_such_table CONDITION FOR SQLSTATE '42S02'",
				ExpectedErr: sql.ErrSyntaxError,
			},
			{
				Query:       "DECLARE no_such_table CONDITION FOR 1051",
				ExpectedErr: sql.ErrSyntaxError,
			},
			{
				Query:       "DECLARE a CHAR(16)",
				ExpectedErr: sql.ErrSyntaxError,
			},
			{
				Query:       "DECLARE cur2 CURSOR FOR SELECT i FROM test.t2",
				ExpectedErr: sql.ErrSyntaxError,
			},
			{
				Query:       "DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE",
				ExpectedErr: sql.ErrSyntaxError,
			},
		},
	},
	{
		Name: "last_insert_id() behavior",
		SetUpScript: []string{
			"create table a (x int primary key auto_increment, y int)",
			"create table b (x int primary key)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select last_insert_id()",
				Expected: []sql.Row{{0}},
			},
			{
				Query:    "insert into a (y) values (1)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 1}}},
			},
			{
				Query:    "select last_insert_id()",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "insert into a (y) values (2), (3)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 2}}},
			},
			{
				Query:    "select last_insert_id()",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "insert into b (x) values (1), (2)",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "select last_insert_id()",
				Expected: []sql.Row{{2}},
			},
		},
	},
	{
		Name: "last_insert_id(expr) behavior",
		SetUpScript: []string{
			"create table a (x int primary key auto_increment, y int)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "insert into a (y) values (1)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 1}}},
			},
			{
				Query:    "select last_insert_id()",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "insert into a (x, y) values (1, 1) on duplicate key update y = 2, x=last_insert_id(x)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 1}}},
			},
			{
				Query:    "select last_insert_id()",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "row_count() behavior",
		SetUpScript: []string{
			"create table b (x int primary key)",
			"insert into b values (1), (2), (3), (4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{4}},
			},
			{
				Query:    "replace into b values (1)",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{-1}},
			},
			{
				Query:    "select count(*) from b",
				Expected: []sql.Row{{4}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{-1}},
			},
			{
				Query: "update b set x = x + 10 where x <> 2",
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 3,
					Info: plan.UpdateInfo{
						Matched: 3,
						Updated: 3,
					},
				}}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{3}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{-1}},
			},
			{
				Query:    "delete from b where x <> 2",
				Expected: []sql.Row{{types.NewOkResult(3)}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{3}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{-1}},
			},
			{
				Query:    "alter table b add column y int null",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{0}},
			},
			{
				Query:    "select row_count()",
				Expected: []sql.Row{{-1}},
			},
		},
	},
	{
		Name: "same alias names for result column name and alias table column name",
		SetUpScript: []string{
			"CREATE TABLE tab0(col0 INTEGER, col1 INTEGER, col2 INTEGER)",
			"INSERT INTO tab0 VALUES(83,0,38)",
			"INSERT INTO tab0 VALUES(26,0,79)",
			"INSERT INTO tab0 VALUES(43,81,24)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT + 13 AS col0 FROM tab0 GROUP BY tab0.col0",
				Expected: []sql.Row{{13}, {13}, {13}},
			},
			{
				Query:    "SELECT 82 col1 FROM tab0 AS cor0 GROUP BY cor0.col1",
				Expected: []sql.Row{{82}, {82}},
			},
			{
				Query:    "SELECT - cor0.col2 * - col2 AS col1 FROM tab0 AS cor0 GROUP BY col2, cor0.col1",
				Expected: []sql.Row{{1444}, {6241}, {576}},
			},
			{
				Query:    "SELECT ALL + 40 col1 FROM tab0 AS cor0 GROUP BY cor0.col1",
				Expected: []sql.Row{{40}, {40}},
			},
			{
				Query:    "SELECT DISTINCT - cor0.col1 col1 FROM tab0 AS cor0 GROUP BY cor0.col1, cor0.col2",
				Expected: []sql.Row{{-81}, {0}},
			},
			{
				Query:    "SELECT DISTINCT ( cor0.col0 ) - col0 AS col2 FROM tab0 AS cor0 GROUP BY cor0.col2, cor0.col0, cor0.col0",
				Expected: []sql.Row{{0}},
			},
		},
	},
	{
		Name: "found_rows() behavior",
		SetUpScript: []string{
			"create table b (x int primary key)",
			"insert into b values (1), (2), (3), (4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from b where x < 2",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "select * from b",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{4}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "select * from b order by x  limit 3",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{3}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "select sql_calc_found_rows * from b order by x limit 3",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{4}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "select sql_calc_found_rows * from b where x <= 2 order by x limit 1",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "select sql_calc_found_rows * from b where x <= 2 order by x limit 1",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "insert into b values (10), (11), (12), (13)",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "update b set x = x where x < 40",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0, Info: plan.UpdateInfo{Matched: 8}}}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{8}},
			},
			{
				Query:    "update b set x = x where x > 10",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0, Info: plan.UpdateInfo{Matched: 3}}}},
			},
			{
				Query:    "select found_rows()",
				Expected: []sql.Row{{3}},
			},
		},
	},
	{
		Name: "INSERT INTO ... SELECT with AUTO_INCREMENT",
		SetUpScript: []string{
			"create table ai (pk int primary key auto_increment, c0 int);",
			"create table other (pk int primary key);",
			"insert into other values (1), (2), (3)",
			"insert into ai (c0) select * from other order by other.pk;",
		},
		Query: "select * from ai;",
		Expected: []sql.Row{
			{1, 1},
			{2, 2},
			{3, 3},
		},
	},
	{
		Name: "Indexed Join On Keyless Table",
		SetUpScript: []string{
			"create table l (pk int primary key, c0 int, c1 int);",
			"create table r (c0 int, c1 int, third int);",
			"create index r_c0 on r (c0);",
			"create index r_c1 on r (c1);",
			"create index r_third on r (third);",
			"insert into l values (0, 0, 0), (1, 0, 1), (2, 1, 0), (3, 0, 2), (4, 2, 0), (5, 1, 2), (6, 2, 1), (7, 2, 2);",
			"insert into l values (256, 1024, 4096);",
			"insert into r values (1, 1, -1), (2, 2, -1), (2, 2, -1);",
			"insert into r values (-1, -1, 256);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select pk, l.c0, l.c1 from l join r on l.c0 = r.c0 or l.c1 = r.c1 order by 1, 2, 3;",
				Expected: []sql.Row{
					{1, 0, 1},
					{2, 1, 0},
					{3, 0, 2},
					{3, 0, 2},
					{4, 2, 0},
					{4, 2, 0},
					{5, 1, 2},
					{5, 1, 2},
					{5, 1, 2},
					{6, 2, 1},
					{6, 2, 1},
					{6, 2, 1},
					{7, 2, 2},
					{7, 2, 2},
				},
			},
			{
				Query: "select pk, l.c0, l.c1 from l join r on l.c0 = r.c0 or l.c1 = r.c1 or l.pk = r.third order by 1, 2, 3;",
				Expected: []sql.Row{
					{1, 0, 1},
					{2, 1, 0},
					{3, 0, 2},
					{3, 0, 2},
					{4, 2, 0},
					{4, 2, 0},
					{5, 1, 2},
					{5, 1, 2},
					{5, 1, 2},
					{6, 2, 1},
					{6, 2, 1},
					{6, 2, 1},
					{7, 2, 2},
					{7, 2, 2},
					{256, 1024, 4096},
				},
			},
			{
				Query: "select pk, l.c0, l.c1 from l join r on l.c0 = r.c0 or l.c1 < 4 and l.c1 = r.c1 or l.c1 >= 4 and l.c1 = r.c1 order by 1, 2, 3;",
				Expected: []sql.Row{
					{1, 0, 1},
					{2, 1, 0},
					{3, 0, 2},
					{3, 0, 2},
					{4, 2, 0},
					{4, 2, 0},
					{5, 1, 2},
					{5, 1, 2},
					{5, 1, 2},
					{6, 2, 1},
					{6, 2, 1},
					{6, 2, 1},
					{7, 2, 2},
					{7, 2, 2},
				},
			},
		},
	},
	{
		Name: "Group Concat Queries",
		SetUpScript: []string{
			"CREATE TABLE x (pk int)",
			"INSERT INTO x VALUES (1),(2),(3),(4),(NULL)",

			"create table t (o_id int, attribute longtext, value longtext)",
			"INSERT INTO t VALUES (2, 'color', 'red'), (2, 'fabric', 'silk')",
			"INSERT INTO t VALUES (3, 'color', 'green'), (3, 'shape', 'square')",

			"create table nulls(pk int)",
			"INSERT INTO nulls VALUES (NULL)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    `SELECT group_concat(pk ORDER BY pk) FROM x;`,
				Expected: []sql.Row{{"1,2,3,4"}},
			},
			{
				Query:    `SELECT group_concat(DISTINCT pk ORDER BY pk) FROM x;`,
				Expected: []sql.Row{{"1,2,3,4"}},
			},
			{
				Query:    `SELECT group_concat(DISTINCT pk ORDER BY pk SEPARATOR '-') FROM x;`,
				Expected: []sql.Row{{"1-2-3-4"}},
			},
			{
				Query:    "SELECT group_concat(`attribute` ORDER BY `attribute`) FROM t group by o_id order by o_id asc",
				Expected: []sql.Row{{"color,fabric"}, {"color,shape"}},
			},
			{
				Query:    "SELECT group_concat(DISTINCT `attribute` ORDER BY value DESC SEPARATOR ';') FROM t group by o_id order by o_id asc",
				Expected: []sql.Row{{"fabric;color"}, {"shape;color"}},
			},
			{
				Query:    "SELECT group_concat(DISTINCT `attribute` ORDER BY `attribute`) FROM t",
				Expected: []sql.Row{{"color,fabric,shape"}},
			},
			{
				Query:    "SELECT group_concat(`attribute` ORDER BY `attribute`) FROM t",
				Expected: []sql.Row{{"color,color,fabric,shape"}},
			},
			{
				Query:    `SELECT group_concat((SELECT 2)) FROM x;`,
				Expected: []sql.Row{{"2,2,2,2,2"}},
			},
			{
				Query:    `SELECT group_concat(DISTINCT (SELECT 2)) FROM x;`,
				Expected: []sql.Row{{"2"}},
			},
			{
				Query:    "SELECT group_concat(DISTINCT `attribute` ORDER BY `attribute` ASC) FROM t",
				Expected: []sql.Row{{"color,fabric,shape"}},
			},
			{
				Query:    "SELECT group_concat(DISTINCT `attribute` ORDER BY `attribute` DESC) FROM t",
				Expected: []sql.Row{{"shape,fabric,color"}},
			},
			{
				Query:    `SELECT group_concat(pk) FROM nulls`,
				Expected: []sql.Row{{nil}},
			},
			{
				Query:       `SELECT group_concat((SELECT * FROM t LIMIT 1)) from t`,
				ExpectedErr: sql.ErrInvalidOperandColumns,
			},
			{
				Query:       `SELECT group_concat((SELECT * FROM x)) from t`,
				ExpectedErr: sql.ErrExpectedSingleRow,
			},
			{
				Query:    "SELECT group_concat(`attribute`) FROM t where o_id=2 order by attribute",
				Expected: []sql.Row{{"color,fabric"}},
			},
			{
				Query:    "SELECT group_concat(DISTINCT `attribute` ORDER BY value DESC SEPARATOR ';') FROM t group by o_id order by o_id asc",
				Expected: []sql.Row{{"fabric;color"}, {"shape;color"}},
			},
			{
				Query:    "SELECT group_concat(o_id) FROM t WHERE `attribute`='color' order by o_id",
				Expected: []sql.Row{{"2,3"}},
			},
		},
	},
	{
		Name: "ALTER TABLE ... ALTER COLUMN SET / DROP DEFAULT",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT NOT NULL DEFAULT 88);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO test (pk) VALUES (1);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 88}},
			},
			{
				Query:    "ALTER TABLE test ALTER v1 SET DEFAULT (CONVERT('42', SIGNED));",
				Expected: []sql.Row{},
			},
			{
				Query:    "INSERT INTO test (pk) VALUES (2);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 88}, {2, 42}},
			},
			{
				Query:       "ALTER TABLE test ALTER v2 SET DEFAULT 1;",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query:    "ALTER TABLE test ALTER v1 DROP DEFAULT;",
				Expected: []sql.Row{},
			},
			{
				Query:       "INSERT INTO test (pk) VALUES (3);",
				ExpectedErr: sql.ErrInsertIntoNonNullableDefaultNullColumn,
			},
			{
				Query:       "ALTER TABLE test ALTER v2 DROP DEFAULT;",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, 88}, {2, 42}},
			},
			{
				Query:    "ALTER TABLE test ALTER v1 SET DEFAULT 100, alter v1 DROP DEFAULT",
				Expected: []sql.Row{},
			},
			{
				Query:       "INSERT INTO test (pk) VALUES (2);",
				ExpectedErr: sql.ErrInsertIntoNonNullableDefaultNullColumn,
			},
			{
				Query:    "ALTER TABLE test ALTER v1 SET DEFAULT 100, alter v1 SET DEFAULT 200",
				Expected: []sql.Row{},
			},
			{
				Query:       "ALTER TABLE test DROP COLUMN v1, alter v1 SET DEFAULT 5000",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query: "DESCRIBE test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", ""},
					{"v1", "bigint", "NO", "", "200", ""},
				},
			},
		},
	},
	{
		Name: "ALTER TABLE ... ALTER ADD CHECK / DROP CHECK",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT NOT NULL DEFAULT 88);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE test ADD CONSTRAINT cx CHECK (v1 < 100)",
				Expected: []sql.Row{},
			},
			{
				Query:    "ALTER TABLE test DROP CHECK cx, ADD CHECK (v1 < 50)",
				Expected: []sql.Row{},
			},
			{
				Query:       "INSERT INTO test VALUES (1, 99)",
				ExpectedErr: sql.ErrCheckConstraintViolated,
			},
			{
				Query:    "INSERT INTO test VALUES (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
		},
	},
	{
		Name: "ALTER TABLE AUTO INCREMENT no-ops on table with no original auto increment key",
		SetUpScript: []string{
			"CREATE table test (pk int primary key)",
			"ALTER TABLE `test` auto_increment = 2;",
			"INSERT INTO test VALUES (1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM test",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "ALTER TABLE MODIFY column with UNIQUE KEY",
		SetUpScript: []string{
			"CREATE table test (pk int primary key, uk int unique)",
			"ALTER TABLE `test` MODIFY column uk int auto_increment",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"uk", "int", "YES", "UNI", "NULL", "auto_increment"},
				},
			},
		},
	},
	{
		Name: "ALTER TABLE MODIFY column with KEY",
		SetUpScript: []string{
			"CREATE table test (pk int primary key, mk int, index (mk))",
			"ALTER TABLE `test` MODIFY column mk int auto_increment",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"mk", "int", "YES", "MUL", "NULL", "auto_increment"},
				},
			},
		},
	},
	{
		Name: "ALTER TABLE AUTO INCREMENT no-ops on table with no original auto increment key",
		SetUpScript: []string{
			"CREATE table test (pk int primary key)",
			"ALTER TABLE `test` auto_increment = 2;",
			"INSERT INTO test VALUES (1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM test",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "Run through some complex queries with DISTINCT and aggregates",
		SetUpScript: []string{
			"CREATE TABLE tab1(col0 INTEGER, col1 INTEGER, col2 INTEGER)",
			"CREATE TABLE tab2(col0 INTEGER, col1 INTEGER, col2 INTEGER)",
			"INSERT INTO tab1 VALUES(51,14,96)",
			"INSERT INTO tab1 VALUES(85,5,59)",
			"INSERT INTO tab1 VALUES(91,47,68)",
			"INSERT INTO tab2 VALUES(64,77,40)",
			"INSERT INTO tab2 VALUES(75,67,58)",
			"INSERT INTO tab2 VALUES(46,51,23)",
			"CREATE TABLE mytable (pk int, v1 int)",
			"INSERT INTO mytable VALUES(1,1)",
			"INSERT INTO mytable VALUES(1,1)",
			"INSERT INTO mytable VALUES(2,2)",
			"INSERT INTO mytable VALUES(1,2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT - SUM( DISTINCT - - 71 ) AS col2 FROM tab2 cor0",
				Expected: []sql.Row{{float64(-71)}},
			},
			{
				Query:    "SELECT - SUM ( DISTINCT - - 71 ) AS col2 FROM tab2 cor0",
				Expected: []sql.Row{{float64(-71)}},
			},
			{
				Query:    "SELECT + MAX( DISTINCT ( - col0 ) ) FROM tab1 AS cor0",
				Expected: []sql.Row{{-51}},
			},
			{
				Query:    "SELECT SUM( DISTINCT + col1 ) * - 22 - - ( - COUNT( * ) ) col0 FROM tab1 AS cor0",
				Expected: []sql.Row{{int64(-1455)}},
			},
			{
				Query:    "SELECT MIN (DISTINCT col1) from tab1 GROUP BY col0 ORDER BY col0",
				Expected: []sql.Row{{14}, {5}, {47}},
			},
			{
				Query:    "SELECT SUM (DISTINCT col1) from tab1 GROUP BY col0 ORDER BY col0",
				Expected: []sql.Row{{float64(14)}, {float64(5)}, {float64(47)}},
			},
			{
				Query:    "SELECT pk, SUM(DISTINCT v1), MAX(v1) FROM mytable GROUP BY pk ORDER BY pk",
				Expected: []sql.Row{{int64(1), float64(3), int64(2)}, {int64(2), float64(2), int64(2)}},
			},
			{
				Query:    "SELECT pk, MIN(DISTINCT v1), MAX(DISTINCT v1) FROM mytable GROUP BY pk ORDER BY pk",
				Expected: []sql.Row{{int64(1), int64(1), int64(2)}, {int64(2), int64(2), int64(2)}},
			},
			{
				Query:    "SELECT SUM(DISTINCT pk * v1) from mytable",
				Expected: []sql.Row{{float64(7)}},
			},
			{
				Query:    "SELECT SUM(DISTINCT POWER(v1, 2)) FROM mytable",
				Expected: []sql.Row{{float64(5)}},
			},
			{
				Query:    "SELECT + + 97 FROM tab1 GROUP BY tab1.col1",
				Expected: []sql.Row{{97}, {97}, {97}},
			},
			{
				Query:    "SELECT rand(10) FROM tab1 GROUP BY tab1.col1",
				Expected: []sql.Row{{0.5660920659323543}, {0.5660920659323543}, {0.5660920659323543}},
			},
			{
				Query:    "SELECT ALL - cor0.col0 * + cor0.col0 AS col2 FROM tab1 AS cor0 GROUP BY cor0.col0",
				Expected: []sql.Row{{-2601}, {-7225}, {-8281}},
			},
			{
				Query:    "SELECT cor0.col0 * cor0.col0 + cor0.col0 AS col2 FROM tab1 AS cor0 GROUP BY cor0.col0 order by 1",
				Expected: []sql.Row{{2652}, {7310}, {8372}},
			},
			{
				Query:    "SELECT - floor(cor0.col0) * ceil(cor0.col0) AS col2 FROM tab1 AS cor0 GROUP BY cor0.col0",
				Expected: []sql.Row{{-2601}, {-7225}, {-8281}},
			},
			{
				Query:    "SELECT col0 FROM tab1 AS cor0 GROUP BY cor0.col0",
				Expected: []sql.Row{{51}, {85}, {91}},
			},
			{
				Query:    "SELECT - cor0.col0 FROM tab1 AS cor0 GROUP BY cor0.col0",
				Expected: []sql.Row{{-51}, {-85}, {-91}},
			},
			{
				Query:    "SELECT col0 BETWEEN 2 and 4 from tab1 group by col0",
				Expected: []sql.Row{{false}, {false}, {false}},
			},
			{
				Query:       "SELECT col0, col1 FROM tab1 GROUP by col0;",
				ExpectedErr: analyzer.ErrValidationGroupBy,
			},
			{
				Query:       "SELECT col0, floor(col1) FROM tab1 GROUP by col0;",
				ExpectedErr: analyzer.ErrValidationGroupBy,
			},
			{
				Query:       "SELECT floor(cor0.col1) * ceil(cor0.col0) AS col2 FROM tab1 AS cor0 GROUP BY cor0.col0",
				ExpectedErr: analyzer.ErrValidationGroupBy,
			},
		},
	},
	{
		Name: "Nested Subquery projections (NTC)",
		SetUpScript: []string{
			`CREATE TABLE dcim_site (id char(32) NOT NULL,created date,last_updated datetime,_custom_field_data json NOT NULL,name varchar(100) NOT NULL,_name varchar(100) NOT NULL,slug varchar(100) NOT NULL,facility varchar(50) NOT NULL,asn bigint,time_zone varchar(63) NOT NULL,description varchar(200) NOT NULL,physical_address varchar(200) NOT NULL,shipping_address varchar(200) NOT NULL,latitude decimal(8,6),longitude decimal(9,6),contact_name varchar(50) NOT NULL,contact_phone varchar(20) NOT NULL,contact_email varchar(254) NOT NULL,comments longtext NOT NULL,region_id char(32),status_id char(32),tenant_id char(32),PRIMARY KEY (id),KEY dcim_site_region_id_45210932 (region_id),KEY dcim_site_status_id_e6a50f56 (status_id),KEY dcim_site_tenant_id_15e7df63 (tenant_id),UNIQUE KEY name (name),UNIQUE KEY slug (slug)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;`,
			`CREATE TABLE dcim_rackgroup (id char(32) NOT NULL,created date,last_updated datetime,_custom_field_data json NOT NULL,name varchar(100) NOT NULL,slug varchar(100) NOT NULL,description varchar(200) NOT NULL,lft int unsigned NOT NULL,rght int unsigned NOT NULL,tree_id int unsigned NOT NULL,level int unsigned NOT NULL,parent_id char(32),site_id char(32) NOT NULL,PRIMARY KEY (id),KEY dcim_rackgroup_parent_id_cc315105 (parent_id),KEY dcim_rackgroup_site_id_13520e89 (site_id),KEY dcim_rackgroup_slug_3f4582a7 (slug),KEY dcim_rackgroup_tree_id_9c2ad6f4 (tree_id),UNIQUE KEY site_idname (site_id,name),UNIQUE KEY site_idslug (site_id,slug),CONSTRAINT dcim_rackgroup_parent_id_cc315105_fk_dcim_rackgroup_id FOREIGN KEY (parent_id) REFERENCES dcim_rackgroup (id),CONSTRAINT dcim_rackgroup_site_id_13520e89_fk_dcim_site_id FOREIGN KEY (site_id) REFERENCES dcim_site (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;`,
			`CREATE TABLE dcim_rack (id char(32) NOT NULL,created date,last_updated datetime,_custom_field_data json NOT NULL,name varchar(100) NOT NULL,_name varchar(100) NOT NULL,facility_id varchar(50),serial varchar(50) NOT NULL,asset_tag varchar(50),type varchar(50) NOT NULL,width smallint unsigned NOT NULL,u_height smallint unsigned NOT NULL,desc_units tinyint NOT NULL,outer_width smallint unsigned,outer_depth smallint unsigned,outer_unit varchar(50) NOT NULL,comments longtext NOT NULL,group_id char(32),role_id char(32),site_id char(32) NOT NULL,status_id char(32),tenant_id char(32),PRIMARY KEY (id),UNIQUE KEY asset_tag (asset_tag),KEY dcim_rack_group_id_44e90ea9 (group_id),KEY dcim_rack_role_id_62d6919e (role_id),KEY dcim_rack_site_id_403c7b3a (site_id),KEY dcim_rack_status_id_ee3dee3e (status_id),KEY dcim_rack_tenant_id_7cdf3725 (tenant_id),UNIQUE KEY group_idfacility_id (group_id,facility_id),UNIQUE KEY group_idname (group_id,name),CONSTRAINT dcim_rack_group_id_44e90ea9_fk_dcim_rackgroup_id FOREIGN KEY (group_id) REFERENCES dcim_rackgroup (id),CONSTRAINT dcim_rack_site_id_403c7b3a_fk_dcim_site_id FOREIGN KEY (site_id) REFERENCES dcim_site (id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;`,
			`INSERT INTO dcim_site (id, created, last_updated, _custom_field_data, status_id, name, _name, slug, region_id, tenant_id, facility, asn, time_zone, description, physical_address, shipping_address, latitude, longitude, contact_name, contact_phone, contact_email, comments) VALUES ('f0471f313b694d388c8ec39d9590e396', '2021-05-20', '2021-05-20 18:51:46.416695', '{}', NULL, 'Site 1', 'Site 00000001', 'site-1', NULL, NULL, '', NULL, '', '', '', '', NULL, NULL, '', '', '', '')`,
			`INSERT INTO dcim_site (id, created, last_updated, _custom_field_data, status_id, name, _name, slug, region_id, tenant_id, facility, asn, time_zone, description, physical_address, shipping_address, latitude, longitude, contact_name, contact_phone, contact_email, comments) VALUES ('442bab8b517149ab87207e8fb5ba1569', '2021-05-20', '2021-05-20 18:51:47.333720', '{}', NULL, 'Site 2', 'Site 00000002', 'site-2', NULL, NULL, '', NULL, '', '', '', '', NULL, NULL, '', '', '', '')`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('5c107f979f434bf7a7820622f18a5211', '2021-05-20', '2021-05-20 18:51:48.150116', '{}', 'Parent Rack Group 1', 'parent-rack-group-1', 'f0471f313b694d388c8ec39d9590e396', NULL, '', 1, 2, 1, 0)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('6707c20336a2406da6a9d394477f7e8c', '2021-05-20', '2021-05-20 18:51:48.969713', '{}', 'Parent Rack Group 2', 'parent-rack-group-2', '442bab8b517149ab87207e8fb5ba1569', NULL, '', 1, 2, 2, 0)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('6bc0d9b1affe46918b09911359241db6', '2021-05-20', '2021-05-20 18:51:50.566160', '{}', 'Rack Group 1', 'rack-group-1', 'f0471f313b694d388c8ec39d9590e396', '5c107f979f434bf7a7820622f18a5211', '', 2, 3, 1, 1)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('a773cac9dc9842228cdfd8c97a67136e', '2021-05-20', '2021-05-20 18:51:52.126952', '{}', 'Rack Group 2', 'rack-group-2', 'f0471f313b694d388c8ec39d9590e396', '5c107f979f434bf7a7820622f18a5211', '', 4, 5, 1, 1)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('a35a843eb181404bb9da2126c6580977', '2021-05-20', '2021-05-20 18:51:53.706000', '{}', 'Rack Group 3', 'rack-group-3', 'f0471f313b694d388c8ec39d9590e396', '5c107f979f434bf7a7820622f18a5211', '', 6, 7, 1, 1)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('f09a02c95b064533b823e25374f5962a', '2021-05-20', '2021-05-20 18:52:03.037056', '{}', 'Test Rack Group 4', 'test-rack-group-4', '442bab8b517149ab87207e8fb5ba1569', '6707c20336a2406da6a9d394477f7e8c', '', 2, 3, 2, 1)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('ecff5b528c5140d4a58f1b24a1c80ebc', '2021-05-20', '2021-05-20 18:52:05.390373', '{}', 'Test Rack Group 5', 'test-rack-group-5', '442bab8b517149ab87207e8fb5ba1569', '6707c20336a2406da6a9d394477f7e8c', '', 4, 5, 2, 1)`,
			`INSERT INTO dcim_rackgroup (id, created, last_updated, _custom_field_data, name, slug, site_id, parent_id, description, lft, rght, tree_id, level) VALUES ('d31b3772910e4418bdd5725d905e2699', '2021-05-20', '2021-05-20 18:52:07.758547', '{}', 'Test Rack Group 6', 'test-rack-group-6', '442bab8b517149ab87207e8fb5ba1569', '6707c20336a2406da6a9d394477f7e8c', '', 6, 7, 2, 1)`,
			`INSERT INTO dcim_rack (id,created,last_updated,_custom_field_data,name,_name,facility_id,serial,asset_tag,type,width,u_height,desc_units,outer_width,outer_depth,outer_unit,comments,group_id,role_id,site_id,status_id,tenant_id) VALUES ('abc123',  '2021-05-20', '2021-05-20 18:51:48.150116', '{}', "name", "name", "facility", "serial", "assettag", "type", 1, 1, 1, 1, 1, "outer units", "comment", "6bc0d9b1affe46918b09911359241db6", "role", "f0471f313b694d388c8ec39d9590e396", "status", "tenant")`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `SELECT 
                             ((
                               SELECT COUNT(*)
                               FROM dcim_rack
                               WHERE group_id 
                               IN (
                                 SELECT m2.id
                                 FROM dcim_rackgroup m2
                                 WHERE m2.tree_id = dcim_rackgroup.tree_id
                                   AND m2.lft BETWEEN dcim_rackgroup.lft
                                   AND dcim_rackgroup.rght
                               )
                             )) AS rack_count,
                             dcim_rackgroup.id,
                             dcim_rackgroup._custom_field_data,
                             dcim_rackgroup.name,
                             dcim_rackgroup.slug,
                             dcim_rackgroup.site_id,
                             dcim_rackgroup.parent_id,
                             dcim_rackgroup.description,
                             dcim_rackgroup.lft,
                             dcim_rackgroup.rght,
                             dcim_rackgroup.tree_id,
                             dcim_rackgroup.level 
                           FROM dcim_rackgroup
							order by 2 limit 1`,
				Expected: []sql.Row{{1, "5c107f979f434bf7a7820622f18a5211", types.JSONDocument{Val: map[string]interface{}{}}, "Parent Rack Group 1", "parent-rack-group-1", "f0471f313b694d388c8ec39d9590e396", interface{}(nil), "", uint64(1), uint64(2), uint64(1), uint64(0)}},
			},
		},
	},
	{
		Name: "CREATE TABLE SELECT Queries",
		SetUpScript: []string{
			`CREATE TABLE t1 (pk int PRIMARY KEY, v1 varchar(10))`,
			`INSERT INTO t1 VALUES (1,"1"), (2,"2"), (3,"3")`,
			`CREATE TABLE t2 AS SELECT * FROM t1`,

			`CREATE TABLE t3 AS SELECT pk FROM t1`,
			`CREATE TABLE t4 AS SELECT pk, v1 FROM t1`,
			`CREATE TABLE t5 SELECT * FROM t1 ORDER BY pk LIMIT 1`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    `SELECT * FROM t2`,
				Expected: []sql.Row{{1, "1"}, {2, "2"}, {3, "3"}},
			},
			{
				Query:    `SELECT * FROM t3`,
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				Query:    `SELECT * FROM t4`,
				Expected: []sql.Row{{1, "1"}, {2, "2"}, {3, "3"}},
			},
			{
				Query:    `SELECT * FROM t5`,
				Expected: []sql.Row{{1, "1"}},
			},
			{
				Query: `CREATE TABLE test SELECT * FROM t1`,
				Expected: []sql.Row{sql.Row{types.OkResult{
					RowsAffected: 3,
					InsertID:     0,
					Info:         nil,
				}}},
			},
		},
	},
	{
		Name: "Issue #499",
		SetUpScript: []string{
			"set time_zone = '+0:00';",
			"CREATE TABLE test (time TIMESTAMP, value DOUBLE);",
			`INSERT INTO test VALUES 
			("2021-07-04 10:00:00", 1.0),
			("2021-07-03 10:00:00", 2.0),
			("2021-07-02 10:00:00", 3.0),
			("2021-07-01 10:00:00", 4.0);`,
		},
		Assertions: []ScriptTestAssertion{
			{

				Query: `SELECT UNIX_TIMESTAMP(time) DIV 60 * 60 AS "time", avg(value) AS "value"
				FROM test GROUP BY 1 ORDER BY UNIX_TIMESTAMP(test.time) DIV 60 * 60`,
				Expected: []sql.Row{
					{"1625133600", 4.0},
					{"1625220000", 3.0},
					{"1625306400", 2.0},
					{"1625392800", 1.0},
				},
			},
		},

		SkipPrepared: true,
	},
	{
		Name: "WHERE clause considers ENUM/SET types for comparisons",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 ENUM('a', 'b', 'c'), v2 SET('a', 'b', 'c'));",
			"INSERT INTO test VALUES (1, 2, 2), (2, 1, 1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, uint16(2), uint64(2)}, {2, uint16(1), uint64(1)}},
			},
			{
				Query:    "UPDATE test SET v1 = 3 WHERE v1 = 2;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 0, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, uint16(3), uint64(2)}, {2, uint16(1), uint64(1)}},
			},
			{
				Query:    "UPDATE test SET v2 = 3 WHERE 2 = v2;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 0, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1, uint16(3), uint64(3)}, {2, uint16(1), uint64(1)}},
			},
		},
	},
	{
		Name: "Slightly more complex example for the Exists Clause",
		SetUpScript: []string{
			"create table store(store_id int, item_id int, primary key (store_id, item_id))",
			"create table items(item_id int primary key, price int)",
			"insert into store values (0, 1), (0,2),(0,3),(1,2),(1,4),(2,1)",
			"insert into items values (1, 10), (2, 20), (3, 30),(4,40)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * from store WHERE EXISTS (SELECT price from items where price > 10 and store.item_id = items.item_id)",
				Expected: []sql.Row{{0, 2}, {0, 3}, {1, 2}, {1, 4}},
			},
		},
	},
	{
		Name: "Simple Update Join test that manipulates two tables",
		SetUpScript: []string{
			"CREATE TABLE test (pk int primary key);",
			`CREATE TABLE test2 (pk int primary key, val int);`,
			`INSERT into test values (0),(1),(2),(3)`,
			`INSERT into test2 values (0, 0),(1, 1),(2, 2),(3, 3)`,
			`CREATE TABLE test3(k int, val int, primary key (k, val))`,
			`INSERT into test3 values (1,2),(1,3),(1,4)`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `update test2 inner join (select * from test3 order by val) as t3 on test2.pk = t3.k SET test2.val=t3.val`,
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{
					Matched:  1,
					Updated:  1,
					Warnings: 0,
				}}}},
			},
			{
				Query: "SELECT val FROM test2 where pk = 1",
				Expected: []sql.Row{
					{2},
				},
			},
			{
				Query: `update test inner join test2 on test.pk = test2.pk SET test.pk=test.pk*10, test2.pk = test2.pk * 4 where test.pk < 10;`,
				Expected: []sql.Row{{types.OkResult{RowsAffected: 6, Info: plan.UpdateInfo{
					Matched:  6,
					Updated:  6,
					Warnings: 0,
				}}}},
			},
			{
				Query: "SELECT * FROM test",
				Expected: []sql.Row{
					{0},
					{10},
					{20},
					{30},
				},
			},
			{
				Query: "SELECT * FROM test2",
				Expected: []sql.Row{
					{0, 0},
					{4, 2},
					{8, 2},
					{12, 3},
				},
			},
		},
	},
	{
		Name: "Partial indexes are used and return the expected result",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, v3 BIGINT, INDEX vx (v3, v2, v1));",
			"INSERT INTO test VALUES (1,2,3,4), (2,3,4,5), (3,4,5,6), (4,5,6,7), (5,6,7,8);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM test WHERE v3 = 4;",
				Expected: []sql.Row{{1, 2, 3, 4}},
			},
			{
				Query:    "SELECT * FROM test WHERE v3 = 8 AND v2 = 7;",
				Expected: []sql.Row{{5, 6, 7, 8}},
			},
			{
				Query:    "SELECT * FROM test WHERE v3 >= 6 AND v2 >= 6;",
				Expected: []sql.Row{{4, 5, 6, 7}, {5, 6, 7, 8}},
			},
			{
				Query:    "SELECT * FROM test WHERE v3 = 7 AND v2 >= 6;",
				Expected: []sql.Row{{4, 5, 6, 7}},
			},
		},
	},
	{
		Name: "Multiple indexes on the same columns in a different order",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT, v2 BIGINT, v3 BIGINT, INDEX v123 (v1, v2, v3), INDEX v321 (v3, v2, v1), INDEX v132 (v1, v3, v2));",
			"INSERT INTO test VALUES (1,2,3,4), (2,3,4,5), (3,4,5,6), (4,5,6,7), (5,6,7,8);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM test WHERE v1 = 2 AND v2 > 1;",
				Expected: []sql.Row{{1, 2, 3, 4}},
			},
			{
				Query:    "SELECT * FROM test WHERE v2 = 4 AND v3 > 1;",
				Expected: []sql.Row{{2, 3, 4, 5}},
			},
			{
				Query:    "SELECT * FROM test WHERE v3 = 6 AND v1 > 1;",
				Expected: []sql.Row{{3, 4, 5, 6}},
			},
			{
				Query:    "SELECT * FROM test WHERE v1 = 5 AND v3 <= 10 AND v2 >= 1;",
				Expected: []sql.Row{{4, 5, 6, 7}},
			},
		},
	},
	{
		Name: "Ensure proper DECIMAL support (found by fuzzer)",
		SetUpScript: []string{
			"CREATE TABLE `GzaKtwgIya` (`K7t5WY` DECIMAL(64,5), `qBjVrN` VARBINARY(1000), `PvqQtc` SET('c3q6y','kxMqhfkK','XlRI8','dF0N63H','hMPjt0KXRLwCGRr','27fi2s','1FSJ','NcPzIN','Za18lbIgxmZ','on4BKKXykVTbJ','WBfO','RMNG','Sd7','FDzbEO','cLRdLOj1y','syo4','Ul','jfsfDCx6s','yEW3','JyQcWFDl'), `1kv7el` FLOAT, `Y3vfRG` BLOB, `Ijq8CK` TINYTEXT, `tzeStN` MEDIUMINT, `Ak83FQ` BINARY(64), `8Nbp3L` DOUBLE, PRIMARY KEY (`K7t5WY`));",
			"REPLACE INTO `GzaKtwgIya` VALUES ('58567047399981325523662211357420045483361289734772861386428.89028','bvo5~Tt8%kMW2nm2!8HghaeulI6!pMadE+j-J2LeU1O1*-#@Lm8Ibh00bTYiA*H1Q8P1_kQq 24Rrd4@HeF%#7#C#U7%mqOMrQ0%!HVrGV1li.XyYa:7#3V^DtAMDTQ9 cY=07T4|DStrwy4.MAQxOG#1d#fcq+7675$y0e96-2@8-WlQ^p|%E!a^TV!Yj2_eqZZys1z:883l5I%zAT:i56K^T!cx#us $60Tb#gH$1#$P.709E#VrH9FbQ5QZK2hZUH!qUa4Xl8*I*0fT~oAha$8jU5AoWs+Uv!~:14Yq%pLXpP9RlZ:Gd1g|*$Qa.9*^K~YlYWVaxwY~_g6zOMpU$YijT+!_*m3=||cMNn#uN0!!OyCg~GTQlJ11+#@Ohqc7b#2|Jp2Aei56GOmq^I=7cQ=sQh~V.D^HzwK5~4E$QzFXfWNVN5J_w2b4dkR~bB~7F%=@R@9qE~e:-_RnoJcOLfBS@0:*hTIP$5ui|5Ea-l+qU4nx98X6rV2bLBxn8am@p~:xLF#T^_9kJVN76q^18=i *FJo.v-xA2GP==^C^Jz3yBF0OY4bIxC59Y#6G=$w:xh71kMxBcYJKf3+$Ci_uWx0P*AfFNne0_1E0Lwv#3J8vm:. 8Wo~F3VT:@w.t@w .JZz$bok9Tls7RGo=~4 Y$~iELr$s@53YuTPM8oqu!x*1%GswpJR=0K#qs00nW-1MqEUc:0wZv#X4qY^pzVDb:!:!yDhjhh+KIT%2%w@+t8c!f~o!%EnwBIr_OyzL6e1$-R8n0nWPU.toODd*|fW3H$9ZLc9!dMS:QfjI0M$nK 8aGvUVP@9kS~W#Y=Q%=37$@pAUkDTXkJo~-DRvCG6phPp*Xji@9|AEODHi+-6p%X4YM5Y3WasPHcZQ8QgTwi9 N=2RQD_MtVU~0J~3SAx*HrMlKvCPTswZq#q_96ny_A@7g!E2jyaxWFJD:C233onBdchW$WdAc.LZdZHYDR^uwZb9B9p-q.BkD1I',608583,'-7.276514330627342e-28','FN3O_E:$ 5S40T7^Vu1g!Ktn^N|4RE!9GnZiW5dG:%SJb5|SNuuI.d2^qnMY.Xn*_fRfk Eo7OhqY8OZ~pA0^ !2P.uN~r@pZ2!A0+4b*%nxO.tm%S6=$CZ9+c1zu-p $b:7:fOkC%@E3951st@2Q93~8hj:ZGeJ6S@nw-TAG+^lad37aB#xN*rD^9TO0|hleA#.Nh28S2PB72L*TxD0$|XE3S5eVVmbI*pkzE~lPecopX1fUyFj#LC+%~pjmab7^ Kdd4B%8I!ohOCQV.oiw++N|#W2=D4:_sK0@~kTTeNA8_+FMKRwro.M0| LdKHf-McKm0Z-R9+H%!9r l6%7UEB50yNH-ld%eW8!f=LKgZLc*TuTP2DA_o0izvzZokNp3ShR+PA7Fk* 1RcSt5KXe+8tLc+WGP','3RvfN2N.Q1tIffE965#2r=u_-4!u:9w!F1p7+mSsO8ckio|ib 1t@~GtgUkJX',1858932,'DJMaQcI=vS-Jk2L#^2N8qZcRpMJ2Ga!30A+@I!+35d-9bwVEVi5-~i.a%!KdoF5h','1.0354401044541863e+255');",
			"INSERT INTO `GzaKtwgIya` VALUES ('91198031969464085142628031466155813748261645250257051732159.65596','96Lu=focmodq4otVAUN6TD-F$@k^4443higo=KH!1WBDH9|vpEGdO* 1uF6yWjT4:7G|altXnWSv+d:c8Km8vL!b%-nuB8mAxO9E|a5N5#v@z!ij5ifeIEoZGXrhBJl.m*Rx-@%g~t:y$3Pp3Q7Bd3y$=YG%6yibqXWO9$SS+g=*6QzdSCzuR~@v!:.ATye0A@y~DG=uq!PaZd6wN7.2S Aq868-RN3RM61V#N+Qywqo=%iYV*554@h6GPKZ| pmNwQw=PywuyBhr*MHAOXV+u9_-#imKI-wT4gEcA1~lGg1cfL2IvhkwOXRhrjAx-8+R3#4!Ai J6SYP|YUuuGalJ_N8k_8K^~h!JyiH$0JbGQ4AOxO3-eW=BaopOd8FF1.cfFMK!tXR ^I15g:npOuZZO$Vq3yQ4bl4s$E9:t2^.4f.:I4_@u9_UI1ApBthJZNiv~o#*uhs9K@ufZ1YPJQY-pMj$v-lQ2#%=Uu!iEAO3%vQ^5YITKcWRk~$kd1H#F675r@P5#M%*F_xP3Js7$YuEC4YuQjZ A74tMw:KwQ8dR:k_ Sa85G~42-K3%:jk5G9csC@iW3nY|@-:_dg~5@J!FWF5F+nyBgz4fDpdkdk9^:_.t$A3W-C@^Ax.~o|Rq96_i%HeG*7jBjOGhY-e1k@aD@WW.@GmpGAI|T-84gZFG3BU9@#9lpL|U2YCEA.BEA%sxDZ Kw:n+d$Y!SZw0Iml$Bdtyr:02Np=DZpiI%$N9*U=%Jq#$P5BI60WOTK+UynVx9Dd**5q8y9^v+I|PPa#_2XheV5YQU.ONdQQNJxsiRaEl!*=xv4bTWj1wBH#_-eM3T',490529,'-8.419238802182018e+25','|WD!NpWJOfN+_Au 1y!|XF8l38#%%R5%$TRUEaFt%4ywKQ8 O1LD-3qRDrnHAXboH~0uivbo87f+V%=q9~Mvz1EIxsU!whSmPqtb9r*11346R_@L+H#@@Z9H-Dc6j%.D0o##m@B9o7jO#~N81ACI|f#J3z4dho:jc54Xws$8r%cxuov^1$w_58Fv2*.8qbAW$TF153A:8wwj4YIhkd#^Q7 |g7I0iQG0p+yE64rk!Pu!SA-z=ELtLNOCJBk_4!lV$izn%sB6JwM+uq~ 49I7','v|eUA_h2@%t~bn26ci8Ngjm@Lk*G=l2MhxhceV2V|ka#c',8150267,'nX-=1Q$3riw_jlukGuHmjodT_Y_SM$xRbEt$%$%hlIUF1+GpRp~U6JvRX^: k@n#','7.956726808353253e+267');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "DELETE FROM `GzaKtwgIya` WHERE `K7t5WY` = '58567047399981325523662211357420045483361289734772861386428.89028';",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT COUNT(*) FROM GzaKtwgIya",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "Ensure scale is not rounded when inserting to DECIMAL type through float64",
		SetUpScript: []string{
			"create table test (number decimal(40,16));",
			"insert into test values ('11981.5923291839784651');",
			"create table small_test (n decimal(3,2));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT COUNT(*) FROM test WHERE number = CONVERT('11981.5923291839784651', DECIMAL)",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "INSERT INTO test VALUES (11981.5923291839784651);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT COUNT(*) FROM test WHERE number = CONVERT('11981.5923291839784651', DECIMAL)",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "INSERT INTO test VALUES (119815923291839784651.11981592329183978465111981592329183978465144);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT COUNT(*) FROM test WHERE number = CONVERT('119815923291839784651.1198159232918398', DECIMAL)",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "INSERT INTO test VALUES (1.1981592329183978465111981592329183978465111981592329183978465144);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT COUNT(*) FROM test WHERE number = CONVERT('1.1981592329183978', DECIMAL)",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "INSERT INTO test VALUES (1.1981592329183978545111981592329183978465111981592329183978465144);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT COUNT(*) FROM test WHERE number = CONVERT('1.1981592329183979', DECIMAL)",
				Expected: []sql.Row{{1}},
			},
			{
				Query:       "INSERT INTO small_test VALUES (12.1);",
				ExpectedErr: types.ErrConvertToDecimalLimit,
			},
		},
	},
	{
		Name: "JOIN on non-index-prefix columns do not panic (Dolt Issue #2366)",
		SetUpScript: []string{
			"CREATE TABLE `player_season_stat_totals` (`player_id` int NOT NULL, `team_id` int NOT NULL, `season_id` int NOT NULL, `minutes` int, `games_started` int, `games_played` int, `2pm` int, `2pa` int, `3pm` int, `3pa` int, `ftm` int, `fta` int, `ast` int, `stl` int, `blk` int, `tov` int, `pts` int, `orb` int, `drb` int, `trb` int, `pf` int, `season_type_id` int NOT NULL, `league_id` int NOT NULL DEFAULT 0, PRIMARY KEY (`player_id`,`team_id`,`season_id`,`season_type_id`,`league_id`));",
			"CREATE TABLE `team_seasons` (`team_id` int NOT NULL, `league_id` int NOT NULL, `season_id` int NOT NULL, `prefix` varchar(100), `nickname` varchar(100), `abbreviation` varchar(100), `city` varchar(100), `state` varchar(100), `country` varchar(100), PRIMARY KEY (`team_id`,`league_id`,`season_id`));",
			"INSERT INTO player_season_stat_totals VALUES (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);",
			"INSERT INTO team_seasons VALUES (1,1,1,'','','','','','');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT stats.* FROM player_season_stat_totals stats LEFT JOIN team_seasons ON team_seasons.team_id = stats.team_id AND team_seasons.season_id = stats.season_id;",
				Expected: []sql.Row{{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}},
			},
		},
	},
	{
		Name: "Issue #709",
		SetUpScript: []string{
			"create table a(id int primary key, v int , key (v));",
		},
	},
	{
		Name: "Show create table with various keys and constraints",
		SetUpScript: []string{
			"create table t1(a int primary key, b varchar(10) not null default 'abc')",
			"alter table t1 add constraint ck1 check (b like '%abc%')",
			"create index t1b on t1(b)",
			"create table t2(c int primary key, d varchar(10))",
			"alter table t2 add constraint t2du unique (d)",
			"alter table t2 add constraint fk1 foreign key (d) references t1 (b)",
			"create table t3 (a int, b varchar(100), c datetime, primary key (b,a))",
			"create table t4 (a int default (floor(1)), b int default (coalesce(a, 10)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "show create table t1",
				Expected: []sql.Row{
					{"t1", "CREATE TABLE `t1` (\n" +
						"  `a` int NOT NULL,\n" +
						"  `b` varchar(10) NOT NULL DEFAULT 'abc',\n" +
						"  PRIMARY KEY (`a`),\n" +
						"  KEY `t1b` (`b`),\n" +
						"  CONSTRAINT `ck1` CHECK (`b` LIKE '%abc%')\n" +
						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "show create table t2",
				Expected: []sql.Row{
					{"t2", "CREATE TABLE `t2` (\n" +
						"  `c` int NOT NULL,\n" +
						"  `d` varchar(10),\n" +
						"  PRIMARY KEY (`c`),\n" +
						"  UNIQUE KEY `t2du` (`d`),\n" +
						"  CONSTRAINT `fk1` FOREIGN KEY (`d`) REFERENCES `t1` (`b`)\n" +
						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "show create table t3",
				Expected: []sql.Row{
					{"t3", "CREATE TABLE `t3` (\n" +
						"  `a` int NOT NULL,\n" +
						"  `b` varchar(100) NOT NULL,\n" +
						"  `c` datetime,\n" +
						"  PRIMARY KEY (`b`,`a`)\n" +
						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "show create table t4",
				Expected: []sql.Row{
					{"t4", "CREATE TABLE `t4` (\n" +
						"  `a` int DEFAULT (floor(1)),\n" +
						"  `b` int DEFAULT (coalesce(a,10))\n" +
						") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
		},
	},
	{
		Name: "table with defaults, insert with on duplicate key update",
		SetUpScript: []string{
			"create table t (a int primary key, b int default 100);",
			"insert into t values (1, 1), (2, 2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "insert into t values (1, 10) on duplicate key update b = 10",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
		},
	},
	{
		Name: "delete from table with misordered pks",
		SetUpScript: []string{
			"create table a (x int, y int, z int, primary key (z,x))",
			"insert into a values (0,1,2), (3,4,5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT count(*) FROM a where x = 0",
				Expected: []sql.Row{
					{1},
				},
			},
			{
				Query:    "delete from a where x = 0",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "SELECT * FROM a where x = 0",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "recreate primary key rebuilds secondary indexes",
		SetUpScript: []string{
			"create table a (x int, y int, z int, primary key (x,y,z), index idx1 (y))",
			"insert into a values (1,2,3), (4,5,6), (7,8,9)",
			"alter table a drop primary key",
			"alter table a add primary key (y,z,x)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "delete from a where y = 2",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "delete from a where y = 2",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "select * from a where y = 2",
				Expected: []sql.Row{},
			},
			{
				Query:    "select * from a where y = 5",
				Expected: []sql.Row{{4, 5, 6}},
			},
		},
	},
	{
		Name: "Handle hex number to binary conversion",
		SetUpScript: []string{
			"CREATE TABLE hex_nums1 (pk BIGINT PRIMARY KEY, v1 INT, v2 BIGINT UNSIGNED, v3 DOUBLE, v4 BINARY(32));",
			"INSERT INTO hex_nums1 values (1, 0x7ED0599B, 0x765a8ce4ce74b187, 0xF753AD20B0C4, 0x148aa875c3cdb9af8919493926a3d7c6862fec7f330152f400c0aecb4467508a);",
			"CREATE TABLE hex_nums2 (pk BIGINT PRIMARY KEY, v1 VARBINARY(255), v2 BLOB);",
			"INSERT INTO hex_nums2 values (1, 0x765a8ce4ce74b187, 0x148aa875c3cdb9af8919493926a3d7c6862fec7f330152f400c0aecb4467508a);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT v1, v2, v3, hex(v4) FROM hex_nums1;",
				Expected: []sql.Row{{2127583643, uint64(8528283758723641735), float64(271938758947012), "148AA875C3CDB9AF8919493926A3D7C6862FEC7F330152F400C0AECB4467508A"}},
			},
			{
				Query:    "SELECT hex(v1), hex(v2), hex(v3), hex(v4) FROM hex_nums1;",
				Expected: []sql.Row{{"7ED0599B", "765A8CE4CE74B187", "F753AD20B0C4", "148AA875C3CDB9AF8919493926A3D7C6862FEC7F330152F400C0AECB4467508A"}},
			},
			{
				Query:    "SELECT hex(v1), hex(v2) FROM hex_nums2;",
				Expected: []sql.Row{{"765A8CE4CE74B187", "148AA875C3CDB9AF8919493926A3D7C6862FEC7F330152F400C0AECB4467508A"}},
			},
		},
	},
	{
		Name: "Multialter DDL with ADD/DROP Primary Key",
		SetUpScript: []string{
			"CREATE TABLE t(pk int primary key, v1 int)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE t ADD COLUMN (v2 int), drop primary key, add primary key (v2)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "NO", "PRI", "NULL", ""},
				},
			},
			{
				Query:       "ALTER TABLE t ADD COLUMN (v3 int), drop primary key, add primary key (notacolumn)",
				ExpectedErr: sql.ErrKeyColumnDoesNotExist,
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "NO", "PRI", "NULL", ""},
				},
			},
		},
	},
	{
		Name: "Multialter DDL with ADD/DROP INDEX",
		SetUpScript: []string{
			"CREATE TABLE t(pk int primary key, v1 int)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "ALTER TABLE t DROP COLUMN v1, ADD INDEX myidx (v1)",
				ExpectedErr: sql.ErrKeyColumnDoesNotExist,
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
				},
			},
			{
				Query:    "ALTER TABLE t ADD COLUMN (v2 int), ADD INDEX myidx (v2)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "YES", "MUL", "NULL", ""},
				},
			},
			{
				Query:       "ALTER TABLE t ADD COLUMN (v3 int), DROP INDEX notanindex",
				ExpectedErr: sql.ErrCantDropFieldOrKey,
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "YES", "MUL", "NULL", ""},
				},
			},
			{
				Query:       "ALTER TABLE t ADD COLUMN (v4 int), ADD INDEX myidx (notacolumn)",
				ExpectedErr: sql.ErrKeyColumnDoesNotExist,
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "YES", "MUL", "NULL", ""},
				},
			},
			{
				Query:       "ALTER TABLE t ADD COLUMN (v4 int), ADD INDEX myidx2 (v4), DROP INDEX notanindex;",
				ExpectedErr: sql.ErrCantDropFieldOrKey,
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "YES", "MUL", "NULL", ""},
				},
			},
			{
				Query:    "ALTER TABLE t ADD COLUMN (v4 int), ADD INDEX myidx2 (v4)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "YES", "MUL", "NULL", ""},
					{"v4", "int", "YES", "MUL", "NULL", ""},
				},
			},
			{
				Query:    "ALTER TABLE t ADD COLUMN (v5 int), RENAME INDEX myidx2 TO myidx3",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "ALTER TABLE t DROP INDEX myidx, ADD INDEX v5idx (v5)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"v1", "int", "YES", "", "NULL", ""},
					{"v2", "int", "YES", "", "NULL", ""},
					{"v4", "int", "YES", "MUL", "NULL", ""},
					{"v5", "int", "YES", "MUL", "NULL", ""},
				},
			},
		},
	},
	{
		Name: "ALTER AUTO INCREMENT TABLE ADD column",
		SetUpScript: []string{
			"CREATE TABLE test (pk int primary key, uk int UNIQUE KEY auto_increment);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table test add column j int;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "alter json column default; from scorewarrior: https://github.com/dolthub/dolt/issues/4543",
		SetUpScript: []string{
			"CREATE TABLE test (i int default 999, j json);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "alter table test alter column j set default ('[]');",
				Expected: []sql.Row{},
			},
			{
				Query: "show create table test",
				Expected: []sql.Row{
					{"test", "CREATE TABLE `test` (\n  `i` int DEFAULT '999',\n  `j` json DEFAULT ('[]')\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
		},
	},
	{
		Name: "ALTER TABLE MULTI ADD/DROP COLUMN",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT NOT NULL DEFAULT 88);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO test (pk) VALUES (1);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "ALTER TABLE test DROP COLUMN v1, ADD COLUMN v2 INT NOT NULL DEFAULT 100",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", ""},
					{"v2", "int", "NO", "", "100", ""},
				},
			},
			{
				Query:    "ALTER TABLE TEST MODIFY COLUMN pk BIGINT AUTO_INCREMENT, AUTO_INCREMENT = 100",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO test (v2) values (11)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 100}}},
			},
			{
				Query:    "SELECT * from test where pk = 100",
				Expected: []sql.Row{{100, 11}},
			},
			{
				Query:       "ALTER TABLE test DROP COLUMN v2, ADD COLUMN v3 int NOT NULL after v2",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", "auto_increment"},
					{"v2", "int", "NO", "", "100", ""},
				},
			},
			{
				Query:       "ALTER TABLE test DROP COLUMN v2, RENAME COLUMN v2 to v3",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", "auto_increment"},
					{"v2", "int", "NO", "", "100", ""},
				},
			},
			{
				Query:       "ALTER TABLE test RENAME COLUMN v2 to v3, DROP COLUMN v2",
				ExpectedErr: sql.ErrTableColumnNotFound,
			},
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", "auto_increment"},
					{"v2", "int", "NO", "", "100", ""},
				},
			},
			{
				Query:    "ALTER TABLE test ADD COLUMN (v3 int NOT NULL), add column (v4 int), drop column v2, add column (v5 int NOT NULL)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "DESCRIBE test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", "auto_increment"},
					{"v3", "int", "NO", "", "NULL", ""},
					{"v4", "int", "YES", "", "NULL", ""},
					{"v5", "int", "NO", "", "NULL", ""},
				},
			},
			{
				Query:    "ALTER TABLE test ADD COLUMN (v6 int not null), RENAME COLUMN v5 TO mycol, DROP COLUMN v4, ADD COLUMN (v7 int);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "describe test",
				Expected: []sql.Row{
					{"pk", "bigint", "NO", "PRI", "NULL", "auto_increment"},
					{"v3", "int", "NO", "", "NULL", ""},
					{"mycol", "int", "NO", "", "NULL", ""},
					{"v6", "int", "NO", "", "NULL", ""},
					{"v7", "int", "YES", "", "NULL", ""},
				},
			},
		},
	},
	{

		Name: "join index lookups do not handle filters",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key, x int, index idx_x(x))",
			"create table c (z int primary key, x int, y int, index idx_x(x))",
			"insert into a values (0),(1),(2),(3)",
			"insert into b values (0,1), (1,1), (2,2), (3,2)",
			"insert into c values (0,1,0), (1,1,0), (2,2,1), (3,2,1)",
		},
		Query: "select a.* from a join b on a.x = b.x join c where c.x = a.x and b.x = 1",
		Expected: []sql.Row{
			{1},
			{1},
			{1},
			{1},
		},
	},
	{
		Name: "failed conversion shows warning",
		Assertions: []ScriptTestAssertion{
			{
				Query:                           "SELECT CONVERT('10000-12-31 23:59:59', DATETIME)",
				ExpectedWarning:                 1292,
				ExpectedWarningsCount:           1,
				ExpectedWarningMessageSubstring: "Incorrect datetime value: 10000-12-31 23:59:59",
				SkipResultsCheck:                true,
			},
			{
				Query:                           "SELECT CONVERT('this is not a datetime', DATETIME)",
				ExpectedWarning:                 1292,
				ExpectedWarningsCount:           1,
				ExpectedWarningMessageSubstring: "Incorrect datetime value: this is not a datetime",
				SkipResultsCheck:                true,
			},
			{
				Query:                           "SELECT CAST('this is not a datetime' as DATETIME)",
				ExpectedWarning:                 1292,
				ExpectedWarningsCount:           1,
				ExpectedWarningMessageSubstring: "Incorrect datetime value: this is not a datetime",
				SkipResultsCheck:                true,
			},
			{
				Query:                           "SELECT CONVERT('this is not a date', DATE)",
				ExpectedWarning:                 1292,
				ExpectedWarningsCount:           1,
				ExpectedWarningMessageSubstring: "Incorrect date value: this is not a date",
				SkipResultsCheck:                true,
			},
			{
				Query:                           "SELECT CAST('this is not a date' as DATE)",
				ExpectedWarning:                 1292,
				ExpectedWarningsCount:           1,
				ExpectedWarningMessageSubstring: "Incorrect date value: this is not a date",
				SkipResultsCheck:                true,
			},
		},
	},
	{
		Name: "Describe with expressions and views work correctly",
		SetUpScript: []string{
			"CREATE TABLE t(pk int primary key, val int DEFAULT (pk * 2))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "DESCRIBE t",
				Expected: []sql.Row{
					{"pk", "int", "NO", "PRI", "NULL", ""},
					{"val", "int", "YES", "", "((pk * 2))", "DEFAULT_GENERATED"},
				},
			},
		},
	},
	{
		Name: "Check support for deprecated BINARY attribute after character set",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) COLLATE utf8mb4_0900_bin);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SHOW CREATE TABLE test;",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(255),\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "ALTER TABLE test CHANGE v1 v2 VARCHAR(255) CHARACTER SET utf8mb4 BINARY NOT NULL;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SHOW CREATE TABLE test;",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `pk` bigint NOT NULL,\n  `v2` varchar(255) COLLATE utf8mb4_bin NOT NULL,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "CREATE TABLE test2 (pk BIGINT PRIMARY KEY, v1 VARCHAR(255) CHARACTER SET utf8mb4 BINARY);",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "SHOW CREATE TABLE test2;",
				Expected: []sql.Row{{"test2", "CREATE TABLE `test2` (\n  `pk` bigint NOT NULL,\n  `v1` varchar(255) COLLATE utf8mb4_bin,\n  PRIMARY KEY (`pk`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "sum() and avg() on DECIMAL type column returns the DECIMAL type result",
		SetUpScript: []string{
			"create table decimal_table (id int, val decimal(18,16));",
			"insert into decimal_table values (1,-2.5633000000000384);",
			"insert into decimal_table values (2,2.5633000000000370);",
			"insert into decimal_table values (3,0.0000000000000004);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT val FROM decimal_table;",
				Expected: []sql.Row{{"-2.5633000000000384"}, {"2.5633000000000370"}, {"0.0000000000000004"}},
			},
			{
				Query:    "SELECT sum(val) FROM decimal_table;",
				Expected: []sql.Row{{"-0.0000000000000010"}},
			},
			{
				Query:    "SELECT avg(val) FROM decimal_table;",
				Expected: []sql.Row{{"-0.00000000000000033333"}},
			},
		},
	},
	{
		Name: "sum() and avg() on non-DECIMAL type column returns the DOUBLE type result",
		SetUpScript: []string{
			"create table float_table (id int, val1 double, val2 float);",
			"insert into float_table values (1,-2.5633000000000384, 2.3);",
			"insert into float_table values (2,2.5633000000000370, 2.4);",
			"insert into float_table values (3,0.0000000000000004, 5.3);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT sum(id), sum(val1), sum(val2) FROM float_table ORDER BY id;",
				Expected: []sql.Row{{float64(6), -9.322676295501879e-16, 10.000000238418579}},
			},
			{
				Query:    "SELECT avg(id), avg(val1), avg(val2) FROM float_table ORDER BY id;;",
				Expected: []sql.Row{{float64(2), -3.107558765167293e-16, 3.333333412806193}},
			},
		},
	},
	{
		Name: "compare DECIMAL type columns with different precision and scale",
		SetUpScript: []string{
			"create table t (id int primary key, val1 decimal(2, 1), val2 decimal(3, 1));",
			"insert into t values (1, 1.2, 1.1), (2, 1.2, 10.1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select if(val1 < val2, 'YES', 'NO') from t order by id;",
				Expected: []sql.Row{{"NO"}, {"YES"}},
			},
		},
	},
	{
		Name: "basic test on tables dual and `dual`",
		SetUpScript: []string{
			"CREATE TABLE `dual` (id int)",
			"INSERT INTO `dual` VALUES (2)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * from `dual`;",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "SELECT 3 from dual;",
				Expected: []sql.Row{{3}},
			},
			{
				Query:       "SELECT * from dual;",
				ExpectedErr: sql.ErrNoTablesUsed,
			},
		},
	},
	{
		Name: "having clause without groupby clause, all rows implicitly form a single aggregate group",
		SetUpScript: []string{
			"create table numbers (val int);",
			"insert into numbers values (1), (2), (3);",
			"insert into numbers values (2), (4);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select val from numbers;",
				Expected: []sql.Row{{1}, {2}, {3}, {2}, {4}},
			},
			{
				Query:    "select val as a from numbers having a = val;",
				Expected: []sql.Row{{1}, {2}, {3}, {2}, {4}},
			},
			{
				Query:    "select val as a from numbers group by val having a = val;",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
			{
				Query:    "select val as a from numbers as t1 group by t1.val having a = t1.val;",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
			{
				Query:    "select t1.val as a from numbers as t1 group by 1 having a = t1.val;",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
			{
				Query:    "select t1.val as a from numbers as t1 having a = t1.val;",
				Expected: []sql.Row{{1}, {2}, {3}, {2}, {4}},
			},
			{
				Query:    "select count(*) from numbers having count(*) = 5;",
				Expected: []sql.Row{{5}},
			},
			{

				Skip:  true,
				Query: "select count(*) from numbers having count(*) > val;",
			},
			{
				Query:    "select count(*) from numbers group by val having count(*) < val;",
				Expected: []sql.Row{{1}, {1}},
			},
		},
	},
	{
		Name: "using having and group by clauses in subquery ",
		SetUpScript: []string{
			"CREATE TABLE t (i int, t varchar(2));",
			"insert into t values (1, 'a'), (1, 'a2'), (2, 'b'), (3, 'c'), (3, 'c2'), (4, 'd'), (5, 'e'), (5, 'e2');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select i from t group by i having count(1) = 1 order by i asc",
				Expected: []sql.Row{{2}, {4}},
			},
			{
				Query:    "select i from t group by i having count(1) != 1 order by i asc",
				Expected: []sql.Row{{1}, {3}, {5}},
			},
			{
				Query:    "select * from t where i in (select i from t group by i having count(1) = 1) order by i, t asc;",
				Expected: []sql.Row{{2, "b"}, {4, "d"}},
			},
			{
				Query:    "select * from t where i in (select i from t group by i having count(1) != 1) order by i, t asc;",
				Expected: []sql.Row{{1, "a"}, {1, "a2"}, {3, "c"}, {3, "c2"}, {5, "e"}, {5, "e2"}},
			},
			{
				Query:    "select * from t where i in (select i from t where i = 2 group by i having count(1) = 1) order by i, t asc;",
				Expected: []sql.Row{{2, "b"}},
			},
			{
				Query:    "select * from t where i in (select i from t where i = 3 group by i having count(1) != 1) order by i, t asc;",
				Expected: []sql.Row{{3, "c"}, {3, "c2"}},
			},
			{
				Query:    "select * from t where i in (select i from t where i > 2 group by i having count(1) != 1) order by i, t asc;",
				Expected: []sql.Row{{3, "c"}, {3, "c2"}, {5, "e"}, {5, "e2"}},
			},
			{
				Query:    "select * from t where i in (select i from t where i > 2 group by i having count(1) != 1 order by i desc) order by i, t asc;",
				Expected: []sql.Row{{3, "c"}, {3, "c2"}, {5, "e"}, {5, "e2"}},
			},
			{
				Query:    "select * from t where i in (select i from t where i > 2 group by i having count(1) != 1) order by i desc, t asc;",
				Expected: []sql.Row{{5, "e"}, {5, "e2"}, {3, "c"}, {3, "c2"}},
			},
		},
	},
	{
		Name: "can't create view with same name as existing table",
		SetUpScript: []string{
			"create table t (i int);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "create view t as select 1 from dual",
				ExpectedErr: sql.ErrTableAlreadyExists,
			},
		},
	},
	{
		Name: "can't create table with same name as existing view",
		SetUpScript: []string{
			"create view t as select 1 from dual",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "create table t (i int);",
				ExpectedErr: sql.ErrTableAlreadyExists,
			},
		},
	},
	{
		Name: "'/' division operation result in decimal or float",
		SetUpScript: []string{
			"create table floats (f float);",
			"insert into floats values (1.1), (1.2), (1.3);",
			"create table decimals (d decimal(2,1));",
			"insert into decimals values (1.0), (2.0), (2.5);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select f/2 from floats;",
				Expected: []sql.Row{{0.550000011920929}, {0.6000000238418579}, {0.6499999761581421}},
			},
			{
				Query:    "select 2/f from floats;",
				Expected: []sql.Row{{1.8181817787737895}, {1.6666666004392863}, {1.5384615948919735}},
			},
			{
				Query:    "select d/2 from decimals;",
				Expected: []sql.Row{{"0.50000"}, {"1.00000"}, {"1.25000"}},
			},
			{
				Query:    "select 2/d from decimals;",
				Expected: []sql.Row{{"2.0000"}, {"1.0000"}, {"0.8000"}},
			},
			{
				Query: "select f/d from floats, decimals;",
				Expected: []sql.Row{{1.2999999523162842}, {1.2000000476837158}, {1.100000023841858},
					{0.6499999761581421}, {0.6000000238418579}, {0.550000011920929},
					{0.5199999809265137}, {0.48000001907348633}, {0.4400000095367432}},
			},
			{
				Query: "select d/f from floats, decimals;",
				Expected: []sql.Row{{0.7692307974459868}, {0.8333333002196431}, {0.9090908893868948},
					{1.5384615948919735}, {1.6666666004392863}, {1.8181817787737895},
					{1.9230769936149668}, {2.083333250549108}, {2.272727223467237}},
			},
			{
				Query:    `select f/'a' from floats;`,
				Expected: []sql.Row{{nil}, {nil}, {nil}},
			},
		},
	},
	{
		Name: "'%' mod operation result in decimal or float",
		SetUpScript: []string{
			"create table a (pk int primary key, c1 int, c2 double, c3 decimal(5,3));",
			"insert into a values (1, 1, 1.111, 1.111), (2, 2, 2.111, 2.111);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select c1 % 2, c2 % 2, c3 % 2 from a;",
				Expected: []sql.Row{{"1", 1.111, "1.111"}, {"0", 0.11100000000000021, "0.111"}},
			},
			{
				Query:    "select c1 % 0.5, c2 % 0.5, c3 % 0.5 from a;",
				Expected: []sql.Row{{"0.0", 0.11099999999999999, "0.111"}, {"0.0", 0.11100000000000021, "0.111"}},
			},
			{
				Query:    "select 20 % c1, 20 % c2, 20 % c3 from a;",
				Expected: []sql.Row{{"0", 0.002000000000000224, "0.002"}, {"0", 1.0009999999999981, "1.001"}},
			},
		},
	},
	{
		Name: "arithmetic bit operations on int, float and decimal types",
		SetUpScript: []string{
			"CREATE TABLE num_types (pk int primary key, a int, b float, c decimal(5,3));",
			"insert into num_types values (1,1,1.1,1.1), (2,2,1.2,2.2), (3,3,1.6,3.7), (4,4,1.7,4.0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select a & 2.4, a | 2.4, a ^ 2.4 from num_types;",
				Expected: []sql.Row{
					{uint64(0), uint64(3), uint64(3)},
					{uint64(2), uint64(2), uint64(0)},
					{uint64(2), uint64(3), uint64(1)},
					{uint64(0), uint64(6), uint64(6)},
				},
			},
			{
				Query: "select b & 2.4, b | 2.4, b ^ 2.4 from num_types;",
				Expected: []sql.Row{
					{uint64(0), uint64(3), uint64(3)},
					{uint64(0), uint64(3), uint64(3)},
					{uint64(2), uint64(2), uint64(0)},
					{uint64(2), uint64(2), uint64(0)},
				},
			},
			{
				Query: "select c & 2.4, c | 2.4, c ^ 2.4 from num_types;",
				Expected: []sql.Row{
					{uint64(0), uint64(3), uint64(3)},
					{uint64(2), uint64(2), uint64(0)},
					{uint64(0), uint64(6), uint64(6)},
					{uint64(0), uint64(6), uint64(6)},
				},
			},
		},
	},
	{
		Name: "year type behavior",
		SetUpScript: []string{
			"create table t (pk int primary key, col1 year);",
		},
		Assertions: []ScriptTestAssertion{

			{
				Query:    "INSERT INTO t VALUES (1, '1901'), (2, 1901);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO t VALUES (3, '2000'), (4, 2000);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO t VALUES (5, '2155'), (6, 2155);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},

			{
				Query:    "INSERT INTO t VALUES (7, '1'), (8, 1);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO t VALUES (9, '35'), (10, 35);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO t VALUES (11, '69'), (12, 69);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},

			{
				Query:    "INSERT INTO t VALUES (13, '70'), (14, 70);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO t VALUES (15, '85'), (16, 85);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query:    "INSERT INTO t VALUES (17, '99'), (18, 99);",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},

			{
				Query:    "INSERT INTO t VALUES (19, '0'), (20, '00');",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},

			{
				Query:    "INSERT INTO t VALUES (21, 0)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},

			{
				Query: "SELECT * from t order by pk;",
				Expected: []sql.Row{
					{1, int16(1901)},
					{2, int16(1901)},
					{3, int16(2000)},
					{4, int16(2000)},
					{5, int16(2155)},
					{6, int16(2155)},
					{7, int16(2001)},
					{8, int16(2001)},
					{9, int16(2035)},
					{10, int16(2035)},
					{11, int16(2069)},
					{12, int16(2069)},
					{13, int16(1970)},
					{14, int16(1970)},
					{15, int16(1985)},
					{16, int16(1985)},
					{17, int16(1999)},
					{18, int16(1999)},
					{19, int16(2000)},
					{20, int16(2000)},
					{21, int16(0)},
				},
			},
		},
	},
	{
		Name: "INSERT IGNORE correctly truncates column data",
		SetUpScript: []string{
			`
			CREATE TABLE t (
				pk int primary key,
				col1 boolean,
				col2 integer,
				col3 tinyint,
				col4 smallint,
				col5 mediumint,
				col6 int,
				col7 bigint,
				col8 decimal,
				col9 float,
				col10 double,
				col11 date,
				col12 time,
				col13 datetime,
				col14 timestamp,
				col15 year,
				col16 ENUM('first', 'second'),
				col17 SET('a', 'b')
			);
			`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `
					INSERT IGNORE INTO t VALUES (
						1, 'val1', 'val2', 'val3', 'val4', 'val5', 'val6', 'val7', 'val8', 'val9', 'val10',
						'val11', 'val12', 'val13', 'val14', 'val15', 'val16', 'val17'
					);
				`,
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query: "SELECT * from t",
				Expected: []sql.Row{
					{
						1,
						0,
						0,
						0,
						0,
						0,
						0,
						0,
						"0",
						float64(0),
						float64(0),
						time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
						types.Timespan(0),
						time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
						time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC),
						0,
						uint64(1),
						uint64(0),
					},
				},
			},
		},
	},
	{
		Name: "INSERT IGNORE throws an error when json is badly formatted",
		SetUpScript: []string{
			"CREATE TABLE t (pk int primary key, col1 json);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "INSERT IGNORE into t VALUES (1, 'val1');",
				ExpectedErr: sql.ErrInvalidJson,
			},
		},
	},
	{
		Name: "hash lookup for joins works with binary",
		SetUpScript: []string{
			"create table uv (u int primary key, v int);",
			"create table xy (x int primary key, y int);",
			"insert into uv values (0,0), (1,1), (2,2);",
			"insert into xy values (0,0), (1,1), (2,2);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select uv.u from uv join xy on binary xy.x = binary uv.u;",
				Expected: []sql.Row{
					{0},
					{1},
					{2},
				},
			},
		},
	},
	{
		Name: "enum columns work as expected in when clauses",
		SetUpScript: []string{
			"create table enums (e enum('a'));",
			"insert into enums values ('a');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select (case e when 'a' then 42 end) from enums",
				Expected: []sql.Row{{42}},
			},
			{
				Query:    "select (case 'a' when e then 42 end) from enums",
				Expected: []sql.Row{{42}},
			},
		},
	},
	{
		Name: "SET and ENUM properly handle integers using UPDATE and DELETE statements",
		SetUpScript: []string{
			"CREATE TABLE setenumtest (pk INT PRIMARY KEY, v1 ENUM('a', 'b', 'c'), v2 SET('a', 'b', 'c'));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "INSERT INTO setenumtest VALUES (1, 1, 1), (2, 1, 1), (3, 3, 1), (4, 1, 3);",
				Expected: []sql.Row{{types.NewOkResult(4)}},
			},
			{
				Query: "UPDATE setenumtest SET v1 = 2, v2 = 2 WHERE pk = 2;",
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 1,
					Info: plan.UpdateInfo{
						Matched:  1,
						Updated:  1,
						Warnings: 0,
					},
				}}},
			},
			{
				Query: "SELECT * FROM setenumtest ORDER BY pk;",
				Expected: []sql.Row{
					{1, uint16(1), uint64(1)},
					{2, uint16(2), uint64(2)},
					{3, uint16(3), uint64(1)},
					{4, uint16(1), uint64(3)},
				},
			},
			{
				Query:    "DELETE FROM setenumtest WHERE v1 = 3;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "DELETE FROM setenumtest WHERE v2 = 3;",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query: "SELECT * FROM setenumtest ORDER BY pk;",
				Expected: []sql.Row{
					{1, uint16(1), uint64(1)},
					{2, uint16(2), uint64(2)},
				},
			},
		},
	},
	{
		Name: "identical expressions over different windows should produce different results",
		SetUpScript: []string{
			"CREATE TABLE t(a INT, b INT);",
			"INSERT INTO t(a, b) VALUES (1, 1), (1, 2), (1, 3), (2, 4), (2, 5), (2, 6);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT SUM(b) OVER (PARTITION BY a ORDER BY b) FROM t ORDER BY 1;",
				Expected: []sql.Row{{float64(1)}, {float64(3)}, {float64(4)}, {float64(6)}, {float64(9)}, {float64(15)}},
			},
			{
				Query:    "SELECT SUM(b) OVER (ORDER BY b) FROM t ORDER BY 1;",
				Expected: []sql.Row{{float64(1)}, {float64(3)}, {float64(6)}, {float64(10)}, {float64(15)}, {float64(21)}},
			},
			{
				Query: "SELECT SUM(b) OVER (PARTITION BY a ORDER BY b), SUM(b) OVER (ORDER BY b) FROM t ORDER BY 1;",
				Expected: []sql.Row{
					{float64(1), float64(1)},
					{float64(3), float64(3)},
					{float64(4), float64(10)},
					{float64(6), float64(6)},
					{float64(9), float64(15)},
					{float64(15), float64(21)},
				},
			},
		},
	},
	{
		Name: "windows without ORDER BY should be treated as RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING",
		SetUpScript: []string{
			"CREATE TABLE t(a INT, b INT);",
			"INSERT INTO t(a, b) VALUES (1, 1), (1, 2), (1, 3), (2, 4), (2, 5), (2, 6);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT SUM(b) OVER (PARTITION BY a) FROM t ORDER BY 1;",
				Expected: []sql.Row{{float64(6)}, {float64(6)}, {float64(6)}, {float64(15)}, {float64(15)}, {float64(15)}},
			},
			{
				Query:    "SELECT SUM(b) OVER () FROM t ORDER BY 1;",
				Expected: []sql.Row{{float64(21)}, {float64(21)}, {float64(21)}, {float64(21)}, {float64(21)}, {float64(21)}},
			},
			{
				Query: "SELECT SUM(b) OVER (PARTITION BY a), SUM(b) OVER () FROM t;",
				Expected: []sql.Row{
					{float64(6), float64(21)},
					{float64(6), float64(21)},
					{float64(6), float64(21)},
					{float64(15), float64(21)},
					{float64(15), float64(21)},
					{float64(15), float64(21)},
				},
			},
		},
	},
	{
		Name: "decimal literals should be parsed correctly",
		SetUpScript: []string{
			"SET @testValue = 809826404100301269648758758005707100;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @testValue;",
				Expected: []sql.Row{{"809826404100301269648758758005707100"}},
			},
		},
	},
	{
		Name: "division and int division operation on negative, small and big value for decimal type column of table",
		SetUpScript: []string{
			"create table t (d decimal(25,10) primary key);",
			"insert into t values (-4990), (2), (22336578);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select d div 314990 from t order by d;",
				Expected: []sql.Row{{0}, {0}, {70}},
			},
			{
				Query:    "select d / 314990 from t order by d;",
				Expected: []sql.Row{{"-0.01584177275469"}, {"0.00000634940792"}, {"70.91202260389219"}},
			},
		},
	},
	{
		Name: "drop table if exists on unknown table shows warning",
		Assertions: []ScriptTestAssertion{
			{
				Query:                           "DROP TABLE IF EXISTS non_existent_table;",
				ExpectedWarning:                 1051,
				ExpectedWarningsCount:           1,
				ExpectedWarningMessageSubstring: "Unknown table 'non_existent_table'",
				SkipResultsCheck:                true,
			},
		},
	},
}

ScriptTests are a set of test scripts to run. Unlike other engine tests, ScriptTests must be self-contained. No other tables are created outside the definition of the tests.

View Source
var ServerAuthTests = []ServerAuthenticationTest{
	{
		Name: "DROP USER reports correct string for missing address",
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:       "root",
				Password:       "",
				Query:          "DROP USER xyz;",
				ExpectedErrStr: "Error 1105: Operation DROP USER failed for 'xyz'@'%'",
			},
		},
	},
	{
		Name: "CREATE USER with an empty password",
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:    "root",
				Password:    "",
				Query:       "CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);",
				ExpectedErr: false,
			},
			{
				Username:    "root",
				Password:    "",
				Query:       "CREATE USER rand_user@localhost IDENTIFIED BY '';",
				ExpectedErr: false,
			},
			{
				Username:    "root",
				Password:    "",
				Query:       "GRANT ALL ON *.* TO rand_user@localhost;",
				ExpectedErr: false,
			},
			{
				Username:    "rand_user",
				Password:    "",
				Query:       "SELECT * FROM mydb.test;",
				ExpectedErr: false,
			},
		},
	},
	{
		Name: "Basic root authentication",
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:    "root",
				Password:    "",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: false,
			},
			{
				Username:    "root",
				Password:    "pass",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
		},
	},
	{
		Name: "Create User without plugin specification",
		SetUpScript: []string{
			"CREATE USER rand_user@localhost IDENTIFIED BY 'rand_pass';",
			"GRANT ALL ON *.* TO rand_user@localhost WITH GRANT OPTION;",
		},
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:    "rand_user",
				Password:    "rand_pass",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: false,
			},
			{
				Username:    "rand_user",
				Password:    "rand_pass1",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
			{
				Username:    "rand_user",
				Password:    "",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
			{
				Username:    "rand_use",
				Password:    "rand_pass",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
		},
	},
	{
		Name: "Create User with plugin specification",
		SetUpScript: []string{
			"CREATE USER ranuse@localhost IDENTIFIED WITH mysql_native_password BY 'ranpas';",
			"GRANT ALL ON *.* TO ranuse@localhost WITH GRANT OPTION;",
		},
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:    "ranuse",
				Password:    "ranpas",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: false,
			},
			{
				Username:    "ranuse",
				Password:    "what",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
			{
				Username:    "ranuse",
				Password:    "",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
		},
	},
	{
		Name: "Create User with jwt plugin specification",
		SetUpScript: []string{
			"CREATE USER `test-user`@localhost IDENTIFIED WITH authentication_dolt_jwt AS 'jwks=testing,sub=test-user,iss=dolthub.com,aud=some_id';",
			"GRANT ALL ON *.* TO `test-user`@localhost WITH GRANT OPTION;",
		},
		SetUpFunc: func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) {
			plugins := map[string]mysql_db.PlaintextAuthPlugin{"authentication_dolt_jwt": &NoopPlaintextPlugin{}}
			engine.Analyzer.Catalog.MySQLDb.SetPlugins(plugins)
		},
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:    "test-user",
				Password:    "what",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
			{
				Username:    "test-user",
				Password:    "",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
			{
				Username:    "test-user",
				Password:    "right-password",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: false,
			},
		},
	},
	{
		Name: "Adding a Super User directly",
		SetUpFunc: func(ctx *sql.Context, t *testing.T, engine *sqle.Engine) {
			engine.Analyzer.Catalog.MySQLDb.AddSuperUser("bestuser", "localhost", "the_pass")
		},
		Assertions: []ServerAuthenticationTestAssertion{
			{
				Username:    "bestuser",
				Password:    "the_past",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: true,
			},
			{
				Username:    "bestuser",
				Password:    "the_pass",
				Query:       "SELECT * FROM mysql.user;",
				ExpectedErr: false,
			},
		},
	},
}

ServerAuthTests test the server authentication system. These tests always have the root account available, and the root account is used with any queries in the SetUpScript, along as being set to the context passed to SetUpFunc.

View Source
var ShowTableStatusQueries = []QueryTest{
	{
		Query: `SHOW TABLE STATUS FROM mydb`,
		Expected: []sql.Row{
			{"mytable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
			{"othertable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
		},
	},
	{
		Query: `SHOW TABLE STATUS LIKE '%table'`,
		Expected: []sql.Row{
			{"mytable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
			{"othertable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
		},
	},
	{
		Query: `SHOW TABLE STATUS FROM mydb LIKE 'othertable'`,
		Expected: []sql.Row{
			{"othertable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
		},
	},
	{
		Query: `SHOW TABLE STATUS WHERE Name = 'mytable'`,
		Expected: []sql.Row{
			{"mytable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
		},
	},
	{
		Query: `SHOW TABLE STATUS`,
		Expected: []sql.Row{
			{"mytable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
			{"othertable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
		},
	},
	{
		Query: `SHOW TABLE STATUS FROM mydb LIKE 'othertable'`,
		Expected: []sql.Row{
			{"othertable", "InnoDB", "10", "Fixed", uint64(3), uint64(88), uint64(264), uint64(0), int64(0), int64(0), nil, nil, nil, nil, "utf8mb4_0900_bin", nil, nil, nil},
		},
	},
}
View Source
var SkippedInfoSchemaQueries = []QueryTest{
	{

		Query: `
		SELECT COLUMN_NAME AS COLUMN_NAME FROM information_schema.COLUMNS
		WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME LIKE '%table'
		GROUP BY 1 HAVING SUBSTRING(COLUMN_NAME, 1, 1) = "s"
		`,
		Expected: []sql.Row{{"s"}},
	},
}
View Source
var SkippedInfoSchemaScripts = []ScriptTest{
	{
		Name: "information_schema.key_column_usage works with foreign key across different databases",
		SetUpScript: []string{
			"CREATE TABLE my_table (i int primary key, height int)",
			"CREATE DATABASE keydb",
			"USE keydb",
			"CREATE TABLE key_table (a int primary key, weight int)",
			"alter table key_table add constraint fk_across_dbs foreign key (a) references mydb.my_table(i)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.key_column_usage where constraint_name = 'fk_across_dbs'",
				Expected: []sql.Row{
					{"def", "keydb", "fk_across_dbs", "def", "keydb", "key_table", "a", 1, 1, "mydb", "my_table", "i"},
				},
			},
		},
	},
}
View Source
var SkippedJoinQueryTests = []QueryTest{
	{

		Query:    "select x from xy, uv join ab on x = a and u = -1",
		Expected: []sql.Row{{}},
	},
}
View Source
var SkippedUpdateTests = []WriteQueryTest{
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, two_pk.c1 = two_pk.c2 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(8, 6)}},
		SelectQuery:         "SELECT * FROM two_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 2, 1, 2, 3, 4),
			sql.NewRow(0, 1, 12, 11, 12, 13, 14),
			sql.NewRow(1, 0, 22, 21, 22, 23, 24),
			sql.NewRow(1, 1, 32, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM othertable;",
		ExpectedSelect: []sql.Row{
			sql.NewRow("third", 1),
			sql.NewRow("second", 2),
			sql.NewRow("fourth", 3),
		},
	},
}

These tests return the correct select query answer but the wrong write result.

View Source
var SpatialDeleteTests = []WriteQueryTest{
	{
		WriteQuery:          "DELETE FROM point_table;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM point_table;",
		ExpectedSelect:      nil,
	},
	{
		WriteQuery:          "DELETE FROM line_table;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM line_table;",
		ExpectedSelect:      nil,
	},
	{
		WriteQuery:          "DELETE FROM polygon_table;",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(2)}},
		SelectQuery:         "SELECT * FROM polygon_table;",
		ExpectedSelect:      nil,
	},
}
View Source
var SpatialIndexScriptTests = []ScriptTest{
	{
		Name:        "create spatial index errors",
		SetUpScript: []string{},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "create table geom(g geometry, SPATIAL INDEX(g))",
				ExpectedErr: sql.ErrNullableSpatialIdx,
			},
			{
				Query:       "create table geom(g geometry SRID 4326, SPATIAL INDEX(g))",
				ExpectedErr: sql.ErrNullableSpatialIdx,
			},
			{
				Query:       "create table geom(g1 geometry NOT NULL SRID 0, g2 geometry NOT NULL SRID 4326, SPATIAL INDEX(g1, g2))",
				ExpectedErr: sql.ErrTooManyKeyParts,
			},
		},
	},
	{
		Name: "alter table spatial index nullable",
		SetUpScript: []string{
			"create table geom(g geometry)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table geom add spatial index (g)",
				ExpectedErr: sql.ErrNullableSpatialIdx,
			},
		},
	},
	{
		Name: "alter table spatial index with srid nullable",
		SetUpScript: []string{
			"create table geom(g geometry SRID 4326)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table geom add spatial index (g)",
				ExpectedErr: sql.ErrNullableSpatialIdx,
			},
		},
	},
	{
		Name: "show table with spatial indexes",
		SetUpScript: []string{
			"create table geom(" +
				"p point not null srid 0," +
				"l linestring not null srid 0," +
				"py polygon not null srid 0," +
				"mp multipoint not null srid 0," +
				"ml multilinestring not null srid 0," +
				"mpy multipolygon not null srid 0," +
				"gc geometrycollection not null srid 0," +
				"g geometry not null srid 0)",
			"alter table geom add spatial index (p)",
			"alter table geom add spatial index (l)",
			"alter table geom add spatial index (py)",
			"alter table geom add spatial index (mp)",
			"alter table geom add spatial index (ml)",
			"alter table geom add spatial index (mpy)",
			"alter table geom add spatial index (gc)",
			"alter table geom add spatial index (g)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "show create table geom",
				Expected: []sql.Row{
					{
						"geom",
						"CREATE TABLE `geom` (\n" +
							"  `p` point NOT NULL SRID 0,\n" +
							"  `l` linestring NOT NULL SRID 0,\n" +
							"  `py` polygon NOT NULL SRID 0,\n" +
							"  `mp` multipoint NOT NULL SRID 0,\n" +
							"  `ml` multilinestring NOT NULL SRID 0,\n" +
							"  `mpy` multipolygon NOT NULL SRID 0,\n" +
							"  `gc` geometrycollection NOT NULL SRID 0,\n" +
							"  `g` geometry NOT NULL SRID 0,\n" +
							"  SPATIAL KEY `g` (`g`),\n" +
							"  SPATIAL KEY `gc` (`gc`),\n" +
							"  SPATIAL KEY `l` (`l`),\n" +
							"  SPATIAL KEY `ml` (`ml`),\n" +
							"  SPATIAL KEY `mp` (`mp`),\n" +
							"  SPATIAL KEY `mpy` (`mpy`),\n" +
							"  SPATIAL KEY `p` (`p`),\n" +
							"  SPATIAL KEY `py` (`py`)\n" +
							") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
					},
				},
			},
		},
	},
	{
		Name: "add spatial index to non-empty table",
		SetUpScript: []string{
			"create table geom_tbl(g geometry not null srid 0)",
			"insert into geom_tbl values (point(0,0)), (linestring(point(1,1), point(2,2)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "alter table geom_tbl add spatial index (g)",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "show create table geom_tbl",
				Expected: []sql.Row{
					{"geom_tbl", "CREATE TABLE `geom_tbl` (\n  `g` geometry NOT NULL SRID 0,\n  SPATIAL KEY `g` (`g`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "select count(*) from geom_tbl where st_intersects(g, st_geomfromtext('polygon((0 0,0 10,10 10,10 0,0 0))'))",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
	{
		Name: "add spatial index to non-empty table with primary key",
		SetUpScript: []string{
			"create table geom_tbl(i int, j int, g geometry not null srid 0, primary key (i, j))",
			"insert into geom_tbl values (1, 10, point(0,0)), (2, 20, linestring(point(1,1), point(2,2)))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "alter table geom_tbl add spatial index (g)",
				Expected: []sql.Row{
					{types.NewOkResult(0)},
				},
			},
			{
				Query: "show create table geom_tbl",
				Expected: []sql.Row{
					{"geom_tbl", "CREATE TABLE `geom_tbl` (\n  `i` int NOT NULL,\n  `j` int NOT NULL,\n  `g` geometry NOT NULL SRID 0,\n  PRIMARY KEY (`i`,`j`),\n  SPATIAL KEY `g` (`g`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
				},
			},
			{
				Query: "select count(*) from geom_tbl where st_intersects(g, st_geomfromtext('polygon((0 0,0 10,10 10,10 0,0 0))'))",
				Expected: []sql.Row{
					{2},
				},
			},
		},
	},
	{
		Name: "spatial indexes do not work as foreign keys",
		SetUpScript: []string{
			"create table parent (i int primary key, p point not null srid 0, spatial index (p))",
			"create table child1 (j int primary key, p point not null srid 0, spatial index (p))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "alter table child1 add foreign key (p) references parent (p)",
				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
			},
			{
				Query:       "create table child2 (p point not null srid 0, spatial index (p), foreign key (p) references parent (p))",
				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
			},
		},
	},
}
View Source
var SpatialInsertQueries = []WriteQueryTest{
	{
		WriteQuery:          "INSERT INTO point_table VALUES (1, POINT(1,1));",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM point_table;",
		ExpectedSelect:      []sql.Row{{5, types.Point{X: 1, Y: 2}}, {1, types.Point{X: 1, Y: 1}}},
	},
	{
		WriteQuery:          "INSERT INTO point_table VALUES (1, 0x000000000101000000000000000000F03F0000000000000040);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM point_table;",
		ExpectedSelect:      []sql.Row{{5, types.Point{X: 1, Y: 2}}, {1, types.Point{X: 1, Y: 2}}},
	},
	{
		WriteQuery:          "INSERT INTO line_table VALUES (2, LINESTRING(POINT(1,2),POINT(3,4)));",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM line_table;",
		ExpectedSelect:      []sql.Row{{0, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}, {1, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}, {X: 5, Y: 6}}}}, {2, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}},
	},
	{
		WriteQuery:          "INSERT INTO line_table VALUES (2, 0x00000000010200000002000000000000000000F03F000000000000004000000000000008400000000000001040);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM line_table;",
		ExpectedSelect:      []sql.Row{{0, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}, {1, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}, {X: 5, Y: 6}}}}, {2, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}},
	},
	{
		WriteQuery:          "INSERT INTO polygon_table VALUES (2, POLYGON(LINESTRING(POINT(1,1),POINT(1,-1),POINT(-1,-1),POINT(-1,1),POINT(1,1))));",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM polygon_table;",
		ExpectedSelect: []sql.Row{
			{0, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{1, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}, {Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{2, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
		},
	},
	{
		WriteQuery:          "INSERT INTO polygon_table VALUES (2, 0x0000000001030000000100000005000000000000000000F03F000000000000F03F000000000000F03F000000000000F0BF000000000000F0BF000000000000F0BF000000000000F0BF000000000000F03F000000000000F03F000000000000F03F);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM polygon_table;",
		ExpectedSelect: []sql.Row{
			{0, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{1, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}, {Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{2, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}}},
	},
	{
		WriteQuery:          "INSERT INTO geometry_table VALUES (100, POINT(123.456,7.89));",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM geometry_table;",
		ExpectedSelect: []sql.Row{
			{1, types.Point{X: 1, Y: 2}},
			{2, types.Point{SRID: 4326, X: 1, Y: 2}},
			{3, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{4, types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{5, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{6, types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{7, types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{8, types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{9, types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}}},
			{10, types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{11, types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, {X: 0, Y: 0}}}}}}}},
			{12, types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{13, types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{14, types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
			{100, types.Point{X: 123.456, Y: 7.89}},
		},
	},
	{
		WriteQuery:          "INSERT INTO geometry_table VALUES (100, 0x00000000010100000077BE9F1A2FDD5E408FC2F5285C8F1F40);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM geometry_table;",
		ExpectedSelect: []sql.Row{
			{1, types.Point{X: 1, Y: 2}},
			{2, types.Point{SRID: 4326, X: 1, Y: 2}},
			{3, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{4, types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{5, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{6, types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{7, types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{8, types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{9, types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}}},
			{10, types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{11, types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, {X: 0, Y: 0}}}}}}}},
			{12, types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{13, types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{14, types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
			{100, types.Point{X: 123.456, Y: 7.89}},
		},
	},
	{
		WriteQuery:          "INSERT INTO geometry_table VALUES (100, LINESTRING(POINT(1,2),POINT(3,4)));",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM geometry_table;",
		ExpectedSelect: []sql.Row{
			{1, types.Point{X: 1, Y: 2}},
			{2, types.Point{SRID: 4326, X: 1, Y: 2}},
			{3, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{4, types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{5, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{6, types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{7, types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{8, types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{9, types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}}},
			{10, types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{11, types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, {X: 0, Y: 0}}}}}}}},
			{12, types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{13, types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{14, types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
			{100, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
		},
	},
	{
		WriteQuery:          "INSERT INTO geometry_table VALUES (100, 0x00000000010200000002000000000000000000F03F000000000000004000000000000008400000000000001040);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM geometry_table;",
		ExpectedSelect: []sql.Row{
			{1, types.Point{X: 1, Y: 2}},
			{2, types.Point{SRID: 4326, X: 1, Y: 2}},
			{3, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{4, types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{5, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{6, types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{7, types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{8, types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{9, types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}}},
			{10, types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{11, types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, {X: 0, Y: 0}}}}}}}},
			{12, types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{13, types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{14, types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
			{100, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
		},
	},
	{
		WriteQuery:          "INSERT INTO geometry_table VALUES (100, POLYGON(LINESTRING(POINT(1,1),POINT(1,-1),POINT(-1,-1),POINT(-1,1),POINT(1,1))));",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM geometry_table;",
		ExpectedSelect: []sql.Row{
			{1, types.Point{X: 1, Y: 2}},
			{2, types.Point{SRID: 4326, X: 1, Y: 2}},
			{3, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{4, types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{5, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{6, types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{7, types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{8, types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{9, types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}}},
			{10, types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{11, types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, {X: 0, Y: 0}}}}}}}},
			{12, types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{13, types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{14, types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
			{100, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
		},
	},
	{
		WriteQuery:          "INSERT INTO geometry_table VALUES (100, 0x0000000001030000000100000005000000000000000000F03F000000000000F03F000000000000F03F000000000000F0BF000000000000F0BF000000000000F0BF000000000000F0BF000000000000F03F000000000000F03F000000000000F03F);",
		ExpectedWriteResult: []sql.Row{{types.NewOkResult(1)}},
		SelectQuery:         "SELECT * FROM geometry_table;",
		ExpectedSelect: []sql.Row{
			{1, types.Point{X: 1, Y: 2}},
			{2, types.Point{SRID: 4326, X: 1, Y: 2}},
			{3, types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{4, types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{5, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{6, types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{7, types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{8, types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{9, types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}}}},
			{10, types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{11, types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 2}, {X: 3, Y: 4}, {X: 0, Y: 0}}}}}}}},
			{12, types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{13, types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{14, types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
			{100, types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
		},
	},
}
View Source
var SpatialQueryTests = []QueryTest{
	{
		Query: `SHOW CREATE TABLE point_table`,
		Expected: []sql.Row{{
			"point_table",
			"CREATE TABLE `point_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `p` point NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query: `SHOW CREATE TABLE line_table`,
		Expected: []sql.Row{{
			"line_table",
			"CREATE TABLE `line_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `l` linestring NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query: `SHOW CREATE TABLE polygon_table`,
		Expected: []sql.Row{{
			"polygon_table",
			"CREATE TABLE `polygon_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `p` polygon NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query: `SHOW CREATE TABLE mpoint_table`,
		Expected: []sql.Row{{
			"mpoint_table",
			"CREATE TABLE `mpoint_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `p` multipoint NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query: `SHOW CREATE TABLE mline_table`,
		Expected: []sql.Row{{
			"mline_table",
			"CREATE TABLE `mline_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `l` multilinestring NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query: `SHOW CREATE TABLE mpoly_table`,
		Expected: []sql.Row{{
			"mpoly_table",
			"CREATE TABLE `mpoly_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `p` multipolygon NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query: `SHOW CREATE TABLE geometry_table`,
		Expected: []sql.Row{{
			"geometry_table",
			"CREATE TABLE `geometry_table` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `g` geometry NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin",
		}},
	},
	{
		Query:    `SELECT HEX(ST_ASWKB(p)) from point_table`,
		Expected: []sql.Row{{"0101000000000000000000F03F0000000000000040"}},
	},
	{
		Query: `SELECT HEX(ST_ASWKB(l)) from line_table`,
		Expected: []sql.Row{
			{"010200000002000000000000000000F03F000000000000004000000000000008400000000000001040"},
			{"010200000003000000000000000000F03F00000000000000400000000000000840000000000000104000000000000014400000000000001840"},
		},
	},
	{
		Query: `SELECT HEX(ST_ASWKB(p)) from polygon_table`,
		Expected: []sql.Row{
			{"01030000000100000004000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000000000000000000000"},
			{"01030000000200000004000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000000000000000000000"},
		},
	},
	{
		Query:    `SELECT ST_GEOMFROMWKB(ST_ASWKB(POINT(123.45,6.78)))`,
		Expected: []sql.Row{{types.Point{X: 123.45, Y: 6.78}}},
	},
	{
		Query:    `SELECT ST_GEOMFROMWKB(ST_ASWKB(LINESTRING(POINT(1.2,3.45),point(67.8,9))))`,
		Expected: []sql.Row{{types.LineString{Points: []types.Point{{X: 1.2, Y: 3.45}, {X: 67.8, Y: 9}}}}},
	},
	{
		Query:    `SELECT ST_GEOMFROMWKB(ST_ASWKB(POLYGON(LINESTRING(POINT(0,0),POINT(2,2),POINT(1,1),POINT(0,0)))))`,
		Expected: []sql.Row{{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 2, Y: 2}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}}},
	},
	{
		Query:    `SELECT ST_ASWKT(p) from point_table`,
		Expected: []sql.Row{{"POINT(1 2)"}},
	},
	{
		Query: `SELECT ST_ASWKT(l) from line_table`,
		Expected: []sql.Row{
			{"LINESTRING(1 2,3 4)"},
			{"LINESTRING(1 2,3 4,5 6)"},
		},
	},
	{
		Query: `SELECT ST_ASWKT(p) from polygon_table`,
		Expected: []sql.Row{
			{"POLYGON((0 0,0 1,1 1,0 0))"},
			{"POLYGON((0 0,0 1,1 1,0 0),(0 0,0 1,1 1,0 0))"},
		},
	},
	{
		Query: `SELECT ST_ASTEXT(p) from polygon_table`,
		Expected: []sql.Row{
			{"POLYGON((0 0,0 1,1 1,0 0))"},
			{"POLYGON((0 0,0 1,1 1,0 0),(0 0,0 1,1 1,0 0))"},
		},
	},
	{
		Query:    `SELECT ST_GEOMFROMTEXT(ST_ASWKT(POINT(1,2)))`,
		Expected: []sql.Row{{types.Point{X: 1, Y: 2}}},
	},
	{
		Query:    `SELECT ST_GEOMFROMTEXT(ST_ASWKT(LINESTRING(POINT(1.1,2.22),POINT(3.333,4.4444))))`,
		Expected: []sql.Row{{types.LineString{Points: []types.Point{{X: 1.1, Y: 2.22}, {X: 3.333, Y: 4.4444}}}}},
	},
	{
		Query:    `SELECT ST_GEOMFROMTEXT(ST_ASWKT(POLYGON(LINESTRING(POINT(1.2, 3.4),POINT(2.5, -6.7),POINT(33, 44),POINT(1.2,3.4)))))`,
		Expected: []sql.Row{{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 2.5, Y: -6.7}, {X: 33, Y: 44}, {X: 1.2, Y: 3.4}}}}}}},
	},
	{
		Query:    `SELECT ST_X(POINT(1,2))`,
		Expected: []sql.Row{{1.0}},
	},
	{
		Query:    `SELECT ST_Y(POINT(1,2))`,
		Expected: []sql.Row{{2.0}},
	},
	{
		Query:    `SELECT ST_X(POINT(123.45,6.789))`,
		Expected: []sql.Row{{123.45}},
	},
	{
		Query:    `SELECT ST_Y(POINT(123.45,6.789))`,
		Expected: []sql.Row{{6.789}},
	},
	{
		Query:    `SELECT ST_X(POINT(1,2),99.9)`,
		Expected: []sql.Row{{types.Point{X: 99.9, Y: 2}}},
	},
	{
		Query:    `SELECT ST_Y(POINT(1,2),99.9)`,
		Expected: []sql.Row{{types.Point{X: 1, Y: 99.9}}},
	},
	{
		Query:    `SELECT ST_X(p) from point_table`,
		Expected: []sql.Row{{1.0}},
	},
	{
		Query:    `SELECT ST_X(p) from point_table`,
		Expected: []sql.Row{{1.0}},
	},
	{
		Query:    `SELECT ST_Y(p) from point_table`,
		Expected: []sql.Row{{2.0}},
	},
	{
		Query:    `SELECT ST_SRID(p) from point_table`,
		Expected: []sql.Row{{uint32(0)}},
	},
	{
		Query:    `SELECT ST_SRID(l) from line_table`,
		Expected: []sql.Row{{uint32(0)}, {uint32(0)}},
	},
	{
		Query: `SELECT ST_SRID(p) from polygon_table`,
		Expected: []sql.Row{
			{uint32(0)},
			{uint32(0)},
		},
	},
	{
		Query:    `SELECT ST_SRID(p, 4326) from point_table`,
		Expected: []sql.Row{{types.Point{SRID: 4326, X: 1, Y: 2}}},
	},
	{
		Query: `SELECT ST_SRID(l, 4326) from line_table ORDER BY l`,
		Expected: []sql.Row{
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 5, Y: 6}}}},
		},
	},
	{
		Query: `SELECT ST_SRID(p, 4326) from polygon_table`,
		Expected: []sql.Row{
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}, {SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(s) from stringtogeojson_table`,
		Expected: []sql.Row{
			{types.Point{SRID: 4326, X: 1, Y: 2}},
			{types.Point{SRID: 4326, X: 123.45, Y: 56.789}},
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1.23, Y: 2.345}, {SRID: 4326, X: 3.56789, Y: 4.56}}}},
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1.1, Y: 2.2}, {SRID: 4326, X: 3.3, Y: 4.4}, {SRID: 4326, X: 5.5, Y: 6.6}, {SRID: 4326, X: 1.1, Y: 2.2}}}}}},
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 2, Y: 2}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1.23, Y: 2.345}, {SRID: 4326, X: 3.56789, Y: 4.56}}}},
			{types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1.1, Y: 2.2}, {SRID: 4326, X: 3.3, Y: 4.4}}}, {SRID: 4326, Points: []types.Point{{SRID: 4326, X: 5.5, Y: 6.6}, {SRID: 4326, X: 7.7, Y: 8.8}}}}}},
			{types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{
				{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1.1, Y: 2.2}, {SRID: 4326, X: 3.3, Y: 4.4}, {SRID: 4326, X: 0, Y: 0}}}}},
				{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1.1, Y: 1.1}, {SRID: 4326, X: 1.1, Y: 2.2}, {SRID: 4326, X: 3.3, Y: 4.4}, {SRID: 4326, X: 1.1, Y: 1.1}}}}},
			}}},
			{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
		},
	},
	{
		Query: `SELECT ST_ASGEOJSON(p) from point_table`,
		Expected: []sql.Row{
			{types.JSONDocument{Val: map[string]interface{}{"type": "Point", "coordinates": [2]float64{1, 2}}}},
		},
	},
	{
		Query: `SELECT ST_ASGEOJSON(l) from line_table`,
		Expected: []sql.Row{
			{types.JSONDocument{Val: map[string]interface{}{"type": "LineString", "coordinates": [][2]float64{{1, 2}, {3, 4}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "LineString", "coordinates": [][2]float64{{1, 2}, {3, 4}, {5, 6}}}}},
		},
	},
	{
		Query: `SELECT ST_ASGEOJSON(p) from polygon_table`,
		Expected: []sql.Row{
			{types.JSONDocument{Val: map[string]interface{}{"type": "Polygon", "coordinates": [][][2]float64{{{0, 0}, {0, 1}, {1, 1}, {0, 0}}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "Polygon", "coordinates": [][][2]float64{{{0, 0}, {0, 1}, {1, 1}, {0, 0}}, {{0, 0}, {0, 1}, {1, 1}, {0, 0}}}}}},
		},
	},
	{
		Query: `SELECT ST_ASGEOJSON(p) from mpoint_table`,
		Expected: []sql.Row{
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiPoint", "coordinates": [][2]float64{{1, 2}, {3, 4}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiPoint", "coordinates": [][2]float64{{1, 2}, {3, 4}, {5, 6}}}}},
		},
	},
	{
		Query: `SELECT ST_ASGEOJSON(l) from mline_table`,
		Expected: []sql.Row{
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiLineString", "coordinates": [][][2]float64{{{1, 2}, {3, 4}}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiLineString", "coordinates": [][][2]float64{{{1, 2}, {3, 4}, {5, 6}}}}}},
		},
	},
	{
		Query: `SELECT ST_ASGEOJSON(ST_GEOMFROMGEOJSON(s)) from stringtogeojson_table`,
		Expected: []sql.Row{
			{types.JSONDocument{Val: map[string]interface{}{"type": "Point", "coordinates": [2]float64{1, 2}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "Point", "coordinates": [2]float64{123.45, 56.789}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "LineString", "coordinates": [][2]float64{{1, 2}, {3, 4}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "LineString", "coordinates": [][2]float64{{1.23, 2.345}, {3.56789, 4.56}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "Polygon", "coordinates": [][][2]float64{{{1.1, 2.2}, {3.3, 4.4}, {5.5, 6.6}, {1.1, 2.2}}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "Polygon", "coordinates": [][][2]float64{{{0, 0}, {1, 1}, {2, 2}, {0, 0}}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiPoint", "coordinates": [][2]float64{{1, 2}, {3, 4}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiPoint", "coordinates": [][2]float64{{1.23, 2.345}, {3.56789, 4.56}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiLineString", "coordinates": [][][2]float64{{{1.1, 2.2}, {3.3, 4.4}}, {{5.5, 6.6}, {7.7, 8.8}}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "MultiPolygon", "coordinates": [][][][2]float64{{{{0, 0}, {1.1, 2.2}, {3.3, 4.4}, {0, 0}}}, {{{1.1, 1.1}, {1.1, 2.2}, {3.3, 4.4}, {1.1, 1.1}}}}}}},
			{types.JSONDocument{Val: map[string]interface{}{"type": "GeometryCollection", "geometries": []interface{}{map[string]interface{}{"type": "GeometryCollection", "geometries": []interface{}{}}}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(p)) from point_table`,
		Expected: []sql.Row{
			{types.Point{SRID: 4326, X: 1, Y: 2}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(l)) from line_table`,
		Expected: []sql.Row{
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 5, Y: 6}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(p)) from polygon_table`,
		Expected: []sql.Row{
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}, {SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 0, Y: 1}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(p)) from mpoint_table`,
		Expected: []sql.Row{
			{types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}},
			{types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 5, Y: 6}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(l)) from mline_table`,
		Expected: []sql.Row{
			{types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}}}}}},
			{types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 5, Y: 6}}}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(p)) from mpoly_table`,
		Expected: []sql.Row{
			{types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{
				{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 2}, {SRID: 4326, X: 3, Y: 4}, {SRID: 4326, X: 0, Y: 0}}}}},
				{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 2, Y: 3}, {SRID: 4326, X: 4, Y: 5}, {SRID: 4326, X: 1, Y: 1}}}}}}}},
		},
	},
	{
		Query: `SELECT ST_GEOMFROMGEOJSON(ST_ASGEOJSON(g)) from geom_coll_table`,
		Expected: []sql.Row{
			{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(p) from point_table`,
		Expected: []sql.Row{
			{0},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(l) from line_table`,
		Expected: []sql.Row{
			{1},
			{1},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(p) from polygon_table`,
		Expected: []sql.Row{
			{2},
			{2},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(p) from mpoint_table`,
		Expected: []sql.Row{
			{0},
			{0},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(l) from mline_table`,
		Expected: []sql.Row{
			{1},
			{1},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(p) from mpoly_table`,
		Expected: []sql.Row{
			{2},
			{2},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(g) from geom_coll_table`,
		Expected: []sql.Row{
			{nil},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(p) from point_table`,
		Expected: []sql.Row{
			{types.Point{X: 2, Y: 1}},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(l) from line_table`,
		Expected: []sql.Row{
			{types.LineString{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}}}},
			{types.LineString{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}, {X: 6, Y: 5}}}},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(p) from polygon_table`,
		Expected: []sql.Row{
			{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 1, Y: 1}, {X: 0, Y: 0}}}, {Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
		},
	},
	{
		Query: `SELECT ST_ASWKT(g) from geometry_table ORDER BY i`,
		Expected: []sql.Row{
			{"POINT(1 2)"},
			{"POINT(2 1)"},
			{"LINESTRING(1 2,3 4)"},
			{"LINESTRING(2 1,4 3)"},
			{"POLYGON((0 0,0 1,1 1,0 0))"},
			{"POLYGON((0 0,1 0,1 1,0 0))"},
			{"MULTIPOINT(1 2,3 4)"},
			{"MULTIPOINT(2 1,4 3)"},
			{"MULTILINESTRING((1 2,3 4))"},
			{"MULTILINESTRING((2 1,4 3))"},
			{"MULTIPOLYGON(((0 0,1 2,3 4,0 0)))"},
			{"MULTIPOLYGON(((0 0,2 1,4 3,0 0)))"},
			{"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION())"},
			{"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION())"},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(p) from mpoint_table`,
		Expected: []sql.Row{
			{types.MultiPoint{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}}}},
			{types.MultiPoint{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}, {X: 6, Y: 5}}}},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(l) from mline_table`,
		Expected: []sql.Row{
			{types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}}}}}},
			{types.MultiLineString{Lines: []types.LineString{{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}, {X: 6, Y: 5}}}}}},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(p) from mpoly_table`,
		Expected: []sql.Row{
			{types.MultiPolygon{Polygons: []types.Polygon{{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 2, Y: 1}, {X: 4, Y: 3}, {X: 0, Y: 0}}}}}}}},
			{types.MultiPolygon{Polygons: []types.Polygon{
				{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 2, Y: 1}, {X: 4, Y: 3}, {X: 0, Y: 0}}}}},
				{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 3, Y: 2}, {X: 5, Y: 4}, {X: 1, Y: 1}}}}},
			}}},
		},
	},
	{
		Query: `SELECT HEX(ST_ASWKB(g)) from geometry_table ORDER BY i`,
		Expected: []sql.Row{
			{"0101000000000000000000F03F0000000000000040"},
			{"01010000000000000000000040000000000000F03F"},
			{"010200000002000000000000000000F03F000000000000004000000000000008400000000000001040"},
			{"0102000000020000000000000000000040000000000000F03F00000000000010400000000000000840"},
			{"01030000000100000004000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F00000000000000000000000000000000"},
			{"0103000000010000000400000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000"},
			{"0104000000020000000101000000000000000000F03F0000000000000040010100000000000000000008400000000000001040"},
			{"01040000000200000001010000000000000000000040000000000000F03F010100000000000000000010400000000000000840"},
			{"010500000001000000010200000002000000000000000000F03F000000000000004000000000000008400000000000001040"},
			{"0105000000010000000102000000020000000000000000000040000000000000F03F00000000000010400000000000000840"},
			{"0106000000010000000103000000010000000400000000000000000000000000000000000000000000000000F03F00000000000000400000000000000840000000000000104000000000000000000000000000000000"},
			{"01060000000100000001030000000100000004000000000000000000000000000000000000000000000000000040000000000000F03F0000000000001040000000000000084000000000000000000000000000000000"},
			{"010700000001000000010700000000000000"},
			{"010700000001000000010700000000000000"},
		},
	},
	{
		Query: `SELECT ST_SRID(g) from geometry_table order by i`,
		Expected: []sql.Row{
			{uint64(0)},
			{uint64(4326)},
			{uint64(0)},
			{uint64(4326)},
			{uint64(0)},
			{uint64(4326)},
			{uint64(0)},
			{uint64(4326)},
			{uint64(0)},
			{uint64(4326)},
			{uint64(0)},
			{uint64(4326)},
			{uint64(0)},
			{uint64(4326)},
		},
	},
	{
		Query: `SELECT ST_SRID(g, 0) from geometry_table order by i`,
		Expected: []sql.Row{
			{types.Point{X: 1, Y: 2}},
			{types.Point{X: 1, Y: 2}},
			{types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{types.LineString{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 0, Y: 1}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{types.MultiPoint{Points: []types.Point{{X: 1, Y: 2}, {X: 3, Y: 4}}}},
			{types.MultiLineString{SRID: 0, Lines: []types.LineString{{SRID: 0, Points: []types.Point{{SRID: 0, X: 1, Y: 2}, {SRID: 0, X: 3, Y: 4}}}}}},
			{types.MultiLineString{SRID: 0, Lines: []types.LineString{{SRID: 0, Points: []types.Point{{SRID: 0, X: 1, Y: 2}, {SRID: 0, X: 3, Y: 4}}}}}},
			{types.MultiPolygon{SRID: 0, Polygons: []types.Polygon{{SRID: 0, Lines: []types.LineString{{SRID: 0, Points: []types.Point{{SRID: 0, X: 0, Y: 0}, {SRID: 0, X: 1, Y: 2}, {SRID: 0, X: 3, Y: 4}, {SRID: 0, X: 0, Y: 0}}}}}}}},
			{types.MultiPolygon{SRID: 0, Polygons: []types.Polygon{{SRID: 0, Lines: []types.LineString{{SRID: 0, Points: []types.Point{{SRID: 0, X: 0, Y: 0}, {SRID: 0, X: 1, Y: 2}, {SRID: 0, X: 3, Y: 4}, {SRID: 0, X: 0, Y: 0}}}}}}}},
			{types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
		},
	},
	{
		Query: `SELECT ST_DIMENSION(g) from geometry_table order by i`,
		Expected: []sql.Row{
			{0},
			{0},
			{1},
			{1},
			{2},
			{2},
			{0},
			{0},
			{1},
			{1},
			{2},
			{2},
			{nil},
			{nil},
		},
	},
	{
		Query: `SELECT ST_SWAPXY(g) from geometry_table order by i`,
		Expected: []sql.Row{
			{types.Point{X: 2, Y: 1}},
			{types.Point{SRID: 4326, X: 2, Y: 1}},
			{types.LineString{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}}}},
			{types.LineString{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 2, Y: 1}, {SRID: 4326, X: 4, Y: 3}}}},
			{types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: 1, Y: 1}, {X: 0, Y: 0}}}}}},
			{types.Polygon{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 1, Y: 0}, {SRID: 4326, X: 1, Y: 1}, {SRID: 4326, X: 0, Y: 0}}}}}},
			{types.MultiPoint{Points: []types.Point{{X: 2, Y: 1}, {X: 4, Y: 3}}}},
			{types.MultiPoint{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 2, Y: 1}, {SRID: 4326, X: 4, Y: 3}}}},
			{types.MultiLineString{SRID: 0, Lines: []types.LineString{{SRID: 0, Points: []types.Point{{SRID: 0, X: 2, Y: 1}, {SRID: 0, X: 4, Y: 3}}}}}},
			{types.MultiLineString{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 2, Y: 1}, {SRID: 4326, X: 4, Y: 3}}}}}},
			{types.MultiPolygon{SRID: 0, Polygons: []types.Polygon{{SRID: 0, Lines: []types.LineString{{SRID: 0, Points: []types.Point{{SRID: 0, X: 0, Y: 0}, {SRID: 0, X: 2, Y: 1}, {SRID: 0, X: 4, Y: 3}, {SRID: 0, X: 0, Y: 0}}}}}}}},
			{types.MultiPolygon{SRID: 4326, Polygons: []types.Polygon{{SRID: 4326, Lines: []types.LineString{{SRID: 4326, Points: []types.Point{{SRID: 4326, X: 0, Y: 0}, {SRID: 4326, X: 2, Y: 1}, {SRID: 4326, X: 4, Y: 3}, {SRID: 4326, X: 0, Y: 0}}}}}}}},
			{types.GeomColl{Geoms: []types.GeometryValue{types.GeomColl{Geoms: []types.GeometryValue{}}}}},
			{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{types.GeomColl{SRID: 4326, Geoms: []types.GeometryValue{}}}}},
		},
	},
	{
		Query: `SELECT ST_AREA(p) from polygon_table`,
		Expected: []sql.Row{
			{0.5},
			{0.0},
		},
	},
	{
		Query: `SELECT ST_PERIMETER(p) from polygon_table`,
		Expected: []sql.Row{
			{3.414213562373095},
			{6.82842712474619},
		},
	},
	{
		Query: `SELECT ST_LENGTH(l) from line_table`,
		Expected: []sql.Row{
			{2.8284271247461903},
			{5.656854249492381},
		},
	},
	{
		Query: `SELECT ST_ASWKT(g) from geometry_table where g = point(1,2)`,
		Expected: []sql.Row{
			{"POINT(1 2)"},
		},
	},
	{
		Query: `SELECT ST_ASWKT(g) from geometry_table where g = st_srid(point(1,2),4326)`,
		Expected: []sql.Row{
			{"POINT(2 1)"},
		},
	},
	{
		Query: `SELECT ST_ASWKT(g) from geometry_table where g = unhex(hex(point(1,2)))`,
		Expected: []sql.Row{
			{"POINT(1 2)"},
		},
	},
	{
		Query: `SELECT unhex(hex(point(1,2))) < unhex(hex(point(3,4)))`,
		Expected: []sql.Row{
			{false},
		},
	},
	{
		Query: `SELECT ST_ASWKT(g) from geometry_table where g = st_geomfromtext('MultiPolygon(((0 0,1 2,3 4,0 0)))')`,
		Expected: []sql.Row{
			{"MULTIPOLYGON(((0 0,1 2,3 4,0 0)))"},
		},
	},
	{
		Query: `SELECT ST_ASWKT(g) from geometry_table ORDER BY g`,
		Expected: []sql.Row{
			{"POINT(1 2)"},
			{"LINESTRING(1 2,3 4)"},
			{"POLYGON((0 0,0 1,1 1,0 0))"},
			{"MULTIPOINT(1 2,3 4)"},
			{"MULTILINESTRING((1 2,3 4))"},
			{"MULTIPOLYGON(((0 0,1 2,3 4,0 0)))"},
			{"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION())"},
			{"POINT(2 1)"},
			{"LINESTRING(2 1,4 3)"},
			{"POLYGON((0 0,1 0,1 1,0 0))"},
			{"MULTIPOINT(2 1,4 3)"},
			{"MULTILINESTRING((2 1,4 3))"},
			{"MULTIPOLYGON(((0 0,2 1,4 3,0 0)))"},
			{"GEOMETRYCOLLECTION(GEOMETRYCOLLECTION())"},
		},
	},
	{
		Query: `SELECT ST_DISTANCE(st_srid(g, 0), point(0,0)) from geometry_table ORDER BY g`,
		Expected: []sql.Row{
			{math.Sqrt(5)},
			{math.Sqrt(5)},
			{0.0},
			{math.Sqrt(5)},
			{math.Sqrt(5)},
			{0.0},
			{nil},
			{math.Sqrt(5)},
			{math.Sqrt(5)},
			{0.0},
			{math.Sqrt(5)},
			{math.Sqrt(5)},
			{0.0},
			{nil},
		},
	},
	{
		Query: `SELECT st_startpoint(g) from geometry_table ORDER BY g`,
		Expected: []sql.Row{
			{nil},
			{types.Point{X: 1, Y: 2}},
			{nil},
			{nil},
			{nil},
			{nil},
			{nil},
			{nil},
			{types.Point{SRID: types.GeoSpatialSRID, X: 1, Y: 2}},
			{nil},
			{nil},
			{nil},
			{nil},
			{nil},
		},
	},
	{
		Query: `SELECT st_endpoint(g) from geometry_table ORDER BY g`,
		Expected: []sql.Row{
			{nil},
			{types.Point{X: 3, Y: 4}},
			{nil},
			{nil},
			{nil},
			{nil},
			{nil},
			{nil},
			{types.Point{SRID: types.GeoSpatialSRID, X: 3, Y: 4}},
			{nil},
			{nil},
			{nil},
			{nil},
			{nil},
		},
	},
	{
		Query: `SELECT st_isclosed(g) from geometry_table ORDER BY g`,
		Expected: []sql.Row{
			{nil},
			{false},
			{nil},
			{nil},
			{false},
			{nil},
			{nil},
			{nil},
			{false},
			{nil},
			{nil},
			{false},
			{nil},
			{nil},
		},
	},
	{
		Query: `SELECT st_intersects(st_srid(g, 0), point(1,2)) from geometry_table ORDER BY g`,
		Expected: []sql.Row{
			{true},
			{true},
			{false},
			{true},
			{true},
			{true},
			{false},
			{true},
			{true},
			{false},
			{true},
			{true},
			{true},
			{false},
		},
	},
}
View Source
var SpatialScriptTests = []ScriptTest{
	{
		Name: "create table using default point value",
		SetUpScript: []string{
			"CREATE TABLE test (i int primary key, p point default (point(123.456, 7.89)));",
			"insert into test (i) values (0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select st_aswkt(p) from test",
				Expected: []sql.Row{{"POINT(123.456 7.89)"}},
			},
			{
				Query:    "show create table test",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `i` int NOT NULL,\n  `p` point DEFAULT (point(123.456,7.89)),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "describe test",
				Expected: []sql.Row{{"i", "int", "NO", "PRI", "NULL", ""}, {"p", "point", "YES", "", "(point(123.456,7.89))", "DEFAULT_GENERATED"}},
			},
		},
	},
	{
		Name: "create table using default linestring value",
		SetUpScript: []string{
			"CREATE TABLE test (i int primary key, l linestring default (linestring(point(1,2), point(3,4))));",
			"insert into test (i) values (0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select st_aswkt(l) from test",
				Expected: []sql.Row{{"LINESTRING(1 2,3 4)"}},
			},
			{
				Query:    "show create table test",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `i` int NOT NULL,\n  `l` linestring DEFAULT (linestring(point(1,2),point(3,4))),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "describe test",
				Expected: []sql.Row{{"i", "int", "NO", "PRI", "NULL", ""}, {"l", "linestring", "YES", "", "(linestring(point(1,2),point(3,4)))", "DEFAULT_GENERATED"}},
			},
		},
	},
	{
		Name: "create table using default polygon value",
		SetUpScript: []string{
			"CREATE TABLE test (i int primary key, p polygon default (polygon(linestring(point(0,0), point(1,1), point(2,2), point(0,0)))));",
			"insert into test (i) values (0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select st_aswkt(p) from test",
				Expected: []sql.Row{{"POLYGON((0 0,1 1,2 2,0 0))"}},
			},
			{
				Query:    "show create table test",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `i` int NOT NULL,\n  `p` polygon DEFAULT (polygon(linestring(point(0,0),point(1,1),point(2,2),point(0,0)))),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "describe test",
				Expected: []sql.Row{{"i", "int", "NO", "PRI", "NULL", ""}, {"p", "polygon", "YES", "", "(polygon(linestring(point(0,0),point(1,1),point(2,2),point(0,0))))", "DEFAULT_GENERATED"}},
			},
		},
	},
	{
		Name: "create geometry table using default point value",
		SetUpScript: []string{
			"CREATE TABLE test (i int primary key, g geometry  default (point(123.456, 7.89)));",
			"insert into test (i) values (0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select st_aswkt(g) from test",
				Expected: []sql.Row{{"POINT(123.456 7.89)"}},
			},
			{
				Query:    "show create table test",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `i` int NOT NULL,\n  `g` geometry DEFAULT (point(123.456,7.89)),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "describe test",
				Expected: []sql.Row{{"i", "int", "NO", "PRI", "NULL", ""}, {"g", "geometry", "YES", "", "(point(123.456,7.89))", "DEFAULT_GENERATED"}},
			},
		},
	},
	{
		Name: "create geometry table using default linestring value",
		SetUpScript: []string{
			"CREATE TABLE test (i int primary key, g geometry default (linestring(point(1,2), point(3,4))));",
			"insert into test (i) values (0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select st_aswkt(g) from test",
				Expected: []sql.Row{{"LINESTRING(1 2,3 4)"}},
			},
			{
				Query:    "show create table test",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `i` int NOT NULL,\n  `g` geometry DEFAULT (linestring(point(1,2),point(3,4))),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "describe test",
				Expected: []sql.Row{{"i", "int", "NO", "PRI", "NULL", ""}, {"g", "geometry", "YES", "", "(linestring(point(1,2),point(3,4)))", "DEFAULT_GENERATED"}},
			},
		},
	},
	{
		Name: "create geometry table using default polygon value",
		SetUpScript: []string{
			"CREATE TABLE test (i int primary key, g geometry default (polygon(linestring(point(0,0), point(1,1), point(2,2), point(0,0)))));",
			"insert into test (i) values (0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select st_aswkt(g) from test",
				Expected: []sql.Row{{"POLYGON((0 0,1 1,2 2,0 0))"}},
			},
			{
				Query:    "show create table test",
				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `i` int NOT NULL,\n  `g` geometry DEFAULT (polygon(linestring(point(0,0),point(1,1),point(2,2),point(0,0)))),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "describe test",
				Expected: []sql.Row{{"i", "int", "NO", "PRI", "NULL", ""}, {"g", "geometry", "YES", "", "(polygon(linestring(point(0,0),point(1,1),point(2,2),point(0,0))))", "DEFAULT_GENERATED"}},
			},
		},
	},
	{
		Name: "create table with NULL default values for geometry types",
		SetUpScript: []string{
			"CREATE TABLE null_default (pk int NOT NULL PRIMARY KEY, v1 geometry DEFAULT NULL, v2 linestring DEFAULT NULL, v3 point DEFAULT NULL, v4 polygon DEFAULT NULL)",
			"insert into null_default(pk) values (0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from null_default",
				Expected: []sql.Row{{0, nil, nil, nil, nil}},
			},
		},
	},
	{
		Name: "create table using SRID value for geometry type",
		SetUpScript: []string{
			"CREATE TABLE tab0 (i int primary key, g geometry srid 4326 default (point(1,1)));",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table tab0",
				Expected: []sql.Row{{"tab0", "CREATE TABLE `tab0` (\n  `i` int NOT NULL,\n  `g` geometry SRID 4326 DEFAULT (point(1,1)),\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "INSERT INTO tab0 VALUES (1, ST_GEOMFROMTEXT(ST_ASWKT(POINT(1,2)), 4326))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "select i, ST_ASWKT(g) FROM tab0",
				Expected: []sql.Row{{1, "POINT(1 2)"}},
			},
			{
				Query:       "INSERT INTO tab0 VALUES (2, ST_GEOMFROMTEXT(ST_ASWKT(POINT(2,4))))",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "INSERT INTO tab0 VALUES (2, ST_GEOMFROMTEXT(ST_ASWKT(LINESTRING(POINT(1, 6),POINT(4, 3))), 4326))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "select i, ST_ASWKT(g) FROM tab0",
				Expected: []sql.Row{{1, "POINT(1 2)"}, {2, "LINESTRING(1 6,4 3)"}},
			},
		},
	},
	{
		Name: "create table using SRID value for linestring type",
		SetUpScript: []string{
			"CREATE TABLE tab1 (i int primary key, l linestring srid 0);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table tab1",
				Expected: []sql.Row{{"tab1", "CREATE TABLE `tab1` (\n  `i` int NOT NULL,\n  `l` linestring SRID 0,\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "INSERT INTO tab1 VALUES (1, LINESTRING(POINT(0, 0),POINT(2, 2)))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "select i, ST_ASWKT(l) FROM tab1",
				Expected: []sql.Row{{1, "LINESTRING(0 0,2 2)"}},
			},
			{
				Query:       "INSERT INTO tab1 VALUES (2, ST_GEOMFROMTEXT(ST_ASWKT(LINESTRING(POINT(1, 6),POINT(4, 3))), 4326))",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "select i, ST_ASWKT(l) FROM tab1",
				Expected: []sql.Row{{1, "LINESTRING(0 0,2 2)"}},
			},
		},
	},
	{
		Name: "create table using SRID value for point type",
		SetUpScript: []string{
			"CREATE TABLE tab2 (i int primary key);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "ALTER TABLE tab2 ADD COLUMN p POINT NOT NULL SRID 0",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table tab2",
				Expected: []sql.Row{{"tab2", "CREATE TABLE `tab2` (\n  `i` int NOT NULL,\n  `p` point NOT NULL SRID 0,\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "INSERT INTO tab2 VALUES (1, POINT(2, 2))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "select i, ST_ASWKT(p) FROM tab2",
				Expected: []sql.Row{{1, "POINT(2 2)"}},
			},
			{
				Query:       "INSERT INTO tab2 VALUES (2, ST_GEOMFROMTEXT(ST_ASWKT(POINT(1, 6)), 4326))",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "select i, ST_ASWKT(p) FROM tab2",
				Expected: []sql.Row{{1, "POINT(2 2)"}},
			},
			{
				Query:    "ALTER TABLE tab2 CHANGE COLUMN p p POINT NOT NULL",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO tab2 VALUES (2, ST_GEOMFROMTEXT(ST_ASWKT(POINT(1, 6)), 4326))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "select i, ST_ASWKT(p) FROM tab2",
				Expected: []sql.Row{{1, "POINT(2 2)"}, {2, "POINT(1 6)"}},
			},
			{
				Query:       "ALTER TABLE tab2 CHANGE COLUMN p p POINT NOT NULL SRID 4326",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "delete from tab2 where i = 1",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "ALTER TABLE tab2 CHANGE COLUMN p p POINT NOT NULL SRID 4326",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table tab2",
				Expected: []sql.Row{{"tab2", "CREATE TABLE `tab2` (\n  `i` int NOT NULL,\n  `p` point NOT NULL SRID 4326,\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
		},
	},
	{
		Name: "create table using SRID value for polygon type",
		SetUpScript: []string{
			"CREATE TABLE tab3 (i int primary key, y polygon NOT NULL);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "show create table tab3",
				Expected: []sql.Row{{"tab3", "CREATE TABLE `tab3` (\n  `i` int NOT NULL,\n  `y` polygon NOT NULL,\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "INSERT INTO tab3 VALUES (1, polygon(linestring(point(0,0),point(8,0),point(12,9),point(0,9),point(0,0))))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "select i, ST_ASWKT(y) FROM tab3",
				Expected: []sql.Row{{1, "POLYGON((0 0,8 0,12 9,0 9,0 0))"}},
			},
			{
				Query:    "ALTER TABLE tab3 MODIFY COLUMN y POLYGON NOT NULL SRID 0",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:       "ALTER TABLE tab3 MODIFY COLUMN y POLYGON NOT NULL SRID 4326",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "select i, ST_ASWKT(y) FROM tab3",
				Expected: []sql.Row{{1, "POLYGON((0 0,8 0,12 9,0 9,0 0))"}},
			},
			{
				Query:    "ALTER TABLE tab3 MODIFY COLUMN y GEOMETRY NULL SRID 0",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "select i, ST_ASWKT(y) FROM tab3",
				Expected: []sql.Row{{1, "POLYGON((0 0,8 0,12 9,0 9,0 0))"}},
			},
		},
	},
	{
		Name: "invalid cases of SRID value",
		SetUpScript: []string{
			"CREATE TABLE table1 (i int primary key, p point srid 4326);",
			"INSERT INTO table1 VALUES (1, ST_SRID(POINT(1, 5), 4326))",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "CREATE TABLE table2 (i int primary key, p point srid 1);",

				ExpectedErr: sql.ErrUnsupportedFeature,
			},
			{
				Query:    "SELECT i, ST_ASWKT(p) FROM table1;",
				Expected: []sql.Row{{1, "POINT(5 1)"}},
			},
			{
				Query:       "INSERT INTO table1 VALUES (2, POINT(2, 5))",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "SELECT i, ST_ASWKT(p) FROM table1;",
				Expected: []sql.Row{{1, "POINT(5 1)"}},
			},
			{
				Query:       "ALTER TABLE table1 CHANGE COLUMN p p linestring srid 4326",
				ExpectedErr: sql.ErrSpatialTypeConversion,
			},
			{
				Query:       "ALTER TABLE table1 CHANGE COLUMN p p geometry srid 0",
				ExpectedErr: sql.ErrNotMatchingSRIDWithColName,
			},
			{
				Query:    "ALTER TABLE table1 CHANGE COLUMN p p geometry srid 4326",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show create table table1",
				Expected: []sql.Row{{"table1", "CREATE TABLE `table1` (\n  `i` int NOT NULL,\n  `p` geometry SRID 4326,\n  PRIMARY KEY (`i`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
			},
			{
				Query:    "INSERT INTO table1 VALUES (2, ST_SRID(LINESTRING(POINT(0, 0),POINT(2, 2)),4326))",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "ALTER TABLE table1 CHANGE COLUMN p p point srid 4326",
				ExpectedErr: sql.ErrSpatialTypeConversion,
			},
		},
	},
}
View Source
var SpatialUpdateTests = []WriteQueryTest{
	{
		WriteQuery:          "UPDATE point_table SET p = point(123.456,789);",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM point_table;",
		ExpectedSelect:      []sql.Row{{int64(5), types.Point{X: 123.456, Y: 789}}},
	},
	{
		WriteQuery:          "UPDATE line_table SET l = linestring(point(1.2,3.4),point(5.6,7.8));",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM line_table;",
		ExpectedSelect:      []sql.Row{{int64(0), types.LineString{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 5.6, Y: 7.8}}}}, {int64(1), types.LineString{Points: []types.Point{{X: 1.2, Y: 3.4}, {X: 5.6, Y: 7.8}}}}},
	},
	{
		WriteQuery:          "UPDATE polygon_table SET p = polygon(linestring(point(1,1),point(1,-1),point(-1,-1),point(-1,1),point(1,1)));",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM polygon_table;",
		ExpectedSelect: []sql.Row{
			{int64(0), types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
			{int64(1), types.Polygon{Lines: []types.LineString{{Points: []types.Point{{X: 1, Y: 1}, {X: 1, Y: -1}, {X: -1, Y: -1}, {X: -1, Y: 1}, {X: 1, Y: 1}}}}}},
		},
	},
}
View Source
var StatisticsQueries = []ScriptTest{
	{
		Name: "analyze single int column",
		SetUpScript: []string{
			"CREATE TABLE t (i int primary key)",
			"INSERT INTO t VALUES (1), (2), (3)",
			"ANALYZE TABLE t",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.column_statistics",
				Expected: []sql.Row{
					{"mydb", "t", "i", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"1.00", "1.00", "0.33"}, []interface{}{"2.00", "2.00", "0.33"}, []interface{}{"3.00", "3.00", "0.33"}}}}},
				},
			},
		},
	},
	{
		Name: "analyze two int columns",
		SetUpScript: []string{
			"CREATE TABLE t (i int, j int)",
			"INSERT INTO t VALUES (1, 4), (2, 5), (3, 6)",
			"ANALYZE TABLE t",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.column_statistics",
				Expected: []sql.Row{
					{"mydb", "t", "i", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"1.00", "1.00", "0.33"}, []interface{}{"2.00", "2.00", "0.33"}, []interface{}{"3.00", "3.00", "0.33"}}}}},
					{"mydb", "t", "j", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"4.00", "4.00", "0.33"}, []interface{}{"5.00", "5.00", "0.33"}, []interface{}{"6.00", "6.00", "0.33"}}}}},
				},
			},
		},
	},
	{
		Name: "analyze float columns",
		SetUpScript: []string{
			"CREATE TABLE t (i float)",
			"INSERT INTO t VALUES (1.25), (45.25), (7.5), (10.5)",
			"ANALYZE TABLE t",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.column_statistics",
				Expected: []sql.Row{
					{"mydb", "t", "i", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"1.25", "1.25", "0.25"}, []interface{}{"7.50", "7.50", "0.25"}, []interface{}{"10.50", "10.50", "0.25"}, []interface{}{"45.25", "45.25", "0.25"}}}}},
				},
			},
		},
	},
	{
		Name: "analyze empty table creates stats with 0s",
		SetUpScript: []string{
			"CREATE TABLE t (i float)",
			"ANALYZE TABLE t",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM information_schema.column_statistics",
				Expected: []sql.Row{
					{"mydb", "t", "i", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{}}}},
				},
			},
		},
	},
	{
		Name: "analyze columns that can't be converted to float throws error",
		SetUpScript: []string{
			"CREATE TABLE t (t longtext)",
			"INSERT INTO t VALUES ('not a number')",
			"ANALYZE TABLE t",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM information_schema.column_statistics",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Query: `
		SELECT
			COLUMN_NAME,
			JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"')
		FROM information_schema.COLUMN_STATISTICS
		WHERE SCHEMA_NAME = 'mydb'
		AND TABLE_NAME = 'mytable'
		`,
		Expected: nil,
	},
}
View Source
var TransactionTests = []TransactionTest{
	{
		Name: "Changes from transactions are available before analyzing statements in other sessions (autocommit off)",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set @@autocommit = 0;",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set @@autocommit = 0;",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ select @@autocommit;",
				Expected: []sql.Row{{0}},
			},
			{
				Query:    "/* client b */ select @@autocommit;",
				Expected: []sql.Row{{0}},
			},
			{
				Query:    "/* client a */ start transaction;",
				Expected: []sql.Row{},
			},
			{
				Query:       "/* client a */ select * from t;",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:    "/* client a */ create table t(pk int primary key);",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{

				Query:       "/* client a */ select * from t2;",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:    "/* client a */ commit;",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ start transaction;",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select count(*) from t;",
				Expected: []sql.Row{{0}},
			},
		},
	},
	{
		Name: "autocommit on",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ insert into t values (3, 3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
		},
	},
	{
		Name: "autocommit off",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:    "/* client b */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query: "/* client a */ select * from t order by x",
				Expected: []sql.Row{
					{1, 1},
				},
			},
			{
				Query:    "/* client a */ insert into t values (3,3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client a */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
		},
	},
	{
		Name: "toggle autocommit",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ insert into t values (2,2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},

			{
				Query:    "/* client b */ set autocommit = on",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},

			{
				Query:    "/* client a */ set autocommit = on",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
		},
	},
	{
		Name: "autocommit on with explicit transactions",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ start transaction",
				Expected: []sql.Row{},
			},
			{

				Query:       "/* client a */ select * from doesnotexist;",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},
			{

				Query:       "/* client a */ select * from doesnotexist;",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:    "/* client a */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},

			{
				Query:    "/* client a */ insert into t values (3, 3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
		},
	},
	{
		Name: "rollback",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ insert into t values (3, 3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client a */ rollback",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client a */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client b */ rollback",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
		},
	},
	{
		Name: "rollback to savepoint",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ insert into t values (3, 3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ savepoint spa1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ savepoint spb1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (4, 4)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ insert into t values (5, 5)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ savepoint spa2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ savepoint spb2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (6, 6)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ insert into t values (7, 7)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}, {6, 6}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}, {5, 5}, {7, 7}},
			},
			{
				Query:    "/* client a */ rollback to SPA2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ rollback to spB2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}, {5, 5}},
			},
			{
				Query:    "/* client a */ rollback to sPa2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ rollback to Spb2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}, {5, 5}},
			},
			{
				Query:    "/* client a */ rollback to spA1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ rollback to SPb1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:       "/* client a */ rollback to spa2",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
			{
				Query:       "/* client b */ rollback to spb2",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
			{
				Query:    "/* client a */ rollback to Spa1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ rollback to spB1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client a */ rollback",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:       "/* client a */ rollback to spa1",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
			{
				Query:       "/* client b */ rollback to spb1",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
		},
	},
	{
		Name: "release savepoint",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client b */ insert into t values (3, 3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ savepoint spa1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ savepoint spb1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ release savepoint Spa1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ release savepoint sPb1",
				Expected: []sql.Row{},
			},
			{
				Query:       "/* client a */ rollback to spa1",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
			{
				Query:       "/* client b */ rollback to spb1",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
		},
	},
	{
		Name: "overwrite savepoint",
		SetUpScript: []string{
			"create table t (x int primary key, y int)",
			"insert into t values (1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (2, 2)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ savepoint spa1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (3, 3)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ savepoint spa2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (4, 4)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ savepoint SPA1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ insert into t values (5, 5)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}},
			},
			{
				Query:    "/* client a */ rollback to Spa1",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
			},
			{
				Query:    "/* client a */ rollback to spa2",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:       "/* client a */ rollback to spa1",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
			{
				Query:       "/* client a */ release savepoint spa1",
				ExpectedErr: sql.ErrSavepointDoesNotExist,
			},
		},
	},
	{
		Name: "Test AUTO INCREMENT with no autocommit",
		SetUpScript: []string{
			"CREATE table t (x int PRIMARY KEY AUTO_INCREMENT, y int);",
			"CREATE table t2 (x int PRIMARY KEY AUTO_INCREMENT, y int);",
			"CREATE table t3 (x int PRIMARY KEY AUTO_INCREMENT, y int);",
			"insert into t (y) values (1);",
			"insert into t2 values (10, 10);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client b */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client c */ set autocommit = off",
				Expected: []sql.Row{{}},
			},

			{
				Query:    "/* client a */ insert into t (y) values (2)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 2}}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},
			{
				Query:    "/* client c*/ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},

			{
				Query:    "/* client b */ insert into t (y) values (3)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 3}}},
			},
			{
				Query: "/* client a */ select * from t order by x",
				Expected: []sql.Row{
					{1, 1}, {2, 2},
				},
			},
			{
				Query: "/* client c */ select * from t order by x",
				Expected: []sql.Row{
					{1, 1},
				},
			},

			{
				Query:    "/* client c */ insert into t2 (y) values (11)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 11}}},
			},
			{
				Query:    "/* client a */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}},
			},
			{
				Query:    "/* client b */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}},
			},
			{
				Query:    "/* client c */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}},
			},

			{
				Query:    "/* client a */ insert into t2 (y) values (12)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 12}}},
			},
			{
				Query:    "/* client a */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {12, 12}},
			},
			{
				Query:    "/* client b */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}},
			},
			{
				Query:    "/* client c */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}},
			},

			{
				Query:    "/* client a */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {3, 3}},
			},
			{
				Query:    "/* client b */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}},
			},
			{
				Query:    "/* client c */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}},
			},
			{
				Query: "/* client c */ select * from t order by x",
				Expected: []sql.Row{
					{1, 1},
				},
			},

			{
				Query:    "/* client b */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client a */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {12, 12}},
			},
			{
				Query:    "/* client c */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}},
			},
			{
				Query:    "/* client c */ select * from t order by x",
				Expected: []sql.Row{{1, 1}},
			},

			{
				Query:    "/* client c */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client a */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {12, 12}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client b */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
			},

			{
				Query:    "/* client a */ start transaction",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client c */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client a */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
			},
			{
				Query:    "/* client b */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
			},
			{
				Query:    "/* client c */ select * from t2 order by x",
				Expected: []sql.Row{{10, 10}, {11, 11}, {12, 12}},
			},

			{
				Query:    "/* client a */ insert into t values (10, 10)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 10}}},
			},
			{
				Query:    "/* client b */ insert into t (y) values (11)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 11}}},
			},

			{
				Query:    "/* client c */ insert into t values (50, 50)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 50}}},
			},
			{
				Query:    "/* client b */ insert into t (y) values (51)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 51}}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {11, 11}, {51, 51}},
			},
			{
				Query:    "/* client c */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {50, 50}},
			},
			{
				Query:    "/* client a */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client c */ commit",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}},
			},
			{
				Query:    "/* client b */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}},
			},
			{
				Query:    "/* client c */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}},
			},

			{
				Query:    "/* client a */ insert into t values (NULL, 52)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 52}}},
			},
			{
				Query:    "/* client a */ select * from t order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}, {10, 10}, {11, 11}, {50, 50}, {51, 51}, {52, 52}},
			},
		},
	},
	{
		Name: "AUTO_INCREMENT transactions off",
		SetUpScript: []string{
			"CREATE table t2 (x int PRIMARY KEY AUTO_INCREMENT, y int);",
			"insert into t2 (y) values (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ insert into t2 (y) values (2)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 2}}},
			},
			{
				Query:    "/* client b */ select * from t2 order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}},
			},
			{
				Query:    "/* client b */ insert into t2 (y) values (3)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 3}}},
			},
			{
				Query:    "/* client a */ select * from t2 order by x",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
			},
			{
				Query:    "/* client a */ alter table t2 modify column x int",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0}}},
			},
			{
				Query:       "/* client a */ INSERT INTO t2 values (NULL, 3)",
				ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull,
			},
			{
				Query:    "/* client a */ DROP TABLE t2",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0}}},
			},
			{
				Query:    "/* client a */ CREATE table t2 (x int PRIMARY KEY AUTO_INCREMENT, y int)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 0, InsertID: 0}}},
			},
			{
				Query:    "/* client a */ insert into t2 (y) values (4)",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 1}}},
			},
			{
				Query:    "/* client a */ SELECT * FROM t2",
				Expected: []sql.Row{{1, 4}},
			},
		},
	},
	{
		Name: "READ ONLY Transactions",
		SetUpScript: []string{
			"create table t2 (pk int primary key, val int)",
			"insert into t2 values (0,0)",
			"commit",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "/* client a */ set autocommit = off",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "/* client a */ create temporary table tmp(pk int primary key)",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "/* client a */  START TRANSACTION READ ONLY",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client a */ INSERT INTO tmp VALUES (1)",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:       "/* client a */ insert into t2 values (1, 1)",
				ExpectedErr: sql.ErrReadOnlyTransaction,
			},
			{
				Query:       "/* client a */ insert into t2 values (2, 2)",
				ExpectedErr: sql.ErrReadOnlyTransaction,
			},
			{
				Query:       "/* client a */ delete from t2 where pk = 0",
				ExpectedErr: sql.ErrReadOnlyTransaction,
			},
			{

				Query:    "/* client a */ alter table t2 add val2 int",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "/* client a */ select * from t2",
				Expected: []sql.Row{{0, 0, nil}},
			},
			{
				Query:       "/* client a */ create temporary table tmp2(pk int primary key)",
				ExpectedErr: sql.ErrReadOnlyTransaction,
			},
			{
				Query:    "/* client a */ COMMIT",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ START TRANSACTION READ ONLY",
				Expected: []sql.Row{},
			},
			{
				Query:    "/* client b */ SELECT * FROM t2",
				Expected: []sql.Row{{0, 0, nil}},
			},
		},
	},
}
View Source
var TriggerErrorTests = []ScriptTest{
	{
		Name: "table doesn't exist",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger not_found before insert on y for each row set new.a = new.a + 1",
		ExpectedErr: sql.ErrTableNotFound,
	},
	{
		Name: "trigger errors on execution",
		SetUpScript: []string{
			"create table x (a int primary key, b int)",
			"create table y (c int primary key not null)",
			"create trigger trigger_has_error before insert on x for each row insert into y values (null)",
		},
		Query:       "insert into x values (1,2)",
		ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull,
	},
	{
		Name: "self update on insert",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger a1 before insert on a for each row insert into a values (new.x * 2)",
		},
		Query:       "insert into a values (1), (2), (3)",
		ExpectedErr: sql.ErrTriggerTableInUse,
	},
	{
		Name: "self update on delete",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger a1 before delete on a for each row delete from a",
		},
		Query:       "delete from a",
		ExpectedErr: sql.ErrTriggerTableInUse,
	},
	{
		Name: "self update on update",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger a1 before update on a for each row update a set x = 1",
		},
		Query:       "update a set x = 2",
		ExpectedErr: sql.ErrTriggerTableInUse,
	},
	{
		Name: "circular dependency",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before insert on a for each row insert into b values (new.x * 2)",
			"create trigger b1 before insert on b for each row insert into a values (new.y * 7)",
		},
		Query:       "insert into a values (1), (2), (3)",
		ExpectedErr: sql.ErrTriggerTableInUse,
	},
	{
		Name: "circular dependency, nested two deep",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create table c (z int primary key)",
			"create trigger a1 before insert on a for each row insert into b values (new.x * 2)",
			"create trigger b1 before insert on b for each row insert into c values (new.y * 5)",
			"create trigger c1 before insert on c for each row insert into a values (new.z * 7)",
		},
		Query:       "insert into a values (1), (2), (3)",
		ExpectedErr: sql.ErrTriggerTableInUse,
	},
	{
		Name: "reference to old on insert",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger old_on_insert before insert on x for each row set new.c = old.a + 1",
		ExpectedErr: sql.ErrInvalidUseOfOldNew,
	},
	{
		Name: "reference to new on delete",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger new_on_delete before delete on x for each row set new.c = old.a + 1",
		ExpectedErr: sql.ErrInvalidUseOfOldNew,
	},
	{
		Name: "set old row on update",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger update_old before update on x for each row set old.c = new.a + 1",
		ExpectedErr: sql.ErrInvalidUpdateOfOldRow,
	},
	{
		Name: "set old row on update, begin block",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger update_old before update on x for each row BEGIN set old.c = new.a + 1; END",
		ExpectedErr: sql.ErrInvalidUpdateOfOldRow,
	},
	{
		Name: "set new row after insert",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger update_new after insert on x for each row set new.c = new.a + 1",
		ExpectedErr: sql.ErrInvalidUpdateInAfterTrigger,
	},
	{
		Name: "set new row after update",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger update_new after update on x for each row set new.c = new.a + 1",
		ExpectedErr: sql.ErrInvalidUpdateInAfterTrigger,
	},
	{
		Name: "set new row after update, begin block",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger update_new after update on x for each row BEGIN set new.c = new.a + 1; END",
		ExpectedErr: sql.ErrInvalidUpdateInAfterTrigger,
	},
	{
		Name: "source column doesn't exist",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger not_found before insert on x for each row set new.d = new.d + 1",
		ExpectedErr: sql.ErrUnknownColumn,
	},
	{
		Name: "target column doesn't exist",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
		},
		Query:       "create trigger not_found before insert on x for each row set new.d = new.a + 1",
		ExpectedErr: sql.ErrUnknownColumn,
	},
}
View Source
var TriggerTests = []ScriptTest{

	{
		Name: "trigger before inserts, use updated reference to other table",
		SetUpScript: []string{
			"create table a (i int primary key, j int)",
			"create table b (x int primary key)",
			"create trigger trig before insert on a for each row begin set new.j = (select coalesce(max(x),1) from b); update b set x = x + 1; end;",
			"insert into b values (1)",
			"insert into a values (1,0), (2,0), (3,0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from a order by i",
				Expected: []sql.Row{
					{1, 1}, {2, 2}, {3, 3},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{4},
				},
			},
			{
				Query: "insert into a values (4,0), (5,0)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger before inserts, use count updated reference to other table",
		SetUpScript: []string{
			"create table a (i int, j int)",
			"create table b (x int)",
			"create trigger trig before insert on a for each row begin set new.j = (select count(x) from b); insert into b values (new.i + new.j); end;",
			"insert into a values (0,0), (0,0), (0,0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from a order by j",
				Expected: []sql.Row{
					{0, 0}, {0, 1}, {0, 2},
				},
			},
			{
				Query: "select x from b",
				Expected: []sql.Row{
					{0}, {1}, {2},
				},
			},
			{
				Query: "insert into a values (0,0), (0,0)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger after insert, insert into other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger insert_into_b after insert on a for each row insert into b values (new.x + 1)",
			"insert into a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{2}, {4}, {6},
				},
			},
			{
				Query: "insert into a values (7), (9)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger after insert, delete from other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into b values (0), (2), (4), (6), (8)",
			"create trigger insert_into_b after insert on a for each row delete from b where y = (new.x + 1)",
			"insert into a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "insert into a values (7), (9)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger after insert, update other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into b values (0), (2), (4), (6), (8)",
			"create trigger insert_into_b after insert on a for each row update b set y = new.x where y = new.x + 1",
			"insert into a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {1}, {3}, {5}, {8},
				},
			},
		},
	},
	{
		Name: "trigger before insert, insert into other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger insert_into_b before insert on a for each row insert into b values (new.x + 1)",
			"insert into a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{2}, {4}, {6},
				},
			},
			{
				Query: "insert into a values (7), (9)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger before insert, insert into other table with different schema",
		SetUpScript: []string{
			"create table a (x int primary key, y int)",
			"create table b (z int primary key)",
			"create trigger insert_into_b before insert on a for each row insert into b values (new.x + 1)",
			"insert into a values (1,2), (3,4), (5,6)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select z from b order by 1",
				Expected: []sql.Row{
					{2}, {4}, {6},
				},
			},
			{
				Query: "insert into a values (7,8), (9,10)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger before insert, delete from other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into b values (0), (2), (4), (6), (8)",
			"create trigger insert_into_b before insert on a for each row delete from b where y = (new.x + 1)",
			"insert into a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "insert into a values (7), (9)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger before insert, update other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into b values (0), (2), (4), (6), (8)",
			"create trigger insert_into_b before insert on a for each row update b set y = new.x where y = new.x + 1",
			"insert into a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {1}, {3}, {5}, {8},
				},
			},
		},
	},
	{
		Name: "trigger before insert, updates references to 2 tables",
		SetUpScript: []string{
			"create table a (i int, j int, k int)",
			"create table b (x int)",
			"create table c (y int)",
			"insert into b values (0)",
			"insert into c values (0)",
			"create trigger trig before insert on a for each row begin set new.j = (select x from b); set new.k = (select y from c); update b set x = x + 1; update c set y = y + 2; end;",
			"insert into a values (0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), (4, 0, 0)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select * from a order by 1",
				Expected: []sql.Row{
					{0, 0, 0}, {1, 1, 2}, {2, 2, 4}, {3, 3, 6}, {4, 4, 8},
				},
			},
			{
				Query: "select x from b order by 1",
				Expected: []sql.Row{
					{5},
				},
			},
			{
				Query: "select y from c order by 1",
				Expected: []sql.Row{
					{10},
				},
			},
		},
	},
	{
		Name: "trigger before insert, alter inserted value",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger insert_into_a before insert on a for each row set new.x = new.x + 1",
			"insert into a values (1)",
		},
		Query: "select x from a order by 1",
		Expected: []sql.Row{
			{2},
		},
	},
	{
		Name: "trigger before insert, alter inserted value, multiple columns",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
			"create trigger insert_into_x before insert on x for each row set new.a = new.a + 1, new.b = new.c, new.c = 0",
			"insert into x values (1, 10, 100)",
		},
		Query: "select * from x order by 1",
		Expected: []sql.Row{
			{2, 100, 0},
		},
	},
	{
		Name: "trigger before insert, alter inserted value, multiple columns, system var",
		SetUpScript: []string{
			"create table x (a int primary key, b int, c int)",
			"set @@auto_increment_increment = 1",
			"create trigger insert_into_x before insert on x for each row " +
				"set new.a = new.a + 1, new.b = new.c, new.c = 0, @@auto_increment_increment = @@auto_increment_increment + 1",
			"insert into x values (1, 10, 100), (2, 20, 200)",
		},
		Query: "select *, @@auto_increment_increment from x order by 1",
		Expected: []sql.Row{
			{2, 100, 0, 3},
			{3, 200, 0, 3},
		},
	},
	{
		Name: "trigger before insert, alter inserted value, out of order insertion",
		SetUpScript: []string{
			"create table a (x int primary key, y int)",
			"create trigger a1 before insert on a for each row set new.x = new.x * 2, new.y = new.y * 3",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a (y, x) values (5,7), (9,11)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select x, y from a order by 1",
				Expected: []sql.Row{
					{14, 15},
					{22, 27},
				},
			},
		},
	},
	{
		Name: "trigger before insert, alter inserted value, incomplete insertion",
		SetUpScript: []string{
			"create table a (x int primary key, y int, z int default 5)",
			"create trigger a1 before insert on a for each row set new.x = new.x * 2, new.y = new.y * 3, new.z = new.z * 5",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a (y, x) values (5,7), (9,11)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query: "select x, y, z from a order by 1",
				Expected: []sql.Row{
					{14, 15, 25},
					{22, 27, 25},
				},
			},
		},
	},
	{
		Name: "trigger before insert, begin block with multiple set statements",
		SetUpScript: []string{
			"CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"INSERT INTO test VALUES (0,2),(1,3)",
			`CREATE TRIGGER tt BEFORE INSERT ON test FOR EACH ROW 
				BEGIN 
					SET NEW.v1 = NEW.v1 * 11;
					SET NEW.v1 = NEW.v1 * -10;
				END;`,
			"INSERT INTO test VALUES (2,4), (6,8);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM test ORDER BY 1",
				Expected: []sql.Row{
					{0, 2}, {1, 3}, {2, -440}, {6, -880},
				},
			},
		},
	},
	{
		Name: "trigger before insert, begin block with multiple set statements and inserts",
		SetUpScript: []string{
			"CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"CREATE TABLE test2(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"CREATE TABLE test3(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"INSERT INTO test VALUES (0,2),(1,3)",
			`CREATE TRIGGER tt BEFORE INSERT ON test FOR EACH ROW 
				BEGIN 
					SET NEW.v1 = NEW.v1 * 11;
					insert into test2 values (new.pk * 3, new.v1);
					SET NEW.v1 = NEW.v1 * -10;
					insert into test3 values (new.pk * 5, new.v1);
					set @var = 0;
				END;`,
			"INSERT INTO test VALUES (2,4), (6,8);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM test ORDER BY 1",
				Expected: []sql.Row{
					{0, 2}, {1, 3}, {2, -440}, {6, -880},
				},
			},
			{
				Query: "SELECT * FROM test2 ORDER BY 1",
				Expected: []sql.Row{
					{6, 44}, {18, 88},
				},
			},
			{
				Query: "SELECT * FROM test3 ORDER BY 1",
				Expected: []sql.Row{
					{10, -440}, {30, -880},
				},
			},
		},
	},
	{
		Name: "Create a trigger on a new database and verify that the trigger works when selected on another database",
		SetUpScript: []string{
			"create table foo.a (x int primary key)",
			"create table foo.b (y int primary key)",
			"use foo",
			"create trigger insert_into_b after insert on foo.a for each row insert into foo.b values (new.x + 1)",
			"use mydb",
			"insert into foo.a values (1), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from foo.a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from foo.b order by 1",
				Expected: []sql.Row{
					{2}, {4}, {6},
				},
			},
			{
				Query: "insert into foo.a values (7), (9)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
		},
	},
	{
		Name: "trigger with escaped chars",
		SetUpScript: []string{
			"CREATE TABLE testInt(v1 BIGINT);",
			"CREATE TABLE testStr(s1 VARCHAR(255), s2 VARCHAR(255), s3 VARCHAR(255));",
			`CREATE TRIGGER tt BEFORE INSERT ON testInt FOR EACH ROW
				BEGIN
					insert into testStr values (CONCAT('joe''s:', NEW.v1),
                                                CONCAT('jill\'s:', NEW.v1 + 1),
                                                CONCAT("stan""s:", NEW.v1 + 2)
                                               );
				END;`,
			"INSERT INTO testInt VALUES (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM testStr",
				Expected: []sql.Row{
					{"joe's:1", "jill's:2", "stan\"s:3"},
				},
			},
		},
	},

	{
		Name: "trigger after update, insert into other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (1), (3), (5)",
			"create trigger insert_into_b after update on a for each row insert into b values (old.x + new.x + 1)",
			"update a set x = x + 1 where x in (1, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{2}, {4}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{4}, {8},
				},
			},
			{
				Query: "update a set x = x + 1 where x = 5",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
		},
	},
	{
		Name: "trigger after update, delete from other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (1), (3), (5), (7), (9)",
			"create trigger delete_from_b after update on a for each row delete from b where y = old.x + new.x",
			"update a set x = x + 1 where x in (2,4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {3}, {5}, {6}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{1}, {3}, {7},
				},
			},
		},
	},
	{
		Name: "trigger after update, update other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (0), (2), (4), (8)",
			"create trigger update_b after update on a for each row update b set y = old.x + new.x + 1 where y = old.x",
			"update a set x = x + 1 where x in (2, 4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {3}, {5}, {6}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {6}, {8}, {10},
				},
			},
		},
	},
	{
		Name: "trigger before update, insert into other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (1), (3), (5)",
			"create trigger insert_into_b before update on a for each row insert into b values (old.x + new.x + 1)",
			"update a set x = x + 1 where x in (1, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{2}, {4}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{4}, {8},
				},
			},
			{
				Query: "update a set x = x + 1 where x = 5",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 1,
						Info: plan.UpdateInfo{
							Matched: 1,
							Updated: 1,
						},
					}},
				},
			},
		},
	},
	{
		Name: "trigger before update, delete from other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (1), (3), (5), (7), (9)",
			"create trigger delete_from_b before update on a for each row delete from b where y = old.x + new.x",
			"update a set x = x + 1 where x in (2,4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {3}, {5}, {6}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{1}, {3}, {7},
				},
			},
		},
	},
	{
		Name: "trigger before update, update other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (0), (2), (4), (8)",
			"create trigger update_b before update on a for each row update b set y = old.x + new.x + 1 where y = old.x",
			"update a set x = x + 1 where x in (2, 4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {3}, {5}, {6}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {6}, {8}, {10},
				},
			},
		},
	},
	{
		Name: "trigger before update, set new value",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"insert into a values (1), (10)",
			"create trigger update_a before update on a for each row set new.x = new.x + old.x",
			"update a set x = x + 1",
		},
		Query: "select x from a order by 1",
		Expected: []sql.Row{
			{3}, {21},
		},
	},
	{
		Name: "trigger before update, set new value to old value",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"insert into a values (1), (10)",
			"create trigger no_step_on_snek before update on a for each row set new.x = old.x",
			"update a set x = x + 1",
		},
		Query: "select x from a order by 1",
		Expected: []sql.Row{
			{1}, {10},
		},
	},
	{
		Name: "trigger before update, set new values, multiple cols",
		SetUpScript: []string{
			"create table a (x int primary key, y int)",
			"insert into a values (1,3), (10,20)",
			"create trigger update_a before update on a for each row set new.x = new.x + old.y, new.y = new.y + old.x",
			"update a set x = x + 1, y = y + 1",
		},
		Query: "select x, y from a order by 1",
		Expected: []sql.Row{
			{5, 5},
			{31, 31},
		},
	},
	{
		Name: "trigger before update, set new values, multiple cols (2)",
		SetUpScript: []string{
			"create table a (x int primary key, y int)",
			"insert into a values (1,3), (10,20)",
			"create trigger update_a before update on a for each row set new.x = new.x + new.y, new.y = new.y + old.y",
			"update a set x = x + 1, y = y + 1",
		},
		Query: "select x, y from a order by 1",
		Expected: []sql.Row{
			{6, 7},
			{32, 41},
		},
	},
	{
		Name: "trigger before update, with indexed update",
		SetUpScript: []string{
			"create table a (x int primary key, y int, unique key (y))",
			"create table b (z int primary key)",
			"insert into a values (1,3), (10,20)",
			"create trigger insert_b before update on a for each row insert into b values (old.x * 10)",
			"update a set x = x + 1 where y = 20",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x, y from a order by 1",
				Expected: []sql.Row{
					{1, 3},
					{11, 20},
				},
			},
			{
				Query: "select z from b",
				Expected: []sql.Row{
					{100},
				},
			},
		},
	},
	{
		Name: "trigger before update, begin block with multiple set statements",
		SetUpScript: []string{
			"CREATE TABLE test(pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"INSERT INTO test VALUES (0,2),(1,3)",
			"CREATE TRIGGER tt BEFORE UPDATE ON test FOR EACH ROW BEGIN SET NEW.v1 = (OLD.v1 * 2) + NEW.v1; SET NEW.v1 = NEW.v1 * -10; END;",
			"UPDATE test SET v1 = v1 + 1;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * FROM test ORDER BY 1",
				Expected: []sql.Row{
					{0, -70}, {1, -100},
				},
			},
		},
	},
	{
		Name: "trigger before update with set clause inside if statement with '!' operator",
		SetUpScript: []string{
			"CREATE TABLE test (stat_id INT);",
			"INSERT INTO test VALUES (-1), (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `
CREATE TRIGGER before_test_stat_update BEFORE UPDATE ON test FOR EACH ROW
BEGIN
	IF !(new.stat_id < 0)
		THEN SET new.stat_id = new.stat_id * -1;
	END IF;
END;`,
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:    "update test set stat_id=2 where stat_id=1;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "select * from test order by stat_id;",
				Expected: []sql.Row{{-2}, {-1}},
			},
			{
				Query:    "update test set stat_id=-2 where stat_id=-1;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "select * from test;",
				Expected: []sql.Row{{-2}, {-2}},
			},
		},
	},
	{
		Name: "trigger before update with set clause inside if statement with 'NOT'",
		SetUpScript: []string{
			"CREATE TABLE test (stat_id INT);",
			"INSERT INTO test VALUES (-1), (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: `
CREATE TRIGGER before_test_stat_update BEFORE UPDATE ON test FOR EACH ROW
BEGIN
	IF NOT(new.stat_id < 0)
		THEN SET new.stat_id = new.stat_id * -1;
	END IF;
END;`,
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:    "update test set stat_id=2 where stat_id=1;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "select * from test order by stat_id;",
				Expected: []sql.Row{{-2}, {-1}},
			},
			{
				Query:    "update test set stat_id=-2 where stat_id=-1;",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
			},
			{
				Query:    "select * from test;",
				Expected: []sql.Row{{-2}, {-2}},
			},
		},
	},

	{
		Name: "trigger after delete, insert into other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (1), (3), (5)",
			"create trigger insert_into_b after delete on a for each row insert into b values (old.x + 1)",
			"delete from a where x in (1, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{2}, {4},
				},
			},
			{
				Query: "delete from a where x = 5",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
		},
	},
	{
		Name: "trigger after delete, delete from other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (0), (2), (4), (6), (8)",
			"create trigger delete_from_b after delete on a for each row delete from b where y = old.x",
			"delete from a where x in (2,4,6)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
		},
	},
	{
		Name: "trigger after delete, update other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (0), (2), (4), (6), (8)",
			"create trigger update_b after delete on a for each row update b set y = old.x + 1 where y = old.x",
			"delete from a where x in (2,4,6)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{0}, {3}, {5}, {7}, {8},
				},
			},
		},
	},
	{
		Name: "trigger before delete, insert into other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"create trigger insert_into_b before delete on a for each row insert into b values (old.x + 1)",
			"delete from a where x in (2, 4, 6)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{3}, {5}, {7},
				},
			},
			{
				Query: "delete from a where x = 0",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 1}},
				},
			},
		},
	},
	{
		Name: "trigger before delete, delete from other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (1), (3), (5), (7), (9)",
			"create trigger delete_from_b before delete on a for each row delete from b where y = (old.x + 1)",
			"delete from a where x in (2, 4, 6)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{1}, {9},
				},
			},
		},
	},
	{
		Name: "trigger before delete, update other table",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into a values (0), (2), (4), (6), (8)",
			"insert into b values (1), (3), (5), (7), (9)",
			"create trigger update_b before delete on a for each row update b set y = old.x where y = old.x + 1",
			"delete from a where x in (2, 4, 6)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0}, {8},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{1}, {2}, {4}, {6}, {9},
				},
			},
		},
	},
	{
		Name: "trigger before delete, delete with index",
		SetUpScript: []string{
			"create table a (x int primary key, z int, unique key (z))",
			"create table b (y int primary key)",
			"insert into a values (0,1), (2,3), (4,5)",
			"create trigger insert_b before delete on a for each row insert into b values (old.x * 2)",
			"delete from a where z > 2",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{0},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{4}, {8},
				},
			},
		},
	},
	{
		Name: "trigger before delete, update other table",
		SetUpScript: []string{
			"create table a (i int primary key, j int)",
			"insert into a values (0,1), (2,3), (4,5)",
			"create table b (x int)",
			"insert into b values (0)",
			"create trigger trig before delete on a for each row begin update b set x = x + old.j; end;",
			"delete from a where true",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select * from a order by 1",
				Expected: []sql.Row{},
			},
			{
				Query: "select x from b order by 1",
				Expected: []sql.Row{
					{9},
				},
			},
		},
	},
	{
		Name: "single trigger before single target table delete from join",
		SetUpScript: []string{
			"create table a (i int primary key, j int)",
			"insert into a values (0,1), (2,3), (4,5)",
			"create table b (i int primary key)",
			"insert into b values (1), (3), (5)",
			"create table c (x int)",
			"insert into c values (0)",
			"create trigger trig before delete on a for each row begin update c set x = x + 1; end;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "delete a from a inner join b on a.j=b.i;",
				ExpectedErrStr: "delete from with explicit target tables does not support triggers; retry with single table deletes",
			},
		},
	},
	{
		Name: "multiple trigger before single target table delete from join",
		SetUpScript: []string{
			"create table a (i int primary key, j int)",
			"insert into a values (0,1), (2,3), (4,5)",
			"create table b (i int primary key)",
			"insert into b values (1), (3), (5)",
			"create table c (x int)",
			"insert into c values (0)",
			"create trigger trig1 before delete on a for each row begin update c set x = x + 1; end;",
			"create trigger trig2 before delete on b for each row begin update c set x = x + 1; end;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "delete a from a inner join b on a.j=b.i where a.i >= 0;",
				ExpectedErrStr: "delete from with explicit target tables does not support triggers; retry with single table deletes",
			},
		},
	},
	{
		Name: "multiple trigger before multiple target table delete from join",
		SetUpScript: []string{
			"create table a (i int primary key, j int)",
			"insert into a values (0,1), (2,3), (4,5)",
			"create table b (i int primary key)",
			"insert into b values (1), (3), (5)",
			"create table c (x int)",
			"insert into c values (0)",
			"create trigger trig1 before delete on a for each row begin update c set x = x + 1; end;",
			"create trigger trig2 before delete on b for each row begin update c set x = x + 1; end;",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "delete a, b from a inner join b on a.j=b.i where a.i >= 0;",
				ExpectedErrStr: "delete from with explicit target tables does not support triggers; retry with single table deletes",
			},
		},
	},

	{
		Name: "triggers before and after insert",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before insert on a for each row insert into b values (NEW.x * 7)",
			"create trigger a2 after insert on a for each row insert into b values (New.x * 11)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (2), (3), (5)",
				Expected: []sql.Row{
					{types.NewOkResult(3)},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{2}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {33}, {35}, {55},
				},
			},
		},
	},
	{
		Name: "multiple triggers before insert",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger a1 before insert on a for each row set new.x = New.x + 1",
			"create trigger a2 before insert on a for each row set new.x = New.x * 2",
			"create trigger a3 before insert on a for each row set new.x = New.x - 5",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (3)",
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{-1}, {3},
				},
			},
		},
	},
	{
		Name: "multiple triggers before insert, with precedes / follows",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger a1 before insert on a for each row set new.x = New.x + 1",
			"create trigger a2 before insert on a for each row precedes a1 set new.x = New.x * 2",
			"create trigger a3 before insert on a for each row precedes a2 set new.x = New.x - 5",
			"create trigger a4 before insert on a for each row follows a2 set new.x = New.x * 3",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (3)",
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{-23}, {-11},
				},
			},
		},
	},
	{
		Name: "triggers before and after update",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before update on a for each row insert into b values (old.x * 7)",
			"create trigger a2 after update on a for each row insert into b values (old.x * 11)",
			"insert into a values (2), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set x = x * 2",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 3,
						Info: plan.UpdateInfo{
							Matched: 3,
							Updated: 3,
						},
					}},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{4}, {6}, {10},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {33}, {35}, {55},
				},
			},
		},
	},
	{
		Name: "multiple triggers before and after update",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before update on a for each row insert into b values (old.x * 7)",
			"create trigger a2 after update on a for each row insert into b values (old.x * 11)",
			"create trigger a3 before update on a for each row insert into b values (old.x * 13)",
			"create trigger a4 after update on a for each row insert into b values (old.x * 17)",
			"insert into a values (2), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "update a set x = x * 2",
				Expected: []sql.Row{
					{types.OkResult{
						RowsAffected: 3,
						Info: plan.UpdateInfo{
							Matched: 3,
							Updated: 3,
						},
					}},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{4}, {6}, {10},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {26}, {33}, {34}, {35}, {39}, {51}, {55}, {65}, {85},
				},
			},
		},
	},
	{
		Name: "triggers before and after delete",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before delete on a for each row insert into b values (old.x * 7)",
			"create trigger a2 after delete on a for each row insert into b values (old.x * 11)",
			"insert into a values (2), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "delete from a",
				Expected: []sql.Row{
					{types.NewOkResult(3)},
				},
			},
			{
				Query:    "select x from a order by 1",
				Expected: []sql.Row{},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {33}, {35}, {55},
				},
			},
		},
	},
	{
		Name: "multiple triggers before and after delete",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create trigger a1 before delete on a for each row insert into b values (old.x * 7)",
			"create trigger a2 after delete on a for each row insert into b values (old.x * 11)",
			"create trigger a3 before delete on a for each row insert into b values (old.x * 13)",
			"create trigger a4 after delete on a for each row insert into b values (old.x * 17)",
			"insert into a values (2), (3), (5)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "delete from a",
				Expected: []sql.Row{
					{types.NewOkResult(3)},
				},
			},
			{
				Query:    "select x from a order by 1",
				Expected: []sql.Row{},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{14}, {21}, {22}, {26}, {33}, {34}, {35}, {39}, {51}, {55}, {65}, {85},
				},
			},
		},
	},
	{
		Name: "multiple triggers before and after insert, with precedes / follows",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"insert into b values (1), (3)",
			"create trigger a1 before insert on a for each row set new.x = New.x + 1",
			"create trigger a2 before insert on a for each row precedes a1 set new.x = New.x * 2",
			"create trigger a3 before insert on a for each row precedes a2 set new.x = New.x - 5",
			"create trigger a4 before insert on a for each row follows a2 set new.x = New.x * 3",

			"create trigger a5 after insert on a for each row update b set y = y + 1 order by y asc",
			"create trigger a6 after insert on a for each row precedes a5 update b set y = y * 2 order by y asc",
			"create trigger a7 after insert on a for each row precedes a6 update b set y = y - 5 order by y asc",
			"create trigger a8 after insert on a for each row follows a6 update b set y = y * 3 order by y asc",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (3)",
				Expected: []sql.Row{
					{types.NewOkResult(2)},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{-23}, {-11},
				},
			},
			{
				Query: "select y from b order by 1",

				Expected: []sql.Row{
					{-167}, {-95},
				},
			},
		},
	},
	{
		Name: "triggered update query which could project",
		SetUpScript: []string{
			"create table trigger_on_update (id int primary key, first varchar(25), last varchar(25))",
			"create table is_dirty (id int primary key, is_dirty bool)",
			"insert into is_dirty values (1, false)",
			"insert into trigger_on_update values (1, 'george', 'smith')",
			`create trigger trigger_on_update_on_update before update on trigger_on_update for each row
begin
  update is_dirty set is_dirty = true;
end;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select id, is_dirty from is_dirty",
				Expected: []sql.Row{
					{1, 0},
				},
			},
			{
				Query: "update trigger_on_update set id = 1, first = 'george', last = 'smith' where id = 1",
				Expected: []sql.Row{
					{
						types.OkResult{
							RowsAffected: 0,
							Info: plan.UpdateInfo{
								Matched: 1,
								Updated: 0,
							},
						},
					},
				},
			},
			{
				Query: "select id, is_dirty from is_dirty",
				Expected: []sql.Row{
					{1, 1},
				},
			},
		},
	},

	{
		Name: "trigger before insert with subquery expressions",
		SetUpScript: []string{
			"create table rn (id int primary key, upstream_edge_id int, downstream_edge_id int)",
			"create table sn (id int primary key, target_id int, source_id int)",
			`
create trigger rn_on_insert before insert on rn
for each row
begin
  if
    (select target_id from sn where id = NEW.upstream_edge_id) <> (select source_id from sn where id = NEW.downstream_edge_id)
  then
    set @myvar = concat('bro', 'ken');
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @myvar;
  end if;
end;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into rn values (1,1,1)",
			},
			{
				Query:    "select id from rn",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "trigger with signal and user var",
		SetUpScript: []string{
			"create table t1 (id int primary key)",
			"create table t2 (id int primary key)",
			`
create trigger trigger1 before insert on t1
for each row
begin
	set @myvar = concat('bro', 'ken');
	SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = @myvar;
end;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:          "insert into t1 values (1)",
				ExpectedErrStr: "broken (errno 1644) (sqlstate 45000)",
			},
			{
				Query:    "select id from t1",
				Expected: []sql.Row{},
			},
		},
	},

	{
		Name: "trigger before insert, multiple triggers defined",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create table c (z int primary key)",

			"create trigger a1 before insert on a for each row insert into b values (new.x * 2)",
			"create trigger a2 before update on a for each row insert into b values (new.x * 3)",
			"create trigger a3 before delete on a for each row insert into b values (old.x * 5)",
			"create trigger b1 before insert on b for each row insert into c values (new.y * 7)",
			"create trigger b2 before update on b for each row insert into c values (new.y * 11)",
			"create trigger b3 before delete on b for each row insert into c values (old.y * 13)",
			"insert into a values (1), (2), (3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {2}, {3},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{2}, {4}, {6},
				},
			},
			{
				Query: "select z from c order by 1",
				Expected: []sql.Row{
					{14}, {28}, {42},
				},
			},
		},
	},
	{
		Name: "trigger with signal",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create table b (y int primary key)",
			"create table c (z int primary key)",
			"insert into c values (-1)",
			`create trigger trig_with_signal before insert on a for each row
begin
	declare cond_name condition for sqlstate '45000';
	if new.x = 5 then signal cond_name set message_text = 'trig err';
	end if;
	insert into b values (new.x + 1);
	update c set z = new.x;
end;`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "insert into a values (1), (3)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 2}},
				},
			},
			{
				Query:          "insert into a values (5)",
				ExpectedErrStr: "trig err (errno 1644) (sqlstate 45000)",
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{2}, {4},
				},
			},
			{
				Query: "select z from c order by 1",
				Expected: []sql.Row{
					{3},
				},
			},
		},
	},

	{
		Name: "show create triggers",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger a1 before insert on a for each row set new.x = new.x + 1",
			"create table b (y int primary key)",
			"create trigger b1 before insert on b for each row set new.y = new.y + 2",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "show create trigger a1",
				Expected: []sql.Row{
					{
						"a1",
						"",
						"create trigger a1 before insert on a for each row set new.x = new.x + 1",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
						time.Unix(0, 0).UTC(),
					},
				},
			},
			{
				Query: "show create trigger b1",
				Expected: []sql.Row{
					{
						"b1",
						"",
						"create trigger b1 before insert on b for each row set new.y = new.y + 2",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
						time.Unix(0, 0).UTC(),
					},
				},
			},
			{
				Query:       "show create trigger b2",
				ExpectedErr: sql.ErrTriggerDoesNotExist,
			},
		},
	},

	{
		Name: "show triggers",
		SetUpScript: []string{
			"create table abb (x int primary key)",
			"create table acc (y int primary key)",
			"create trigger t1 before insert on abb for each row set new.x = new.x + 1",
			"create trigger t2 before insert on abb for each row set new.x = new.x + 2",
			"create trigger t3 after insert on acc for each row insert into abb values (new.y)",
			"create trigger t4 before update on acc for each row set new.y = old.y + 2",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "show triggers",
				Expected: []sql.Row{
					{
						"t1",
						"INSERT",
						"abb",
						"set new.x = new.x + 1",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t2",
						"INSERT",
						"abb",
						"set new.x = new.x + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t3",
						"INSERT",
						"acc",
						"insert into abb values (new.y)",
						"AFTER",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t4",
						"UPDATE",
						"acc",
						"set new.y = old.y + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
				},
			},
			{
				Query: "show triggers from mydb",
				Expected: []sql.Row{
					{
						"t1",
						"INSERT",
						"abb",
						"set new.x = new.x + 1",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t2",
						"INSERT",
						"abb",
						"set new.x = new.x + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t3",
						"INSERT",
						"acc",
						"insert into abb values (new.y)",
						"AFTER",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t4",
						"UPDATE",
						"acc",
						"set new.y = old.y + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
				},
			},
			{
				Query: "show triggers like '%cc'",
				Expected: []sql.Row{
					{
						"t3",
						"INSERT",
						"acc",
						"insert into abb values (new.y)",
						"AFTER",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t4",
						"UPDATE",
						"acc",
						"set new.y = old.y + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
				},
			},
			{
				Query: "show triggers where `event` = 'INSERT'",
				Expected: []sql.Row{
					{
						"t1",
						"INSERT",
						"abb",
						"set new.x = new.x + 1",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t2",
						"INSERT",
						"abb",
						"set new.x = new.x + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t3",
						"INSERT",
						"acc",
						"insert into abb values (new.y)",
						"AFTER",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
				},
			},
			{
				Query: "show triggers where timing = 'AFTER'",
				Expected: []sql.Row{
					{
						"t3",
						"INSERT",
						"acc",
						"insert into abb values (new.y)",
						"AFTER",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
				},
			},
			{
				Query: "show triggers where timing = 'BEFORE' and `Table` like '%bb'",
				Expected: []sql.Row{
					{
						"t1",
						"INSERT",
						"abb",
						"set new.x = new.x + 1",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
					{
						"t2",
						"INSERT",
						"abb",
						"set new.x = new.x + 2",
						"BEFORE",
						time.Unix(0, 0).UTC(),
						"",
						"",
						sql.Collation_Default.CharacterSet().String(),
						sql.Collation_Default.String(),
						sql.Collation_Default.String(),
					},
				},
			},
		},
	},

	{
		Name: "drop trigger",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger t1 before insert on a for each row set new.x = new.x * 1",
			"create trigger t2 before insert on a for each row follows t1 set new.x = new.x * 2",
			"create trigger t3 before insert on a for each row set new.x = new.x * 3",
			"create trigger t4 before insert on a for each row precedes t3 set new.x = new.x * 5",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:       "drop trigger t1",
				ExpectedErr: sql.ErrTriggerCannotBeDropped,
			},
			{
				Query:       "drop trigger t3",
				ExpectedErr: sql.ErrTriggerCannotBeDropped,
			},
			{
				Query:    "drop trigger t4",
				Expected: []sql.Row{},
			},
			{
				Query:    "drop trigger t3",
				Expected: []sql.Row{},
			},
			{
				Query:    "drop trigger if exists t5",
				Expected: []sql.Row{},
			},
			{
				Query:       "drop trigger t5",
				ExpectedErr: sql.ErrTriggerDoesNotExist,
			},
			{
				Query: "select trigger_name from information_schema.triggers order by 1",
				Expected: []sql.Row{
					{"t1"},
					{"t2"},
				},
			},
			{
				Query:    "drop trigger if exists t2",
				Expected: []sql.Row{},
			},
			{
				Query: "select trigger_name from information_schema.triggers order by 1",
				Expected: []sql.Row{
					{"t1"},
				},
			},
		},
	},

	{
		Name: "drop table referenced in triggers",
		SetUpScript: []string{
			"create table a (w int primary key)",
			"create table b (x int primary key)",
			"create table c (y int primary key)",
			"create table d (z int primary key)",
			"create trigger t1 before insert on a for each row set new.w = new.w",
			"create trigger t2 before insert on a for each row set new.w = new.w * 100",
			"create trigger t3 before insert on b for each row set new.x = new.x",
			"create trigger t4 before insert on b for each row set new.x = new.x * 100",
			"create trigger t5 before insert on c for each row set new.y = new.y",
			"create trigger t6 before insert on c for each row set new.y = new.y * 100",
			"create trigger t7 before insert on d for each row set new.z = new.z",
			"create trigger t8 before insert on d for each row set new.z = new.z * 100",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "drop table a",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "select trigger_name from information_schema.triggers order by 1",
				Expected: []sql.Row{
					{"t3"},
					{"t4"},
					{"t5"},
					{"t6"},
					{"t7"},
					{"t8"},
				},
			},
			{
				Query:    "drop table if exists b, d, e",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query: "select trigger_name from information_schema.triggers order by 1",
				Expected: []sql.Row{
					{"t5"},
					{"t6"},
				},
			},
		},
	},
	{
		Name: "drop table referenced in triggers with follows/precedes",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger t1 before insert on a for each row set new.x = new.x",
			"create trigger t2 before insert on a for each row follows t1 set new.x = new.x * 10",
			"create trigger t3 before insert on a for each row precedes t1 set new.x = new.x * 100",
			"create trigger t4 before insert on a for each row follows t3 set new.x = new.x * 1000",
			"create trigger t5 before insert on a for each row precedes t2 set new.x = new.x * 10000",
			"create trigger t6 before insert on a for each row follows t4 set new.x = new.x * 100000",
			"create trigger t7 before insert on a for each row precedes t1 set new.x = new.x * 1000000",
			"create trigger t8 before insert on a for each row follows t6 set new.x = new.x * 10000000",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "drop table a",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "show triggers",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "triggers with subquery expressions analyze",
		SetUpScript: []string{
			"create table a (x int primary key)",
			"create trigger t1 before insert on a for each row begin if NEW.x in (select 2+2 from dual) then signal SQLSTATE '45000' SET MESSAGE_TEXT = 'String field contains invalid value, like empty string, ''none'', ''null'', ''n/a'', ''nan'' etc.'; end if; end;",
		},
		Assertions: nil,
	},
	{
		Name: "insert into common sequence table (https://github.com/dolthub/dolt/issues/2534)",
		SetUpScript: []string{
			"create table mytable (id integer PRIMARY KEY DEFAULT 0, sometext text);",
			"create table sequence_table (max_id integer PRIMARY KEY);",
			"create trigger update_position_id before insert on mytable for each row begin set new.id = (select coalesce(max(max_id),1) from sequence_table); update sequence_table set max_id = max_id + 1; end;",
			"insert into sequence_table values (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "insert into mytable () values ();",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "insert into mytable (sometext) values ('hello');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "insert into mytable values (10, 'goodbye');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query: "select * from mytable order by id",
				Expected: []sql.Row{
					{1, nil},
					{2, "hello"},
					{3, "goodbye"},
				},
			},
		},
	},
	{
		Name: "insert into common sequence table workaround",
		SetUpScript: []string{
			"create table mytable (id integer PRIMARY KEY DEFAULT 0, sometext text);",
			"create table sequence_table (max_id integer PRIMARY KEY);",
			`create trigger update_position_id before insert on mytable for each row 
			begin 
				if @max_id is null then set @max_id = (select coalesce(max(max_id),1) from sequence_table);
				end if;
				set new.id = @max_id;
				set @max_id = @max_id + 1;
				update sequence_table set max_id = @max_id; 
			end;`,
			"insert into sequence_table values (1);",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "insert into mytable () values ();",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "insert into mytable (sometext) values ('hello');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "insert into mytable values (10, 'goodbye');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query:    "insert into mytable () values (), ();",
				Expected: []sql.Row{{types.NewOkResult(2)}},
			},
			{
				Query: "select * from mytable order by id",
				Expected: []sql.Row{
					{1, nil},
					{2, "hello"},
					{3, "goodbye"},
					{4, nil},
					{5, nil},
				},
			},
		},
	},
	{
		Name: "simple trigger with non-existent table in trigger body",
		SetUpScript: []string{
			"create table a (x int primary key)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "create trigger insert_into_b after insert on a for each row insert into b values (new.x + 1)",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:       "insert into a values (1), (3), (5)",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:    "create table b (y int primary key)",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query: "insert into a values (1), (3), (5)",
				Expected: []sql.Row{
					{types.OkResult{RowsAffected: 3}},
				},
			},
			{
				Query: "select x from a order by 1",
				Expected: []sql.Row{
					{1}, {3}, {5},
				},
			},
			{
				Query: "select y from b order by 1",
				Expected: []sql.Row{
					{2}, {4}, {6},
				},
			},
		},
	},
	{
		Name: "insert, update, delete triggers with non-existent table in trigger body",
		SetUpScript: []string{
			"CREATE TABLE film (film_id smallint unsigned NOT NULL AUTO_INCREMENT, title varchar(128) NOT NULL, description text, PRIMARY KEY (film_id))",
			"INSERT INTO `film` VALUES (1,'ACADEMY DINOSAUR','A Epic Drama in The Canadian Rockies'),(2,'ACE GOLDFINGER','An Astounding Epistle of a Database Administrator in Ancient China');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "CREATE TRIGGER ins_film AFTER INSERT ON film FOR EACH ROW BEGIN INSERT INTO film_text (film_id, title, description) VALUES (new.film_id, new.title, new.description); END;",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query: `CREATE TRIGGER upd_film AFTER UPDATE ON film FOR EACH ROW BEGIN
    IF (old.title != new.title) OR (old.description != new.description) OR (old.film_id != new.film_id)
    THEN
        UPDATE film_text
            SET title=new.title,
                description=new.description,
                film_id=new.film_id
        WHERE film_id=old.film_id;
    END IF; END;`,
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:    "CREATE TRIGGER del_film AFTER DELETE ON film FOR EACH ROW BEGIN DELETE FROM film_text WHERE film_id = old.film_id; END;",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:       "INSERT INTO `film` VALUES (3,'ADAPTATION HOLES','An Astounding Reflection in A Baloon Factory'),(4,'AFFAIR PREJUDICE','A Fanciful Documentary in A Shark Tank')",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:       "UPDATE film SET title = 'THE ACADEMY DINOSAUR' WHERE title = 'ACADEMY DINOSAUR'",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:       "DELETE FROM film WHERE title = 'ACE GOLDFINGER'",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				Query:    "CREATE TABLE film_text (film_id smallint NOT NULL, title varchar(255) NOT NULL, description text, PRIMARY KEY (film_id))",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:    "SELECT COUNT(*) FROM film",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "INSERT INTO `film` VALUES (3,'ADAPTATION HOLES','An Astounding Reflection in A Baloon Factory'),(4,'AFFAIR PREJUDICE','A Fanciful Documentary in A Shark Tank')",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 3}}},
			},
			{
				Query:    "SELECT COUNT(*) FROM film",
				Expected: []sql.Row{{4}},
			},
			{
				Query:    "SELECT COUNT(*) FROM film_text",
				Expected: []sql.Row{{2}},
			},
			{
				Query:    "UPDATE film SET title = 'DIFFERENT MOVIE' WHERE title = 'ADAPTATION HOLES'",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 0, Info: plan.UpdateInfo{Matched: 1, Updated: 1, Warnings: 0}}}},
			},
			{
				Query:    "SELECT COUNT(*) FROM film_text WHERE title = 'DIFFERENT MOVIE'",
				Expected: []sql.Row{{1}},
			},
			{
				Query:    "DELETE FROM film WHERE title = 'DIFFERENT MOVIE'",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
			},
			{
				Query:    "SELECT COUNT(*) FROM film_text WHERE title = 'DIFFERENT MOVIE'",
				Expected: []sql.Row{{0}},
			},
		},
	},
	{
		Name: "non-existent procedure in trigger body",
		SetUpScript: []string{
			"CREATE TABLE t0 (id INT PRIMARY KEY AUTO_INCREMENT, v1 INT, v2 TEXT);",
			"CREATE TABLE t1 (id INT PRIMARY KEY AUTO_INCREMENT, v1 INT, v2 TEXT);",
			"INSERT INTO t0 VALUES (1, 2, 'abc'), (2, 3, 'def');",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT * FROM t0;",
				Expected: []sql.Row{{1, 2, "abc"}, {2, 3, "def"}},
			},
			{
				Query: `CREATE PROCEDURE add_entry(i INT, s TEXT) BEGIN IF i > 50 THEN 
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'too big number'; END IF;
INSERT INTO t0 (v1, v2) VALUES (i, s); END;`,
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:    "CREATE TRIGGER trig AFTER INSERT ON t0 FOR EACH ROW BEGIN CALL back_up(NEW.v1, NEW.v2); END;",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:       "INSERT INTO t0 (v1, v2) VALUES (5, 'ggg');",
				ExpectedErr: sql.ErrStoredProcedureDoesNotExist,
			},
			{
				Query:    "CREATE PROCEDURE back_up(num INT, msg TEXT) INSERT INTO t1 (v1, v2) VALUES (num*2, msg);",
				Expected: []sql.Row{{types.OkResult{}}},
			},
			{
				Query:    "CALL add_entry(4, 'aaa');",
				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, InsertID: 1}}},
			},
			{
				Query:    "SELECT * FROM t0;",
				Expected: []sql.Row{{1, 2, "abc"}, {2, 3, "def"}, {3, 4, "aaa"}},
			},
			{
				Query:    "SELECT * FROM t1;",
				Expected: []sql.Row{{1, 8, "aaa"}},
			},
			{
				Query:          "CALL add_entry(54, 'bbb');",
				ExpectedErrStr: "too big number (errno 1644) (sqlstate 45000)",
			},
		},
	},
}
View Source
var TypeWireTests = []TypeWireTest{
	{
		Name: "TINYINT",
		SetUpScript: []string{
			`CREATE TABLE test (pk TINYINT PRIMARY KEY, v1 TINYINT);`,
			`INSERT INTO test VALUES (-75, "-25"), (0, 0), (107.2, 0025), (107.5, 0025), (120, -120);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk > "119";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75", "-26"}, {"0", "0"}, {"107", "25"}, {"108", "25"}},
			{{"-26", "-75"}, {"0", "0"}, {"25", "107"}, {"25", "108"}},
			{{"-52", "-74"}, {"0", "1"}, {"50", "108"}, {"50", "109"}},
		},
	},
	{
		Name: "SMALLINT",
		SetUpScript: []string{
			`CREATE TABLE test (pk SMALLINT PRIMARY KEY, v1 SMALLINT);`,
			`INSERT INTO test VALUES (-75.7, "-2531"), (-75, "-2531"), (0, 0), (2547.2, 03325), (2547.6, 03325), (9999, 9999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk >= "9999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-76", "-2532"}, {"-75", "-2532"}, {"0", "0"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"-2532", "-76"}, {"-2532", "-75"}, {"0", "0"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"-5064", "-75"}, {"-5064", "-74"}, {"0", "1"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "MEDIUMINT",
		SetUpScript: []string{
			`CREATE TABLE test (pk MEDIUMINT PRIMARY KEY, v1 MEDIUMINT);`,
			`INSERT INTO test VALUES (-75, "-2531"), (0, 0), (2547.2, 03325), (2547.7, 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75", "-2532"}, {"0", "0"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"-2532", "-75"}, {"0", "0"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"-5064", "-74"}, {"0", "1"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "INT",
		SetUpScript: []string{
			`CREATE TABLE test (pk INT PRIMARY KEY, v1 INT);`,
			`INSERT INTO test VALUES (-75, "-2531"), (0, 0), (2547.2, 03325), (2547.8, 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75", "-2532"}, {"0", "0"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"-2532", "-75"}, {"0", "0"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"-5064", "-74"}, {"0", "1"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "BIGINT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BIGINT);`,
			`INSERT INTO test VALUES (-75, "-2531"), (0, 0), (2547.2, 03325), (2547.9, 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75", "-2532"}, {"0", "0"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"-2532", "-75"}, {"0", "0"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"-5064", "-74"}, {"0", "1"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "TINYINT UNSIGNED",
		SetUpScript: []string{
			`CREATE TABLE test (pk TINYINT UNSIGNED PRIMARY KEY, v1 TINYINT UNSIGNED);`,
			`INSERT INTO test VALUES (0, 0), (25, "26"), (32.1, 0126), (42.8, 0126), (255, 255);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk > 0 AND pk < 30;`,
			`DELETE FROM test WHERE pk >= "255";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"0", "0"}, {"25", "25"}, {"32", "126"}, {"43", "126"}},
			{{"0", "0"}, {"25", "25"}, {"126", "32"}, {"126", "43"}},
			{{"0", "1"}, {"50", "26"}, {"252", "33"}, {"252", "44"}},
		},
	},
	{
		Name: "SMALLINT UNSIGNED",
		SetUpScript: []string{
			`CREATE TABLE test (pk SMALLINT UNSIGNED PRIMARY KEY, v1 SMALLINT UNSIGNED);`,
			`INSERT INTO test VALUES (0, 0), (25, "2531"), (2547.2, 03325), (2547.5, 03325), (9999, 9999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk > 0 AND pk < 100;`,
			`DELETE FROM test WHERE pk >= "9999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"0", "0"}, {"25", "2530"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"0", "0"}, {"2530", "25"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"0", "1"}, {"5060", "26"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "MEDIUMINT UNSIGNED",
		SetUpScript: []string{
			`CREATE TABLE test (pk MEDIUMINT UNSIGNED PRIMARY KEY, v1 MEDIUMINT UNSIGNED);`,
			`INSERT INTO test VALUES (75, "2531"), (0, 0), (2547.2, 03325), (2547.6, 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 + 1 WHERE pk < 100;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"0", "1"}, {"75", "2532"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"1", "0"}, {"2532", "75"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"2", "1"}, {"5064", "76"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "INT UNSIGNED",
		SetUpScript: []string{
			`CREATE TABLE test (pk INT UNSIGNED PRIMARY KEY, v1 INT UNSIGNED);`,
			`INSERT INTO test VALUES (75, "2531"), (0, 0), (2547.2, 03325), (2547.7, 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 + 1 WHERE pk < 100;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"0", "1"}, {"75", "2532"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"1", "0"}, {"2532", "75"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"2", "1"}, {"5064", "76"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "BIGINT UNSIGNED",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 BIGINT UNSIGNED);`,
			`INSERT INTO test VALUES (75, "2531"), (0, 0), (2547.2, 03325), (2547.8, 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 + 1 WHERE pk < 100;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"0", "1"}, {"75", "2532"}, {"2547", "3325"}, {"2548", "3325"}},
			{{"1", "0"}, {"2532", "75"}, {"3325", "2547"}, {"3325", "2548"}},
			{{"2", "1"}, {"5064", "76"}, {"6650", "2548"}, {"6650", "2549"}},
		},
	},
	{
		Name: "FLOAT",
		SetUpScript: []string{
			`CREATE TABLE test (pk FLOAT PRIMARY KEY, v1 FLOAT);`,
			`INSERT INTO test VALUES (-75.11, "-2531"), (0, 0), ("2547.2", 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75.11", "-2532"}, {"0", "0"}, {"2547.2", "3325"}},
			{{"-2532", "-75.11"}, {"0", "0"}, {"3325", "2547.2"}},
			{{"-5064", "-74.11000061035156"}, {"0", "1"}, {"6650", "2548.199951171875"}},
		},
	},
	{
		Name: "DOUBLE",
		SetUpScript: []string{
			`CREATE TABLE test (pk DOUBLE PRIMARY KEY, v1 DOUBLE);`,
			`INSERT INTO test VALUES (-75.11, "-2531"), (0, 0), ("2547.2", 03325), (999999, 999999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk > "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75.11", "-2532"}, {"0", "0"}, {"2547.2", "3325"}},
			{{"-2532", "-75.11"}, {"0", "0"}, {"3325", "2547.2"}},
			{{"-5064", "-74.11"}, {"0", "1"}, {"6650", "2548.2"}},
		},
	},
	{
		Name: "DECIMAL",
		SetUpScript: []string{
			`CREATE TABLE test (pk DECIMAL(5,0) PRIMARY KEY, v1 DECIMAL(25,5));`,
			`INSERT INTO test VALUES (-75, "-2531.356"), (0, 0), (2547.2, 03325), (99999, 999999);`,
			`UPDATE test SET v1 = v1 - 1 WHERE pk < 0;`,
			`DELETE FROM test WHERE pk >= "99999";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*2, pk+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-75", "-2532.35600"}, {"0", "0.00000"}, {"2547", "3325.00000"}},
			{{"-2532.35600", "-75"}, {"0.00000", "0"}, {"3325.00000", "2547"}},
			{{"-5064.71200", "-74"}, {"0.00000", "1"}, {"6650.00000", "2548"}},
		},
	},
	{
		Name: "BIT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIT(55) PRIMARY KEY, v1 BIT(1), v2 BIT(24));`,
			`INSERT INTO test VALUES (75, 0, "21"), (0, 0, 0), (2547.2, 1, 03325), (999999, 1, 999999);`,
			`UPDATE test SET v2 = v2 - 1 WHERE pk > 0 AND pk < 100;`,
			`DELETE FROM test WHERE pk > 99999;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v2, v1, pk FROM test ORDER BY pk;`,
			`SELECT v1*1, pk/10, v2+1 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"\x00\x00\x00\x00\x00\x00\x00", "\x00", "\x00\x00\x00"}, {"\x00\x00\x00\x00\x00\x00K", "\x00", "\x0020"}, {"\x00\x00\x00\x00\x00\t\xf3", "�", "\x00\xfd"}},
			{{"\x00\x00\x00", "\x00", "\x00\x00\x00\x00\x00\x00\x00"}, {"\x0020", "\x00", "\x00\x00\x00\x00\x00\x00K"}, {"\x00\xfd", "�", "\x00\x00\x00\x00\x00\t\xf3"}},
			{{"0", "0.0000", "1"}, {"0", "7.5000", "12849"}, {"1", "254.7000", "3326"}},
		},
	},
	{
		Name: "YEAR",
		SetUpScript: []string{
			`CREATE TABLE test (pk YEAR PRIMARY KEY, v1 YEAR);`,
			`INSERT INTO test VALUES (1901, 1901), (1950, "1950"), (1979.2, 01986), (2122, 2122);`,
			`UPDATE test SET v1 = v1 + 1 WHERE pk < 1975;`,
			`DELETE FROM test WHERE pk > "2100";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT v1+3, pk+2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1901", "1902"}, {"1950", "1951"}, {"1979", "1986"}},
			{{"1902", "1901"}, {"1951", "1950"}, {"1986", "1979"}},
			{{"1905", "1903"}, {"1954", "1952"}, {"1989", "1981"}},
		},
	},
	{
		Name: "TIMESTAMP",
		SetUpScript: []string{
			`CREATE TABLE test (pk TIMESTAMP PRIMARY KEY, v1 TIMESTAMP);`,
			`INSERT INTO test VALUES ("1980-04-12 12:02:11", "1986-08-02 17:04:22"), ("1999-11-28 13:06:33", "2022-01-14 15:08:44"), ("2020-05-06 18:10:55", "1975-09-15 11:12:16");`,
			`UPDATE test SET v1 = "2000-01-01 00:00:00" WHERE pk < "1990-01-01 00:00:00";`,
			`DELETE FROM test WHERE pk > "2015-01-01 00:00:00";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT DATE_ADD(TIMESTAMP('2022-10-26 13:14:15'), INTERVAL 1 DAY);`,
			`SELECT DATE_ADD('2022-10-26 13:14:15', INTERVAL 1 DAY);`,
			`SELECT DATE_ADD('2022-10-26', INTERVAL 1 SECOND);`,
			`SELECT DATE_ADD('2022-10-26', INTERVAL 1 MINUTE);`,
			`SELECT DATE_ADD('2022-10-26', INTERVAL 1 HOUR);`,
		},
		Results: [][]sql.Row{
			{{"1980-04-12 12:02:11", "2000-01-01 00:00:00"}, {"1999-11-28 13:06:33", "2022-01-14 15:08:44"}},
			{{"1980-04-12 12:02:11", "2000-01-01 00:00:00"}, {"1999-11-28 13:06:33", "2022-01-14 15:08:44"}},
			{{"2000-01-01 00:00:00", "1980-04-12 12:02:11"}, {"2022-01-14 15:08:44", "1999-11-28 13:06:33"}},
			{{"2022-10-27 13:14:15"}},
			{{"2022-10-27 13:14:15"}},
			{{"2022-10-26 00:00:01"}},
			{{"2022-10-26 00:01:00"}},
			{{"2022-10-26 01:00:00"}},
		},
	},
	{
		Name: "DATETIME",
		SetUpScript: []string{
			`CREATE TABLE test (pk DATETIME PRIMARY KEY, v1 DATETIME);`,
			`INSERT INTO test VALUES ("1000-04-12 12:02:11", "1986-08-02 17:04:22"), ("1999-11-28 13:06:33", "2022-01-14 15:08:44"), ("5020-05-06 18:10:55", "1975-09-15 11:12:16");`,
			`UPDATE test SET v1 = "2000-01-01 00:00:00" WHERE pk < "1990-01-01 00:00:00";`,
			`DELETE FROM test WHERE pk > "5000-01-01 00:00:00";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT DATE_ADD('2022-10-26 13:14:15', INTERVAL 1 DAY);`,
			`SELECT DATE_ADD('2022-10-26', INTERVAL 1 SECOND);`,
			`SELECT DATE_ADD('2022-10-26', INTERVAL 1 MINUTE);`,
			`SELECT DATE_ADD('2022-10-26', INTERVAL 1 HOUR);`,
		},
		Results: [][]sql.Row{
			{{"1000-04-12 12:02:11", "2000-01-01 00:00:00"}, {"1999-11-28 13:06:33", "2022-01-14 15:08:44"}},
			{{"1000-04-12 12:02:11", "2000-01-01 00:00:00"}, {"1999-11-28 13:06:33", "2022-01-14 15:08:44"}},
			{{"2000-01-01 00:00:00", "1000-04-12 12:02:11"}, {"2022-01-14 15:08:44", "1999-11-28 13:06:33"}},
			{{"2022-10-27 13:14:15"}},
			{{"2022-10-26 00:00:01"}},
			{{"2022-10-26 00:01:00"}},
			{{"2022-10-26 01:00:00"}},
		},
	},
	{
		Name: "DATE",
		SetUpScript: []string{
			`CREATE TABLE test (pk DATE PRIMARY KEY, v1 DATE);`,
			`INSERT INTO test VALUES ("1000-04-12", "1986-08-02"), ("1999-11-28", "2022-01-14"), ("5020-05-06", "1975-09-15");`,
			`UPDATE test SET v1 = "2000-01-01" WHERE pk < "1990-01-01";`,
			`DELETE FROM test WHERE pk > "5000-01-01";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT DATE_ADD(DATE('2022-10-26'), INTERVAL 1 DAY);`,
			`SELECT DATE_ADD(DATE('2022-10-26'), INTERVAL 1 WEEK);`,
			`SELECT DATE_ADD(DATE('2022-10-26'), INTERVAL 1 MONTH);`,
			`SELECT DATE_ADD(DATE('2022-10-26'), INTERVAL 1 QUARTER);`,
			`SELECT DATE_ADD(DATE('2022-10-26'), INTERVAL 1 YEAR);`,
		},
		Results: [][]sql.Row{
			{{"1000-04-12", "2000-01-01"}, {"1999-11-28", "2022-01-14"}},
			{{"1000-04-12", "2000-01-01"}, {"1999-11-28", "2022-01-14"}},
			{{"2000-01-01", "1000-04-12"}, {"2022-01-14", "1999-11-28"}},
			{{"2022-10-27"}},
			{{"2022-11-02"}},
			{{"2022-11-26"}},
			{{"2023-01-26"}},
			{{"2023-10-26"}},
		},
	},
	{
		Name: "TIME",
		SetUpScript: []string{
			`CREATE TABLE test (pk TIME PRIMARY KEY, v1 TIME);`,
			`INSERT INTO test VALUES ("-800:00:00", "-20:21:22"), ("00:00:00", "00:00:00"), ("10:26:57", "30:53:14"), ("700:23:51", "300:25:52");`,
			`UPDATE test SET v1 =  "-120:12:20" WHERE pk < "00:00:00";`,
			`DELETE FROM test WHERE pk > "600:00:00";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"-800:00:00", "-120:12:20"}, {"00:00:00", "00:00:00"}, {"10:26:57", "30:53:14"}},
			{{"-800:00:00", "-120:12:20"}, {"00:00:00", "00:00:00"}, {"10:26:57", "30:53:14"}},
			{{"-120:12:20", "-800:00:00"}, {"00:00:00", "00:00:00"}, {"30:53:14", "10:26:57"}},
		},
	},
	{
		Name: "CHAR",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 CHAR(5), v2 CHAR(10));`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = "a-c" WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "a-c", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "a-c"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"a-cr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "VARCHAR",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 VARCHAR(5), v2 VARCHAR(10));`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
			`SELECT DATE_ADD('2022-10-26 13:14:15', INTERVAL 1 DAY);`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
			{{"2022-10-27 13:14:15"}},
		},
	},
	{
		Name: "BINARY",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BINARY(5), v2 BINARY(10));`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = "a-c" WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc\x00\x00", "def\x00\x00\x00\x00\x00\x00\x00"}, {"2", "a-c\x00\x00", "123\x00\x00\x00\x00\x00\x00\x00"}, {"3", "__2\x00\x00", "456\x00\x00\x00\x00\x00\x00\x00"}},
			{{"1", "def\x00\x00\x00\x00\x00\x00\x00", "abc\x00\x00"}, {"2", "123\x00\x00\x00\x00\x00\x00\x00", "a-c\x00\x00"}, {"3", "456\x00\x00\x00\x00\x00\x00\x00", "__2\x00\x00"}},
			{{"abc\x00\x00r", "1", "def\x00\x00\x00\x00\x00\x00\x00"}, {"a-c\x00\x00r", "2", "123\x00\x00\x00\x00\x00\x00\x00"}, {"__2\x00\x00r", "3", "456\x00\x00\x00\x00\x00\x00\x00"}},
		},
	},
	{
		Name: "VARBINARY",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 VARBINARY(5), v2 VARBINARY(10));`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "TINYTEXT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 TINYTEXT, v2 TINYTEXT);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "TEXT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 TEXT, v2 TEXT);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "MEDIUMTEXT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 MEDIUMTEXT, v2 MEDIUMTEXT);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "LONGTEXT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 LONGTEXT, v2 LONGTEXT);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "TINYBLOB",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 TINYBLOB, v2 TINYBLOB);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "BLOB",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 BLOB, v2 BLOB);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "MEDIUMBLOB",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 MEDIUMBLOB, v2 MEDIUMBLOB);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "LONGBLOB",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 LONGBLOB, v2 LONGBLOB);`,
			`INSERT INTO test VALUES (1, "abc", "def"), (2, "c-a", "123"), (3, "__2", 456), (4, "?hi?", "\\n");`,
			`UPDATE test SET v1 = CONCAT(v1, "x") WHERE pk = 2;`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v2, v1 FROM test ORDER BY pk;`,
			`SELECT CONCAT(v1, "r"), pk, v2 FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "abc", "def"}, {"2", "c-ax", "123"}, {"3", "__2", "456"}},
			{{"1", "def", "abc"}, {"2", "123", "c-ax"}, {"3", "456", "__2"}},
			{{"abcr", "1", "def"}, {"c-axr", "2", "123"}, {"__2r", "3", "456"}},
		},
	},
	{
		Name: "ENUM",
		SetUpScript: []string{
			`CREATE TABLE test (pk ENUM("a","b","c") PRIMARY KEY, v1 ENUM("x","y","z"));`,
			`INSERT INTO test VALUES (1, 1), ("b", "y"), (3, "z");`,
			`UPDATE test SET v1 = "x" WHERE pk = 2;`,
			`DELETE FROM test WHERE pk > 2;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"a", "x"}, {"b", "x"}},
			{{"a", "x"}, {"b", "x"}},
			{{"x", "a"}, {"x", "b"}},
		},
	},
	{
		Name: "SET",
		SetUpScript: []string{
			`CREATE TABLE test (pk SET("a","b","c") PRIMARY KEY, v1 SET("w","x","y","z"));`,
			`INSERT INTO test VALUES (0, 1), ("b", "y"), ("b,c", "z,z"), ("a,c,b", 10);`,
			`UPDATE test SET v1 = "y,x,w" WHERE pk >= 4`,
			`DELETE FROM test WHERE pk > "b,c";`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"", "w"}, {"b", "y"}, {"b,c", "w,x,y"}},
			{{"", "w"}, {"b", "y"}, {"b,c", "w,x,y"}},
			{{"w", ""}, {"y", "b"}, {"w,x,y", "b,c"}},
		},
	},
	{
		Name: "GEOMETRY",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 GEOMETRY);`,
			`INSERT INTO test VALUES (1, POINT(1, 2)), (2, LINESTRING(POINT(1, 2), POINT(3, 4))), (3, ST_GeomFromText('POLYGON((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))'));`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT pk, ST_ASWKT(v1) FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40})},
				{"2", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40})},
				{"3", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F})},
			},
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40})},
				{"2", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40})},
				{"3", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F})},
			},
			{
				{"1", "POINT(1 2)"},
				{"2", "LINESTRING(1 2,3 4)"},
				{"3", "POLYGON((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))"},
			},
		},
	},
	{
		Name: "POINT",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 POINT);`,
			`INSERT INTO test VALUES (1, POINT(1, 2)), (2, POINT(3.4, 5.6)), (3, POINT(10, -20)), (4, POINT(1000, -1000));`,
			`DELETE FROM test WHERE pk = 4;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT pk, ST_ASWKT(v1) FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40})},
				{"2", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x0B, 0x40, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x16, 0x40})},
				{"3", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC0})},
			},
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40})},
				{"2", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x0B, 0x40, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x16, 0x40})},
				{"3", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC0})},
			},
			{
				{"1", "POINT(1 2)"},
				{"2", "POINT(3.4 5.6)"},
				{"3", "POINT(10 -20)"},
			},
		},
	},
	{
		Name: "LINESTRING",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 LINESTRING);`,
			`INSERT INTO test VALUES (1, LINESTRING(POINT(1, 2), POINT(3, 4))), (2, LINESTRING(POINT(5, 6), POINT(7, 8)));`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT pk, ST_ASWKT(v1) FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40})},
				{"2", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40})},
			},
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40})},
				{"2", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40})},
			},
			{
				{"1", "LINESTRING(1 2,3 4)"},
				{"2", "LINESTRING(5 6,7 8)"},
			},
		},
	},
	{
		Name: "POLYGON",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 POLYGON);`,
			`INSERT INTO test VALUES (1, ST_GeomFromText('POLYGON((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))'));`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT pk, v1 FROM test ORDER BY pk;`,
			`SELECT pk, ST_ASWKT(v1) FROM test ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F})},
			},
			{
				{"1", string([]byte{0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F})},
			},
			{
				{"1", "POLYGON((0 0,0 3,3 0,0 0),(1 1,1 2,2 1,1 1))"},
			},
		},
	},
	{
		Name: "JSON",
		SetUpScript: []string{
			`CREATE TABLE test (pk BIGINT PRIMARY KEY, v1 JSON);`,
			`INSERT INTO test VALUES (1, '{"key1": {"key": "value"}}'), (2, '{"key1": "value1", "key2": "value2"}'), (3, '{"key1": {"key": [2,3]}}');`,
			`UPDATE test SET v1 = '["a", 1]' WHERE pk = 1;`,
			`DELETE FROM test WHERE pk = 3;`,
		},
		Queries: []string{
			`SELECT * FROM test ORDER BY pk;`,
			`SELECT v1, pk FROM test ORDER BY pk;`,
			`SELECT pk, JSON_ARRAYAGG(v1) FROM (SELECT * FROM test ORDER BY pk) as sub GROUP BY v1 ORDER BY pk;`,
		},
		Results: [][]sql.Row{
			{{"1", "[\"a\",1]"}, {"2", "{\"key1\":\"value1\",\"key2\":\"value2\"}"}},
			{{"[\"a\",1]", "1"}, {"{\"key1\":\"value1\",\"key2\":\"value2\"}", "2"}},
			{{"1", "[[\"a\",1]]"}, {"2", "[{\"key1\":\"value1\",\"key2\":\"value2\"}]"}},
		},
	},
}

TypeWireTests are used to ensure that types are properly represented over the wire (vs being directly returned from the engine).

View Source
var UpdateErrorScripts = []ScriptTest{
	{
		Name: "try updating string that is too long",
		SetUpScript: []string{
			"create table bad (s varchar(9))",
			"insert into bad values ('good')",
		},
		Query:       "update bad set s = '1234567890'",
		ExpectedErr: types.ErrLengthBeyondLimit,
	},
}
View Source
var UpdateErrorTests = []QueryErrorTest{
	{
		Query:       `UPDATE keyless INNER JOIN one_pk on keyless.c0 = one_pk.pk SET keyless.c0 = keyless.c0 + 1`,
		ExpectedErr: sql.ErrUnsupportedFeature,
	},
	{
		Query:       `UPDATE people set height_inches = null where height_inches < 100`,
		ExpectedErr: sql.ErrInsertIntoNonNullableProvidedNull,
	},
}
View Source
var UpdateIgnoreScripts = []ScriptTest{
	{
		Name: "UPDATE IGNORE with primary keys and indexes",
		SetUpScript: []string{
			"CREATE TABLE pkTable(pk int, val int, primary key(pk, val))",
			"CREATE TABLE idxTable(pk int primary key, val int UNIQUE)",
			"INSERT INTO pkTable VALUES (1, 1), (2, 2), (3, 3)",
			"INSERT INTO idxTable VALUES (1, 1), (2, 2), (3, 3)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:           "UPDATE IGNORE pkTable set pk = pk + 1, val = val + 1",
				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query:    "SELECT * FROM pkTable order by pk",
				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 4}},
			},
			{
				Query:           "UPDATE IGNORE idxTable set val = val + 1",
				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query:    "SELECT * FROM idxTable order by pk",
				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 4}},
			},
			{
				Query:    "UPDATE IGNORE pkTable set val = val + 1 where pk = 2",
				Expected: []sql.Row{{newUpdateResult(1, 1)}},
			},
			{
				Query:    "SELECT * FROM pkTable order by pk",
				Expected: []sql.Row{{1, 1}, {2, 3}, {4, 4}},
			},
			{
				Query:           "UPDATE IGNORE pkTable SET pk = NULL",
				Expected:        []sql.Row{{newUpdateResult(3, 3)}},
				ExpectedWarning: mysql.ERBadNullError,
			},
			{
				Query:    "SELECT * FROM pkTable order by pk",
				Expected: []sql.Row{{0, 1}, {0, 3}, {0, 4}},
			},
			{
				Query:    "UPDATE IGNORE pkTable SET val = NULL",
				Expected: []sql.Row{{newUpdateResult(3, 1)}},
			},
			{
				Query:    "SELECT * FROM pkTable order by pk",
				Expected: []sql.Row{{0, 0}, {0, 3}, {0, 4}},
			},
			{
				Query:           "UPDATE IGNORE idxTable set pk = pk + 1, val = val + 1",
				Expected:        []sql.Row{{newUpdateResult(3, 1)}},
				ExpectedWarning: mysql.ERDupEntry,
			},
			{
				Query:    "SELECT * FROM idxTable order by pk",
				Expected: []sql.Row{{1, 1}, {2, 2}, {4, 5}},
			},
		},
	},
	{
		Name: "UPDATE IGNORE with type conversions",
		SetUpScript: []string{
			"CREATE TABLE t1 (pk int primary key, v1 int, v2 int)",
			"INSERT INTO t1 VALUES (1, 1, 1)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:           "UPDATE IGNORE t1 SET v1 = 'dsddads'",
				Expected:        []sql.Row{{newUpdateResult(1, 1)}},
				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
			},
			{
				Query:    "SELECT * FROM t1",
				Expected: []sql.Row{{1, 0, 1}},
			},
			{
				Query:           "UPDATE IGNORE t1 SET pk = 'dasda', v2 = 'dsddads'",
				Expected:        []sql.Row{{newUpdateResult(1, 1)}},
				ExpectedWarning: mysql.ERTruncatedWrongValueForField,
			},
			{
				Query:    "SELECT * FROM t1",
				Expected: []sql.Row{{0, 0, 0}},
			},
		},
	},
	{
		Name: "UPDATE IGNORE with foreign keys",
		SetUpScript: []string{
			"CREATE TABLE colors ( id INT NOT NULL, color VARCHAR(32) NOT NULL, PRIMARY KEY (id), INDEX color_index(color));",
			"CREATE TABLE objects (id INT NOT NULL, name VARCHAR(64) NOT NULL,color VARCHAR(32), PRIMARY KEY(id),FOREIGN KEY (color) REFERENCES colors(color))",
			"INSERT INTO colors (id,color) VALUES (1,'red'),(2,'green'),(3,'blue'),(4,'purple')",
			"INSERT INTO objects (id,name,color) VALUES (1,'truck','red'),(2,'ball','green'),(3,'shoe','blue')",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:           "UPDATE IGNORE objects SET color = 'orange' where id = 2",
				Expected:        []sql.Row{{newUpdateResult(1, 0)}},
				ExpectedWarning: mysql.ErNoReferencedRow2,
			},
			{
				Query:    "SELECT * FROM objects ORDER BY id",
				Expected: []sql.Row{{1, "truck", "red"}, {2, "ball", "green"}, {3, "shoe", "blue"}},
			},
		},
	},
	{
		Name: "UPDATE IGNORE with check constraints",
		SetUpScript: []string{
			"CREATE TABLE checksTable(pk int primary key)",
			"ALTER TABLE checksTable ADD CONSTRAINT mycx CHECK (pk < 5)",
			"INSERT INTO checksTable VALUES (1),(2),(3),(4)",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:           "UPDATE IGNORE checksTable SET pk = pk + 1 where pk = 4",
				Expected:        []sql.Row{{newUpdateResult(1, 0)}},
				ExpectedWarning: mysql.ERUnknownError,
			},
			{
				Query:    "SELECT * from checksTable ORDER BY pk",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
		},
	},
}
View Source
var UpdateIgnoreTests = []WriteQueryTest{
	{
		WriteQuery:          "UPDATE IGNORE mytable SET i = 2 where i = 1",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}},
		SelectQuery:         "SELECT * FROM mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "first row"),
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
		},
	},
	{
		WriteQuery:          "UPDATE IGNORE mytable SET i = i+1 where i = 1",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}},
		SelectQuery:         "SELECT * FROM mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "first row"),
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
		},
	},
}
View Source
var UpdateTests = []WriteQueryTest{
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated';",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET S = 'updated';",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated' WHERE i > 9999;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated' WHERE i = 1;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated' WHERE i <> 9999;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
	},
	{
		WriteQuery:          "UPDATE floattable SET f32 = f32 + f32, f64 = f32 * f64 WHERE i = 2;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM floattable WHERE i = 2;",
		ExpectedSelect:      []sql.Row{{int64(2), float32(3.0), float64(4.5)}},
	},
	{
		WriteQuery:          "UPDATE floattable SET f32 = 5, f32 = 4 WHERE i = 1;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT f32 FROM floattable WHERE i = 1;",
		ExpectedSelect:      []sql.Row{{float32(4.0)}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'first row' WHERE i = 1;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 0)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "UPDATE niltable SET b = NULL WHERE f IS NULL;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 2)}},
		SelectQuery:         "SELECT i,b FROM niltable WHERE f IS NULL;",
		ExpectedSelect:      []sql.Row{{int64(1), nil}, {int64(2), nil}, {int64(3), nil}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated' ORDER BY i ASC LIMIT 2;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated' ORDER BY i DESC LIMIT 2;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "updated"}, {int64(3), "updated"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated' ORDER BY i LIMIT 1 OFFSET 1;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "updated"}, {int64(3), "third row"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = 'updated';",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "updated"}, {int64(2), "updated"}, {int64(3), "updated"}},
	},
	{
		WriteQuery:          "UPDATE mytable SET s = _binary 'updated' WHERE i = 3;",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM mytable;",
		ExpectedSelect:      []sql.Row{{int64(1), "first row"}, {int64(2), "second row"}, {int64(3), "updated"}},
	},
	{
		WriteQuery:          "UPDATE typestable SET ti = '2020-03-06 00:00:00';",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM typestable;",
		ExpectedSelect: []sql.Row{{
			int64(1),
			int8(2),
			int16(3),
			int32(4),
			int64(5),
			uint8(6),
			uint16(7),
			uint32(8),
			uint64(9),
			float32(10),
			float64(11),
			sql.MustConvert(types.Timestamp.Convert("2020-03-06 00:00:00")),
			sql.MustConvert(types.Date.Convert("2019-12-31")),
			"fourteen",
			0,
			nil,
			nil,
			uint64(1),
			uint64(0)}},
	},
	{
		WriteQuery:          "UPDATE typestable SET ti = '2020-03-06 00:00:00', da = '2020-03-06';",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM typestable;",
		ExpectedSelect: []sql.Row{{
			int64(1),
			int8(2),
			int16(3),
			int32(4),
			int64(5),
			uint8(6),
			uint16(7),
			uint32(8),
			uint64(9),
			float32(10),
			float64(11),
			sql.MustConvert(types.Timestamp.Convert("2020-03-06 00:00:00")),
			sql.MustConvert(types.Date.Convert("2020-03-06")),
			"fourteen",
			0,
			nil,
			nil,
			uint64(1),
			uint64(0)}},
	},
	{
		WriteQuery:          "UPDATE typestable SET da = '0000-00-00', ti = '0000-00-00 00:00:00';",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM typestable;",
		ExpectedSelect: []sql.Row{{
			int64(1),
			int8(2),
			int16(3),
			int32(4),
			int64(5),
			uint8(6),
			uint16(7),
			uint32(8),
			uint64(9),
			float32(10),
			float64(11),
			types.Timestamp.Zero(),
			types.Date.Zero(),
			"fourteen",
			0,
			nil,
			nil,
			uint64(1),
			uint64(0)}},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET two_pk.c1 = two_pk.c1 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(4, 4)}},
		SelectQuery:         "SELECT * FROM two_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 1, 1, 2, 3, 4),
			sql.NewRow(0, 1, 11, 11, 12, 13, 14),
			sql.NewRow(1, 0, 21, 21, 22, 23, 24),
			sql.NewRow(1, 1, 31, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          "UPDATE mytable INNER JOIN one_pk ON mytable.i = one_pk.c5 SET mytable.i = mytable.i * 10",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
		SelectQuery:         "SELECT * FROM mytable",
		ExpectedSelect: []sql.Row{
			sql.NewRow(int64(1), "first row"),
			sql.NewRow(int64(2), "second row"),
			sql.NewRow(int64(3), "third row"),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET two_pk.c1 = two_pk.c1 + 1 WHERE one_pk.c5 < 10`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM two_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 1, 1, 2, 3, 4),
			sql.NewRow(0, 1, 11, 11, 12, 13, 14),
			sql.NewRow(1, 0, 20, 21, 22, 23, 24),
			sql.NewRow(1, 1, 30, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN othertable on othertable.i2 = two_pk.pk2 SET one_pk.c1 = one_pk.c1 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM one_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 1, 1, 2, 3, 4),
			sql.NewRow(1, 11, 11, 12, 13, 14),
			sql.NewRow(2, 20, 21, 22, 23, 24),
			sql.NewRow(3, 30, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN (SELECT * FROM two_pk order by pk1, pk2) as t2 on one_pk.pk = t2.pk1 SET one_pk.c1 = t2.c1 + 1 where one_pk.pk < 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM one_pk where pk < 1",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 1, 1, 2, 3, 4),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM one_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 1, 1, 2, 3, 4),
			sql.NewRow(1, 11, 11, 12, 13, 14),
			sql.NewRow(2, 20, 21, 22, 23, 24),
			sql.NewRow(3, 30, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, one_pk.c2 = one_pk.c2 + 1 ORDER BY one_pk.pk`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM one_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 1, 2, 2, 3, 4),
			sql.NewRow(1, 11, 12, 12, 13, 14),
			sql.NewRow(2, 20, 21, 22, 23, 24),
			sql.NewRow(3, 30, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 SET one_pk.c1 = one_pk.c1 + 1, two_pk.c1 = two_pk.c2 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(8, 6)}},
		SelectQuery:         "SELECT * FROM two_pk;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 2, 1, 2, 3, 4),
			sql.NewRow(0, 1, 12, 11, 12, 13, 14),
			sql.NewRow(1, 0, 22, 21, 22, 23, 24),
			sql.NewRow(1, 1, 32, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `update mytable h join mytable on h.i = mytable.i and h.s <> mytable.s set h.i = mytable.i;`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
	},
	{
		WriteQuery:          `UPDATE othertable CROSS JOIN tabletest set othertable.i2 = othertable.i2 * 10`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM othertable order by i2",
		ExpectedSelect: []sql.Row{
			sql.NewRow("third", 10),
			sql.NewRow("second", 20),
			sql.NewRow("first", 30),
		},
	},
	{
		WriteQuery:          `UPDATE tabletest cross join tabletest as t2 set tabletest.i = tabletest.i * 10`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM tabletest order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(10, "first row"),
			sql.NewRow(20, "second row"),
			sql.NewRow(30, "third row"),
		},
	},
	{
		WriteQuery:          `UPDATE othertable cross join tabletest set tabletest.i = tabletest.i * 10`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM tabletest order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(10, "first row"),
			sql.NewRow(20, "second row"),
			sql.NewRow(30, "third row"),
		},
	},
	{
		WriteQuery:          `UPDATE one_pk INNER JOIN two_pk on one_pk.pk = two_pk.pk1 INNER JOIN two_pk a1 on one_pk.pk = two_pk.pk2 SET two_pk.c1 = two_pk.c1 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "SELECT * FROM two_pk order by pk1 ASC, pk2 ASC;",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 1, 1, 2, 3, 4),
			sql.NewRow(0, 1, 10, 11, 12, 13, 14),
			sql.NewRow(1, 0, 20, 21, 22, 23, 24),
			sql.NewRow(1, 1, 31, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE othertable INNER JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM othertable order by i2",
		ExpectedSelect: []sql.Row{
			sql.NewRow("third", 1),
			sql.NewRow("second", 2),
			sql.NewRow("fourth", 3),
		},
	},
	{
		WriteQuery:          `UPDATE tabletest cross join tabletest as t2 set t2.i = t2.i * 10`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM tabletest order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(10, "first row"),
			sql.NewRow(20, "second row"),
			sql.NewRow(30, "third row"),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM othertable order by i2",
		ExpectedSelect: []sql.Row{
			sql.NewRow("fourth", 1),
			sql.NewRow("fourth", 2),
			sql.NewRow("fourth", 3),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET tabletest.s = 'fourth row', tabletest.i = tabletest.i + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM tabletest order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "first row"),
			sql.NewRow(2, "second row"),
			sql.NewRow(4, "fourth row"),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest t3 on othertable.i2=3 and t3.i=3 SET t3.s = 'fourth row', t3.i = t3.i + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM tabletest order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "first row"),
			sql.NewRow(2, "second row"),
			sql.NewRow(4, "fourth row"),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = one_pk.pk SET one_pk.c1 = one_pk.c1 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(3, 3)}},
		SelectQuery:         "SELECT * FROM one_pk order by pk",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 1, 2, 3, 4),
			sql.NewRow(1, 11, 11, 12, 13, 14),
			sql.NewRow(2, 21, 21, 22, 23, 24),
			sql.NewRow(3, 31, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = one_pk.pk SET one_pk.c1 = one_pk.c1 + 1 where one_pk.pk > 4`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(0, 0)}},
		SelectQuery:         "SELECT * FROM one_pk order by pk",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 1, 2, 3, 4),
			sql.NewRow(1, 10, 11, 12, 13, 14),
			sql.NewRow(2, 20, 21, 22, 23, 24),
			sql.NewRow(3, 30, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=3 and tabletest.i=3 LEFT JOIN one_pk on othertable.i2 = 1 and one_pk.pk = 1 SET one_pk.c1 = one_pk.c1 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM one_pk order by pk",
		ExpectedSelect: []sql.Row{
			sql.NewRow(0, 0, 1, 2, 3, 4),
			sql.NewRow(1, 11, 11, 12, 13, 14),
			sql.NewRow(2, 20, 21, 22, 23, 24),
			sql.NewRow(3, 30, 31, 32, 33, 34),
		},
	},
	{
		WriteQuery:          `UPDATE othertable RIGHT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.s2 = 'fourth'`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM othertable order by i2",
		ExpectedSelect: []sql.Row{
			sql.NewRow("third", 1),
			sql.NewRow("second", 2),
			sql.NewRow("fourth", 3),
		},
	},
	{
		WriteQuery:          `UPDATE othertable RIGHT JOIN tabletest on othertable.i2=3 and tabletest.i=3 SET othertable.i2 = othertable.i2 + 1`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM othertable order by i2",
		ExpectedSelect: []sql.Row{
			sql.NewRow("third", 1),
			sql.NewRow("second", 2),
			sql.NewRow("first", 4),
		},
	},
	{
		WriteQuery:          `UPDATE othertable LEFT JOIN tabletest on othertable.i2=tabletest.i RIGHT JOIN one_pk on othertable.i2 = 1 and one_pk.pk = 1 SET tabletest.s = 'updated';`,
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "SELECT * FROM tabletest order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "updated"),
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
		},
	},
	{
		WriteQuery:          "with t (n) as (select (1) from dual) UPDATE mytable set s = concat('updated ', i) where i in (select n from t)",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(1, 1)}},
		SelectQuery:         "select * from mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "updated 1"),
			sql.NewRow(2, "second row"),
			sql.NewRow(3, "third row"),
		},
	},
	{
		WriteQuery:          "with recursive t (n) as (select (1) from dual union all select n + 1 from t where n < 2) UPDATE mytable set s = concat('updated ', i) where i in (select n from t)",
		ExpectedWriteResult: []sql.Row{{newUpdateResult(2, 2)}},
		SelectQuery:         "select * from mytable order by i",
		ExpectedSelect: []sql.Row{
			sql.NewRow(1, "updated 1"),
			sql.NewRow(2, "updated 2"),
			sql.NewRow(3, "third row"),
		},
	},
}
View Source
var UserPrivTests = []UserPrivilegeTest{
	{
		Name: "Binlog replication privileges",
		SetUpScript: []string{
			"CREATE USER user@localhost;",
			"CREATE USER 'replica-admin'@localhost;",
			"CREATE USER 'replica-client'@localhost;",
			"CREATE USER 'replica-reload'@localhost;",

			"GRANT REPLICATION_SLAVE_ADMIN ON *.* TO 'replica-admin'@localhost;",

			"GRANT REPLICATION CLIENT ON *.* to 'replica-client'@localhost;",

			"GRANT RELOAD ON *.* TO 'replica-reload'@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{

			{
				User:        "user",
				Host:        "localhost",
				Query:       "START REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{

				User:        "replica-admin",
				Host:        "localhost",
				Query:       "START REPLICA",
				ExpectedErr: plan.ErrNoReplicationController,
			},
			{
				User:        "replica-client",
				Host:        "localhost",
				Query:       "START REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-reload",
				Host:        "localhost",
				Query:       "START REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "START REPLICA",
				ExpectedErr: plan.ErrNoReplicationController,
			},

			{
				User:        "user",
				Host:        "localhost",
				Query:       "STOP REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{

				User:        "replica-admin",
				Host:        "localhost",
				Query:       "STOP REPLICA",
				ExpectedErr: plan.ErrNoReplicationController,
			},
			{
				User:        "replica-client",
				Host:        "localhost",
				Query:       "STOP REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-reload",
				Host:        "localhost",
				Query:       "STOP REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "STOP REPLICA",
				ExpectedErr: plan.ErrNoReplicationController,
			},

			{
				User:        "user",
				Host:        "localhost",
				Query:       "RESET REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-admin",
				Host:        "localhost",
				Query:       "RESET REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-client",
				Host:        "localhost",
				Query:       "RESET REPLICA",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{

				User:        "replica-reload",
				Host:        "localhost",
				Query:       "RESET REPLICA",
				ExpectedErr: plan.ErrNoReplicationController,
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "RESET REPLICA",
				ExpectedErr: plan.ErrNoReplicationController,
			},

			{
				User:        "user",
				Host:        "localhost",
				Query:       "SHOW REPLICA STATUS;",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-admin",
				Host:        "localhost",
				Query:       "SHOW REPLICA STATUS;",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:     "replica-client",
				Host:     "localhost",
				Query:    "SHOW REPLICA STATUS;",
				Expected: []sql.Row{},
			},
			{
				User:        "replica-reload",
				Host:        "localhost",
				Query:       "SHOW REPLICA STATUS;",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SHOW REPLICA STATUS;",
				Expected: []sql.Row{},
			},

			{
				User:        "user",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{

				User:        "replica-admin",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
				ExpectedErr: plan.ErrNoReplicationController,
			},
			{
				User:        "replica-client",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-reload",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost';",
				ExpectedErr: plan.ErrNoReplicationController,
			},

			{
				User:        "user",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{

				User:        "replica-admin",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
				ExpectedErr: plan.ErrNoReplicationController,
			},
			{
				User:        "replica-client",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "replica-reload",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE=(db01.t1);",
				ExpectedErr: plan.ErrNoReplicationController,
			},
		},
	},
	{
		Name: "Basic database and table name visibility",
		SetUpScript: []string{
			"CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO mydb.test VALUES (1);",
			"CREATE USER tester@localhost;",
			"CREATE ROLE test_role;",
			"GRANT SELECT ON mydb.* TO test_role;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test;/*1*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*1*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON *.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM mydb.test;/*2*/",
				Expected: []sql.Row{{1}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*2*/",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE SELECT ON *.* FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test;/*3*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*3*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mydb.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM mydb.test;/*4*/",
				Expected: []sql.Row{{1}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*4*/",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE SELECT ON mydb.* FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test;/*5*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*5*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mydb.test TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM mydb.test;/*6*/",
				Expected: []sql.Row{{1}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*6*/",
				ExpectedErr: sql.ErrTableAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE SELECT ON mydb.test FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test;/*7*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*7*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mydb.test2 TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test;/*8*/",
				ExpectedErr: sql.ErrTableAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*8*/",
				ExpectedErr: sql.ErrTableNotFound,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE SELECT ON mydb.test2 FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test;/*9*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*9*/",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT test_role TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM mydb.test;/*10*/",
				Expected: []sql.Row{{1}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;/*10*/",
				ExpectedErr: sql.ErrTableNotFound,
			},
		},
	},
	{
		Name: "Basic user creation",
		SetUpScript: []string{
			"CREATE USER testuser@`127.0.0.1`;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				Query:       "CREATE USER testuser@`127.0.0.1`;",
				ExpectedErr: sql.ErrUserCreationFailure,
			},
			{
				Query:    "CREATE USER IF NOT EXISTS testuser@`127.0.0.1`;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				Query:    "INSERT INTO mysql.user (Host, User) VALUES ('localhost', 'testuser2');",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				Query: "SELECT * FROM mysql.user WHERE User = 'root';",
				Expected: []sql.Row{
					{
						"localhost",
						"root",
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(2),
						uint16(1),
						[]byte(""),
						[]byte(""),
						[]byte(""),
						uint32(0),
						uint32(0),
						uint32(0),
						uint32(0),
						"mysql_native_password",
						"",
						uint16(1),
						time.Unix(1, 0).UTC(),
						nil,
						uint16(1),
						uint16(2),
						uint16(2),
						nil,
						nil,
						nil,
						nil,
						"",
					},
				},
			},
			{
				Query: "SELECT Host, User FROM mysql.user;",
				Expected: []sql.Row{
					{"localhost", "root"},
					{"localhost", "testuser2"},
					{"127.0.0.1", "testuser"},
				},
			},
		},
	},
	{
		Name: "Dynamic privilege support",
		SetUpScript: []string{
			"CREATE USER testuser@localhost;",
			"GRANT REPLICATION_SLAVE_ADMIN ON *.* TO testuser@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				Query: "SELECT user, host from mysql.user",
				Expected: []sql.Row{
					{"root", "localhost"},
					{"testuser", "localhost"},
				},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR testuser@localhost;",
				Expected: []sql.Row{
					{"GRANT USAGE ON *.* TO `testuser`@`localhost`"},
					{"GRANT REPLICATION_SLAVE_ADMIN ON *.* TO `testuser`@`localhost`"},
				},
			},
			{

				User:        "root",
				Host:        "localhost",
				Query:       "GRANT REPLICATION_SLAVE_ADMIN ON mydb.* TO 'testuser'@'localhost';",
				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
			},
			{

				User:        "root",
				Host:        "localhost",
				Query:       "GRANT REPLICATION_SLAVE_ADMIN ON mydb.mytable TO 'testuser'@'localhost';",
				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
			},
			{

				User:        "root",
				Host:        "localhost",
				Query:       "REVOKE REPLICATION_SLAVE_ADMIN ON mydb.* FROM 'testuser'@'localhost';",
				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
			},
			{

				User:        "root",
				Host:        "localhost",
				Query:       "REVOKE REPLICATION_SLAVE_ADMIN ON mydb.mytable FROM 'testuser'@'localhost';",
				ExpectedErr: sql.ErrGrantRevokeIllegalPrivilegeWithMessage,
			},
		},
	},
	{
		Name: "user creation no host",
		SetUpScript: []string{
			"CREATE USER testuser;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				Query: "SELECT user, host from mysql.user",
				Expected: []sql.Row{
					{"root", "localhost"},
					{"testuser", "%"},
				},
			},
		},
	},
	{
		Name: "grants at various scopes no host",
		SetUpScript: []string{
			"CREATE USER tester;",
			"GRANT SELECT ON *.* to tester",
			"GRANT SELECT ON db.* to tester",
			"GRANT SELECT ON db.tbl to tester",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT ON *.* TO `tester`@`%`"},
					{"GRANT SELECT ON `db`.* TO `tester`@`%`"},
					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`%`"},
				},
			},
		},
	},
	{
		Name: "Valid users without privileges may use the dual table",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT 1+2;",
				Expected: []sql.Row{{3}},
			},
			{
				User:           "noexist",
				Host:           "localhost",
				Query:          "SELECT 1+2;",
				ExpectedErrStr: "Access denied for user 'noexist' (errno 1045) (sqlstate 28000)",
			},
		},
	},
	{
		Name: "Basic SELECT and INSERT privilege checking",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "INSERT INTO test VALUES (4);",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT INSERT ON *.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "INSERT INTO test VALUES (4);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM test;",
				ExpectedErr: sql.ErrPrivilegeCheckFailed,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON *.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
		},
	},
	{
		Name: "Database-level privileges exist",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT, UPDATE, EXECUTE ON mydb.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.db;",
				Expected: []sql.Row{{"localhost", "mydb", "tester", uint16(2), uint16(1), uint16(2), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(2), uint16(1), uint16(1)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE UPDATE ON mydb.* FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.db;",
				Expected: []sql.Row{{"localhost", "mydb", "tester", uint16(2), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(2), uint16(1), uint16(1)}},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "UPDATE mysql.db SET Insert_priv = 'Y' WHERE User = 'tester';",
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 1,
					InsertID:     0,
					Info: plan.UpdateInfo{
						Matched:  1,
						Updated:  1,
						Warnings: 0,
					},
				}}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.db;",
				Expected: []sql.Row{{"localhost", "mydb", "tester", uint16(2), uint16(2), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(2), uint16(1), uint16(1)}},
			},
		},
	},
	{
		Name: "Table-level privileges exist",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT, DELETE, DROP ON mydb.test TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.tables_priv;",
				Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), uint64(0b101001), uint64(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE DELETE ON mydb.test FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.tables_priv;",
				Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), uint64(0b100001), uint64(0)}},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "UPDATE mysql.tables_priv SET table_priv = 'References,Index' WHERE User = 'tester';",
				Expected: []sql.Row{{types.OkResult{
					RowsAffected: 1,
					InsertID:     0,
					Info: plan.UpdateInfo{
						Matched:  1,
						Updated:  1,
						Warnings: 0,
					},
				}}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.tables_priv;",
				Expected: []sql.Row{{"localhost", "mydb", "tester", "test", "", time.Unix(1, 0).UTC(), uint64(0b110000000), uint64(0)}},
			},
		},
	},
	{
		Name: "Basic revoke SELECT privilege",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* TO tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{"tester", "localhost", uint16(2)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE SELECT ON *.* FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM test;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{"tester", "localhost", uint16(1)}},
			},
		},
	},
	{
		Name: "Basic revoke all global static privileges",
		SetUpScript: []string{
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
			"GRANT ALL ON *.* TO tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "INSERT INTO test VALUES (4);",
				Expected: []sql.Row{{types.NewOkResult(1)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}, {4}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{"tester", "localhost", uint16(2), uint16(2)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE ALL ON *.* FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM test;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "INSERT INTO test VALUES (5);",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT User, Host, Select_priv, Insert_priv FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{"tester", "localhost", uint16(1), uint16(1)}},
			},
		},
	},
	{
		Name: "Basic role creation",
		SetUpScript: []string{
			"CREATE ROLE test_role;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT User, Host, account_locked FROM mysql.user WHERE User = 'test_role';",
				Expected: []sql.Row{{"test_role", "%", uint16(2)}},
			},
		},
	},
	{
		Name: "Grant Role with SELECT Privilege",
		SetUpScript: []string{
			"SET @@GLOBAL.activate_all_roles_on_login = true;",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
			"CREATE ROLE test_role;",
			"GRANT SELECT ON *.* TO test_role;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM test;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT test_role TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.role_edges;",
				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", uint16(1)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT User, Host, Select_priv FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{"tester", "localhost", uint16(1)}},
			},
		},
	},
	{
		Name: "Revoke role currently granted to a user",
		SetUpScript: []string{
			"SET @@GLOBAL.activate_all_roles_on_login = true;",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
			"CREATE ROLE test_role;",
			"GRANT SELECT ON *.* TO test_role;",
			"GRANT test_role TO tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.role_edges;",
				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", uint16(1)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "REVOKE test_role FROM tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM test;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
				Expected: []sql.Row{{1}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{1}},
			},
		},
	},
	{
		Name: "Drop role currently granted to a user",
		SetUpScript: []string{
			"SET @@GLOBAL.activate_all_roles_on_login = true;",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
			"CREATE ROLE test_role;",
			"GRANT SELECT ON *.* TO test_role;",
			"GRANT test_role TO tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM test;",
				Expected: []sql.Row{{1}, {2}, {3}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.role_edges;",
				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", uint16(1)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "DROP ROLE test_role;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:        "tester",
				Host:        "localhost",
				Query:       "SELECT * FROM test;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{1}},
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "DROP ROLE test_role;",
				ExpectedErr: sql.ErrRoleDeletionFailure,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "DROP ROLE IF EXISTS test_role;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Drop user with role currently granted",
		SetUpScript: []string{
			"SET @@GLOBAL.activate_all_roles_on_login = true;",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY);",
			"INSERT INTO test VALUES (1), (2), (3);",
			"CREATE USER tester@localhost;",
			"CREATE ROLE test_role;",
			"GRANT SELECT ON *.* TO test_role;",
			"GRANT test_role TO tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT * FROM mysql.role_edges;",
				Expected: []sql.Row{{"%", "test_role", "localhost", "tester", uint16(1)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "DROP USER tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.role_edges;",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'tester';",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "SELECT COUNT(*) FROM mysql.user WHERE User = 'test_role';",
				Expected: []sql.Row{{1}},
			},
			{
				User:        "root",
				Host:        "localhost",
				Query:       "DROP USER tester@localhost;",
				ExpectedErr: sql.ErrUserDeletionFailure,
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "DROP USER IF EXISTS tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
		},
	},
	{
		Name: "Show grants on root account",
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS;",
				Expected: []sql.Row{{"GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, SHUTDOWN, PROCESS, " +
					"FILE, REFERENCES, INDEX, ALTER, SHOW DATABASES, SUPER, CREATE TEMPORARY TABLES, LOCK TABLES, " +
					"EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, " +
					"ALTER ROUTINE, CREATE USER, EVENT, TRIGGER, CREATE TABLESPACE, CREATE ROLE, DROP ROLE ON *.* TO " +
					"`root`@`localhost` WITH GRANT OPTION"}},
			},
		},
	},
	{
		Name: "Show grants on a user from the root account",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* TO tester@localhost;",
			"CREATE ROLE test_role1;",
			"CREATE ROLE test_role2;",
			"GRANT INSERT ON *.* TO test_role1;",
			"GRANT REFERENCES ON *.* TO test_role2;",
			"GRANT test_role1 TO tester@localhost;",
			"GRANT test_role2 TO tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT ON *.* TO `tester`@`localhost`"},
					{"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"},
				},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT UPDATE ON *.* TO tester@localhost WITH GRANT OPTION;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT, UPDATE ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
					{"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"},
				},
			},
			{
				User:  "tester",
				Host:  "localhost",
				Query: "SHOW GRANTS;",
				Expected: []sql.Row{
					{"GRANT SELECT, UPDATE ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
					{"GRANT `test_role1`@`%`, `test_role2`@`%` TO `tester`@`localhost`"},
				},
			},
		},
	},
	{
		Name: "show user with no grants",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT USAGE ON *.* TO `tester`@`localhost`"},
				},
			},
		},
	},
	{
		Name: "show grants with multiple global grants",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* to tester@localhost",
			"GRANT INSERT ON *.* to tester@localhost",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT, INSERT ON *.* TO `tester`@`localhost`"},
				},
			},
		},
	},
	{
		Name: "show grants at various scopes",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* to tester@localhost",
			"GRANT SELECT ON db.* to tester@localhost",
			"GRANT SELECT ON db.tbl to tester@localhost",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT ON *.* TO `tester`@`localhost`"},
					{"GRANT SELECT ON `db`.* TO `tester`@`localhost`"},
					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost`"},
				},
			},
		},
	},
	{
		Name: "show grants at only some scopes",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* to tester@localhost",
			"GRANT SELECT ON db.tbl to tester@localhost",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT ON *.* TO `tester`@`localhost`"},
					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost`"},
				},
			},
		},
	},
	{
		Name: "show always shows global USAGE priv regardless of other privs",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON db.* to tester@localhost",
			"GRANT INSERT ON db1.* to tester@localhost",
			"GRANT DELETE ON db2.* to tester@localhost",
			"GRANT SELECT ON db.tbl to tester@localhost",
			"GRANT INSERT ON db.tbl to tester@localhost",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT USAGE ON *.* TO `tester`@`localhost`"},
					{"GRANT SELECT ON `db`.* TO `tester`@`localhost`"},
					{"GRANT INSERT ON `db1`.* TO `tester`@`localhost`"},
					{"GRANT DELETE ON `db2`.* TO `tester`@`localhost`"},
					{"GRANT SELECT, INSERT ON `db`.`tbl` TO `tester`@`localhost`"},
				},
			},
		},
	},
	{
		Name: "with grant option works at every scope",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* to tester@localhost WITH GRANT OPTION",
			"GRANT SELECT ON db.* to tester@localhost WITH GRANT OPTION",
			"GRANT SELECT ON db.tbl to tester@localhost WITH GRANT OPTION",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
					{"GRANT SELECT ON `db`.* TO `tester`@`localhost` WITH GRANT OPTION"},
					{"GRANT SELECT ON `db`.`tbl` TO `tester`@`localhost` WITH GRANT OPTION"},
				},
			},
		},
	},
	{
		Name: "adding with grant option applies to existing privileges",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"GRANT SELECT ON *.* to tester@localhost",
			"GRANT INSERT ON *.* to tester@localhost WITH GRANT OPTION",
			"GRANT SELECT ON db.* to tester@localhost",
			"GRANT INSERT ON db.* to tester@localhost WITH GRANT OPTION",
			"GRANT SELECT ON db.tbl to tester@localhost",
			"GRANT INSERT ON db.tbl to tester@localhost WITH GRANT OPTION",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW GRANTS FOR tester@localhost;",
				Expected: []sql.Row{
					{"GRANT SELECT, INSERT ON *.* TO `tester`@`localhost` WITH GRANT OPTION"},
					{"GRANT SELECT, INSERT ON `db`.* TO `tester`@`localhost` WITH GRANT OPTION"},
					{"GRANT SELECT, INSERT ON `db`.`tbl` TO `tester`@`localhost` WITH GRANT OPTION"},
				},
			},
		},
	},
	{
		Name: "SHOW DATABASES shows `mysql` database",
		SetUpScript: []string{
			"CREATE USER testuser;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SELECT user FROM mysql.user;",
				Expected: []sql.Row{
					{"root"},
					{"testuser"},
				},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "SELECT USER();",
				Expected: []sql.Row{
					{"root@localhost"},
				},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "SHOW DATABASES",
				Expected: []sql.Row{
					{"information_schema"},
					{"mydb"},
					{"mysql"},
				},
			},
		},
	},
	{
		Name: "Anonymous User",
		SetUpScript: []string{
			"CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"INSERT INTO mydb.test VALUES (0, 0), (1, 1);",
			"INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);",
			"CREATE USER 'rand_user'@'localhost';",
			"CREATE USER ''@'%';",
			"GRANT SELECT ON mydb.test TO 'rand_user'@'localhost';",
			"GRANT SELECT ON mydb.test2 TO ''@'%';",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "rand_user",
				Host:  "localhost",
				Query: "SELECT * FROM mydb.test;",
				Expected: []sql.Row{
					{0, 0},
					{1, 1},
				},
			},
			{
				User:        "rand_user",
				Host:        "localhost",
				Query:       "SELECT * FROM mydb.test2;",
				ExpectedErr: sql.ErrTableAccessDeniedForUser,
			},
			{
				User:        "rand_user",
				Host:        "non_existent_host",
				Query:       "SELECT * FROM mydb.test;",
				ExpectedErr: sql.ErrTableAccessDeniedForUser,
			},
			{
				User:  "rand_user",
				Host:  "non_existent_host",
				Query: "SELECT * FROM mydb.test2;",
				Expected: []sql.Row{
					{0, 1},
					{1, 2},
				},
			},
			{
				User:        "non_existent_user",
				Host:        "non_existent_host",
				Query:       "SELECT * FROM mydb.test;",
				ExpectedErr: sql.ErrTableAccessDeniedForUser,
			},
			{
				User:  "non_existent_user",
				Host:  "non_existent_host",
				Query: "SELECT * FROM mydb.test2;",
				Expected: []sql.Row{
					{0, 1},
					{1, 2},
				},
			},
			{
				User:        "",
				Host:        "%",
				Query:       "SELECT * FROM mydb.test;",
				ExpectedErr: sql.ErrTableAccessDeniedForUser,
			},
			{
				User:  "",
				Host:  "%",
				Query: "SELECT * FROM mydb.test2;",
				Expected: []sql.Row{
					{0, 1},
					{1, 2},
				},
			},
		},
	},
	{
		Name: "IPv4 Loopback == localhost",
		SetUpScript: []string{
			"CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT);",
			"INSERT INTO mydb.test VALUES (0, 0), (1, 1);",
			"INSERT INTO mydb.test2 VALUES (0, 1), (1, 2);",
			"CREATE USER 'rand_user1'@'localhost';",
			"CREATE USER 'rand_user2'@'127.0.0.1';",
			"GRANT SELECT ON mydb.test TO 'rand_user1'@'localhost';",
			"GRANT SELECT ON mydb.test2 TO 'rand_user2'@'127.0.0.1';",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "rand_user1",
				Host:  "localhost",
				Query: "SELECT * FROM mydb.test;",
				Expected: []sql.Row{
					{0, 0},
					{1, 1},
				},
			},
			{
				User:  "rand_user1",
				Host:  "127.0.0.1",
				Query: "SELECT * FROM mydb.test;",
				Expected: []sql.Row{
					{0, 0},
					{1, 1},
				},
			},
			{
				User:        "rand_user1",
				Host:        "54.244.85.252",
				Query:       "SELECT * FROM mydb.test;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
			{
				User:  "rand_user2",
				Host:  "localhost",
				Query: "SELECT * FROM mydb.test2;",
				Expected: []sql.Row{
					{0, 1},
					{1, 2},
				},
			},
			{
				User:  "rand_user2",
				Host:  "127.0.0.1",
				Query: "SELECT * FROM mydb.test2;",
				Expected: []sql.Row{
					{0, 1},
					{1, 2},
				},
			},
			{
				User:        "rand_user2",
				Host:        "54.244.85.252",
				Query:       "SELECT * FROM mydb.test2;",
				ExpectedErr: sql.ErrDatabaseAccessDeniedForUser,
			},
		},
	},
	{
		Name: "DROP USER without a host designation",
		SetUpScript: []string{
			"CREATE USER admin;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "SELECT user FROM mysql.user",
				Expected: []sql.Row{
					{"root"},
					{"admin"},
				},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "DROP USER admin;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:  "root",
				Host:  "localhost",
				Query: "SELECT user FROM mysql.user",
				Expected: []sql.Row{
					{"root"},
				},
			},
		},
	},
	{
		Name: "information_schema.columns table 'privileges' column gets correct values",
		SetUpScript: []string{
			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT count(*) FROM inFORmation_ScHeMa.columns where table_schema = 'mydb' and table_name = 'test';",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT INSERT ON mydb.test TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT column_name, privileges FROM information_schema.columns where table_schema = 'mydb' and table_name = 'test'",
				Expected: []sql.Row{{"pk", "insert"}, {"c", "insert"}, {"p", "insert"}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mydb.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT column_name, privileges FROM information_schema.columns where table_schema = 'mydb' and table_name = 'test'",
				Expected: []sql.Row{{"pk", "insert,select"}, {"c", "insert,select"}, {"p", "insert,select"}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT UPDATE ON mydb.checks TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select table_name, column_name, privileges from information_schema.columns where table_schema = 'mydb' and table_name = 'checks';",
				Expected: []sql.Row{{"checks", "a", "select,update"}, {"checks", "b", "select,update"}, {"checks", "c", "select,update"}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT count(*) FROM information_schema.columns where table_schema = 'information_schema' and table_name = 'columns'",
				Expected: []sql.Row{{22}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "select table_name, column_name, privileges from information_schema.columns where table_schema = 'mydb' and table_name = 'checks';",
				Expected: []sql.Row{{"checks", "a", "insert,references,select,update"}, {"checks", "b", "insert,references,select,update"}, {"checks", "c", "insert,references,select,update"}},
			},
		},
	},
	{
		Name: "information_schema.column_statistics shows columns with privileges only",
		SetUpScript: []string{
			"CREATE TABLE two (i int primary key, j int)",
			"INSERT INTO two VALUES (1, 4), (2, 5), (3, 6)",
			"CREATE TABLE one (f float)",
			"INSERT INTO one VALUES (1.25), (45.25), (7.5), (10.5)",
			"ANALYZE TABLE one",
			"ANALYZE TABLE two",
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mydb.one TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT * FROM information_schema.column_statistics where schema_name = 'mydb';",
				Expected: []sql.Row{{"mydb", "one", "f", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"1.25", "1.25", "0.25"}, []interface{}{"7.50", "7.50", "0.25"}, []interface{}{"10.50", "10.50", "0.25"}, []interface{}{"45.25", "45.25", "0.25"}}}}}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mydb.two TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:  "tester",
				Host:  "localhost",
				Query: "SELECT * FROM information_schema.column_statistics where schema_name = 'mydb';",
				Expected: []sql.Row{{"mydb", "one", "f", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"1.25", "1.25", "0.25"}, []interface{}{"7.50", "7.50", "0.25"}, []interface{}{"10.50", "10.50", "0.25"}, []interface{}{"45.25", "45.25", "0.25"}}}}},
					{"mydb", "two", "i", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"1.00", "1.00", "0.33"}, []interface{}{"2.00", "2.00", "0.33"}, []interface{}{"3.00", "3.00", "0.33"}}}}},
					{"mydb", "two", "j", types.JSONDocument{Val: map[string]interface{}{"buckets": []interface{}{[]interface{}{"4.00", "4.00", "0.33"}, []interface{}{"5.00", "5.00", "0.33"}, []interface{}{"6.00", "6.00", "0.33"}}}}}},
			},
		},
	},
	{
		Name: "information_schema.statistics shows tables with privileges only",
		SetUpScript: []string{
			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
			"CREATE USER tester@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "SELECT count(*) FROM information_schema.statistics where table_schema = 'mydb';",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT INSERT ON mydb.checks TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select table_name, column_name, index_name from information_schema.statistics where table_schema = 'mydb';",
				Expected: []sql.Row{{"checks", "a", "PRIMARY"}},
			},
		},
	},
	{
		Name: "basic tests on information_schema.SCHEMA_PRIVILEGES table",
		SetUpScript: []string{
			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
			"CREATE USER tester@localhost;",
			"CREATE USER admin@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "select * from information_schema.schema_privileges;",
				Expected: []sql.Row{},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT INSERT, REFERENCES ON mydb.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT UPDATE, GRANT OPTION ON mydb.* TO admin@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}, {"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}},
			},
			{
				User:     "admin",
				Host:     "localhost",
				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
				Expected: []sql.Row{{"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mysql.* TO admin@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "admin",
				Host:     "localhost",
				Query:    "select * from information_schema.schema_privileges order by privilege_type, is_grantable;",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "REFERENCES", "NO"}, {"'admin'@'localhost'", "def", "mysql", "SELECT", "NO"}, {"'admin'@'localhost'", "def", "mydb", "UPDATE", "YES"}},
			},
		},
	},
	{
		Name: "basic tests on information_schema.TABLE_PRIVILEGES table",
		SetUpScript: []string{
			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
			"CREATE USER tester@localhost;",
			"CREATE USER admin@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "root",
				Host:     "localhost",
				Query:    "select * from information_schema.table_privileges;",
				Expected: []sql.Row{},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT INSERT ON mydb.checks TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT UPDATE, GRANT OPTION ON mydb.test TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*root*/",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*tester*/",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}},
			},
			{
				User:     "admin",
				Host:     "localhost",
				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*admin1*/",
				Expected: []sql.Row{},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT SELECT ON mysql.* TO admin@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "admin",
				Host:     "localhost",
				Query:    "select * from information_schema.table_privileges order by privilege_type, is_grantable;/*admin2*/",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "mydb", "checks", "INSERT", "NO"}, {"'tester'@'localhost'", "def", "mydb", "test", "UPDATE", "YES"}},
			},
		},
	},
	{
		Name: "basic tests on information_schema.USER_PRIVILEGES table",
		SetUpScript: []string{
			"CREATE TABLE checks (a INTEGER PRIMARY KEY, b INTEGER, c VARCHAR(20))",
			"CREATE TABLE test (pk BIGINT PRIMARY KEY, c VARCHAR(20), p POINT default (POINT(1,1)))",
			"CREATE USER tester@localhost;",
			"CREATE USER admin@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "select * from information_schema.user_privileges order by privilege_type LIMIT 4;/*root*/",
				Expected: []sql.Row{{"'root'@'localhost'", "def", "ALTER", "YES"},
					{"'root'@'localhost'", "def", "ALTER ROUTINE", "YES"},
					{"'root'@'localhost'", "def", "CREATE", "YES"},
					{"'root'@'localhost'", "def", "CREATE ROLE", "YES"}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT INSERT ON *.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*tester1*/",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "INSERT", "NO"}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT UPDATE, GRANT OPTION ON *.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*tester2*/",
				Expected: []sql.Row{{"'tester'@'localhost'", "def", "INSERT", "YES"}, {"'tester'@'localhost'", "def", "UPDATE", "YES"}},
			},
			{
				User:     "admin",
				Host:     "localhost",
				Query:    "select * from information_schema.user_privileges order by privilege_type, is_grantable;/*admin*/",
				Expected: []sql.Row{},
			},
		},
	},
	{
		Name: "basic tests on information_schema.USER_ATTRIBUTES table",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",

			`CREATE USER admin@localhost ATTRIBUTE '{"fname": "Josh", "lname": "Scott"}';`,
			"GRANT UPDATE ON mysql.* TO admin@localhost;",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:  "root",
				Host:  "localhost",
				Query: "select * from information_schema.user_attributes order by user;/*root*/",
				Expected: []sql.Row{{"admin", "localhost", nil},
					{"root", "localhost", nil},
					{"tester", "localhost", nil}},
			},
			{
				User:  "admin",
				Host:  "localhost",
				Query: "select * from information_schema.user_attributes order by user;/*admin*/",
				Expected: []sql.Row{{"admin", "localhost", nil},
					{"root", "localhost", nil},
					{"tester", "localhost", nil}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select * from information_schema.user_attributes order by user;/*tester*/",
				Expected: []sql.Row{{"tester", "localhost", nil}},
			},
		},
	},
	{
		Name: "basic privilege tests on information_schema.ROUTINES and PARAMETERS tables",
		SetUpScript: []string{
			"CREATE USER tester@localhost;",
			"CREATE PROCEDURE testabc(IN x DOUBLE, IN y FLOAT, OUT abc DECIMAL(5,1)) SELECT x*y INTO abc",
		},
		Assertions: []UserPrivilegeTestAssertion{
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select count(*) from information_schema.routines where routine_name = 'testabc'/*tester1*/;",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select count(*) from information_schema.parameters where specific_name = 'testabc'/*tester1*/;",
				Expected: []sql.Row{{0}},
			},
			{
				User:     "root",
				Host:     "localhost",
				Query:    "GRANT CREATE ROUTINE ON mydb.* TO tester@localhost;",
				Expected: []sql.Row{{types.NewOkResult(0)}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select count(*) from information_schema.routines where routine_name = 'testabc';",
				Expected: []sql.Row{{1}},
			},
			{
				User:     "tester",
				Host:     "localhost",
				Query:    "select count(*) from information_schema.parameters where specific_name = 'testabc';",
				Expected: []sql.Row{{3}},
			},
		},
	},
}

UserPrivTests test the user and privilege systems. These tests always have the root account available, and the root account is used with any queries in the SetUpScript.

View Source
var VariableErrorTests = []QueryErrorTest{
	{
		Query:       "set @@does_not_exist = 100",
		ExpectedErr: sql.ErrUnknownSystemVariable,
	},
	{
		Query:       "set @myvar = bareword",
		ExpectedErr: sql.ErrColumnNotFound,
	},
	{
		Query:       "set @@sql_mode = true",
		ExpectedErr: sql.ErrInvalidSystemVariableValue,
	},
	{
		Query:       `set @@sql_mode = "NOT_AN_OPTION"`,
		ExpectedErr: sql.ErrInvalidSetValue,
	},
	{
		Query:       `set global core_file = true`,
		ExpectedErr: sql.ErrSystemVariableReadOnly,
	},
	{
		Query:       `set global require_row_format = on`,
		ExpectedErr: sql.ErrSystemVariableSessionOnly,
	},
	{
		Query:       `set session default_password_lifetime = 5`,
		ExpectedErr: sql.ErrSystemVariableGlobalOnly,
	},
	{
		Query:       `set @custom_var = default`,
		ExpectedErr: sql.ErrUserVariableNoDefault,
	},
	{
		Query:       `set session @@bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set global @@bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set session @@session.bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set session @@global.bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set global @@session.bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set global @@global.bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set session @myvar = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set global @myvar = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set @@session.@@bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set @@global.@@bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set @@session.@bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set @@global.@bulk_insert_buffer_size = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set @@session.@myvar = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
	{
		Query:       `set @@global.@myvar = 5`,
		ExpectedErr: sql.ErrSyntaxError,
	},
}
View Source
var VariableQueries = []ScriptTest{
	{
		Name: "set system variables",
		SetUpScript: []string{
			"set @@auto_increment_increment = 100, sql_select_limit = 1",
		},
		Query: "SELECT @@auto_increment_increment, @@sql_select_limit",
		Expected: []sql.Row{
			{100, 1},
		},
	},
	{
		Name:  "select join_complexity_limit",
		Query: "SELECT @@join_complexity_limit",
		Expected: []sql.Row{
			{uint64(12)},
		},
	},
	{
		Name: "set join_complexity_limit",
		SetUpScript: []string{
			"set @@join_complexity_limit = 2",
		},
		Query: "SELECT @@join_complexity_limit",
		Expected: []sql.Row{
			{uint64(2)},
		},
	},
	{
		Name: "@@server_id",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "select @@server_id;",
				Expected: []sql.Row{{0}},
			},
			{
				Query:    "set @@server_id=123;",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "set @@GLOBAL.server_id=123;",
				Expected: []sql.Row{{}},
			},
		},
	},
	{
		Name: "set system variables and user variables",
		SetUpScript: []string{
			"SET @myvar = @@autocommit",
			"SET autocommit = @myvar",
			"SET @myvar2 = @myvar - 1, @myvar3 = @@autocommit - 1",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "select @myvar, @@autocommit, @myvar2, @myvar3",
				Expected: []sql.Row{
					{1, 1, 0, 0},
				},
			},
		},
	},
	{
		Name: "set system variables mixed case",
		SetUpScript: []string{
			"set @@auto_increment_INCREMENT = 100, sql_select_LIMIT = 1",
		},
		Query: "SELECT @@auto_increment_increment, @@sql_select_limit",
		Expected: []sql.Row{
			{100, 1},
		},
	},
	{
		Name: "set system variable defaults",
		SetUpScript: []string{
			"set @@auto_increment_increment = 100, sql_select_limit = 1",
			"set @@auto_increment_increment = default, sql_select_limit = default",
		},
		Query: "SELECT @@auto_increment_increment, @@sql_select_limit",
		Expected: []sql.Row{
			{1, math.MaxInt32},
		},
	},
	{
		Name: "set system variable ON / OFF",
		SetUpScript: []string{
			"set @@autocommit = ON, sql_mode = \"\"",
		},
		Query: "SELECT @@autocommit, @@session.sql_mode",
		Expected: []sql.Row{
			{1, ""},
		},
	},
	{
		Name: "set system variable ON / OFF",
		SetUpScript: []string{
			"set @@autocommit = ON, session sql_mode = \"\"",
		},
		Query: "SELECT @@autocommit, @@session.sql_mode",
		Expected: []sql.Row{
			{1, ""},
		},
	},
	{
		Name: "set system variable sql_mode to ANSI for session",
		SetUpScript: []string{
			"set SESSION sql_mode = 'ANSI'",
		},
		Query: "SELECT @@session.sql_mode",
		Expected: []sql.Row{
			{"ANSI"},
		},
	},
	{
		Name: "set system variable true / false quoted",
		SetUpScript: []string{
			`set @@autocommit = "true", default_table_encryption = "false"`,
		},
		Query: "SELECT @@autocommit, @@session.default_table_encryption",
		Expected: []sql.Row{
			{1, 0},
		},
	},
	{
		Name: "set system variable true / false",
		SetUpScript: []string{
			`set @@autocommit = true, default_table_encryption = false`,
		},
		Query: "SELECT @@autocommit, @@session.default_table_encryption",
		Expected: []sql.Row{
			{1, 0},
		},
	},
	{
		Name: "set system variable with expressions",
		SetUpScript: []string{
			`set lc_messages = "123", @@auto_increment_increment = 1`,
			`set lc_messages = concat(@@lc_messages, "456"), @@auto_increment_increment = @@auto_increment_increment + 3`,
		},
		Query: "SELECT @@lc_messages, @@auto_increment_increment",
		Expected: []sql.Row{
			{"123456", 4},
		},
	},
	{
		Name: "set system variable to another system variable",
		SetUpScript: []string{
			`set @@auto_increment_increment = 123`,
			`set @@sql_select_limit = @@auto_increment_increment`,
		},
		Query: "SELECT @@sql_select_limit",
		Expected: []sql.Row{
			{123},
		},
	},
	{
		Name: "set names",
		SetUpScript: []string{
			`set names utf8mb4`,
		},
		Query: "SELECT @@character_set_client, @@character_set_connection, @@character_set_results",
		Expected: []sql.Row{
			{"utf8mb4", "utf8mb4", "utf8mb4"},
		},
	},

	{
		Name: "set names quoted",
		SetUpScript: []string{
			`set NAMES "utf8mb3"`,
		},
		Query: "SELECT @@character_set_client, @@character_set_connection, @@character_set_results",
		Expected: []sql.Row{
			{"utf8mb3", "utf8mb3", "utf8mb3"},
		},
	},
	{
		Name: "set character set",
		SetUpScript: []string{
			`set character set utf8`,
		},
		Query: "SELECT @@character_set_client, @@character_set_connection, @@character_set_results",
		Expected: []sql.Row{
			{"utf8", "utf8mb4", "utf8"},
		},
	},
	{
		Name: "set charset",
		SetUpScript: []string{
			`set charset utf8`,
		},
		Query: "SELECT @@character_set_client, @@character_set_connection, @@character_set_results",
		Expected: []sql.Row{
			{"utf8", "utf8mb4", "utf8"},
		},
	},
	{
		Name: "set charset quoted",
		SetUpScript: []string{
			`set charset 'utf8'`,
		},
		Query: "SELECT @@character_set_client, @@character_set_connection, @@character_set_results",
		Expected: []sql.Row{
			{"utf8", "utf8mb4", "utf8"},
		},
	},
	{
		Name: "set system variable to bareword",
		SetUpScript: []string{
			`set @@sql_mode = ALLOW_INVALID_DATES`,
		},
		Query: "SELECT @@sql_mode",
		Expected: []sql.Row{
			{"ALLOW_INVALID_DATES"},
		},
	},
	{
		Name: "set system variable to bareword, unqualified",
		SetUpScript: []string{
			`set sql_mode = ALLOW_INVALID_DATES`,
		},
		Query: "SELECT @@sql_mode",
		Expected: []sql.Row{
			{"ALLOW_INVALID_DATES"},
		},
	},
	{
		Name: "set sql_mode variable from mysqldump",
		SetUpScript: []string{
			`SET sql_mode = 'STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_ENGINE_SUBSTITUTION'`,
		},
		Query: "SELECT @@sql_mode",
		Expected: []sql.Row{
			{"ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,STRICT_ALL_TABLES,STRICT_TRANS_TABLES,TRADITIONAL"},
		},
	},

	{
		Name: "set user var",
		SetUpScript: []string{
			`set @myvar = "hello"`,
		},
		Query: "SELECT @myvar",
		Expected: []sql.Row{
			{"hello"},
		},
	},
	{
		Name: "set user var, integer type",
		SetUpScript: []string{
			`set @myvar = 123`,
		},
		Query: "SELECT @myvar",
		Expected: []sql.Row{
			{123},
		},
	},
	{
		Name: "set user var, floating point",
		SetUpScript: []string{
			`set @myvar = 123.4`,
		},
		Query: "SELECT @myvar",
		Expected: []sql.Row{
			{123.4},
		},
	},
	{
		Name: "set user var and sys var in same statement",
		SetUpScript: []string{
			`set @myvar = 123.4, @@auto_increment_increment = 1234`,
		},
		Query: "SELECT @myvar, @@auto_increment_increment",
		Expected: []sql.Row{
			{123.4, 1234},
		},
	},
	{
		Name: "set sys var to user var",
		SetUpScript: []string{
			`set @myvar = 1234`,
			`set auto_increment_increment = @myvar`,
		},
		Query: "SELECT @myvar, @@auto_increment_increment",
		Expected: []sql.Row{
			{1234, 1234},
		},
	},
	{
		Name: "local is session",
		SetUpScript: []string{
			`set @@LOCAL.cte_max_recursion_depth = 1234`,
		},
		Query: "SELECT @@SESSION.cte_max_recursion_depth",
		Expected: []sql.Row{
			{1234},
		},
	},
	{
		Name: "user and system var with same name",
		SetUpScript: []string{
			`set @cte_max_recursion_depth = 55`,
			`set cte_max_recursion_depth = 77`,
		},
		Query: "SELECT @cte_max_recursion_depth, @@cte_max_recursion_depth",
		Expected: []sql.Row{
			{55, 77},
		},
	},
	{
		Name: "uninitialized user vars",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @doesNotExist;",
				Expected: []sql.Row{{nil}},
			},
			{
				Query:    "SELECT @doesNotExist is NULL;",
				Expected: []sql.Row{{true}},
			},
			{
				Query:    "SELECT @doesNotExist='';",
				Expected: []sql.Row{{nil}},
			},
			{
				Query:    "SELECT @doesNotExist < 123;",
				Expected: []sql.Row{{nil}},
			},
		},
	},

	{
		Name: "eval string user var",
		SetUpScript: []string{
			"set @stringVar = 'abc'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query:    "SELECT @stringVar='abc'",
				Expected: []sql.Row{{true}},
			},
			{
				Query:    "SELECT @stringVar='abcd';",
				Expected: []sql.Row{{false}},
			},
			{
				Query:    "SELECT @stringVar=123;",
				Expected: []sql.Row{{false}},
			},
			{
				Query:    "SELECT @stringVar is null;",
				Expected: []sql.Row{{false}},
			},
		},
	},
	{
		Name: "set transaction",
		Assertions: []ScriptTestAssertion{
			{
				Query:    "set transaction isolation level serializable, read only",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "select @@transaction_isolation, @@transaction_read_only",
				Expected: []sql.Row{{"SERIALIZABLE", 1}},
			},
			{
				Query:    "set transaction read write, isolation level read uncommitted",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "select @@transaction_isolation, @@transaction_read_only",
				Expected: []sql.Row{{"READ-UNCOMMITTED", 0}},
			},
			{
				Query:    "set transaction isolation level read committed",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "select @@transaction_isolation",
				Expected: []sql.Row{{"READ-COMMITTED"}},
			},
			{
				Query:    "set transaction isolation level repeatable read",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "select @@transaction_isolation",
				Expected: []sql.Row{{"REPEATABLE-READ"}},
			},
			{
				Query:    "set session transaction isolation level serializable, read only",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "select @@transaction_isolation, @@transaction_read_only",
				Expected: []sql.Row{{"SERIALIZABLE", 1}},
			},
			{
				Query:    "set global transaction read write, isolation level read uncommitted",
				Expected: []sql.Row{{}},
			},
			{
				Query:    "select @@transaction_isolation, @@transaction_read_only",
				Expected: []sql.Row{{"SERIALIZABLE", 1}},
			},
			{
				Query:    "select @@global.transaction_isolation, @@global.transaction_read_only",
				Expected: []sql.Row{{"READ-UNCOMMITTED", 0}},
			},
		},
	},
}
View Source
var VersionedQueries = []QueryTest{
	{
		Query: "SELECT *  FROM myhistorytable AS OF '2019-01-01' AS foo ORDER BY i",
		Expected: []sql.Row{
			{int64(1), "first row, 1"},
			{int64(2), "second row, 1"},
			{int64(3), "third row, 1"},
		},
	},
	{
		Query: "SELECT *  FROM myhistorytable AS OF '2019-01-02' foo ORDER BY i",
		Expected: []sql.Row{
			{int64(1), "first row, 2"},
			{int64(2), "second row, 2"},
			{int64(3), "third row, 2"},
		},
	},

	{
		Query: "SELECT *  FROM myhistorytable AS OF GREATEST('2019-01-02','2019-01-01','') foo ORDER BY i",
		Expected: []sql.Row{
			{int64(1), "first row, 2"},
			{int64(2), "second row, 2"},
			{int64(3), "third row, 2"},
		},
	},
	{
		Query: "SELECT *  FROM myhistorytable ORDER BY i",
		Expected: []sql.Row{
			{int64(1), "first row, 3", "1"},
			{int64(2), "second row, 3", "2"},
			{int64(3), "third row, 3", "3"},
		},
	},
	{
		Query: "SHOW TABLES AS OF '2019-01-02' LIKE 'myhistorytable'",
		Expected: []sql.Row{
			{"myhistorytable"},
		},
	},
	{
		Query: "SHOW TABLES FROM mydb AS OF '2019-01-02' LIKE 'myhistorytable'",
		Expected: []sql.Row{
			{"myhistorytable"},
		},
	},
	{
		Query: "SHOW CREATE TABLE myhistorytable as of '2019-01-02'",
		Expected: []sql.Row{
			{"myhistorytable", "CREATE TABLE `myhistorytable` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `s` text NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
		},
	},
	{
		Query: "SHOW CREATE TABLE myhistorytable as of '2019-01-03'",
		Expected: []sql.Row{
			{"myhistorytable", "CREATE TABLE `myhistorytable` (\n" +
				"  `i` bigint NOT NULL,\n" +
				"  `s` text NOT NULL,\n" +
				"  `c` text NOT NULL,\n" +
				"  PRIMARY KEY (`i`)\n" +
				") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"},
		},
	},
}
View Source
var VersionedScripts = []ScriptTest{
	{
		Name: "user var for AS OF expression",
		SetUpScript: []string{
			"SET @rev1 = '2019-01-01', @rev2 = '2019-01-02'",
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT *  FROM myhistorytable AS OF @rev1 AS foo ORDER BY i",
				Expected: []sql.Row{
					{int64(1), "first row, 1"},
					{int64(2), "second row, 1"},
					{int64(3), "third row, 1"},
				},
			},
			{
				Query: "SELECT *  FROM myhistorytable AS OF @rev2 AS foo ORDER BY i",
				Expected: []sql.Row{
					{int64(1), "first row, 2"},
					{int64(2), "second row, 2"},
					{int64(3), "third row, 2"},
				},
			},
			{
				Query: "SHOW TABLES AS OF @rev1 LIKE 'myhistorytable'",
				Expected: []sql.Row{
					{"myhistorytable"},
				},
			},
			{
				Query: "DESCRIBE myhistorytable AS OF '2019-01-02'",
				Expected: []sql.Row{
					{"i", "bigint", "NO", "PRI", "NULL", ""},
					{"s", "text", "NO", "", "NULL", ""},
				},
			},
			{
				Query: "DESCRIBE myhistorytable AS OF '2019-01-03'",
				Expected: []sql.Row{
					{"i", "bigint", "NO", "PRI", "NULL", ""},
					{"s", "text", "NO", "", "NULL", ""},
					{"c", "text", "NO", "", "NULL", ""},
				},
			},
		},
	},
}
View Source
var VersionedViewTests = []QueryTest{
	{
		Query: "SELECT * FROM myview1 ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 3", "1"),
			sql.NewRow(int64(2), "second row, 3", "2"),
			sql.NewRow(int64(3), "third row, 3", "3"),
		},
	},
	{
		Query: "SELECT t.* FROM myview1 AS t ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 3", "1"),
			sql.NewRow(int64(2), "second row, 3", "2"),
			sql.NewRow(int64(3), "third row, 3", "3"),
		},
	},
	{
		Query: "SELECT t.i FROM myview1 AS t ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
			sql.NewRow(int64(2)),
			sql.NewRow(int64(3)),
		},
	},
	{
		Query: "SELECT * FROM myview1 AS OF '2019-01-01' ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 1"),
			sql.NewRow(int64(2), "second row, 1"),
			sql.NewRow(int64(3), "third row, 1"),
		},
	},

	{
		Query: "SELECT * FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 3", "1"),
		},
	},
	{
		Query: "SELECT i FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
		},
	},
	{
		Query: "SELECT myview2.i FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
		},
	},
	{
		Query: "SELECT myview2.* FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 3", "1"),
		},
	},
	{
		Query: "SELECT t.* FROM myview2 as t",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 3", "1"),
		},
	},
	{
		Query: "SELECT t.i FROM myview2 as t",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
		},
	},
	{
		Query: "SELECT * FROM myview2 AS OF '2019-01-01'",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row, 1"),
		},
	},

	{
		Query: "SELECT * FROM myview3 AS OF '2019-01-01'",
		Expected: []sql.Row{
			{"1"},
			{"2"},
			{"3"},
			{"first row, 1"},
			{"second row, 1"},
			{"third row, 1"},
		},
	},
	{
		Query: "SELECT * FROM myview3 AS OF '2019-01-02'",
		Expected: []sql.Row{
			{"1"},
			{"2"},
			{"3"},
			{"first row, 2"},
			{"second row, 2"},
			{"third row, 2"},
		},
	},
	{
		Query: "SELECT * FROM myview3 AS OF '2019-01-03'",
		Expected: []sql.Row{
			{"1"},
			{"2"},
			{"3"},
			{"first row, 3"},
			{"second row, 3"},
			{"third row, 3"},
		},
	},

	{
		Query: "SELECT * FROM myview4 AS OF '2019-01-01'",
		Expected: []sql.Row{
			{1, "first row, 1"},
		},
	},
	{
		Query: "SELECT * FROM myview4 AS OF '2019-01-02'",
		Expected: []sql.Row{
			{2, "second row, 2"},
		},
	},
	{
		Query: "SELECT * FROM myview4 AS OF '2019-01-03'",
		Expected: []sql.Row{
			{3, "third row, 3", "3"},
		},
	},

	{
		Query: "SELECT * FROM myview5 AS OF '2019-01-01'",
		Expected: []sql.Row{
			{1, "first row, 1"},
		},
	},
	{
		Query: "SELECT * FROM myview5 AS OF '2019-01-02'",
		Expected: []sql.Row{
			{2, "second row, 2"},
		},
	},
	{
		Query: "SELECT * FROM myview5 AS OF '2019-01-03'",
		Expected: []sql.Row{
			{3, "third row, 3", "3"},
		},
	},

	{
		Query: "select * from information_schema.views where table_schema = 'mydb'",
		Expected: []sql.Row{
			sql.NewRow("def", "mydb", "myview", "SELECT * FROM mytable", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
			sql.NewRow("def", "mydb", "myview1", "SELECT * FROM myhistorytable", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
			sql.NewRow("def", "mydb", "myview2", "SELECT * FROM myview1 WHERE i = 1", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
			sql.NewRow("def", "mydb", "myview3", "SELECT i from myview1 union select s from myhistorytable", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
			sql.NewRow("def", "mydb", "myview4", "SELECT * FROM myhistorytable where i in (select distinct cast(RIGHT(s, 1) as signed) from myhistorytable)", "NONE", "NO", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
			sql.NewRow("def", "mydb", "myview5", "SELECT * FROM (select * from myhistorytable where i in (select distinct cast(RIGHT(s, 1) as signed))) as sq", "NONE", "NO", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
		},
	},
	{
		Query: "select table_name from information_schema.tables where table_schema = 'mydb' and table_type = 'VIEW' order by 1",
		Expected: []sql.Row{
			sql.NewRow("myview"),
			sql.NewRow("myview1"),
			sql.NewRow("myview2"),
			sql.NewRow("myview3"),
			sql.NewRow("myview4"),
			sql.NewRow("myview5"),
		},
	},
}
View Source
var ViewScripts = []ScriptTest{
	{
		Name: "check view with escaped strings",
		SetUpScript: []string{
			`CREATE TABLE strs ( id int NOT NULL AUTO_INCREMENT,
                                 str  varchar(15) NOT NULL,
                                 PRIMARY KEY (id));`,
			`CREATE VIEW quotes AS SELECT * FROM strs WHERE str IN ('joe''s',
                                                                    "jan's",
                                                                    'mia\\''s',
                                                                    'bob\'s'
                                                                   );`,
			`INSERT INTO strs VALUES (0,"joe's");`,
			`INSERT INTO strs VALUES (0,"mia\\'s");`,
			`INSERT INTO strs VALUES (0,"bob's");`,
			`INSERT INTO strs VALUES (0,"joe's");`,
			`INSERT INTO strs VALUES (0,"notInView");`,
			`INSERT INTO strs VALUES (0,"jan's");`,
		},
		Assertions: []ScriptTestAssertion{
			{
				Query: "SELECT * from quotes order by id",
				Expected: []sql.Row{
					{1, "joe's"},
					{2, "mia\\'s"},
					{3, "bob's"},
					{4, "joe's"},
					{6, "jan's"}},
			},
		},
	},
}
View Source
var ViewTests = []QueryTest{
	{
		Query: "SELECT * FROM myview ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row"),
			sql.NewRow(int64(2), "second row"),
			sql.NewRow(int64(3), "third row"),
		},
	},
	{
		Query: "SELECT myview.* FROM myview ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row"),
			sql.NewRow(int64(2), "second row"),
			sql.NewRow(int64(3), "third row"),
		},
	},
	{
		Query: "SELECT i FROM myview ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
			sql.NewRow(int64(2)),
			sql.NewRow(int64(3)),
		},
	},
	{
		Query: "SELECT t.* FROM myview AS t ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row"),
			sql.NewRow(int64(2), "second row"),
			sql.NewRow(int64(3), "third row"),
		},
	},
	{
		Query: "SELECT t.i FROM myview AS t ORDER BY i",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
			sql.NewRow(int64(2)),
			sql.NewRow(int64(3)),
		},
	},
	{
		Query: "SELECT * FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row"),
		},
	},
	{
		Query: "SELECT i FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
		},
	},
	{
		Query: "SELECT myview2.i FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
		},
	},
	{
		Query: "SELECT myview2.* FROM myview2",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row"),
		},
	},
	{
		Query: "SELECT t.* FROM myview2 as t",
		Expected: []sql.Row{
			sql.NewRow(int64(1), "first row"),
		},
	},
	{
		Query: "SELECT t.i FROM myview2 as t",
		Expected: []sql.Row{
			sql.NewRow(int64(1)),
		},
	},

	{
		Query: "select * from information_schema.views where table_schema = 'mydb' order by table_name",
		Expected: []sql.Row{
			sql.NewRow("def", "mydb", "myview", "SELECT * FROM mytable", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
			sql.NewRow("def", "mydb", "myview2", "SELECT * FROM myview WHERE i = 1", "NONE", "YES", "root@localhost", "DEFINER", "utf8mb4", "utf8mb4_0900_bin"),
		},
	},
	{
		Query: "select table_name from information_schema.tables where table_schema = 'mydb' and table_type = 'VIEW' order by 1",
		Expected: []sql.Row{
			sql.NewRow("myview"),
			sql.NewRow("myview2"),
		},
	},
}

Functions

This section is empty.

Types

type CharsetCollationEngineTest

type CharsetCollationEngineTest struct {
	Name        string
	SetUpScript []string
	Queries     []CharsetCollationEngineTestQuery
}

CharsetCollationEngineTest is used to test character sets.

type CharsetCollationEngineTestQuery

type CharsetCollationEngineTestQuery struct {
	Query    string
	Expected []sql.Row
	Error    bool
	ErrKind  *errors.Kind
}

CharsetCollationEngineTestQuery is a query within a CharsetCollationEngineTest. If `Error` is true but `ErrKind` is nil, then just tests that an error has occurred. If `ErrKind` is not nil, then tests that an error is returned and matches the stated kind (has higher precedence than the `Error` field). Only checks the `Expected` rows when both `Error` and `ErrKind` are nil.

type CharsetCollationWireTest

type CharsetCollationWireTest struct {
	Name        string
	SetUpScript []string
	Queries     []CharsetCollationWireTestQuery
}

CharsetCollationWireTest is used to test character sets.

type CharsetCollationWireTestQuery

type CharsetCollationWireTestQuery struct {
	Query    string
	Expected []sql.Row
	Error    bool
}

CharsetCollationWireTestQuery is a query within a CharsetCollationWireTest.

type GenericErrorQueryTest

type GenericErrorQueryTest struct {
	Name     string
	Query    string
	Bindings map[string]sql.Expression
}

GenericErrorQueryTest is a query test that is used to assert an error occurs for some query, without specifying what the error was.

type NoopPlaintextPlugin

type NoopPlaintextPlugin struct{}

NoopPlaintextPlugin is used to authenticate plaintext user plugins

func (*NoopPlaintextPlugin) Authenticate

func (p *NoopPlaintextPlugin) Authenticate(db *mysql_db.MySQLDb, user string, userEntry *mysql_db.User, pass string) (bool, error)

type QueryErrorTest

type QueryErrorTest struct {
	Query          string
	Bindings       map[string]sql.Expression
	ExpectedErr    *errors.Kind
	ExpectedErrStr string
}

type QueryPlanTest

type QueryPlanTest struct {
	Query        string
	ExpectedPlan string
}

type QueryTest

type QueryTest struct {
	Query           string
	Expected        []sql.Row
	ExpectedColumns sql.Schema // only Name and Type matter here, because that's what we send on the wire
	Bindings        map[string]sql.Expression
	SkipPrepared    bool
}

type QuickPrivilegeTest

type QuickPrivilegeTest struct {
	Queries      []string
	Expected     []sql.Row
	ExpectedErr  *errors.Kind
	ExpectingErr bool
}

QuickPrivilegeTest specifically tests privileges on a predefined user (tester@localhost) using predefined tables and databases. Every test here can easily be represented by a UserPrivilegeTest, however this is intended to test specific privileges at a large scale, meaning there may be thousands of these tests, and hence the test data should be as small as possible.

All queries will be run as a root user with full privileges (intended for setup), with the last query running as the testing user (tester@localhost). For example, the first query may grant a SELECT privilege, while the second query is the SELECT query. Of note, the current database as set by the context is retained when switching from the root user to the test user. This does not mean that the test user automatically gains access to the database, but this is used for any queries that (incorrectly) only work with the current database.

ExpectingErr should be set when an error is expected, and it does not matter what the error is so long that it is one of the errors related to privilege checking (meaning a failed INSERT due to a missing column is NOT caught). If ExpectingErr is set and an error is given to ExpectedErr, then it is enforced that the error matches. However, if ExpectingErr is set and ExpectedErr is nil, then any privilege checking error will match.

Expected makes a distinction between the nil value and the empty value. A nil value means that we do not care about the result, only that it did not error (unless one of the error-asserting fields are set). A non-nil value asserts that the returned value matches our Expected value. If the returned value is nil, then we make a special case to match the non-nil empty row with it, due to the aforementioned distinction.

Statements that are run before every test (the state that all tests start with): CREATE TABLE mydb.test (pk BIGINT PRIMARY KEY, v1 BIGINT); CREATE TABLE mydb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT); CREATE TABLE otherdb.test (pk BIGINT PRIMARY KEY, v1 BIGINT); CREATE TABLE otherdb.test2 (pk BIGINT PRIMARY KEY, v1 BIGINT); INSERT INTO mydb.test VALUES (0, 0), (1, 1); INSERT INTO mydb.test2 VALUES (0, 1), (1, 2); INSERT INTO otherdb.test VALUES (1, 1), (2, 2); INSERT INTO otherdb.test2 VALUES (1, 1), (2, 2);

type ScriptTest

type ScriptTest struct {
	// Name of the script test
	Name string
	// The sql statements to execute as setup, in order. Results are not checked, but statements must not error.
	SetUpScript []string
	// The set of assertions to make after setup, in order
	Assertions []ScriptTestAssertion
	// For tests that make a single assertion, Query can be set for the single assertion
	Query string
	// For tests that make a single assertion, Expected can be set for the single assertion
	Expected []sql.Row
	// For tests that make a single assertion, ExpectedErr can be set for the expected error
	ExpectedErr *errors.Kind
	// SkipPrepared is true when we skip a test for prepared statements only
	SkipPrepared bool
}

type ScriptTestAssertion

type ScriptTestAssertion struct {
	Query       string
	Expected    []sql.Row
	ExpectedErr *errors.Kind
	// ExpectedErrStr should be set for tests that expect a specific error string this is not linked to a custom error.
	// In most cases, errors should be linked to a custom error, however there are exceptions where this is not possible,
	// such as the use of the SIGNAL statement.
	ExpectedErrStr string

	// ExpectedWarning contains the expected warning code when a query generates warnings but not errors.
	ExpectedWarning int

	// ExpectedWarningsCount is used to test the expected number of warnings generated by a query.
	// The ExpectedWarning field must be set for warning counts to be checked.
	ExpectedWarningsCount int

	// ExpectedWarningMessageSubstring is used to test the contents of warning messages generated by a
	// query. The ExpectedWarning field must be set for warning messages to be checked.
	ExpectedWarningMessageSubstring string

	// ExpectedColumns indicates the Name and Type of the columns expected; no other schema fields are tested.
	ExpectedColumns sql.Schema

	// SkipResultsCheck is used to skip assertions on expected Rows returned from a query. This should be used
	// sparingly, such as in cases where you only want to test warning messages.
	SkipResultsCheck bool

	// Skip is used to completely skip a test, not execute its query at all, and record it as a skipped test
	// in the test suite results.
	Skip bool

	// Bindings are variable mappings only used for prepared tests
	Bindings map[string]sql.Expression
}

type ServerAuthenticationTest

type ServerAuthenticationTest struct {
	Name        string
	SetUpFunc   func(ctx *sql.Context, t *testing.T, engine *sqle.Engine)
	SetUpScript []string
	Assertions  []ServerAuthenticationTestAssertion
}

ServerAuthenticationTest is used to define a test on the server authentication system. These tests always have the root account available, and the root account is used with any queries in the SetUpScript. The SetUpFunc is run before the SetUpScript.

type ServerAuthenticationTestAssertion

type ServerAuthenticationTestAssertion struct {
	Username        string
	Password        string
	Query           string
	ExpectedErr     bool
	ExpectedErrKind *errors.Kind
	ExpectedErrStr  string
}

ServerAuthenticationTestAssertion is within a ServerAuthenticationTest to assert functionality.

type TransactionTest

type TransactionTest struct {
	// Name of the script test
	Name string
	// The sql statements to execute as setup, in order. Results are not checked, but statements must not error.
	// Setup scripts are run as a distinct client separate from the client used in any assertions.
	SetUpScript []string
	// The set of assertions to make after setup, in order
	// The transaction test runner augments the ScriptTest runner by allowing embedding of a client string in a query
	// comment to name the client running the query, like so:
	// /* client a */ select * from myTable
	Assertions []ScriptTestAssertion
}

TransactionTest is a script to test transaction correctness. It's similar to ScriptTest, but its assertions name clients that participate

type TypeWireTest

type TypeWireTest struct {
	Name        string
	SetUpScript []string
	Queries     []string
	Results     [][]sql.Row
}

TypeWireTest is used to ensure that types are properly represented over the wire (vs being directly returned from the engine).

type UserPrivilegeTest

type UserPrivilegeTest struct {
	Name        string
	SetUpScript []string
	Assertions  []UserPrivilegeTestAssertion
}

UserPrivilegeTest is used to define a test on the user and privilege systems. These tests always have the root account available, and the root account is used with any queries in the SetUpScript.

type UserPrivilegeTestAssertion

type UserPrivilegeTestAssertion struct {
	User           string
	Host           string
	Query          string
	Expected       []sql.Row
	ExpectedErr    *errors.Kind
	ExpectedErrStr string
}

UserPrivilegeTestAssertion is within a UserPrivilegeTest to assert functionality.

type WriteQueryTest

type WriteQueryTest struct {
	WriteQuery          string
	ExpectedWriteResult []sql.Row
	SelectQuery         string
	ExpectedSelect      []sql.Row
	Bindings            map[string]sql.Expression
}

WriteQueryTest is a query test for INSERT, UPDATE, etc. statements. It has a query to run and a select query to validate the results.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL