github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/mock.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     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 plan
    16  
    17  import (
    18  	"context"
    19  	"encoding/json"
    20  	"strings"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/catalog"
    23  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    24  	"github.com/matrixorigin/matrixone/pkg/container/types"
    25  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    26  	pb "github.com/matrixorigin/matrixone/pkg/pb/statsinfo"
    27  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    28  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function"
    29  	"github.com/matrixorigin/matrixone/pkg/testutil"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    31  )
    32  
    33  type MockCompilerContext struct {
    34  	objects         map[string]*ObjectRef
    35  	tables          map[string]*TableDef
    36  	pks             map[string][]int
    37  	id2name         map[uint64]string
    38  	isDml           bool
    39  	mysqlCompatible bool
    40  
    41  	// ctx default: nil
    42  	ctx context.Context
    43  }
    44  
    45  func (m *MockCompilerContext) GetViews() []string {
    46  	return nil
    47  }
    48  
    49  func (m *MockCompilerContext) SetViews(views []string) {
    50  }
    51  
    52  func (m *MockCompilerContext) GetSnapshot() *Snapshot {
    53  	return nil
    54  }
    55  
    56  func (m *MockCompilerContext) SetSnapshot(snapshot *Snapshot) {}
    57  
    58  func (m *MockCompilerContext) ReplacePlan(execPlan *plan.Execute) (*plan.Plan, tree.Statement, error) {
    59  	//TODO implement me
    60  	panic("implement me")
    61  }
    62  
    63  func (m *MockCompilerContext) CheckSubscriptionValid(subName, accName string, pubName string) error {
    64  	//TODO implement me
    65  	panic("implement me")
    66  }
    67  
    68  func (m *MockCompilerContext) ResolveSubscriptionTableById(tableId uint64, pubmeta *SubscriptionMeta) (*ObjectRef, *TableDef) {
    69  	return nil, nil
    70  }
    71  
    72  func (m *MockCompilerContext) ResolveUdf(name string, ast []*plan.Expr) (*function.Udf, error) {
    73  	return nil, nil
    74  }
    75  
    76  func (m *MockCompilerContext) ResolveAccountIds(accountNames []string) ([]uint32, error) {
    77  	return []uint32{catalog.System_Account}, nil
    78  }
    79  
    80  func (m *MockCompilerContext) ResolveVariable(varName string, isSystemVar, isGlobalVar bool) (interface{}, error) {
    81  	vars := make(map[string]interface{})
    82  	vars["str_var"] = "str"
    83  	vars["int_var"] = 20
    84  	vars["bool_var"] = false
    85  	vars["float_var"] = 20.20
    86  	dec, _ := types.ParseDecimal128("200.001", 38, 3)
    87  	vars["decimal_var"] = dec
    88  	vars["null_var"] = nil
    89  
    90  	if m.mysqlCompatible {
    91  		vars["sql_mode"] = ""
    92  	} else {
    93  		vars["sql_mode"] = "ONLY_FULL_GROUP_BY"
    94  	}
    95  
    96  	vars["foreign_key_checks"] = int64(1)
    97  
    98  	if result, ok := vars[varName]; ok {
    99  		return result, nil
   100  	}
   101  
   102  	return nil, moerr.NewInternalError(m.ctx, "var not found")
   103  }
   104  
   105  type col struct {
   106  	Name     string
   107  	Id       types.T
   108  	Nullable bool
   109  	Width    int32
   110  	Scale    int32
   111  }
   112  
   113  type index struct {
   114  	indexName  string
   115  	tableName  string
   116  	unique     bool
   117  	parts      []string
   118  	cols       []col
   119  	tableExist bool
   120  }
   121  
   122  // NewEmptyCompilerContext for test create/drop statement
   123  func NewEmptyCompilerContext() *MockCompilerContext {
   124  	return &MockCompilerContext{
   125  		objects: make(map[string]*ObjectRef),
   126  		tables:  make(map[string]*TableDef),
   127  		ctx:     context.Background(),
   128  	}
   129  }
   130  
   131  type Schema struct {
   132  	cols      []col
   133  	pks       []int
   134  	idxs      []index
   135  	fks       []*ForeignKeyDef
   136  	clusterby *ClusterByDef
   137  	outcnt    float64
   138  	tblId     int64
   139  }
   140  
   141  const SF float64 = 1
   142  
   143  func NewMockCompilerContext(isDml bool) *MockCompilerContext {
   144  	tpchSchema := make(map[string]*Schema)
   145  	moSchema := make(map[string]*Schema)
   146  	constraintTestSchema := make(map[string]*Schema)
   147  
   148  	schemas := map[string]map[string]*Schema{
   149  		"tpch":            tpchSchema,
   150  		"mo_catalog":      moSchema,
   151  		"constraint_test": constraintTestSchema,
   152  	}
   153  
   154  	tpchSchema["nation"] = &Schema{
   155  		cols: []col{
   156  			{"n_nationkey", types.T_int32, false, 0, 0},
   157  			{"n_name", types.T_varchar, false, 25, 0},
   158  			{"n_regionkey", types.T_int32, false, 0, 0},
   159  			{"n_comment", types.T_varchar, true, 152, 0},
   160  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   161  		},
   162  		pks:    []int{0},
   163  		outcnt: 25,
   164  	}
   165  	tpchSchema["nation2"] = &Schema{
   166  		cols: []col{ //not exist in tpch, create for test NaturalJoin And UsingJoin
   167  			{"n_nationkey", types.T_int32, false, 0, 0},
   168  			{"n_name", types.T_varchar, false, 25, 0},
   169  			{"r_regionkey", types.T_int32, false, 0, 0}, //change N_REGIONKEY to R_REGIONKEY for test NaturalJoin And UsingJoin
   170  			{"n_comment", types.T_varchar, true, 152, 0},
   171  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   172  		},
   173  		pks:    []int{0},
   174  		outcnt: 25,
   175  	}
   176  	tpchSchema["test_idx"] = &Schema{
   177  		cols: []col{
   178  			{"n_nationkey", types.T_int32, false, 0, 0},
   179  			{"n_name", types.T_varchar, false, 25, 0},
   180  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   181  		},
   182  		pks:    []int{0},
   183  		outcnt: 25,
   184  	}
   185  	tpchSchema["region"] = &Schema{
   186  		cols: []col{
   187  			{"r_regionkey", types.T_int32, false, 0, 0},
   188  			{"r_name", types.T_varchar, false, 25, 0},
   189  			{"r_comment", types.T_varchar, true, 152, 0},
   190  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   191  		},
   192  		pks:    []int{0},
   193  		outcnt: 5,
   194  	}
   195  	tpchSchema["part"] = &Schema{
   196  		cols: []col{
   197  			{"p_partkey", types.T_int32, false, 0, 0},
   198  			{"p_name", types.T_varchar, false, 55, 0},
   199  			{"p_mfgr", types.T_varchar, false, 25, 0},
   200  			{"p_brand", types.T_varchar, false, 10, 0},
   201  			{"p_type", types.T_varchar, false, 25, 0},
   202  			{"p_size", types.T_int32, false, 0, 0},
   203  			{"p_container", types.T_varchar, false, 10, 0},
   204  			{"p_retailprice", types.T_decimal64, false, 15, 2},
   205  			{"p_comment", types.T_varchar, false, 23, 0},
   206  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   207  		},
   208  		pks:    []int{0},
   209  		outcnt: SF * 2e5,
   210  	}
   211  	tpchSchema["supplier"] = &Schema{
   212  		cols: []col{
   213  			{"s_suppkey", types.T_int32, false, 0, 0},
   214  			{"s_name", types.T_varchar, false, 25, 0},
   215  			{"s_address", types.T_varchar, false, 40, 0},
   216  			{"s_nationkey", types.T_int32, false, 0, 0},
   217  			{"s_phone", types.T_varchar, false, 15, 0},
   218  			{"s_acctbal", types.T_decimal64, false, 15, 2},
   219  			{"s_comment", types.T_varchar, false, 101, 0},
   220  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   221  		},
   222  		pks:    []int{0},
   223  		outcnt: SF * 1e4,
   224  	}
   225  	tpchSchema["partsupp"] = &Schema{
   226  		cols: []col{
   227  			{"ps_partkey", types.T_int32, false, 0, 0},
   228  			{"ps_suppkey", types.T_int32, false, 0, 0},
   229  			{"ps_availqty", types.T_int32, false, 0, 0},
   230  			{"ps_supplycost", types.T_decimal64, false, 15, 2},
   231  			{"ps_comment", types.T_varchar, false, 199, 0},
   232  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   233  		},
   234  		pks:    []int{0, 1},
   235  		outcnt: SF * 8e5,
   236  	}
   237  	tpchSchema["customer"] = &Schema{
   238  		cols: []col{
   239  			{"c_custkey", types.T_int32, false, 0, 0},
   240  			{"c_name", types.T_varchar, false, 25, 0},
   241  			{"c_address", types.T_varchar, false, 40, 0},
   242  			{"c_nationkey", types.T_int32, false, 0, 0},
   243  			{"c_phone", types.T_varchar, false, 15, 0},
   244  			{"c_acctbal", types.T_decimal64, false, 15, 2},
   245  			{"c_mktsegment", types.T_varchar, false, 10, 0},
   246  			{"c_comment", types.T_varchar, false, 117, 0},
   247  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   248  		},
   249  		pks:    []int{0},
   250  		outcnt: SF * 15e4,
   251  	}
   252  	tpchSchema["orders"] = &Schema{
   253  		cols: []col{
   254  			{"o_orderkey", types.T_int64, false, 0, 0},
   255  			{"o_custkey", types.T_int32, false, 0, 0},
   256  			{"o_orderstatus", types.T_varchar, false, 1, 0},
   257  			{"o_totalprice", types.T_decimal64, false, 15, 2},
   258  			{"o_orderdate", types.T_date, false, 0, 0},
   259  			{"o_orderpriority", types.T_varchar, false, 15, 0},
   260  			{"o_clerk", types.T_varchar, false, 15, 0},
   261  			{"o_shippriority", types.T_int32, false, 0, 0},
   262  			{"o_comment", types.T_varchar, false, 79, 0},
   263  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   264  		},
   265  		pks:    []int{0},
   266  		outcnt: SF * 15e5,
   267  	}
   268  	tpchSchema["lineitem"] = &Schema{
   269  		cols: []col{
   270  			{"l_orderkey", types.T_int64, false, 0, 0},
   271  			{"l_partkey", types.T_int32, false, 0, 0},
   272  			{"l_suppkey", types.T_int32, false, 0, 0},
   273  			{"l_linenumber", types.T_int32, false, 0, 0},
   274  			{"l_quantity", types.T_decimal64, false, 15, 2},
   275  			{"l_extendedprice", types.T_decimal64, false, 15, 2},
   276  			{"l_discount", types.T_decimal64, false, 15, 2},
   277  			{"l_tax", types.T_decimal64, false, 15, 2},
   278  			{"l_returnflag", types.T_varchar, false, 1, 0},
   279  			{"l_linestatus", types.T_varchar, false, 1, 0},
   280  			{"l_shipdate", types.T_date, false, 0, 0},
   281  			{"l_commitdate", types.T_date, false, 0, 0},
   282  			{"l_receiptdate", types.T_date, false, 0, 0},
   283  			{"l_shipinstruct", types.T_varchar, false, 25, 0},
   284  			{"l_shipmode", types.T_varchar, false, 10, 0},
   285  			{"l_comment", types.T_varchar, false, 44, 0},
   286  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   287  		},
   288  		pks:    []int{0, 3},
   289  		outcnt: SF * 6e6,
   290  	}
   291  	// it's a view
   292  	tpchSchema["v1"] = &Schema{
   293  		cols: []col{
   294  			{"n_name", types.T_varchar, false, 50, 0},
   295  		},
   296  	}
   297  
   298  	moSchema["mo_database"] = &Schema{
   299  		cols: []col{
   300  			{"datname", types.T_varchar, false, 50, 0},
   301  			{"account_id", types.T_uint32, false, 0, 0},
   302  			{"dat_createsql", types.T_varchar, false, 1024, 0},
   303  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   304  		},
   305  		pks: []int{0},
   306  	}
   307  	moSchema["mo_tables"] = &Schema{
   308  		cols: []col{
   309  			{"reldatabase", types.T_varchar, false, 50, 0},
   310  			{"relname", types.T_varchar, false, 50, 0},
   311  			{"relkind", types.T_varchar, false, 50, 0},
   312  			{"account_id", types.T_uint32, false, 0, 0},
   313  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   314  		},
   315  		pks: []int{0, 1},
   316  	}
   317  	moSchema["mo_columns"] = &Schema{
   318  		cols: []col{
   319  			{"att_uniq_name", types.T_varchar, false, 256, 0},
   320  			{"account_id", types.T_uint32, false, 0, 0},
   321  			{"att_database_id", types.T_uint32, false, 0, 0},
   322  			{"att_database", types.T_varchar, false, 50, 0},
   323  			{"att_relname_id", types.T_uint32, false, 0, 0},
   324  			{"att_relname", types.T_varchar, false, 50, 0},
   325  			{"attname", types.T_varchar, false, 50, 0},
   326  			{"atttyp", types.T_int32, false, 0, 0},
   327  			{"attnum", types.T_int32, false, 0, 0},
   328  			{"att_length", types.T_int32, false, 0, 0},
   329  			{"attnotnull", types.T_int8, false, 0, 0},
   330  			{"atthasdef", types.T_int8, false, 0, 0},
   331  			{"att_default", types.T_varchar, false, 2048, 0},
   332  			{"attisdropped", types.T_int8, false, 0, 0},
   333  			{"att_constraint_type", types.T_varchar, false, 1, 0},
   334  			{"att_is_unsigned", types.T_int8, false, 0, 0},
   335  			{"att_is_auto_increment", types.T_int8, false, 0, 0},
   336  			{"att_comment", types.T_varchar, false, 1024, 0},
   337  			{"att_is_hidden", types.T_bool, false, 0, 0},
   338  			{"attr_has_update", types.T_int8, false, 0, 0},
   339  			{"attr_update", types.T_varchar, false, 2048, 0},
   340  			{"att_attr_is_clusterby", types.T_int8, false, 0, 0},
   341  			{"attr_seqnum", types.T_int8, false, 0, 0},
   342  			{"attr_enum", types.T_varchar, false, 2048, 0},
   343  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   344  		},
   345  		pks: []int{0},
   346  	}
   347  	moSchema["mo_user"] = &Schema{
   348  		cols: []col{
   349  			{"user_id", types.T_int32, false, 50, 0},
   350  			{"user_host", types.T_varchar, false, 100, 0},
   351  			{"user_name", types.T_varchar, false, 300, 0},
   352  			{"authentication_string", types.T_varchar, false, 100, 0},
   353  			{"status", types.T_varchar, false, 100, 0},
   354  			{"created_time", types.T_timestamp, false, 0, 0},
   355  			{"expired_time", types.T_timestamp, false, 0, 0},
   356  			{"login_type", types.T_varchar, false, 100, 0},
   357  			{"creator", types.T_int32, false, 50, 0},
   358  			{"owner", types.T_int32, false, 50, 0},
   359  			{"default_role", types.T_int32, false, 50, 0},
   360  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   361  		},
   362  		pks: []int{0},
   363  	}
   364  
   365  	moSchema["mo_role_privs"] = &Schema{
   366  		cols: []col{
   367  			{"privilege_level", types.T_varchar, false, 100, 0},
   368  			{"obj_id", types.T_uint64, false, 100, 0},
   369  			{"obj_type", types.T_varchar, false, 16, 0},
   370  			{"role_id", types.T_int32, false, 50, 0},
   371  			{"role_name", types.T_varchar, false, 100, 0},
   372  			{"granted_time", types.T_timestamp, false, 0, 0},
   373  			{"operation_user_id", types.T_uint32, false, 50, 0},
   374  			{"privilege_name", types.T_varchar, false, 100, 0},
   375  			{"with_grant_option", types.T_bool, false, 0, 0},
   376  			{"privilege_id", types.T_int32, false, 50, 0},
   377  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   378  		},
   379  	}
   380  
   381  	moSchema["mo_user_defined_function"] = &Schema{
   382  		cols: []col{
   383  			{"function_id", types.T_int32, false, 50, 0},
   384  			{"name", types.T_varchar, false, 100, 0},
   385  			{"creator", types.T_uint64, false, 50, 0},
   386  			{"args", types.T_text, false, 1000, 0},
   387  			{"retType", types.T_varchar, false, 20, 0},
   388  			{"body", types.T_text, false, 1000, 0},
   389  			{"language", types.T_varchar, false, 20, 0},
   390  			{"db", types.T_varchar, false, 100, 0},
   391  			{"definer", types.T_varchar, false, 50, 0},
   392  			{"modified_time", types.T_timestamp, false, 0, 0},
   393  			{"created_time", types.T_timestamp, false, 0, 0},
   394  			{"type", types.T_varchar, false, 10, 0},
   395  			{"security_type", types.T_varchar, false, 10, 0},
   396  			{"comment", types.T_varchar, false, 5000, 0},
   397  			{"character_set_client", types.T_varchar, false, 64, 0},
   398  			{"collation_connection", types.T_varchar, false, 64, 0},
   399  			{"database_collation", types.T_varchar, false, 64, 0},
   400  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   401  		},
   402  		pks: []int{0},
   403  	}
   404  
   405  	moSchema["mo_indexes"] = &Schema{
   406  		cols: []col{
   407  			{"id", types.T_uint64, false, 100, 0},
   408  			{"table_id", types.T_uint64, false, 100, 0},
   409  			{"database_id", types.T_uint64, false, 100, 0},
   410  			{"name", types.T_varchar, false, 64, 0},
   411  			{"type", types.T_varchar, false, 11, 0},
   412  			{"algo", types.T_varchar, false, 11, 0},
   413  			{"algo_table_type", types.T_varchar, false, 11, 0},
   414  			{"algo_params", types.T_varchar, false, 2048, 0},
   415  			{"is_visible", types.T_int8, false, 50, 0},
   416  			{"hidden", types.T_int8, false, 50, 0},
   417  			{"comment", types.T_varchar, false, 2048, 0},
   418  			{"column_name", types.T_varchar, false, 256, 0},
   419  			{"ordinal_position", types.T_uint32, false, 50, 0},
   420  			{"options", types.T_text, true, 50, 0},
   421  			{"index_table_name", types.T_varchar, true, 50, 0},
   422  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   423  		},
   424  		pks: []int{0},
   425  	}
   426  
   427  	moSchema["mo_role"] = &Schema{
   428  		cols: []col{
   429  			{"role_id", types.T_uint64, false, 100, 0},
   430  			{"role_name", types.T_varchar, false, 64, 0},
   431  			{"creator", types.T_int64, false, 50, 0},
   432  			{"owner", types.T_int64, false, 50, 0},
   433  			{"created_time", types.T_timestamp, false, 0, 0},
   434  			{"comments", types.T_varchar, false, 2048, 0},
   435  		},
   436  		pks: []int{0},
   437  	}
   438  
   439  	moSchema["mo_stages"] = &Schema{
   440  		cols: []col{
   441  			{"stage_id", types.T_uint64, false, 100, 0},
   442  			{"stage_name", types.T_varchar, false, 64, 0},
   443  			{"url", types.T_varchar, false, 50, 0},
   444  			{"stage_credentials", types.T_varchar, false, 50, 0},
   445  			{"stage_status", types.T_varchar, false, 50, 0},
   446  			{"created_time", types.T_timestamp, false, 0, 0},
   447  			{"comment", types.T_varchar, false, 2048, 0},
   448  		},
   449  	}
   450  
   451  	moSchema["mo_snapshots"] = &Schema{
   452  		cols: []col{
   453  			{"snapshot_id", types.T_uuid, false, 100, 0},
   454  			{"sname", types.T_varchar, false, 64, 0},
   455  			{"ts", types.T_int64, false, 50, 0},
   456  			{"level", types.T_enum, false, 50, 0},
   457  			{"account_name", types.T_varchar, false, 50, 0},
   458  			{"database_name", types.T_varchar, false, 50, 0},
   459  			{"table_name", types.T_varchar, false, 50, 0},
   460  			{"obj_id", types.T_uint64, false, 100, 0},
   461  		},
   462  		pks: []int{0},
   463  	}
   464  
   465  	//---------------------------------------------constraint test schema---------------------------------------------------------
   466  	/*
   467  		create table emp(
   468  			empno int unsigned primary key,
   469  			ename varchar(15),
   470  			job varchar(10),
   471  			mgr int unsigned,
   472  			hiredate date,
   473  			sal decimal(7,2),
   474  			comm decimal(7,2),
   475  			deptno int unsigned,
   476  			unique key(ename, job),
   477  			key (ename, job),
   478  			foreign key (deptno) references dept(deptno)
   479  		);
   480  	*/
   481  	constraintTestSchema["emp"] = &Schema{
   482  		cols: []col{
   483  			{"empno", types.T_uint32, true, 32, 0},
   484  			{"ename", types.T_varchar, true, 15, 0},
   485  			{"job", types.T_varchar, true, 10, 0},
   486  			{"mgr", types.T_uint32, true, 32, 0},
   487  			{"hiredate", types.T_date, true, 0, 0},
   488  			{"sal", types.T_decimal64, true, 7, 0},
   489  			{"comm", types.T_decimal64, true, 7, 0},
   490  			{"deptno", types.T_uint32, true, 32, 0},
   491  			{catalog.Row_ID, types.T_Rowid, true, 0, 0},
   492  		},
   493  		pks: []int{0}, // primary key "empno"
   494  		fks: []*plan.ForeignKeyDef{
   495  			{
   496  				Name:        "fk1",                       // string
   497  				Cols:        []uint64{7},                 // []uint64
   498  				ForeignTbl:  88888,                       // uint64
   499  				ForeignCols: []uint64{1},                 // []uint64
   500  				OnDelete:    plan.ForeignKeyDef_RESTRICT, // ForeignKeyDef_RefAction
   501  				OnUpdate:    plan.ForeignKeyDef_RESTRICT, // ForeignKeyDef_RefAction
   502  			},
   503  		},
   504  		idxs: []index{
   505  			{
   506  				indexName: "",
   507  				tableName: catalog.UniqueIndexTableNamePrefix + "412f4fad-77ba-11ed-b347-000c29847904",
   508  				parts:     []string{"ename", "job"},
   509  				cols: []col{
   510  					{catalog.IndexTableIndexColName, types.T_varchar, true, 65535, 0},
   511  				},
   512  				tableExist: true,
   513  				unique:     true,
   514  			},
   515  			{
   516  				indexName: "",
   517  				tableName: catalog.SecondaryIndexTableNamePrefix + "512f4fad-77ba-11ed-b347-000c29847904",
   518  				parts:     []string{"ename", "job"},
   519  				cols: []col{
   520  					{catalog.IndexTableIndexColName, types.T_varchar, true, 65535, 0},
   521  				},
   522  				tableExist: true,
   523  				unique:     false,
   524  			},
   525  		},
   526  		outcnt: 14,
   527  	}
   528  
   529  	// index table
   530  	constraintTestSchema[catalog.UniqueIndexTableNamePrefix+"412f4fad-77ba-11ed-b347-000c29847904"] = &Schema{
   531  		cols: []col{
   532  			{catalog.IndexTableIndexColName, types.T_varchar, true, 65535, 0},
   533  			{catalog.IndexTablePrimaryColName, types.T_uint32, true, 32, 0},
   534  			{catalog.Row_ID, types.T_Rowid, true, 0, 0},
   535  		},
   536  		pks:    []int{0},
   537  		outcnt: 13,
   538  	}
   539  	constraintTestSchema[catalog.SecondaryIndexTableNamePrefix+"512f4fad-77ba-11ed-b347-000c29847904"] = &Schema{
   540  		cols: []col{
   541  			{catalog.IndexTableIndexColName, types.T_varchar, true, 65535, 0},
   542  			{catalog.IndexTablePrimaryColName, types.T_uint32, true, 32, 0},
   543  			{catalog.Row_ID, types.T_Rowid, true, 0, 0},
   544  		},
   545  		pks:    []int{0},
   546  		outcnt: 13,
   547  	}
   548  
   549  	/*
   550  		create table dept(
   551  			deptno int unsigned auto_increment,
   552  			dname varchar(15),
   553  			loc varchar(50),
   554  			primary key(deptno),
   555  			unique index(dname)
   556  		);
   557  	*/
   558  	constraintTestSchema["dept"] = &Schema{
   559  		tblId: 88888,
   560  		cols: []col{
   561  			{"deptno", types.T_uint32, true, 32, 0},
   562  			{"dname", types.T_varchar, true, 15, 0},
   563  			{"loc", types.T_varchar, true, 50, 0},
   564  			{catalog.Row_ID, types.T_Rowid, true, 0, 0},
   565  		},
   566  		pks: []int{0}, // primary key "deptno"
   567  		idxs: []index{
   568  			{
   569  				indexName: "",
   570  				tableName: catalog.UniqueIndexTableNamePrefix + "8e3246dd-7a19-11ed-ba7d-000c29847904",
   571  				parts:     []string{"dname"},
   572  				cols: []col{
   573  					{catalog.IndexTableIndexColName, types.T_varchar, true, 15, 0},
   574  				},
   575  				tableExist: true,
   576  				unique:     true,
   577  			},
   578  		},
   579  		outcnt: 4,
   580  	}
   581  
   582  	// index table
   583  	constraintTestSchema[catalog.UniqueIndexTableNamePrefix+"8e3246dd-7a19-11ed-ba7d-000c29847904"] = &Schema{
   584  		cols: []col{
   585  			{catalog.IndexTableIndexColName, types.T_varchar, true, 15, 0},
   586  			{catalog.IndexTablePrimaryColName, types.T_uint32, true, 32, 0},
   587  			{catalog.Row_ID, types.T_Rowid, true, 0, 0},
   588  		},
   589  		pks:    []int{0},
   590  		outcnt: 4,
   591  	}
   592  	/*
   593  		create table products (
   594  			pid int not null,
   595  			pname varchar(50) not null,
   596  			description varchar(20) not null,
   597  			price decimal(9,2) not null
   598  		) cluster by(pid,pname);
   599  	*/
   600  	constraintTestSchema["products"] = &Schema{
   601  		cols: []col{
   602  			{"pid", types.T_int32, true, 32, 0},
   603  			{"pname", types.T_varchar, true, 50, 0},
   604  			{"description", types.T_varchar, true, 20, 0},
   605  			{"price", types.T_uint32, true, 9, 0},
   606  			{"__mo_cbkey_003pid005pname", types.T_varchar, true, 65535, 0},
   607  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   608  		},
   609  		clusterby: &ClusterByDef{
   610  			Name: "__mo_cbkey_003pid005pname",
   611  		},
   612  		outcnt: 14,
   613  	}
   614  
   615  	//+----------+--------------+------+-----+---------+-------+
   616  	//| Field    | Type         | Null | Key | Default | Extra |
   617  	//+----------+--------------+------+-----+---------+-------+
   618  	//| empno    | int unsigned | YES  | MUL | NULL    |       |
   619  	//| ename    | varchar(15)  | YES  |     | NULL    |       |
   620  	//| job      | varchar(10)  | YES  |     | NULL    |       |
   621  	//| mgr      | int unsigned | YES  |     | NULL    |       |
   622  	//| hiredate | date         | YES  |     | NULL    |       |
   623  	//| sal      | decimal(7,2) | YES  |     | NULL    |       |
   624  	//| comm     | decimal(7,2) | YES  |     | NULL    |       |
   625  	//| deptno   | int unsigned | YES  |     | NULL    |       |
   626  	//+----------+--------------+------+-----+---------+-------+
   627  	constraintTestSchema["employees"] = &Schema{
   628  		cols: []col{
   629  			{"empno", types.T_uint32, true, 32, 0},
   630  			{"ename", types.T_varchar, true, 15, 0},
   631  			{"job", types.T_varchar, true, 10, 0},
   632  			{"mgr", types.T_uint32, true, 32, 0},
   633  			{"hiredate", types.T_date, true, 0, 0},
   634  			{"sal", types.T_decimal64, true, 7, 0},
   635  			{"comm", types.T_decimal64, true, 7, 0},
   636  			{"deptno", types.T_uint32, true, 32, 0},
   637  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   638  		},
   639  		pks: []int{0}, // primary key "deptno"
   640  		idxs: []index{
   641  			{
   642  				indexName: "",
   643  				tableName: catalog.UniqueIndexTableNamePrefix + "6380d30e-79f8-11ed-9c02-000c29847904",
   644  				parts:     []string{"empno", "ename"},
   645  				cols: []col{
   646  					{catalog.IndexTableIndexColName, types.T_varchar, true, 65535, 0},
   647  				},
   648  				tableExist: true,
   649  				unique:     true,
   650  			},
   651  		},
   652  		outcnt: 14,
   653  	}
   654  
   655  	constraintTestSchema[catalog.UniqueIndexTableNamePrefix+"6380d30e-79f8-11ed-9c02-000c29847904"] = &Schema{
   656  		cols: []col{
   657  			{catalog.IndexTableIndexColName, types.T_varchar, true, 65535, 0},
   658  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   659  		},
   660  		pks:    []int{0},
   661  		outcnt: 12,
   662  	}
   663  
   664  	constraintTestSchema["t1"] = &Schema{
   665  		cols: []col{
   666  			{"a", types.T_int64, false, 0, 0},
   667  			{"b", types.T_varchar, false, 1, 0},
   668  			{catalog.Row_ID, types.T_Rowid, false, 16, 0},
   669  		},
   670  		pks:    []int{0},
   671  		outcnt: 4,
   672  	}
   673  
   674  	objects := make(map[string]*ObjectRef)
   675  	tables := make(map[string]*TableDef)
   676  	stats := make(map[string]*Stats)
   677  	pks := make(map[string][]int)
   678  	id2name := make(map[uint64]string)
   679  	// build tpch/mo context data(schema)
   680  	for db, schema := range schemas {
   681  		tableIdx := 0
   682  		for tableName, table := range schema {
   683  			tblId := table.tblId
   684  			if tblId == 0 {
   685  				tblId = int64(tableIdx)
   686  			}
   687  			colDefs := make([]*ColDef, 0, len(table.cols))
   688  
   689  			for idx, col := range table.cols {
   690  				colDefs = append(colDefs, &ColDef{
   691  					ColId: uint64(idx),
   692  					Typ: plan.Type{
   693  						Id:          int32(col.Id),
   694  						NotNullable: !col.Nullable,
   695  						Width:       col.Width,
   696  						Scale:       col.Scale,
   697  					},
   698  					Name:    col.Name,
   699  					Primary: idx == 0,
   700  					Hidden:  col.Name == catalog.Row_ID || col.Name == catalog.CPrimaryKeyColName,
   701  					Pkidx:   1,
   702  					Default: &plan.Default{
   703  						NullAbility: col.Nullable,
   704  					},
   705  				})
   706  			}
   707  
   708  			objects[tableName] = &ObjectRef{
   709  				Server:     0,
   710  				Db:         0,
   711  				Schema:     0,
   712  				Obj:        int64(tableIdx),
   713  				ServerName: "",
   714  				DbName:     "",
   715  				SchemaName: db,
   716  				ObjName:    tableName,
   717  			}
   718  
   719  			tableDef := &TableDef{
   720  				TableType: catalog.SystemOrdinaryRel,
   721  				TblId:     uint64(tblId),
   722  				Name:      tableName,
   723  				Cols:      colDefs,
   724  				Indexes:   make([]*IndexDef, len(table.idxs)),
   725  			}
   726  			if len(table.pks) == 1 {
   727  				tableDef.Pkey = &plan.PrimaryKeyDef{
   728  					PkeyColName: colDefs[table.pks[0]].Name,
   729  					Cols:        []uint64{uint64(table.pks[0])},
   730  					Names:       []string{colDefs[table.pks[0]].Name},
   731  					CompPkeyCol: colDefs[table.pks[0]],
   732  				}
   733  			} else if len(table.pks) > 1 {
   734  				names := make([]string, len(table.pks))
   735  				cols := make([]uint64, len(table.pks))
   736  				for pkidx := range table.pks {
   737  					names = append(names, colDefs[table.pks[pkidx]].Name)
   738  					cols = append(cols, uint64(pkidx))
   739  				}
   740  				pkName := catalog.PrefixCBColName + "_" + tableName
   741  				tableDef.Pkey = &plan.PrimaryKeyDef{
   742  					PkeyColName: pkName,
   743  					Names:       names,
   744  					Cols:        cols,
   745  					CompPkeyCol: MakeHiddenColDefByName(pkName),
   746  				}
   747  			}
   748  
   749  			if table.idxs != nil {
   750  				for i, idx := range table.idxs {
   751  					indexdef := &plan.IndexDef{
   752  						IndexName:      idx.indexName,
   753  						Parts:          idx.parts,
   754  						Unique:         idx.unique,
   755  						IndexTableName: idx.tableName,
   756  						TableExist:     true,
   757  					}
   758  					tableDef.Indexes[i] = indexdef
   759  				}
   760  			}
   761  
   762  			if table.fks != nil {
   763  				tableDef.Fkeys = table.fks
   764  			}
   765  
   766  			if table.clusterby != nil {
   767  				tableDef.ClusterBy = &plan.ClusterByDef{
   768  					Name: "__mo_cbkey_003pid005pname",
   769  				}
   770  			}
   771  
   772  			if tableName != "v1" {
   773  				properties := []*plan.Property{
   774  					{
   775  						Key:   catalog.SystemRelAttr_Kind,
   776  						Value: catalog.SystemOrdinaryRel,
   777  					},
   778  					{
   779  						Key:   catalog.SystemRelAttr_Comment,
   780  						Value: tableName,
   781  					},
   782  				}
   783  				tableDef.Defs = append(tableDef.Defs, &plan.TableDef_DefType{
   784  					Def: &plan.TableDef_DefType_Properties{
   785  						Properties: &plan.PropertiesDef{
   786  							Properties: properties,
   787  						},
   788  					},
   789  				})
   790  			}
   791  
   792  			if tableName == "test_idx" {
   793  				indexParts := []string{"n_nationkey"}
   794  
   795  				p := &plan.IndexDef{
   796  					IndexName:      "idx1",
   797  					Parts:          indexParts,
   798  					Unique:         true,
   799  					IndexTableName: "nation",
   800  					TableExist:     true,
   801  				}
   802  				tableDef.Indexes = []*plan.IndexDef{p}
   803  			}
   804  
   805  			if tableName == "v1" {
   806  				tableDef.TableType = catalog.SystemViewRel
   807  				viewData, _ := json.Marshal(ViewData{
   808  					Stmt:            "select n_name from nation where n_nationkey > ?",
   809  					DefaultDatabase: "tpch",
   810  				})
   811  				tableDef.ViewSql = &plan.ViewDef{
   812  					View: string(viewData),
   813  				}
   814  				properties := []*plan.Property{
   815  					{
   816  						Key:   catalog.SystemRelAttr_Kind,
   817  						Value: catalog.SystemViewRel,
   818  					},
   819  				}
   820  				tableDef.Defs = append(tableDef.Defs, &plan.TableDef_DefType{
   821  					Def: &plan.TableDef_DefType_Properties{
   822  						Properties: &plan.PropertiesDef{
   823  							Properties: properties,
   824  						},
   825  					},
   826  				})
   827  			}
   828  
   829  			tables[tableName] = tableDef
   830  			id2name[tableDef.TblId] = tableName
   831  			tableIdx++
   832  
   833  			if table.outcnt == 0 {
   834  				table.outcnt = 1
   835  			}
   836  			stats[tableName] = &plan.Stats{
   837  				Outcnt: table.outcnt,
   838  			}
   839  
   840  			pks[tableName] = table.pks
   841  		}
   842  	}
   843  
   844  	return &MockCompilerContext{
   845  		isDml:   isDml,
   846  		objects: objects,
   847  		tables:  tables,
   848  		id2name: id2name,
   849  		pks:     pks,
   850  		ctx:     context.TODO(),
   851  	}
   852  }
   853  
   854  func (m *MockCompilerContext) DatabaseExists(name string, snapshot Snapshot) bool {
   855  	return strings.ToLower(name) == "tpch" || strings.ToLower(name) == "mo" || strings.ToLower(name) == "mo_catalog"
   856  }
   857  
   858  func (m *MockCompilerContext) GetDatabaseId(dbName string, snapshot Snapshot) (uint64, error) {
   859  	return 0, nil
   860  }
   861  
   862  func (m *MockCompilerContext) DefaultDatabase() string {
   863  	return "tpch"
   864  }
   865  
   866  func (m *MockCompilerContext) GetRootSql() string {
   867  	return ""
   868  }
   869  
   870  func (m *MockCompilerContext) GetUserName() string {
   871  	return "root"
   872  }
   873  
   874  func (m *MockCompilerContext) Resolve(dbName string, tableName string, snapshot Snapshot) (*ObjectRef, *TableDef) {
   875  	name := strings.ToLower(tableName)
   876  	tableDef := DeepCopyTableDef(m.tables[name], true)
   877  	if tableDef != nil && !m.isDml {
   878  		for i, col := range tableDef.Cols {
   879  			if col.Typ.Id == int32(types.T_Rowid) {
   880  				tableDef.Cols = append(tableDef.Cols[:i], tableDef.Cols[i+1:]...)
   881  				break
   882  			}
   883  		}
   884  
   885  		for i, col := range tableDef.Cols {
   886  			// judege whether it is a composite primary key
   887  			if col.Name == catalog.CPrimaryKeyColName {
   888  				tableDef.Cols = append(tableDef.Cols[:i], tableDef.Cols[i+1:]...)
   889  				break
   890  			}
   891  		}
   892  	}
   893  	return m.objects[name], tableDef
   894  }
   895  
   896  func (m *MockCompilerContext) ResolveById(tableId uint64, snapshot Snapshot) (*ObjectRef, *TableDef) {
   897  	name := m.id2name[tableId]
   898  	tableDef := DeepCopyTableDef(m.tables[name], true)
   899  	if tableDef != nil && !m.isDml {
   900  		for i, col := range tableDef.Cols {
   901  			if col.Typ.Id == int32(types.T_Rowid) {
   902  				tableDef.Cols = append(tableDef.Cols[:i], tableDef.Cols[i+1:]...)
   903  				break
   904  			}
   905  		}
   906  	}
   907  	return m.objects[name], tableDef
   908  }
   909  
   910  func (m *MockCompilerContext) GetPrimaryKeyDef(dbName string, tableName string, snapshot Snapshot) []*ColDef {
   911  	defs := make([]*ColDef, 0, 2)
   912  	for _, pk := range m.pks[tableName] {
   913  		defs = append(defs, m.tables[tableName].Cols[pk])
   914  	}
   915  	return defs
   916  }
   917  
   918  func (m *MockCompilerContext) Stats(obj *ObjectRef, snapshot Snapshot) (*pb.StatsInfo, error) {
   919  	return nil, nil
   920  }
   921  
   922  func (m *MockCompilerContext) GetStatsCache() *StatsCache {
   923  	return nil
   924  }
   925  
   926  func (m *MockCompilerContext) GetAccountId() (uint32, error) {
   927  	return 0, nil
   928  }
   929  
   930  func (m *MockCompilerContext) GetContext() context.Context {
   931  	return m.ctx
   932  }
   933  
   934  func (m *MockCompilerContext) GetProcess() *process.Process {
   935  	return testutil.NewProc()
   936  }
   937  
   938  func (m *MockCompilerContext) GetQueryResultMeta(uuid string) ([]*ColDef, string, error) {
   939  	return nil, "", nil
   940  }
   941  
   942  func (m *MockCompilerContext) SetBuildingAlterView(yesOrNo bool, dbName, viewName string) {
   943  }
   944  
   945  func (m *MockCompilerContext) GetBuildingAlterView() (bool, string, string) {
   946  	return false, "", ""
   947  }
   948  
   949  func (m *MockCompilerContext) GetSubscriptionMeta(dbName string, snapshot Snapshot) (*SubscriptionMeta, error) {
   950  	return nil, nil
   951  }
   952  func (m *MockCompilerContext) SetQueryingSubscription(*SubscriptionMeta) {
   953  
   954  }
   955  func (m *MockCompilerContext) GetQueryingSubscription() *SubscriptionMeta {
   956  	return nil
   957  }
   958  func (m *MockCompilerContext) IsPublishing(dbName string) (bool, error) {
   959  	return false, nil
   960  }
   961  
   962  func (m *MockCompilerContext) ResolveSnapshotWithSnapshotName(snapshotName string) (*Snapshot, error) {
   963  	return nil, nil
   964  }
   965  
   966  func (m *MockCompilerContext) CheckTimeStampValid(ts int64) (bool, error) {
   967  	return false, nil
   968  }
   969  
   970  type MockOptimizer struct {
   971  	ctxt MockCompilerContext
   972  }
   973  
   974  func NewEmptyMockOptimizer() *MockOptimizer {
   975  	return &MockOptimizer{
   976  		ctxt: *NewEmptyCompilerContext(),
   977  	}
   978  }
   979  
   980  func NewMockOptimizer(_ bool) *MockOptimizer {
   981  	return &MockOptimizer{
   982  		ctxt: *NewMockCompilerContext(true),
   983  	}
   984  }
   985  
   986  func (moc *MockOptimizer) Optimize(stmt tree.Statement) (*Query, error) {
   987  	ctx := moc.CurrentContext()
   988  	query, err := BuildPlan(ctx, stmt, false)
   989  	if err != nil {
   990  		// logutil.Infof("Optimize statement error: '%v'", tree.String(stmt, dialect.MYSQL))
   991  		return nil, err
   992  	}
   993  	return query.GetQuery(), nil
   994  }
   995  
   996  func (moc *MockOptimizer) CurrentContext() CompilerContext {
   997  	return &moc.ctxt
   998  }