github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/sqle/enginetest/dolt_branch_queries.go (about)

     1  // Copyright 2022 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package enginetest
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"github.com/dolthub/go-mysql-server/enginetest"
    22  	"github.com/dolthub/go-mysql-server/enginetest/queries"
    23  	"github.com/dolthub/go-mysql-server/sql"
    24  	"github.com/dolthub/go-mysql-server/sql/plan"
    25  	"github.com/dolthub/go-mysql-server/sql/planbuilder"
    26  	"github.com/dolthub/go-mysql-server/sql/transform"
    27  	"github.com/dolthub/go-mysql-server/sql/types"
    28  	"github.com/stretchr/testify/require"
    29  )
    30  
    31  var ForeignKeyBranchTests = []queries.ScriptTest{
    32  	{
    33  		Name: "create fk on branch",
    34  		SetUpScript: []string{
    35  			"call dolt_branch('b1')",
    36  			"use mydb/b1",
    37  			"ALTER TABLE child ADD CONSTRAINT fk_named FOREIGN KEY (v1) REFERENCES parent(v1);",
    38  		},
    39  		Assertions: []queries.ScriptTestAssertion{
    40  			{
    41  				Query:            "use mydb/b1",
    42  				SkipResultsCheck: true,
    43  			},
    44  			{
    45  				Query: "SHOW CREATE TABLE child;",
    46  				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n" +
    47  					"  `id` int NOT NULL,\n" +
    48  					"  `v1` int,\n" +
    49  					"  `v2` int,\n" +
    50  					"  PRIMARY KEY (`id`),\n" +
    51  					"  KEY `v1` (`v1`),\n" +
    52  					"  CONSTRAINT `fk_named` FOREIGN KEY (`v1`) REFERENCES `parent` (`v1`)\n" +
    53  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
    54  			},
    55  			{
    56  				Query:       "insert into child values (1, 1, 1)",
    57  				ExpectedErr: sql.ErrForeignKeyChildViolation,
    58  			},
    59  			{
    60  				Query:            "use mydb/main",
    61  				SkipResultsCheck: true,
    62  			},
    63  			{
    64  				Query: "SHOW CREATE TABLE child;",
    65  				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n" +
    66  					"  `id` int NOT NULL,\n" +
    67  					"  `v1` int,\n" +
    68  					"  `v2` int,\n" +
    69  					"  PRIMARY KEY (`id`)\n" +
    70  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
    71  			},
    72  			{
    73  				Query:    "insert into child values (1, 1, 1)",
    74  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
    75  			},
    76  			{
    77  				Query:       "insert into `mydb/b1`.child values (1, 1, 1)",
    78  				ExpectedErr: sql.ErrForeignKeyChildViolation,
    79  			},
    80  		},
    81  	},
    82  	{
    83  		Name: "create fk with branch checkout",
    84  		SetUpScript: []string{
    85  			"call dolt_branch('b1')",
    86  			"call dolt_checkout('b1')",
    87  			"ALTER TABLE child ADD CONSTRAINT fk_named FOREIGN KEY (v1) REFERENCES parent(v1);",
    88  		},
    89  		Assertions: []queries.ScriptTestAssertion{
    90  			{
    91  				Query:            "call dolt_checkout('b1')",
    92  				SkipResultsCheck: true,
    93  			},
    94  			{
    95  				Query: "SHOW CREATE TABLE child;",
    96  				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n" +
    97  					"  `id` int NOT NULL,\n" +
    98  					"  `v1` int,\n" +
    99  					"  `v2` int,\n" +
   100  					"  PRIMARY KEY (`id`),\n" +
   101  					"  KEY `v1` (`v1`),\n" +
   102  					"  CONSTRAINT `fk_named` FOREIGN KEY (`v1`) REFERENCES `parent` (`v1`)\n" +
   103  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   104  			},
   105  			{
   106  				Query:       "insert into child values (1, 1, 1)",
   107  				ExpectedErr: sql.ErrForeignKeyChildViolation,
   108  			},
   109  			{
   110  				Query:            "call dolt_checkout('main')",
   111  				SkipResultsCheck: true,
   112  			},
   113  			{
   114  				Query: "SHOW CREATE TABLE child;",
   115  				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n" +
   116  					"  `id` int NOT NULL,\n" +
   117  					"  `v1` int,\n" +
   118  					"  `v2` int,\n" +
   119  					"  PRIMARY KEY (`id`)\n" +
   120  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   121  			},
   122  			{
   123  				Query:    "insert into child values (1, 1, 1)",
   124  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
   125  			},
   126  		},
   127  	},
   128  	{
   129  		Name: "create fk on branch not being used",
   130  		SetUpScript: []string{
   131  			"call dolt_branch('b1')",
   132  		},
   133  		Assertions: []queries.ScriptTestAssertion{
   134  			{
   135  				Query: "ALTER TABLE `mydb/b1`.child ADD CONSTRAINT fk_named FOREIGN KEY (v1) REFERENCES parent(v1);",
   136  				Skip:  true, // Incorrectly flagged as a cross-DB foreign key relation
   137  			},
   138  			{
   139  				Query: "SHOW CREATE TABLE `mydb/b1`.child;",
   140  				Skip:  true,
   141  				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n" +
   142  					"  `id` int NOT NULL,\n" +
   143  					"  `v1` int,\n" +
   144  					"  `v2` int,\n" +
   145  					"  PRIMARY KEY (`id`),\n" +
   146  					"  KEY `v1` (`v1`),\n" +
   147  					"  CONSTRAINT `fk_named` FOREIGN KEY (`v1`) REFERENCES `parent` (`v1`)\n" +
   148  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   149  			},
   150  			{
   151  				Query:       "insert into `mydb/b1`.child values (1, 1, 1)",
   152  				Skip:        true,
   153  				ExpectedErr: sql.ErrForeignKeyChildViolation,
   154  			},
   155  			{
   156  				Query: "SHOW CREATE TABLE child;",
   157  				Skip:  true,
   158  				Expected: []sql.Row{{"child", "CREATE TABLE `child` (\n" +
   159  					"  `id` int NOT NULL,\n" +
   160  					"  `v1` int,\n" +
   161  					"  `v2` int,\n" +
   162  					"  PRIMARY KEY (`id`)\n" +
   163  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   164  			},
   165  			{
   166  				Query:    "insert into child values (1, 1, 1)",
   167  				Skip:     true,
   168  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
   169  			},
   170  		},
   171  	},
   172  }
   173  
   174  var ViewBranchTests = []queries.ScriptTest{
   175  	{
   176  		Name: "create view on branch",
   177  		SetUpScript: []string{
   178  			"create table t1 (a int primary key, b int)",
   179  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   180  			"call dolt_commit('-Am', 'first commit')",
   181  			"call dolt_branch('b1')",
   182  			"use mydb/b1",
   183  			"create view v1 as select * from t1 where a > 2",
   184  		},
   185  		Assertions: []queries.ScriptTestAssertion{
   186  			{
   187  				Query:            "use mydb/b1",
   188  				SkipResultsCheck: true,
   189  			},
   190  			{
   191  				Query:    "select * from v1",
   192  				Expected: []sql.Row{{3, 3}},
   193  			},
   194  			{
   195  				Query:            "use mydb/main",
   196  				SkipResultsCheck: true,
   197  			},
   198  			{
   199  				Query:       "select * from v1",
   200  				ExpectedErr: sql.ErrTableNotFound,
   201  			},
   202  			{
   203  				Query:    "select * from `mydb/b1`.v1",
   204  				Expected: []sql.Row{{3, 3}},
   205  			},
   206  		},
   207  	},
   208  	{
   209  		Name: "create view on different branch",
   210  		SetUpScript: []string{
   211  			"create table t1 (a int primary key, b int)",
   212  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   213  			"call dolt_commit('-Am', 'first commit')",
   214  			"call dolt_branch('b1')",
   215  			"create view `mydb/b1`.v1 as select * from t1 where a > 2",
   216  		},
   217  		Assertions: []queries.ScriptTestAssertion{
   218  			{
   219  				Query:            "use mydb/b1",
   220  				SkipResultsCheck: true,
   221  			},
   222  			{
   223  				Query:    "select * from v1",
   224  				Expected: []sql.Row{{3, 3}},
   225  				Skip:     true, // https://github.com/dolthub/dolt/issues/6078
   226  			},
   227  			{
   228  				Query:            "use mydb/main",
   229  				SkipResultsCheck: true,
   230  			},
   231  			{
   232  				Query:       "select * from v1",
   233  				ExpectedErr: sql.ErrTableNotFound,
   234  				Skip:        true, // https://github.com/dolthub/dolt/issues/6078
   235  			},
   236  			{
   237  				Query:    "select * from `mydb/b1`.v1",
   238  				Expected: []sql.Row{{3, 3}},
   239  				Skip:     true, // https://github.com/dolthub/dolt/issues/6078
   240  			},
   241  		},
   242  	},
   243  }
   244  
   245  var DdlBranchTests = []queries.ScriptTest{
   246  	{
   247  		Name: "create table on branch",
   248  		SetUpScript: []string{
   249  			"create table t1 (a int primary key, b int)",
   250  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   251  			"call dolt_commit('-Am', 'first commit')",
   252  			"call dolt_branch('b1')",
   253  			"use mydb/b1",
   254  			"create table t2 (a int primary key, b int)",
   255  			"insert into t2 values (4, 4)",
   256  		},
   257  		Assertions: []queries.ScriptTestAssertion{
   258  			{
   259  				Query:            "use mydb/b1",
   260  				SkipResultsCheck: true,
   261  			},
   262  			{
   263  				Query:    "select * from t2",
   264  				Expected: []sql.Row{{4, 4}},
   265  			},
   266  			{
   267  				Query:            "use mydb/main",
   268  				SkipResultsCheck: true,
   269  			},
   270  			{
   271  				Query:       "select * from t2",
   272  				ExpectedErr: sql.ErrTableNotFound,
   273  			},
   274  			{
   275  				Query:    "select * from `mydb/b1`.t2",
   276  				Expected: []sql.Row{{4, 4}},
   277  			},
   278  		},
   279  	},
   280  	{
   281  		Name: "create table on different branch",
   282  		SetUpScript: []string{
   283  			"create table t1 (a int primary key, b int)",
   284  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   285  			"call dolt_commit('-Am', 'first commit')",
   286  			"call dolt_branch('b1')",
   287  			"create table `mydb/b1`.t2 (a int primary key, b int)",
   288  			"insert into `mydb/b1`.t2 values (4,4)",
   289  		},
   290  		Assertions: []queries.ScriptTestAssertion{
   291  			{
   292  				Query:            "use mydb/b1",
   293  				SkipResultsCheck: true,
   294  			},
   295  			{
   296  				Query:    "select * from t2",
   297  				Expected: []sql.Row{{4, 4}},
   298  			},
   299  			{
   300  				Query:            "use mydb/main",
   301  				SkipResultsCheck: true,
   302  			},
   303  			{
   304  				Query:       "select * from t2",
   305  				ExpectedErr: sql.ErrTableNotFound,
   306  			},
   307  			{
   308  				Query:    "select * from `mydb/b1`.t2",
   309  				Expected: []sql.Row{{4, 4}},
   310  			},
   311  		},
   312  	},
   313  	{
   314  		Name: "create table on different branch, autocommit off",
   315  		SetUpScript: []string{
   316  			"create table t1 (a int primary key, b int)",
   317  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   318  			"call dolt_commit('-Am', 'first commit')",
   319  			"call dolt_branch('b1')",
   320  			"set autocommit = off",
   321  			"create table `mydb/b1`.t2 (a int primary key, b int)",
   322  			"insert into `mydb/b1`.t2 values (4,4)",
   323  			"commit",
   324  		},
   325  		Assertions: []queries.ScriptTestAssertion{
   326  			{
   327  				Query:            "use mydb/b1",
   328  				SkipResultsCheck: true,
   329  			},
   330  			{
   331  				Query:    "select * from t2",
   332  				Expected: []sql.Row{{4, 4}},
   333  			},
   334  			{
   335  				Query:            "use mydb/main",
   336  				SkipResultsCheck: true,
   337  			},
   338  			{
   339  				Query:       "select * from t2",
   340  				ExpectedErr: sql.ErrTableNotFound,
   341  			},
   342  			{
   343  				Query:    "select * from `mydb/b1`.t2",
   344  				Expected: []sql.Row{{4, 4}},
   345  			},
   346  		},
   347  	},
   348  	{
   349  		Name: "alter table on different branch, add column",
   350  		SetUpScript: []string{
   351  			"create table t1 (a int primary key, b int)",
   352  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   353  			"call dolt_commit('-Am', 'first commit')",
   354  			"call dolt_branch('b1')",
   355  		},
   356  		Assertions: []queries.ScriptTestAssertion{
   357  			{
   358  				Query:    "alter table `mydb/b1`.t1 add column c int",
   359  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0}}},
   360  			},
   361  			{
   362  				Query:    "select * from `mydb/b1`.t1",
   363  				Expected: []sql.Row{{1, 1, nil}, {2, 2, nil}, {3, 3, nil}},
   364  			},
   365  			{
   366  				Query:    "select * from t1",
   367  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   368  			},
   369  		},
   370  	},
   371  	{
   372  		Name: "alter table on different branch, drop column",
   373  		SetUpScript: []string{
   374  			"create table t1 (a int primary key, b int)",
   375  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   376  			"call dolt_commit('-Am', 'first commit')",
   377  			"call dolt_branch('b1')",
   378  		},
   379  		Assertions: []queries.ScriptTestAssertion{
   380  			{
   381  				Query:    "alter table `mydb/b1`.t1 drop column b",
   382  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0}}},
   383  			},
   384  			{
   385  				Query:    "select * from `mydb/b1`.t1",
   386  				Expected: []sql.Row{{1}, {2}, {3}},
   387  			},
   388  			{
   389  				Query:    "select * from t1",
   390  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   391  			},
   392  		},
   393  	},
   394  	{
   395  		Name: "alter table on different branch, modify column",
   396  		SetUpScript: []string{
   397  			"create table t1 (a int primary key, b int)",
   398  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   399  			"call dolt_commit('-Am', 'first commit')",
   400  			"call dolt_branch('b1')",
   401  		},
   402  		Assertions: []queries.ScriptTestAssertion{
   403  			{
   404  				Query:    "alter table `mydb/b1`.t1 modify column b varchar(1) first",
   405  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0}}},
   406  			},
   407  			{
   408  				Query:    "select * from `mydb/b1`.t1",
   409  				Expected: []sql.Row{{"1", 1}, {"2", 2}, {"3", 3}},
   410  			},
   411  			{
   412  				Query:    "select * from t1",
   413  				Expected: []sql.Row{{1, 1}, {2, 2}, {3, 3}},
   414  			},
   415  		},
   416  	},
   417  	{
   418  		Name: "alter table on different branch, create and drop index",
   419  		SetUpScript: []string{
   420  			"create table t1 (a int primary key, b int)",
   421  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   422  			"call dolt_commit('-Am', 'first commit')",
   423  			"call dolt_branch('b1')",
   424  		},
   425  		Assertions: []queries.ScriptTestAssertion{
   426  			{
   427  				Query:    "create index idx on `mydb/b1`.t1 (b)",
   428  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0}}},
   429  			},
   430  			{
   431  				Query: "show create table `mydb/b1`.t1",
   432  				Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n" +
   433  					"  `a` int NOT NULL,\n" +
   434  					"  `b` int,\n" +
   435  					"  PRIMARY KEY (`a`),\n" +
   436  					"  KEY `idx` (`b`)\n" +
   437  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   438  			},
   439  			{
   440  				Query: "show create table t1",
   441  				Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n" +
   442  					"  `a` int NOT NULL,\n" +
   443  					"  `b` int,\n" +
   444  					"  PRIMARY KEY (`a`)\n" +
   445  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   446  			},
   447  			{
   448  				Query:    "alter table `mydb/b1`.t1 drop index idx",
   449  				Expected: []sql.Row{{types.OkResult{RowsAffected: 0}}},
   450  			},
   451  			{
   452  				Query: "show create table `mydb/b1`.t1",
   453  				Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n" +
   454  					"  `a` int NOT NULL,\n" +
   455  					"  `b` int,\n" +
   456  					"  PRIMARY KEY (`a`)\n" +
   457  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   458  			},
   459  		},
   460  	},
   461  	{
   462  		Name: "alter table on different branch, add and drop constraint",
   463  		SetUpScript: []string{
   464  			"create table t1 (a int primary key, b int)",
   465  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   466  			"call dolt_commit('-Am', 'first commit')",
   467  			"call dolt_branch('b1')",
   468  		},
   469  		Assertions: []queries.ScriptTestAssertion{
   470  			{
   471  				Query:    "alter table `mydb/b1`.t1 add constraint chk1 check (b < 4)",
   472  				Expected: []sql.Row{{types.NewOkResult(0)}},
   473  			},
   474  			{
   475  				Query: "show create table `mydb/b1`.t1",
   476  				Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n" +
   477  					"  `a` int NOT NULL,\n" +
   478  					"  `b` int,\n" +
   479  					"  PRIMARY KEY (`a`),\n" +
   480  					"  CONSTRAINT `chk1` CHECK ((`b` < 4))\n" +
   481  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   482  			},
   483  			{
   484  				Query:       "insert into `mydb/b1`.t1 values (4, 4)",
   485  				ExpectedErr: sql.ErrCheckConstraintViolated,
   486  			},
   487  			{
   488  				Query: "show create table t1",
   489  				Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n" +
   490  					"  `a` int NOT NULL,\n" +
   491  					"  `b` int,\n" +
   492  					"  PRIMARY KEY (`a`)\n" +
   493  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   494  			},
   495  			{
   496  				Query:    "insert into t1 values (4, 4)",
   497  				Expected: []sql.Row{{types.OkResult{RowsAffected: 1}}},
   498  			},
   499  			{
   500  				Query:    "alter table `mydb/b1`.t1 drop constraint chk1",
   501  				Expected: []sql.Row{},
   502  			},
   503  			{
   504  				Query: "show create table `mydb/b1`.t1",
   505  				Expected: []sql.Row{{"t1", "CREATE TABLE `t1` (\n" +
   506  					"  `a` int NOT NULL,\n" +
   507  					"  `b` int,\n" +
   508  					"  PRIMARY KEY (`a`)\n" +
   509  					") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin"}},
   510  			},
   511  		},
   512  	},
   513  }
   514  
   515  type indexQuery struct {
   516  	Query string
   517  	Index bool
   518  }
   519  
   520  var BranchPlanTests = []struct {
   521  	Name        string
   522  	SetUpScript []string
   523  	Queries     []indexQuery
   524  }{
   525  	{
   526  		Name: "use index on branch database",
   527  		SetUpScript: []string{
   528  			"create table t1 (a int primary key, b int)",
   529  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   530  			"call dolt_commit('-Am', 'first commit')",
   531  			"call dolt_branch('b1')",
   532  			"use mydb/b1",
   533  			"create index idx on t1 (b)",
   534  		},
   535  		Queries: []indexQuery{
   536  			{
   537  				Query: "select * from t1 where b = 1",
   538  				Index: true,
   539  			},
   540  			{
   541  				Query: "use mydb/main",
   542  			},
   543  			{
   544  				Query: "select * from `mydb/b1`.t1 where b = 1",
   545  				Index: true,
   546  			},
   547  		},
   548  	},
   549  	{
   550  		Name: "use index on branch database join",
   551  		SetUpScript: []string{
   552  			"create table t1 (a int primary key, b int)",
   553  			"insert into t1 values (1, 1), (2, 2), (3, 3)",
   554  			"call dolt_commit('-Am', 'first commit')",
   555  			"call dolt_branch('b1')",
   556  			"use mydb/b1",
   557  			"create index idx on t1 (b)",
   558  		},
   559  		Queries: []indexQuery{
   560  			{
   561  				Query: "select /*+ LOOKUP_JOIN(t1a,t1b) */ * from t1 t1a join t1 t1b on t1a.b = t1b.b order by 1",
   562  				Index: true,
   563  			},
   564  			{
   565  				Query: "select * from `mydb/main`.t1 t1a join `mydb/main`.t1 t1b on t1a.b = t1b.b order by 1",
   566  				Index: false,
   567  			},
   568  			{
   569  				Query: "use mydb/main",
   570  			},
   571  			{
   572  				Query: "select /*+ LOOKUP_JOIN(t1a,t1b) */ * from t1 t1a join t1 t1b on t1a.b = t1b.b order by 1",
   573  				Index: true,
   574  			},
   575  			{
   576  				Query: "select /*+ LOOKUP_JOIN(t1a,t1b) */ * from `mydb/b1`.t1 t1a join `mydb/b1`.t1 t1b on t1a.b = t1b.b order by 1",
   577  				Index: true,
   578  			},
   579  		},
   580  	},
   581  }
   582  
   583  func TestIndexedAccess(t *testing.T, e enginetest.QueryEngine, harness enginetest.Harness, query string, index bool) {
   584  	ctx := enginetest.NewContext(harness)
   585  	ctx = ctx.WithQuery(query)
   586  	a, err := analyzeQuery(ctx, e, query)
   587  	require.NoError(t, err)
   588  	var hasIndex bool
   589  	transform.Inspect(a, func(n sql.Node) bool {
   590  		if n == nil {
   591  			return false
   592  		}
   593  		if _, ok := n.(*plan.IndexedTableAccess); ok {
   594  			hasIndex = true
   595  		}
   596  		return true
   597  	})
   598  
   599  	if index != hasIndex {
   600  		fmt.Println(a.String())
   601  	}
   602  	require.Equal(t, index, hasIndex)
   603  }
   604  
   605  func analyzeQuery(ctx *sql.Context, e enginetest.QueryEngine, query string) (sql.Node, error) {
   606  	binder := planbuilder.New(ctx, e.EngineAnalyzer().Catalog, sql.NewMysqlParser())
   607  	parsed, _, _, err := binder.Parse(query, false)
   608  	if err != nil {
   609  		return nil, err
   610  	}
   611  
   612  	return e.EngineAnalyzer().Analyze(ctx, parsed, nil)
   613  }