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

     1  // Copyright 2023 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package queries
    16  
    17  import (
    18  	"github.com/dolthub/go-mysql-server/sql"
    19  	"github.com/dolthub/go-mysql-server/sql/plan"
    20  	"github.com/dolthub/go-mysql-server/sql/types"
    21  )
    22  
    23  var FulltextTests = []ScriptTest{
    24  	{
    25  		Name: "Basic matching 1 PK",
    26  		SetUpScript: []string{
    27  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
    28  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
    29  		},
    30  		Assertions: []ScriptTestAssertion{
    31  			{
    32  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
    33  				CheckIndexedAccess: true,
    34  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
    35  			},
    36  			{
    37  				Query:              "SELECT pk, v1 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
    38  				CheckIndexedAccess: true,
    39  				Expected:           []sql.Row{{uint64(2), "ghi"}},
    40  			},
    41  			{
    42  				Query:              "SELECT v1, v2 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
    43  				CheckIndexedAccess: true,
    44  				Expected:           []sql.Row{{"ghi", "jkl"}},
    45  			},
    46  			{
    47  				Query:              "SELECT pk, v1, v2 FROM test WHERE MATCH(v2, v1) AGAINST ('jkl');",
    48  				CheckIndexedAccess: true,
    49  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
    50  			},
    51  			{
    52  				Query:              "SELECT pk, v2 FROM test WHERE MATCH(v2, v1) AGAINST ('jkl');",
    53  				CheckIndexedAccess: true,
    54  				Expected:           []sql.Row{{uint64(2), "jkl"}},
    55  			},
    56  			{
    57  				Query:              "SELECT v1 FROM test WHERE MATCH(v2, v1) AGAINST ('jkl');",
    58  				CheckIndexedAccess: true,
    59  				Expected:           []sql.Row{{"ghi"}},
    60  			},
    61  			{
    62  				Query:              "SELECT v2 FROM test WHERE MATCH(v2, v1) AGAINST ('jkl');",
    63  				CheckIndexedAccess: true,
    64  				Expected:           []sql.Row{{"jkl"}},
    65  			},
    66  			{
    67  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl') = 0;",
    68  				CheckIndexedAccess: false,
    69  				Expected:           []sql.Row{{uint64(1), "abc", "def pqr"}, {uint64(3), "mno", "mno"}, {uint64(4), "stu vwx", "xyz zyx yzx"}, {uint64(5), "ghs", "mno shg"}},
    70  			},
    71  			{
    72  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl') > 0;",
    73  				CheckIndexedAccess: false,
    74  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
    75  			},
    76  			{
    77  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
    78  				CheckIndexedAccess: true,
    79  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
    80  			},
    81  			{
    82  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno') AND pk = 3;",
    83  				CheckIndexedAccess: true,
    84  				Expected:           []sql.Row{{uint64(3), "mno", "mno"}},
    85  			},
    86  			{
    87  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno') OR pk = 1;",
    88  				CheckIndexedAccess: false,
    89  				Expected:           []sql.Row{{uint64(1), "abc", "def pqr"}, {uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
    90  			},
    91  		},
    92  	},
    93  	{
    94  		Name: "Basic matching 1 UK",
    95  		SetUpScript: []string{
    96  			"CREATE TABLE test (uk BIGINT UNSIGNED NOT NULL UNIQUE, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
    97  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
    98  		},
    99  		Assertions: []ScriptTestAssertion{
   100  			{
   101  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   102  				CheckIndexedAccess: true,
   103  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   104  			},
   105  			{
   106  				Query:              "SELECT uk, v1 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   107  				CheckIndexedAccess: true,
   108  				Expected:           []sql.Row{{uint64(2), "ghi"}},
   109  			},
   110  			{
   111  				Query:              "SELECT uk, v2, v1 FROM test WHERE MATCH(v2, v1) AGAINST ('jkl');",
   112  				CheckIndexedAccess: true,
   113  				Expected:           []sql.Row{{uint64(2), "jkl", "ghi"}},
   114  			},
   115  			{
   116  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   117  				CheckIndexedAccess: true,
   118  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
   119  			},
   120  		},
   121  	},
   122  	{
   123  		Name: "Basic matching No Keys",
   124  		SetUpScript: []string{
   125  			"CREATE TABLE test (v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   126  			"INSERT INTO test VALUES ('abc', 'def pqr'), ('ghi', 'jkl'), ('mno', 'mno'), ('stu vwx', 'xyz zyx yzx'), ('ghs', 'mno shg');",
   127  		},
   128  		Assertions: []ScriptTestAssertion{
   129  			{
   130  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   131  				CheckIndexedAccess: false,
   132  				Expected:           []sql.Row{{"ghi", "jkl"}},
   133  			},
   134  			{
   135  				Query:              "SELECT v1 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   136  				CheckIndexedAccess: false,
   137  				Expected:           []sql.Row{{"ghi"}},
   138  			},
   139  			{
   140  				Query:              "SELECT v2 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   141  				CheckIndexedAccess: false,
   142  				Expected:           []sql.Row{{"jkl"}},
   143  			},
   144  			{
   145  				Query:              "SELECT v2, v1 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   146  				CheckIndexedAccess: false,
   147  				Expected:           []sql.Row{{"jkl", "ghi"}},
   148  			},
   149  			{
   150  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl');",
   151  				CheckIndexedAccess: false,
   152  				Expected:           []sql.Row{{"ghi", "jkl"}},
   153  			},
   154  			{
   155  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   156  				CheckIndexedAccess: false,
   157  				Expected:           []sql.Row{{"ghi", "jkl"}, {"mno", "mno"}, {"ghs", "mno shg"}},
   158  			},
   159  		},
   160  	},
   161  	{
   162  		Name: "Basic matching 2 PKs",
   163  		SetUpScript: []string{
   164  			"CREATE TABLE test (pk1 BIGINT UNSIGNED, pk2 BIGINT UNSIGNED, v1 VARCHAR(200), v2 VARCHAR(200), PRIMARY KEY (pk1, pk2), FULLTEXT idx (v1, v2));",
   165  			"INSERT INTO test VALUES (1, 1, 'abc', 'def pqr'), (2, 1, 'ghi', 'jkl'), (3, 1, 'mno', 'mno'), (4, 1, 'stu vwx', 'xyz zyx yzx'), (5, 1, 'ghs', 'mno shg');",
   166  		},
   167  		Assertions: []ScriptTestAssertion{
   168  			{
   169  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   170  				CheckIndexedAccess: true,
   171  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}},
   172  			},
   173  			{
   174  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   175  				CheckIndexedAccess: true,
   176  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}, {uint64(3), uint64(1), "mno", "mno"}, {uint64(5), uint64(1), "ghs", "mno shg"}},
   177  			},
   178  		},
   179  	},
   180  	{
   181  		Name: "Basic matching 2 PKs Reversed",
   182  		SetUpScript: []string{
   183  			"CREATE TABLE test (pk1 BIGINT UNSIGNED, pk2 BIGINT UNSIGNED, v1 VARCHAR(200), v2 VARCHAR(200), PRIMARY KEY (pk2, pk1), FULLTEXT idx (v1, v2));",
   184  			"INSERT INTO test VALUES (1, 1, 'abc', 'def pqr'), (2, 1, 'ghi', 'jkl'), (3, 1, 'mno', 'mno'), (4, 1, 'stu vwx', 'xyz zyx yzx'), (5, 1, 'ghs', 'mno shg');",
   185  		},
   186  		Assertions: []ScriptTestAssertion{
   187  			{
   188  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   189  				CheckIndexedAccess: true,
   190  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}},
   191  			},
   192  			{
   193  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   194  				CheckIndexedAccess: true,
   195  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}, {uint64(3), uint64(1), "mno", "mno"}, {uint64(5), uint64(1), "ghs", "mno shg"}},
   196  			},
   197  		},
   198  	},
   199  	{
   200  		Name: "Basic matching 2 PKs Non-Sequential",
   201  		SetUpScript: []string{
   202  			"CREATE TABLE test (pk1 BIGINT UNSIGNED, v1 VARCHAR(200), pk2 BIGINT UNSIGNED, v2 VARCHAR(200), PRIMARY KEY (pk2, pk1), FULLTEXT idx (v1, v2));",
   203  			"INSERT INTO test VALUES (1, 'abc', 1, 'def pqr'), (2, 'ghi', 1, 'jkl'), (3, 'mno', 1, 'mno'), (4, 'stu vwx', 1, 'xyz zyx yzx'), (5, 'ghs', 1, 'mno shg');",
   204  		},
   205  		Assertions: []ScriptTestAssertion{
   206  			{
   207  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   208  				CheckIndexedAccess: true,
   209  				Expected:           []sql.Row{{uint64(2), "ghi", uint64(1), "jkl"}},
   210  			},
   211  			{
   212  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   213  				CheckIndexedAccess: true,
   214  				Expected:           []sql.Row{{uint64(2), "ghi", uint64(1), "jkl"}, {uint64(3), "mno", uint64(1), "mno"}, {uint64(5), "ghs", uint64(1), "mno shg"}},
   215  			},
   216  		},
   217  	},
   218  	{
   219  		Name: "Basic matching 2 UKs",
   220  		SetUpScript: []string{
   221  			"CREATE TABLE test (uk1 BIGINT UNSIGNED NOT NULL, uk2 BIGINT UNSIGNED NOT NULL, v1 VARCHAR(200), v2 VARCHAR(200), UNIQUE KEY (uk1, uk2), FULLTEXT idx (v1, v2));",
   222  			"INSERT INTO test VALUES (1, 1, 'abc', 'def pqr'), (2, 1, 'ghi', 'jkl'), (3, 1, 'mno', 'mno'), (4, 1, 'stu vwx', 'xyz zyx yzx'), (5, 1, 'ghs', 'mno shg');",
   223  		},
   224  		Assertions: []ScriptTestAssertion{
   225  			{
   226  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   227  				CheckIndexedAccess: true,
   228  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}},
   229  			},
   230  			{
   231  				Query:              "SELECT v2, uk2 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   232  				CheckIndexedAccess: true,
   233  				Expected:           []sql.Row{{"jkl", uint64(1)}},
   234  			},
   235  			{
   236  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   237  				CheckIndexedAccess: true,
   238  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}, {uint64(3), uint64(1), "mno", "mno"}, {uint64(5), uint64(1), "ghs", "mno shg"}},
   239  			},
   240  		},
   241  	},
   242  	{
   243  		Name: "Basic matching 2 UKs Reversed",
   244  		SetUpScript: []string{
   245  			"CREATE TABLE test (uk1 BIGINT UNSIGNED NOT NULL, uk2 BIGINT UNSIGNED NOT NULL, v1 VARCHAR(200), v2 VARCHAR(200), UNIQUE KEY (uk2, uk1), FULLTEXT idx (v1, v2));",
   246  			"INSERT INTO test VALUES (1, 1, 'abc', 'def pqr'), (2, 1, 'ghi', 'jkl'), (3, 1, 'mno', 'mno'), (4, 1, 'stu vwx', 'xyz zyx yzx'), (5, 1, 'ghs', 'mno shg');",
   247  		},
   248  		Assertions: []ScriptTestAssertion{
   249  			{
   250  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   251  				CheckIndexedAccess: true,
   252  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}},
   253  			},
   254  			{
   255  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   256  				CheckIndexedAccess: true,
   257  				Expected:           []sql.Row{{uint64(2), uint64(1), "ghi", "jkl"}, {uint64(3), uint64(1), "mno", "mno"}, {uint64(5), uint64(1), "ghs", "mno shg"}},
   258  			},
   259  		},
   260  	},
   261  	{
   262  		Name: "Basic matching 2 UKs Non-Sequential",
   263  		SetUpScript: []string{
   264  			"CREATE TABLE test (uk1 BIGINT UNSIGNED NOT NULL, v1 VARCHAR(200), uk2 BIGINT UNSIGNED NOT NULL, v2 VARCHAR(200), UNIQUE KEY (uk1, uk2), FULLTEXT idx (v1, v2));",
   265  			"INSERT INTO test VALUES (1, 'abc', 1, 'def pqr'), (2, 'ghi', 1, 'jkl'), (3, 'mno', 1, 'mno'), (4, 'stu vwx', 1, 'xyz zyx yzx'), (5, 'ghs', 1, 'mno shg');",
   266  		},
   267  		Assertions: []ScriptTestAssertion{
   268  			{
   269  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   270  				CheckIndexedAccess: true,
   271  				Expected:           []sql.Row{{uint64(2), "ghi", uint64(1), "jkl"}},
   272  			},
   273  			{
   274  				Query:              "SELECT v2, uk2 FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   275  				CheckIndexedAccess: true,
   276  				Expected:           []sql.Row{{"jkl", uint64(1)}},
   277  			},
   278  			{
   279  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   280  				CheckIndexedAccess: true,
   281  				Expected:           []sql.Row{{uint64(2), "ghi", uint64(1), "jkl"}, {uint64(3), "mno", uint64(1), "mno"}, {uint64(5), "ghs", uint64(1), "mno shg"}},
   282  			},
   283  		},
   284  	},
   285  	{
   286  		Name: "Basic UPDATE and DELETE checks",
   287  		SetUpScript: []string{
   288  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   289  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   290  		},
   291  		Assertions: []ScriptTestAssertion{
   292  			{
   293  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   294  				CheckIndexedAccess: true,
   295  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   296  			},
   297  			{
   298  				Query:    "UPDATE test SET v1 = 'rgb' WHERE pk = 2;",
   299  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
   300  			},
   301  			{
   302  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   303  				CheckIndexedAccess: true,
   304  				Expected:           []sql.Row{},
   305  			},
   306  			{
   307  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('rgb');",
   308  				CheckIndexedAccess: true,
   309  				Expected:           []sql.Row{{uint64(2), "rgb", "jkl"}},
   310  			},
   311  			{
   312  				Query:    "UPDATE test SET v2 = 'mno' WHERE pk = 2;",
   313  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
   314  			},
   315  			{
   316  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('mno');",
   317  				CheckIndexedAccess: true,
   318  				Expected:           []sql.Row{{uint64(2), "rgb", "mno"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
   319  			},
   320  			{
   321  				Query:    "DELETE FROM test WHERE pk = 3;",
   322  				Expected: []sql.Row{{types.NewOkResult(1)}},
   323  			},
   324  			{
   325  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('mno');",
   326  				CheckIndexedAccess: true,
   327  				Expected:           []sql.Row{{uint64(2), "rgb", "mno"}, {uint64(5), "ghs", "mno shg"}},
   328  			},
   329  		},
   330  	},
   331  	{
   332  		Name: "NULL handling",
   333  		SetUpScript: []string{
   334  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   335  			"INSERT INTO test VALUES (1, 'abc', NULL), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, NULL, NULL), (5, 'ghs', 'mno shg');",
   336  		},
   337  		Assertions: []ScriptTestAssertion{
   338  			{ // Full-Text handles NULL values by ignoring them, meaning non-null values are still added to the document
   339  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('abc');",
   340  				CheckIndexedAccess: true,
   341  				Expected:           []sql.Row{{uint64(1), "abc", nil}},
   342  			},
   343  			{
   344  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   345  				CheckIndexedAccess: true,
   346  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   347  			},
   348  			{
   349  				Query:    "UPDATE test SET v1 = NULL WHERE pk = 2;",
   350  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1, Info: plan.UpdateInfo{Matched: 1, Updated: 1}}}},
   351  			},
   352  			{
   353  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   354  				CheckIndexedAccess: true,
   355  				Expected:           []sql.Row{},
   356  			},
   357  			{
   358  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('jkl');",
   359  				CheckIndexedAccess: true,
   360  				Expected:           []sql.Row{{uint64(2), nil, "jkl"}},
   361  			},
   362  			{
   363  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST (NULL);",
   364  				CheckIndexedAccess: true,
   365  				Expected:           []sql.Row{},
   366  			},
   367  			{
   368  				Query:              "SELECT pk, v1, v2, MATCH(v1, v2) AGAINST (NULL) FROM test;",
   369  				CheckIndexedAccess: false,
   370  				Expected: []sql.Row{
   371  					{uint64(1), "abc", nil, float32(0)},
   372  					{uint64(2), nil, "jkl", float32(0)},
   373  					{uint64(3), "mno", "mno", float32(0)},
   374  					{uint64(4), nil, nil, float32(0)},
   375  					{uint64(5), "ghs", "mno shg", float32(0)},
   376  				},
   377  			},
   378  			{
   379  				Query:    "DROP INDEX idx ON test;",
   380  				Expected: []sql.Row{{types.NewOkResult(0)}},
   381  			},
   382  			{
   383  				Query:    "ALTER TABLE test ADD FULLTEXT INDEX idx (v1, v2);",
   384  				Expected: []sql.Row{{types.NewOkResult(0)}},
   385  			},
   386  		},
   387  	},
   388  	{
   389  		Name: "Collation handling",
   390  		SetUpScript: []string{
   391  			"CREATE TABLE test1 (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200) COLLATE utf8mb4_0900_bin, v2 VARCHAR(200) COLLATE utf8mb4_0900_bin, FULLTEXT idx (v1, v2));",
   392  			"CREATE TABLE test2 (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200) COLLATE utf8mb4_0900_ai_ci, v2 VARCHAR(200) COLLATE utf8mb4_0900_ai_ci, FULLTEXT idx (v1, v2));",
   393  			"INSERT INTO test1 VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   394  			"INSERT INTO test2 VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   395  		},
   396  		Assertions: []ScriptTestAssertion{
   397  			{
   398  				Query:              "SELECT * FROM test1 WHERE MATCH(v1, v2) AGAINST ('ghi');",
   399  				CheckIndexedAccess: true,
   400  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   401  			},
   402  			{
   403  				Query:              "SELECT * FROM test1 WHERE MATCH(v2, v1) AGAINST ('jkl') = 0;",
   404  				CheckIndexedAccess: false,
   405  				Expected:           []sql.Row{{uint64(1), "abc", "def pqr"}, {uint64(3), "mno", "mno"}, {uint64(4), "stu vwx", "xyz zyx yzx"}, {uint64(5), "ghs", "mno shg"}},
   406  			},
   407  			{
   408  				Query:              "SELECT * FROM test1 WHERE MATCH(v2, v1) AGAINST ('jkl mno') AND pk = 3;",
   409  				CheckIndexedAccess: false,
   410  				Expected:           []sql.Row{{uint64(3), "mno", "mno"}},
   411  			},
   412  			{
   413  				Query:              "SELECT * FROM test1 WHERE MATCH(v1, v2) AGAINST ('GHI');",
   414  				CheckIndexedAccess: true,
   415  				Expected:           []sql.Row{},
   416  			},
   417  			{
   418  				Query:              "SELECT * FROM test1 WHERE MATCH(v2, v1) AGAINST ('JKL') = 0;",
   419  				CheckIndexedAccess: false,
   420  				Expected:           []sql.Row{{uint64(1), "abc", "def pqr"}, {uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(4), "stu vwx", "xyz zyx yzx"}, {uint64(5), "ghs", "mno shg"}},
   421  			},
   422  			{
   423  				Query:              "SELECT * FROM test1 WHERE MATCH(v2, v1) AGAINST ('JKL MNO') AND pk = 3;",
   424  				CheckIndexedAccess: false,
   425  				Expected:           []sql.Row{},
   426  			},
   427  			{
   428  				Query:              "SELECT * FROM test2 WHERE MATCH(v1, v2) AGAINST ('ghi');",
   429  				CheckIndexedAccess: true,
   430  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   431  			},
   432  			{
   433  				Query:              "SELECT * FROM test2 WHERE MATCH(v2, v1) AGAINST ('jkl') = 0;",
   434  				CheckIndexedAccess: false,
   435  				Expected:           []sql.Row{{uint64(1), "abc", "def pqr"}, {uint64(3), "mno", "mno"}, {uint64(4), "stu vwx", "xyz zyx yzx"}, {uint64(5), "ghs", "mno shg"}},
   436  			},
   437  			{
   438  				Query:              "SELECT * FROM test2 WHERE MATCH(v2, v1) AGAINST ('jkl mno') AND pk = 3;",
   439  				CheckIndexedAccess: true,
   440  				Expected:           []sql.Row{{uint64(3), "mno", "mno"}},
   441  			},
   442  			{
   443  				Query:              "SELECT * FROM test2 WHERE MATCH(v1, v2) AGAINST ('GHI');",
   444  				CheckIndexedAccess: true,
   445  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   446  			},
   447  			{
   448  				Query:              "SELECT * FROM test2 WHERE MATCH(v2, v1) AGAINST ('JKL') = 0;",
   449  				CheckIndexedAccess: false,
   450  				Expected:           []sql.Row{{uint64(1), "abc", "def pqr"}, {uint64(3), "mno", "mno"}, {uint64(4), "stu vwx", "xyz zyx yzx"}, {uint64(5), "ghs", "mno shg"}},
   451  			},
   452  			{
   453  				Query:              "SELECT * FROM test2 WHERE MATCH(v2, v1) AGAINST ('JKL MNO') AND pk = 3;",
   454  				CheckIndexedAccess: true,
   455  				Expected:           []sql.Row{{uint64(3), "mno", "mno"}},
   456  			},
   457  		},
   458  	},
   459  	{ // We should not have many relevancy tests since the values are subject to change if/when the algorithm gets updated
   460  		Name: "Relevancy Ordering",
   461  		SetUpScript: []string{
   462  			"CREATE TABLE test (pk INT PRIMARY KEY, doc TEXT, FULLTEXT idx (doc)) COLLATE=utf8mb4_general_ci;",
   463  			"INSERT INTO test VALUES (2, 'g hhhh aaaab ooooo aaaa'), (1, 'bbbb ff cccc ddd eee'), (4, 'AAAA aaaa aaaac aaaa Aaaa aaaa'), (3, 'aaaA ff j kkkk llllllll');",
   464  		},
   465  		Assertions: []ScriptTestAssertion{
   466  			{
   467  				Query: "SELECT MATCH(doc) AGAINST('aaaa') AS relevance FROM test ORDER BY relevance DESC;",
   468  				Expected: []sql.Row{
   469  					{float32(5.9636202)},
   470  					{float32(4.0278959)},
   471  					{float32(3.3721533)},
   472  					{float32(0)},
   473  				},
   474  			},
   475  			{
   476  				Query: "SELECT MATCH(doc) AGAINST('aaaa') AS relevance, pk FROM test ORDER BY relevance DESC;",
   477  				Expected: []sql.Row{
   478  					{float32(5.9636202), int32(4)},
   479  					{float32(4.0278959), int32(2)},
   480  					{float32(3.3721533), int32(3)},
   481  					{float32(0), int32(1)},
   482  				},
   483  			},
   484  			{
   485  				Query: "SELECT pk, MATCH(doc) AGAINST('aaaa') AS relevance FROM test ORDER BY relevance ASC;",
   486  				Expected: []sql.Row{
   487  					{int32(1), float32(0)},
   488  					{int32(3), float32(3.3721533)},
   489  					{int32(2), float32(4.0278959)},
   490  					{int32(4), float32(5.9636202)},
   491  				},
   492  			},
   493  			{
   494  				Query: "SELECT pk, doc, MATCH(doc) AGAINST('aaaa') AS relevance FROM test ORDER BY relevance DESC;",
   495  				Expected: []sql.Row{
   496  					{int32(4), "AAAA aaaa aaaac aaaa Aaaa aaaa", float32(5.9636202)},
   497  					{int32(2), "g hhhh aaaab ooooo aaaa", float32(4.0278959)},
   498  					{int32(3), "aaaA ff j kkkk llllllll", float32(3.3721533)},
   499  					{int32(1), "bbbb ff cccc ddd eee", float32(0)},
   500  				},
   501  			},
   502  			{
   503  				Query: "SELECT pk, doc, MATCH(doc) AGAINST('aaaa') AS relevance FROM test ORDER BY relevance ASC;",
   504  				Expected: []sql.Row{
   505  					{int32(1), "bbbb ff cccc ddd eee", float32(0)},
   506  					{int32(3), "aaaA ff j kkkk llllllll", float32(3.3721533)},
   507  					{int32(2), "g hhhh aaaab ooooo aaaa", float32(4.0278959)},
   508  					{int32(4), "AAAA aaaa aaaac aaaa Aaaa aaaa", float32(5.9636202)},
   509  				},
   510  			},
   511  			{
   512  				Query: "SELECT pk FROM test ORDER BY MATCH(doc) AGAINST('aaaa') DESC;",
   513  				Expected: []sql.Row{
   514  					{int32(4)},
   515  					{int32(2)},
   516  					{int32(3)},
   517  					{int32(1)},
   518  				},
   519  			},
   520  			{
   521  				Query: "SELECT pk, doc FROM test ORDER BY MATCH(doc) AGAINST('aaaa') ASC;",
   522  				Expected: []sql.Row{
   523  					{int32(1), "bbbb ff cccc ddd eee"},
   524  					{int32(3), "aaaA ff j kkkk llllllll"},
   525  					{int32(2), "g hhhh aaaab ooooo aaaa"},
   526  					{int32(4), "AAAA aaaa aaaac aaaa Aaaa aaaa"},
   527  				},
   528  			},
   529  			{
   530  				Query: "SELECT 1 FROM test ORDER BY MATCH(doc) AGAINST('aaaa') DESC;",
   531  				Expected: []sql.Row{
   532  					{int32(1)},
   533  					{int32(1)},
   534  					{int32(1)},
   535  					{int32(1)},
   536  				},
   537  			},
   538  			{
   539  				Query: "SELECT pk, MATCH(doc) AGAINST('aaaa') AS relevance FROM test HAVING relevance > 4 ORDER BY relevance DESC;",
   540  				Expected: []sql.Row{
   541  					{int32(4), float32(5.9636202)},
   542  					{int32(2), float32(4.0278959)},
   543  				},
   544  			},
   545  			{ // Test with an added column to ensure that unnecessary columns do not affect the results
   546  				Query:    "ALTER TABLE test ADD COLUMN extracol INT DEFAULT 7;",
   547  				Expected: []sql.Row{{types.NewOkResult(0)}},
   548  			},
   549  			{
   550  				Query: "SELECT pk FROM test ORDER BY MATCH(doc) AGAINST('aaaa') DESC;",
   551  				Expected: []sql.Row{
   552  					{int32(4)},
   553  					{int32(2)},
   554  					{int32(3)},
   555  					{int32(1)},
   556  				},
   557  			},
   558  			{ // Drop the primary key to ensure that results are still consistent without a primary key
   559  				Query:    "ALTER TABLE test DROP PRIMARY KEY;",
   560  				Expected: []sql.Row{{types.NewOkResult(0)}},
   561  			},
   562  			{
   563  				Query: "SELECT pk FROM test ORDER BY MATCH(doc) AGAINST('aaaa') ASC;",
   564  				Expected: []sql.Row{
   565  					{int32(1)},
   566  					{int32(3)},
   567  					{int32(2)},
   568  					{int32(4)},
   569  				},
   570  			},
   571  			{
   572  				Query: "SELECT pk, MATCH(doc) AGAINST('aaaa') AS relevance FROM test ORDER BY relevance DESC;",
   573  				Expected: []sql.Row{
   574  					{int32(4), float32(5.9636202)},
   575  					{int32(2), float32(4.0278959)},
   576  					{int32(3), float32(3.3721533)},
   577  					{int32(1), float32(0)},
   578  				},
   579  			},
   580  		},
   581  	},
   582  	{
   583  		Name: "CREATE INDEX before insertions",
   584  		SetUpScript: []string{
   585  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200));",
   586  			"CREATE FULLTEXT INDEX idx ON test (v1, v2);",
   587  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   588  		},
   589  		Assertions: []ScriptTestAssertion{
   590  			{
   591  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   592  				CheckIndexedAccess: true,
   593  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   594  			},
   595  			{
   596  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   597  				CheckIndexedAccess: true,
   598  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
   599  			},
   600  		},
   601  	},
   602  	{
   603  		Name: "CREATE INDEX after insertions",
   604  		SetUpScript: []string{
   605  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200));",
   606  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   607  			"CREATE FULLTEXT INDEX idx ON test (v1, v2);",
   608  		},
   609  		Assertions: []ScriptTestAssertion{
   610  			{
   611  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   612  				CheckIndexedAccess: true,
   613  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   614  			},
   615  			{
   616  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   617  				CheckIndexedAccess: true,
   618  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
   619  			},
   620  		},
   621  	},
   622  	{
   623  		Name: "ALTER TABLE CREATE INDEX before insertions",
   624  		SetUpScript: []string{
   625  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200));",
   626  			"ALTER TABLE test ADD FULLTEXT INDEX idx (v1, v2);",
   627  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   628  		},
   629  		Assertions: []ScriptTestAssertion{
   630  			{
   631  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   632  				CheckIndexedAccess: true,
   633  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   634  			},
   635  			{
   636  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   637  				CheckIndexedAccess: true,
   638  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
   639  			},
   640  		},
   641  	},
   642  	{
   643  		Name: "ALTER TABLE CREATE INDEX after insertions",
   644  		SetUpScript: []string{
   645  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200));",
   646  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   647  			"ALTER TABLE test ADD FULLTEXT INDEX idx (v1, v2);",
   648  		},
   649  		Assertions: []ScriptTestAssertion{
   650  			{
   651  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   652  				CheckIndexedAccess: true,
   653  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   654  			},
   655  			{
   656  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('jkl mno');",
   657  				CheckIndexedAccess: true,
   658  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}, {uint64(3), "mno", "mno"}, {uint64(5), "ghs", "mno shg"}},
   659  			},
   660  		},
   661  	},
   662  	{
   663  		Name: "DROP INDEX",
   664  		SetUpScript: []string{
   665  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   666  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   667  		},
   668  		Assertions: []ScriptTestAssertion{
   669  			{
   670  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   671  				CheckIndexedAccess: true,
   672  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   673  			},
   674  			{
   675  				Query:    "DROP INDEX idx ON test;",
   676  				Expected: []sql.Row{{types.NewOkResult(0)}},
   677  			},
   678  			{
   679  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   680  				CheckIndexedAccess: true,
   681  				ExpectedErr:        sql.ErrNoFullTextIndexFound,
   682  			},
   683  		},
   684  	},
   685  	{
   686  		Name: "ALTER TABLE DROP INDEX",
   687  		SetUpScript: []string{
   688  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200));",
   689  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   690  			"CREATE FULLTEXT INDEX idx ON test (v1, v2);",
   691  		},
   692  		Assertions: []ScriptTestAssertion{
   693  			{
   694  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   695  				CheckIndexedAccess: true,
   696  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   697  			},
   698  			{
   699  				Query:    "ALTER TABLE test DROP INDEX idx;",
   700  				Expected: []sql.Row{{types.NewOkResult(0)}},
   701  			},
   702  			{
   703  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   704  				CheckIndexedAccess: true,
   705  				ExpectedErr:        sql.ErrNoFullTextIndexFound,
   706  			},
   707  		},
   708  	},
   709  	{
   710  		Name: "ALTER TABLE ADD COLUMN",
   711  		SetUpScript: []string{
   712  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   713  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   714  		},
   715  		Assertions: []ScriptTestAssertion{
   716  			{
   717  				Query:    "ALTER TABLE test ADD COLUMN v3 FLOAT DEFAULT 7 FIRST;",
   718  				Expected: []sql.Row{{types.NewOkResult(0)}},
   719  			},
   720  			{
   721  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   722  				CheckIndexedAccess: true,
   723  				Expected:           []sql.Row{{float32(7), uint64(2), "ghi", "jkl"}},
   724  			},
   725  		},
   726  	},
   727  	{
   728  		Name: "ALTER TABLE MODIFY COLUMN not used by index",
   729  		SetUpScript: []string{
   730  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), v3 BIGINT UNSIGNED, FULLTEXT idx (v1, v2));",
   731  			"INSERT INTO test VALUES (1, 'abc', 'def pqr', 7), (2, 'ghi', 'jkl', 7), (3, 'mno', 'mno', 7), (4, 'stu vwx', 'xyz zyx yzx', 7), (5, 'ghs', 'mno shg', 7);",
   732  		},
   733  		Assertions: []ScriptTestAssertion{
   734  			{
   735  				Query:    "ALTER TABLE test MODIFY COLUMN v3 FLOAT AFTER pk;",
   736  				Expected: []sql.Row{{types.NewOkResult(0)}},
   737  			},
   738  			{
   739  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   740  				CheckIndexedAccess: true,
   741  				Expected:           []sql.Row{{uint64(2), float32(7), "ghi", "jkl"}},
   742  			},
   743  		},
   744  	},
   745  	{
   746  		Name: "ALTER TABLE MODIFY COLUMN used by index to valid type",
   747  		SetUpScript: []string{
   748  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   749  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   750  		},
   751  		Assertions: []ScriptTestAssertion{
   752  			{
   753  				Query:    "ALTER TABLE test MODIFY COLUMN v2 TEXT;",
   754  				Expected: []sql.Row{{types.NewOkResult(0)}},
   755  			},
   756  			{
   757  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   758  				CheckIndexedAccess: true,
   759  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   760  			},
   761  		},
   762  	},
   763  	{
   764  		Name: "ALTER TABLE MODIFY COLUMN used by index to invalid type",
   765  		SetUpScript: []string{
   766  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   767  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   768  		},
   769  		Assertions: []ScriptTestAssertion{
   770  			{
   771  				Query:       "ALTER TABLE test MODIFY COLUMN v2 VARBINARY(200);",
   772  				ExpectedErr: sql.ErrFullTextInvalidColumnType,
   773  			},
   774  		},
   775  	},
   776  	{
   777  		Name: "ALTER TABLE DROP COLUMN not used by index",
   778  		SetUpScript: []string{
   779  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), v3 BIGINT UNSIGNED, FULLTEXT idx (v1, v2));",
   780  			"INSERT INTO test VALUES (1, 'abc', 'def pqr', 7), (2, 'ghi', 'jkl', 7), (3, 'mno', 'mno', 7), (4, 'stu vwx', 'xyz zyx yzx', 7), (5, 'ghs', 'mno shg', 7);",
   781  		},
   782  		Assertions: []ScriptTestAssertion{
   783  			{
   784  				Query:    "ALTER TABLE test DROP COLUMN v3;",
   785  				Expected: []sql.Row{{types.NewOkResult(0)}},
   786  			},
   787  			{
   788  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   789  				CheckIndexedAccess: true,
   790  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   791  			},
   792  		},
   793  	},
   794  	{
   795  		Name: "ALTER TABLE DROP COLUMN used by index",
   796  		SetUpScript: []string{
   797  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), v3 VARCHAR(200), FULLTEXT idx1 (v1, v2), FULLTEXT idx2 (v2), FULLTEXT idx3 (v2, v3));",
   798  			"INSERT INTO test VALUES (1, 'abc', 'def', 'ghi');",
   799  		},
   800  		Assertions: []ScriptTestAssertion{
   801  			{
   802  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('abc');",
   803  				CheckIndexedAccess: true,
   804  				Expected:           []sql.Row{{uint64(1), "abc", "def", "ghi"}},
   805  			},
   806  			{
   807  				Query:              "SELECT * FROM test WHERE MATCH(v2) AGAINST ('def');",
   808  				CheckIndexedAccess: true,
   809  				Expected:           []sql.Row{{uint64(1), "abc", "def", "ghi"}},
   810  			},
   811  			{
   812  				Query:              "SELECT * FROM test WHERE MATCH(v2, v3) AGAINST ('ghi');",
   813  				CheckIndexedAccess: true,
   814  				Expected:           []sql.Row{{uint64(1), "abc", "def", "ghi"}},
   815  			},
   816  			{
   817  				Query:    "SHOW CREATE TABLE test;",
   818  				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `pk` bigint unsigned NOT NULL,\n  `v1` varchar(200),\n  `v2` varchar(200),\n  `v3` varchar(200),\n  PRIMARY KEY (`pk`),\n  FULLTEXT KEY `idx1` (`v1`,`v2`),\n  FULLTEXT KEY `idx2` (`v2`),\n  FULLTEXT KEY `idx3` (`v2`,`v3`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   819  			},
   820  			{
   821  				Query:    "ALTER TABLE test DROP COLUMN v2;",
   822  				Expected: []sql.Row{{types.NewOkResult(0)}},
   823  			},
   824  			{
   825  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('abc');",
   826  				CheckIndexedAccess: true,
   827  				ExpectedErr:        sql.ErrColumnNotFound,
   828  			},
   829  			{
   830  				Query:              "SELECT * FROM test WHERE MATCH(v2) AGAINST ('def');",
   831  				CheckIndexedAccess: true,
   832  				ExpectedErr:        sql.ErrColumnNotFound,
   833  			},
   834  			{
   835  				Query:              "SELECT * FROM test WHERE MATCH(v2, v3) AGAINST ('ghi');",
   836  				CheckIndexedAccess: true,
   837  				ExpectedErr:        sql.ErrColumnNotFound,
   838  			},
   839  			{
   840  				Query:              "SELECT * FROM test WHERE MATCH(v1) AGAINST ('abc');",
   841  				CheckIndexedAccess: true,
   842  				Expected:           []sql.Row{{uint64(1), "abc", "ghi"}},
   843  			},
   844  			{
   845  				Query:              "SELECT * FROM test WHERE MATCH(v3) AGAINST ('ghi');",
   846  				CheckIndexedAccess: true,
   847  				Expected:           []sql.Row{{uint64(1), "abc", "ghi"}},
   848  			},
   849  			{
   850  				Query:    "SHOW CREATE TABLE test;",
   851  				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `pk` bigint unsigned NOT NULL,\n  `v1` varchar(200),\n  `v3` varchar(200),\n  PRIMARY KEY (`pk`),\n  FULLTEXT KEY `idx1` (`v1`),\n  FULLTEXT KEY `idx3` (`v3`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   852  			},
   853  			{
   854  				Query:    "ALTER TABLE test DROP COLUMN v3;",
   855  				Expected: []sql.Row{{types.NewOkResult(0)}},
   856  			},
   857  			{
   858  				Query:              "SELECT * FROM test WHERE MATCH(v1) AGAINST ('abc');",
   859  				CheckIndexedAccess: true,
   860  				Expected:           []sql.Row{{uint64(1), "abc"}},
   861  			},
   862  			{
   863  				Query:              "SELECT * FROM test WHERE MATCH(v3) AGAINST ('ghi');",
   864  				CheckIndexedAccess: true,
   865  				ExpectedErr:        sql.ErrColumnNotFound,
   866  			},
   867  			{
   868  				Query:    "SHOW CREATE TABLE test;",
   869  				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `pk` bigint unsigned NOT NULL,\n  `v1` varchar(200),\n  PRIMARY KEY (`pk`),\n  FULLTEXT KEY `idx1` (`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   870  			},
   871  		},
   872  	},
   873  	{
   874  		Name: "ALTER TABLE ADD PRIMARY KEY",
   875  		SetUpScript: []string{
   876  			"CREATE TABLE test (pk BIGINT UNSIGNED, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   877  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   878  		},
   879  		Assertions: []ScriptTestAssertion{
   880  			{
   881  				Query:    "ALTER TABLE test ADD PRIMARY KEY (pk);",
   882  				Expected: []sql.Row{{types.NewOkResult(0)}},
   883  			},
   884  			{
   885  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   886  				CheckIndexedAccess: true,
   887  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   888  			},
   889  		},
   890  	},
   891  	{
   892  		Name: "ALTER TABLE DROP PRIMARY KEY",
   893  		SetUpScript: []string{
   894  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   895  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   896  		},
   897  		Assertions: []ScriptTestAssertion{
   898  			{
   899  				Query:    "ALTER TABLE test DROP PRIMARY KEY;",
   900  				Expected: []sql.Row{{types.NewOkResult(0)}},
   901  			},
   902  			{
   903  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   904  				CheckIndexedAccess: false,
   905  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   906  			},
   907  		},
   908  	},
   909  	{
   910  		Name: "ALTER TABLE DROP TABLE",
   911  		SetUpScript: []string{
   912  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   913  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   914  		},
   915  		Assertions: []ScriptTestAssertion{
   916  			{ // This is mainly to check for a panic
   917  				Query:    "DROP TABLE test;",
   918  				Expected: []sql.Row{{types.NewOkResult(0)}},
   919  			},
   920  		},
   921  	},
   922  	{
   923  		Name: "TRUNCATE TABLE",
   924  		SetUpScript: []string{
   925  			"CREATE TABLE test (pk BIGINT UNSIGNED PRIMARY KEY, v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   926  			"INSERT INTO test VALUES (1, 'abc', 'def pqr'), (2, 'ghi', 'jkl'), (3, 'mno', 'mno'), (4, 'stu vwx', 'xyz zyx yzx'), (5, 'ghs', 'mno shg');",
   927  		},
   928  		Assertions: []ScriptTestAssertion{
   929  			{
   930  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   931  				CheckIndexedAccess: true,
   932  				Expected:           []sql.Row{{uint64(2), "ghi", "jkl"}},
   933  			},
   934  			{
   935  				Query:    "TRUNCATE TABLE test;",
   936  				Expected: []sql.Row{{types.NewOkResult(5)}},
   937  			},
   938  			{
   939  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
   940  				CheckIndexedAccess: true,
   941  				Expected:           []sql.Row{},
   942  			},
   943  		},
   944  	},
   945  	{
   946  		Name: "No prefix needed for TEXT columns",
   947  		Assertions: []ScriptTestAssertion{
   948  			{
   949  				Query:    "CREATE TABLE `film_text` (`film_id` SMALLINT NOT NULL, `title` VARCHAR(255) NOT NULL, `description` TEXT, PRIMARY KEY (`film_id`), FULLTEXT KEY `idx_title_description` (`title`,`description`));",
   950  				Expected: []sql.Row{{types.NewOkResult(0)}},
   951  			},
   952  			{
   953  				Query:    "CREATE TABLE other_table (pk BIGINT PRIMARY KEY, v1 TEXT);",
   954  				Expected: []sql.Row{{types.NewOkResult(0)}},
   955  			},
   956  			{
   957  				Query:    "ALTER TABLE other_table ADD FULLTEXT INDEX idx (v1);",
   958  				Expected: []sql.Row{{types.NewOkResult(0)}},
   959  			},
   960  		},
   961  	},
   962  	{
   963  		Name: "Rename new table to match old table",
   964  		SetUpScript: []string{
   965  			"CREATE TABLE test1 (v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   966  			"INSERT INTO test1 VALUES ('abc', 'def');",
   967  		},
   968  		Assertions: []ScriptTestAssertion{
   969  			{
   970  				Query:    "RENAME TABLE test1 TO test2;",
   971  				Expected: []sql.Row{{types.NewOkResult(0)}},
   972  			},
   973  			{
   974  				Query:              "SELECT * FROM test2 WHERE MATCH(v1, v2) AGAINST ('abc');",
   975  				CheckIndexedAccess: false,
   976  				Expected:           []sql.Row{{"abc", "def"}},
   977  			},
   978  			{
   979  				Query:    "CREATE TABLE test1 (v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v2));",
   980  				Expected: []sql.Row{{types.NewOkResult(0)}},
   981  			},
   982  			{
   983  				Query:    "INSERT INTO test1 VALUES ('ghi', 'jkl');",
   984  				Expected: []sql.Row{{types.NewOkResult(1)}},
   985  			},
   986  			{
   987  				Query:              "SELECT * FROM test1 WHERE MATCH(v1, v2) AGAINST ('abc');",
   988  				CheckIndexedAccess: false,
   989  				Expected:           []sql.Row{},
   990  			},
   991  			{
   992  				Query:              "SELECT * FROM test2 WHERE MATCH(v1, v2) AGAINST ('abc');",
   993  				CheckIndexedAccess: false,
   994  				Expected:           []sql.Row{{"abc", "def"}},
   995  			},
   996  			{
   997  				Query:              "SELECT * FROM test1 WHERE MATCH(v1, v2) AGAINST ('jkl');",
   998  				CheckIndexedAccess: false,
   999  				Expected:           []sql.Row{{"ghi", "jkl"}},
  1000  			},
  1001  			{
  1002  				Query:              "SELECT * FROM test2 WHERE MATCH(v1, v2) AGAINST ('jkl');",
  1003  				CheckIndexedAccess: false,
  1004  				Expected:           []sql.Row{},
  1005  			},
  1006  		},
  1007  	},
  1008  	{
  1009  		Name: "Rename index",
  1010  		SetUpScript: []string{
  1011  			"CREATE TABLE test (v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v2, v1));",
  1012  			"INSERT INTO test VALUES ('abc', 'def');",
  1013  		},
  1014  		Assertions: []ScriptTestAssertion{
  1015  			{
  1016  				Query:    "SHOW CREATE TABLE test;",
  1017  				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `v1` varchar(200),\n  `v2` varchar(200),\n  FULLTEXT KEY `idx` (`v2`,`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
  1018  			},
  1019  			{
  1020  				Query:    "ALTER TABLE test RENAME INDEX idx TO new_idx;",
  1021  				Expected: []sql.Row{{types.NewOkResult(0)}},
  1022  			},
  1023  			{
  1024  				Query:              "SELECT * FROM test WHERE MATCH(v2, v1) AGAINST ('abc');",
  1025  				CheckIndexedAccess: false,
  1026  				Expected:           []sql.Row{{"abc", "def"}},
  1027  			},
  1028  			{
  1029  				Query:    "SHOW CREATE TABLE test;",
  1030  				Expected: []sql.Row{{"test", "CREATE TABLE `test` (\n  `v1` varchar(200),\n  `v2` varchar(200),\n  FULLTEXT KEY `new_idx` (`v2`,`v1`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
  1031  			},
  1032  		},
  1033  	},
  1034  	{
  1035  		Name: "Multiple overlapping indexes",
  1036  		SetUpScript: []string{
  1037  			"CREATE TABLE test (v1 TEXT, v2 VARCHAR(200), v3 MEDIUMTEXT, FULLTEXT idx1 (v1, v2), FULLTEXT idx2 (v1, v3), FULLTEXT idx3 (v2, v3));",
  1038  			"INSERT INTO test VALUES ('abc', 'def', 'ghi');",
  1039  		},
  1040  		Assertions: []ScriptTestAssertion{
  1041  			{
  1042  				Query: "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('abc');",
  1043  				// TODO keyColumns are null type, blocks index access
  1044  				CheckIndexedAccess: false,
  1045  				Expected:           []sql.Row{{"abc", "def", "ghi"}},
  1046  			},
  1047  			{
  1048  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('def');",
  1049  				CheckIndexedAccess: false,
  1050  				Expected:           []sql.Row{{"abc", "def", "ghi"}},
  1051  			},
  1052  			{
  1053  				Query:              "SELECT * FROM test WHERE MATCH(v1, v2) AGAINST ('ghi');",
  1054  				CheckIndexedAccess: false,
  1055  				Expected:           []sql.Row{},
  1056  			},
  1057  			{
  1058  				Query:              "SELECT * FROM test WHERE MATCH(v1, v3) AGAINST ('abc');",
  1059  				CheckIndexedAccess: false,
  1060  				Expected:           []sql.Row{{"abc", "def", "ghi"}},
  1061  			},
  1062  			{
  1063  				Query:              "SELECT * FROM test WHERE MATCH(v1, v3) AGAINST ('def');",
  1064  				CheckIndexedAccess: false,
  1065  				Expected:           []sql.Row{},
  1066  			},
  1067  			{
  1068  				Query:              "SELECT * FROM test WHERE MATCH(v1, v3) AGAINST ('ghi');",
  1069  				CheckIndexedAccess: false,
  1070  				Expected:           []sql.Row{{"abc", "def", "ghi"}},
  1071  			},
  1072  			{
  1073  				Query:              "SELECT * FROM test WHERE MATCH(v2, v3) AGAINST ('abc');",
  1074  				CheckIndexedAccess: false,
  1075  				Expected:           []sql.Row{},
  1076  			},
  1077  			{
  1078  				Query:              "SELECT * FROM test WHERE MATCH(v2, v3) AGAINST ('def');",
  1079  				CheckIndexedAccess: false,
  1080  				Expected:           []sql.Row{{"abc", "def", "ghi"}},
  1081  			},
  1082  			{
  1083  				Query:              "SELECT * FROM test WHERE MATCH(v2, v3) AGAINST ('ghi');",
  1084  				CheckIndexedAccess: false,
  1085  				Expected:           []sql.Row{{"abc", "def", "ghi"}},
  1086  			},
  1087  		},
  1088  	},
  1089  	{
  1090  		Name: "Duplicate column names",
  1091  		Assertions: []ScriptTestAssertion{
  1092  			{
  1093  				Query:       "CREATE TABLE test (v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v1, v1));",
  1094  				ExpectedErr: sql.ErrFullTextDuplicateColumn,
  1095  			},
  1096  		},
  1097  	},
  1098  	{
  1099  		Name: "References missing column",
  1100  		Assertions: []ScriptTestAssertion{
  1101  			{
  1102  				Query:       "CREATE TABLE test (v1 VARCHAR(200), v2 VARCHAR(200), FULLTEXT idx (v3));",
  1103  				ExpectedErr: sql.ErrUnknownIndexColumn,
  1104  			},
  1105  		},
  1106  	},
  1107  	{
  1108  		Name: "Creating an index on an invalid type",
  1109  		Assertions: []ScriptTestAssertion{
  1110  			{
  1111  				Query:       "CREATE TABLE test (v1 VARCHAR(200), v2 BIGINT, FULLTEXT idx (v1, v2));",
  1112  				ExpectedErr: sql.ErrFullTextInvalidColumnType,
  1113  			},
  1114  		},
  1115  	},
  1116  	{
  1117  		Name: "Foreign keys ignore Full-Text indexes",
  1118  		SetUpScript: []string{
  1119  			"CREATE TABLE parent (pk BIGINT, v1 VARCHAR(200), FULLTEXT idx (v1));",
  1120  		},
  1121  		Assertions: []ScriptTestAssertion{
  1122  			{
  1123  				Query:       "CREATE TABLE child1 (pk BIGINT, v1 VARCHAR(200), FULLTEXT idx (v1), CONSTRAINT fk FOREIGN KEY (v1) REFERENCES parent(v1));",
  1124  				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
  1125  			},
  1126  			{
  1127  				Query:       "CREATE TABLE child2 (pk BIGINT, v1 VARCHAR(200), INDEX idx (v1), CONSTRAINT fk FOREIGN KEY (v1) REFERENCES parent(v1));",
  1128  				ExpectedErr: sql.ErrForeignKeyMissingReferenceIndex,
  1129  			},
  1130  		},
  1131  	},
  1132  	{
  1133  		Name: "Full-Text with autoincrement",
  1134  		SetUpScript: []string{
  1135  			"CREATE TABLE test (pk BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, v1 VARCHAR(200), PRIMARY KEY(pk), FULLTEXT idx (v1));",
  1136  		},
  1137  		Assertions: []ScriptTestAssertion{
  1138  			{
  1139  				Query:    "INSERT INTO test (v1) VALUES ('abc'), ('def');",
  1140  				Expected: []sql.Row{{types.OkResult{RowsAffected: 2, InsertID: 1}}},
  1141  			},
  1142  			{
  1143  				Query:    "SELECT * FROM test;",
  1144  				Expected: []sql.Row{{uint64(1), "abc"}, {uint64(2), "def"}},
  1145  			},
  1146  		},
  1147  	},
  1148  	{
  1149  		Name: "Full-Text with default columns",
  1150  		SetUpScript: []string{
  1151  			"CREATE TABLE test (pk BIGINT UNSIGNED NOT NULL DEFAULT '1', v1 VARCHAR(200) DEFAULT 'def', PRIMARY KEY(pk), FULLTEXT idx (v1));",
  1152  		},
  1153  		Assertions: []ScriptTestAssertion{
  1154  			{
  1155  				Query:    "INSERT INTO test (v1) VALUES ('abc');",
  1156  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
  1157  			},
  1158  			{
  1159  				Query:    "INSERT INTO test (pk, v1) VALUES (2, 'def');",
  1160  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
  1161  			},
  1162  			{
  1163  				Query:    "SELECT * FROM test;",
  1164  				Expected: []sql.Row{{uint64(1), "abc"}, {uint64(2), "def"}},
  1165  			},
  1166  			{
  1167  				Query:    "SELECT * FROM test WHERE MATCH(v1) AGAINST ('def');",
  1168  				Expected: []sql.Row{{uint64(2), "def"}},
  1169  			},
  1170  		},
  1171  	},
  1172  }