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 }