github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/colexec/index_metadata_test.go (about)

     1  // Copyright 2021 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 colexec
    16  
    17  import (
    18  	"context"
    19  	"testing"
    20  
    21  	"github.com/golang/mock/gomock"
    22  	"github.com/matrixorigin/matrixone/pkg/catalog"
    23  	"github.com/matrixorigin/matrixone/pkg/compress"
    24  	"github.com/matrixorigin/matrixone/pkg/container/batch"
    25  	"github.com/matrixorigin/matrixone/pkg/container/types"
    26  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    27  	mock_frontend "github.com/matrixorigin/matrixone/pkg/frontend/test"
    28  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    29  	"github.com/matrixorigin/matrixone/pkg/testutil"
    30  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    31  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  func TestInsertIndexMetadata(t *testing.T) {
    36  	ctrl := gomock.NewController(t)
    37  	defer ctrl.Finish()
    38  
    39  	txnOperator := mock_frontend.NewMockTxnOperator(ctrl)
    40  	proc := testutil.NewProc()
    41  	proc.TxnOperator = txnOperator
    42  
    43  	mockEngine := mock_frontend.NewMockEngine(ctrl)
    44  	mockEngine.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
    45  	mockEngine.EXPECT().AllocateIDByKey(gomock.Any(), gomock.Any()).Return(uint64(272510), nil).AnyTimes()
    46  	//-------------------------------------------------mo_catalog + mo_indexes-----------------------------------------------------------
    47  	catalog_database := mock_frontend.NewMockDatabase(ctrl)
    48  	mockEngine.EXPECT().Database(gomock.Any(), catalog.MO_CATALOG, txnOperator).Return(catalog_database, nil).AnyTimes()
    49  
    50  	indexes_relation := mock_frontend.NewMockRelation(ctrl)
    51  	indexes_relation.EXPECT().Ranges(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
    52  	indexes_relation.EXPECT().Delete(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
    53  	indexes_relation.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
    54  
    55  	reader := mock_frontend.NewMockReader(ctrl)
    56  	reader.EXPECT().Read(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, attrs []string, b, c interface{}) (*batch.Batch, error) {
    57  		bat := batch.NewWithSize(3)
    58  		bat.Vecs[0] = vector.NewVec(types.T_Rowid.ToType())
    59  		bat.Vecs[1] = vector.NewVec(types.T_uint64.ToType())
    60  		bat.Vecs[2] = vector.NewVec(types.T_varchar.ToType())
    61  
    62  		err := vector.AppendFixed(bat.GetVector(0), types.Rowid([types.RowidSize]byte{}), false, testutil.TestUtilMp)
    63  		if err != nil {
    64  			require.Nil(t, err)
    65  		}
    66  
    67  		err = vector.AppendFixed(bat.GetVector(1), uint64(272464), false, testutil.TestUtilMp)
    68  		if err != nil {
    69  			require.Nil(t, err)
    70  		}
    71  
    72  		err = vector.AppendBytes(bat.GetVector(2), []byte("empno"), false, testutil.TestUtilMp)
    73  		if err != nil {
    74  			require.Nil(t, err)
    75  		}
    76  		bat.SetRowCount(bat.GetVector(1).Length())
    77  		return bat, nil
    78  	}).AnyTimes()
    79  	reader.EXPECT().Close().Return(nil).AnyTimes()
    80  
    81  	indexes_relation.EXPECT().NewReader(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]engine.Reader{reader}, nil).AnyTimes()
    82  	catalog_database.EXPECT().Relation(gomock.Any(), catalog.MO_INDEXES, gomock.Any()).Return(indexes_relation, nil).AnyTimes()
    83  	//---------------------------------------------------------------------------------------------------------------------------
    84  	mock_emp_Relation := mock_frontend.NewMockRelation(ctrl)
    85  	mock_emp_Relation.EXPECT().TableDefs(gomock.Any()).Return(buildMockTableDefs(mock_emp_table), nil).AnyTimes()
    86  	mock_emp_Relation.EXPECT().GetTableID(gomock.Any()).Return(uint64(272464)).AnyTimes()
    87  
    88  	mock_db1_database := mock_frontend.NewMockDatabase(ctrl)
    89  	mock_db1_database.EXPECT().Relation(gomock.Any(), gomock.Any(), gomock.Any()).Return(mock_emp_Relation, nil).AnyTimes()
    90  	mock_db1_database.EXPECT().GetDatabaseId(gomock.Any()).Return("123456").AnyTimes()
    91  
    92  	type args struct {
    93  		eg      engine.Engine
    94  		ctx     context.Context
    95  		db      engine.Database
    96  		proc    *process.Process
    97  		tblName string
    98  	}
    99  	tests := []struct {
   100  		name    string
   101  		args    args
   102  		wantErr bool
   103  	}{
   104  		{
   105  			name: "test03",
   106  			args: args{
   107  				eg:      mockEngine,
   108  				ctx:     proc.Ctx,
   109  				db:      mock_db1_database,
   110  				tblName: "emp",
   111  				proc:    proc,
   112  			},
   113  			wantErr: false,
   114  		},
   115  	}
   116  	for _, tt := range tests {
   117  		t.Run(tt.name, func(t *testing.T) {
   118  			if err := InsertIndexMetadata(tt.args.eg, tt.args.ctx, tt.args.db, tt.args.proc, tt.args.tblName); (err != nil) != tt.wantErr {
   119  				t.Errorf("InsertIndexMetadata() error = %v, wantErr %v", err, tt.wantErr)
   120  			}
   121  		})
   122  	}
   123  }
   124  
   125  func TestInsertOneIndexMetadata(t *testing.T) {
   126  	ctrl := gomock.NewController(t)
   127  	defer ctrl.Finish()
   128  
   129  	txnOperator := mock_frontend.NewMockTxnOperator(ctrl)
   130  
   131  	proc := testutil.NewProc()
   132  	proc.TxnOperator = txnOperator
   133  
   134  	mockEngine := mock_frontend.NewMockEngine(ctrl)
   135  	mockEngine.EXPECT().New(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
   136  	mockEngine.EXPECT().AllocateIDByKey(gomock.Any(), gomock.Any()).Return(uint64(272510), nil).AnyTimes()
   137  	//-------------------------------------------------mo_catalog + mo_indexes-----------------------------------------------------------
   138  	catalog_database := mock_frontend.NewMockDatabase(ctrl)
   139  
   140  	mockEngine.EXPECT().Database(gomock.Any(), catalog.MO_CATALOG, txnOperator).Return(catalog_database, nil).AnyTimes()
   141  
   142  	indexes_relation := mock_frontend.NewMockRelation(ctrl)
   143  	indexes_relation.EXPECT().Ranges(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
   144  	indexes_relation.EXPECT().Delete(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
   145  	indexes_relation.EXPECT().Write(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
   146  
   147  	reader := mock_frontend.NewMockReader(ctrl)
   148  	reader.EXPECT().Read(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, attrs []string, b, c interface{}) (*batch.Batch, error) {
   149  		bat := batch.NewWithSize(3)
   150  		bat.Vecs[0] = vector.NewVec(types.T_Rowid.ToType())
   151  		bat.Vecs[1] = vector.NewVec(types.T_uint64.ToType())
   152  		bat.Vecs[2] = vector.NewVec(types.T_varchar.ToType())
   153  
   154  		err := vector.AppendFixed(bat.GetVector(0), types.Rowid([types.RowidSize]byte{}), false, testutil.TestUtilMp)
   155  		if err != nil {
   156  			require.Nil(t, err)
   157  		}
   158  
   159  		err = vector.AppendFixed(bat.GetVector(1), uint64(272464), false, testutil.TestUtilMp)
   160  		if err != nil {
   161  			require.Nil(t, err)
   162  		}
   163  
   164  		err = vector.AppendBytes(bat.GetVector(2), []byte("empno"), false, testutil.TestUtilMp)
   165  		if err != nil {
   166  			require.Nil(t, err)
   167  		}
   168  		bat.SetRowCount(bat.GetVector(1).Length())
   169  		return bat, nil
   170  	}).AnyTimes()
   171  	reader.EXPECT().Close().Return(nil).AnyTimes()
   172  
   173  	indexes_relation.EXPECT().NewReader(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return([]engine.Reader{reader}, nil).AnyTimes()
   174  	catalog_database.EXPECT().Relation(gomock.Any(), catalog.MO_INDEXES, gomock.Any()).Return(indexes_relation, nil).AnyTimes()
   175  	//---------------------------------------------------------------------------------------------------------------------------
   176  
   177  	mock_emp_Relation := mock_frontend.NewMockRelation(ctrl)
   178  	mock_emp_Relation.EXPECT().TableDefs(gomock.Any()).Return(buildMockTableDefs(mock_emp_table), nil).AnyTimes()
   179  	mock_emp_Relation.EXPECT().GetTableID(gomock.Any()).Return(uint64(272464)).AnyTimes()
   180  
   181  	mock_db1_database := mock_frontend.NewMockDatabase(ctrl)
   182  	mock_db1_database.EXPECT().Relation(gomock.Any(), gomock.Any(), gomock.Any()).Return(mock_emp_Relation, nil).AnyTimes()
   183  	mock_db1_database.EXPECT().GetDatabaseId(gomock.Any()).Return("123456").AnyTimes()
   184  
   185  	type args struct {
   186  		eg      engine.Engine
   187  		ctx     context.Context
   188  		db      engine.Database
   189  		proc    *process.Process
   190  		tblName string
   191  		idxdef  *plan.IndexDef
   192  	}
   193  	tests := []struct {
   194  		name    string
   195  		args    args
   196  		wantErr bool
   197  	}{
   198  		{
   199  			name: "test04",
   200  			args: args{
   201  				eg:      mockEngine,
   202  				ctx:     proc.Ctx,
   203  				db:      mock_db1_database,
   204  				tblName: "emp",
   205  				proc:    proc,
   206  				idxdef: &plan.IndexDef{
   207  					IdxId:          "",
   208  					IndexName:      "idx11",
   209  					Parts:          []string{"ename", "sal", "depto"},
   210  					Unique:         false,
   211  					IndexTableName: "",
   212  					TableExist:     false,
   213  					Comment:        "this is a index on emp",
   214  				},
   215  			},
   216  			wantErr: false,
   217  		},
   218  	}
   219  	for _, tt := range tests {
   220  		t.Run(tt.name, func(t *testing.T) {
   221  			if err := InsertOneIndexMetadata(tt.args.eg, tt.args.ctx, tt.args.db, tt.args.proc, tt.args.tblName, tt.args.idxdef); (err != nil) != tt.wantErr {
   222  				t.Errorf("InsertOneIndexMetadata() error = %v, wantErr %v", err, tt.wantErr)
   223  			}
   224  		})
   225  	}
   226  }
   227  
   228  // Define an anonymous function to construct the table structure
   229  func buildMockTableDefs(table_cols []string) []engine.TableDef {
   230  	exeCols := make([]engine.TableDef, len(table_cols))
   231  	for i := 0; i < len(table_cols); i++ {
   232  		if i == 0 {
   233  			exeCols[i] = &engine.ConstraintDef{
   234  				Cts: []engine.Constraint{
   235  					&engine.IndexDef{
   236  						Indexes: []*plan.IndexDef{
   237  							{
   238  								IdxId:          "",
   239  								IndexName:      "empno",
   240  								Parts:          []string{"empno,ename"},
   241  								Unique:         true,
   242  								IndexTableName: "__mo_index_unique_c1d278ec-bfd6-11ed-9e9d-000c29203f30",
   243  								TableExist:     true,
   244  								Comment:        "",
   245  							},
   246  						},
   247  					},
   248  					&engine.PrimaryKeyDef{
   249  						Pkey: &plan.PrimaryKeyDef{
   250  							PkeyColId:   0,
   251  							PkeyColName: "empno",
   252  							Names:       []string{"empno"},
   253  						},
   254  					},
   255  				},
   256  			}
   257  		} else {
   258  			exeCols[i] = &engine.AttributeDef{
   259  				Attr: engine.Attribute{
   260  					Name:          table_cols[i],
   261  					Alg:           compress.None,
   262  					Type:          mock_emp_map[table_cols[i]],
   263  					Default:       nil,
   264  					OnUpdate:      nil,
   265  					Primary:       i == 0,
   266  					Comment:       "comment message",
   267  					ClusterBy:     false,
   268  					AutoIncrement: i == 1,
   269  				},
   270  			}
   271  		}
   272  	}
   273  	return exeCols
   274  }
   275  
   276  var mock_emp_table = []string{
   277  	"constraint",
   278  	mock_emp_empno,
   279  	mock_emp_ename,
   280  	mock_emp_job,
   281  	mock_emp_mgr,
   282  	mock_emp_hiredate,
   283  	mock_emp_sal,
   284  	mock_emp_comm,
   285  	mock_emp_deptno,
   286  }
   287  
   288  const (
   289  	mock_emp_empno    = "empno"
   290  	mock_emp_ename    = "ename"
   291  	mock_emp_job      = "job"
   292  	mock_emp_mgr      = "mgr"
   293  	mock_emp_hiredate = "hiredate"
   294  	mock_emp_sal      = "sal"
   295  	mock_emp_comm     = "comm"
   296  	mock_emp_deptno   = "deptno"
   297  )
   298  
   299  var mock_emp_map = map[string]types.Type{
   300  	mock_emp_empno: {
   301  		Oid:   types.T_uint32,
   302  		Size:  4,
   303  		Width: 32,
   304  		Scale: -1,
   305  	},
   306  	mock_emp_ename: {
   307  		Oid:   types.T_varchar,
   308  		Size:  24,
   309  		Width: 15,
   310  		Scale: 0,
   311  	},
   312  	mock_emp_job: {
   313  		Oid:   types.T_varchar,
   314  		Size:  24,
   315  		Width: 10,
   316  		Scale: 0,
   317  	},
   318  	mock_emp_mgr: {
   319  		Oid:   types.T_uint32,
   320  		Size:  4,
   321  		Width: 32,
   322  		Scale: -1,
   323  	},
   324  	mock_emp_hiredate: {
   325  		Oid:   types.T_date,
   326  		Size:  4,
   327  		Width: 0,
   328  		Scale: 0,
   329  	},
   330  	mock_emp_sal: {
   331  		Oid:   types.T_decimal64,
   332  		Size:  8,
   333  		Width: 7,
   334  		Scale: 2,
   335  	},
   336  	mock_emp_comm: {
   337  		Oid:   types.T_decimal64,
   338  		Size:  8,
   339  		Width: 7,
   340  		Scale: 2,
   341  	},
   342  	mock_emp_deptno: {
   343  		Oid:   types.T_uint32,
   344  		Size:  4,
   345  		Width: 32,
   346  		Scale: -1,
   347  	},
   348  }