vitess.io/vitess@v0.16.2/go/vt/vttablet/tabletserver/schema/historian_test.go (about) 1 /* 2 Copyright 2020 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package schema 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/require" 24 "google.golang.org/protobuf/proto" 25 26 "vitess.io/vitess/go/sqltypes" 27 binlogdatapb "vitess.io/vitess/go/vt/proto/binlogdata" 28 querypb "vitess.io/vitess/go/vt/proto/query" 29 "vitess.io/vitess/go/vt/sqlparser" 30 ) 31 32 func getTable(name string, fieldNames []string, fieldTypes []querypb.Type, pks []int64) *binlogdatapb.MinimalTable { 33 if name == "" || len(fieldNames) == 0 || len(fieldNames) != len(fieldTypes) || len(pks) == 0 { 34 return nil 35 } 36 fields := []*querypb.Field{} 37 for i := range fieldNames { 38 fields = append(fields, &querypb.Field{ 39 Name: fieldNames[i], 40 Type: fieldTypes[i], 41 Table: name, 42 }) 43 } 44 table := &binlogdatapb.MinimalTable{ 45 Name: name, 46 Fields: fields, 47 PKColumns: pks, 48 } 49 return table 50 } 51 52 func getDbSchemaBlob(t *testing.T, tables map[string]*binlogdatapb.MinimalTable) string { 53 dbSchema := &binlogdatapb.MinimalSchema{ 54 Tables: []*binlogdatapb.MinimalTable{}, 55 } 56 for name, table := range tables { 57 t := &binlogdatapb.MinimalTable{ 58 Name: name, 59 Fields: table.Fields, 60 } 61 pks := make([]int64, 0) 62 for _, pk := range table.PKColumns { 63 pks = append(pks, int64(pk)) 64 } 65 t.PKColumns = pks 66 dbSchema.Tables = append(dbSchema.Tables, t) 67 } 68 blob, err := proto.Marshal(dbSchema) 69 require.NoError(t, err) 70 return string(blob) 71 } 72 73 func TestHistorian(t *testing.T) { 74 se, db, cancel := getTestSchemaEngine(t) 75 defer cancel() 76 77 se.EnableHistorian(false) 78 require.Nil(t, se.RegisterVersionEvent()) 79 gtidPrefix := "MySQL56/7b04699f-f5e9-11e9-bf88-9cb6d089e1c3:" 80 gtid1 := gtidPrefix + "1-10" 81 ddl1 := "create table tracker_test (id int)" 82 ts1 := int64(1427325876) 83 _, _, _ = ddl1, ts1, db 84 _, err := se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid1) 85 require.Equal(t, "table t1 not found in vttablet schema", err.Error()) 86 tab, err := se.GetTableForPos(sqlparser.NewIdentifierCS("dual"), gtid1) 87 require.NoError(t, err) 88 require.Equal(t, `name:"dual"`, fmt.Sprintf("%v", tab)) 89 se.EnableHistorian(true) 90 _, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid1) 91 require.Equal(t, "table t1 not found in vttablet schema", err.Error()) 92 var blob1 string 93 94 fields := []*querypb.Field{{ 95 Name: "id", 96 Type: sqltypes.Int32, 97 }, { 98 Name: "pos", 99 Type: sqltypes.VarBinary, 100 }, { 101 Name: "ddl", 102 Type: sqltypes.VarBinary, 103 }, { 104 Name: "time_updated", 105 Type: sqltypes.Int32, 106 }, { 107 Name: "schemax", 108 Type: sqltypes.Blob, 109 }} 110 111 table := getTable("t1", []string{"id1", "id2"}, []querypb.Type{querypb.Type_INT32, querypb.Type_INT32}, []int64{0}) 112 tables := make(map[string]*binlogdatapb.MinimalTable) 113 tables["t1"] = table 114 blob1 = getDbSchemaBlob(t, tables) 115 db.AddQuery("select id, pos, ddl, time_updated, schemax from _vt.schema_version where id > 0 order by id asc", &sqltypes.Result{ 116 Fields: fields, 117 Rows: [][]sqltypes.Value{ 118 {sqltypes.NewInt32(1), sqltypes.NewVarBinary(gtid1), sqltypes.NewVarBinary(ddl1), sqltypes.NewInt32(int32(ts1)), sqltypes.NewVarBinary(blob1)}, 119 }, 120 }) 121 require.Nil(t, se.RegisterVersionEvent()) 122 exp1 := `name:"t1" fields:{name:"id1" type:INT32 table:"t1"} fields:{name:"id2" type:INT32 table:"t1"} p_k_columns:0` 123 tab, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid1) 124 require.NoError(t, err) 125 require.Equal(t, exp1, fmt.Sprintf("%v", tab)) 126 gtid2 := gtidPrefix + "1-20" 127 _, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid2) 128 require.Equal(t, "table t1 not found in vttablet schema", err.Error()) 129 130 table = getTable("t1", []string{"id1", "id2"}, []querypb.Type{querypb.Type_INT32, querypb.Type_VARBINARY}, []int64{0}) 131 tables["t1"] = table 132 blob2 := getDbSchemaBlob(t, tables) 133 ddl2 := "alter table t1 modify column id2 varbinary" 134 ts2 := ts1 + 100 135 db.AddQuery("select id, pos, ddl, time_updated, schemax from _vt.schema_version where id > 1 order by id asc", &sqltypes.Result{ 136 Fields: fields, 137 Rows: [][]sqltypes.Value{ 138 {sqltypes.NewInt32(2), sqltypes.NewVarBinary(gtid2), sqltypes.NewVarBinary(ddl2), sqltypes.NewInt32(int32(ts2)), sqltypes.NewVarBinary(blob2)}, 139 }, 140 }) 141 require.Nil(t, se.RegisterVersionEvent()) 142 exp2 := `name:"t1" fields:{name:"id1" type:INT32 table:"t1"} fields:{name:"id2" type:VARBINARY table:"t1"} p_k_columns:0` 143 tab, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid2) 144 require.NoError(t, err) 145 require.Equal(t, exp2, fmt.Sprintf("%v", tab)) 146 gtid3 := gtidPrefix + "1-30" 147 _, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid3) 148 require.Equal(t, "table t1 not found in vttablet schema", err.Error()) 149 150 table = getTable("t1", []string{"id1", "id2", "id3"}, []querypb.Type{querypb.Type_INT32, querypb.Type_VARBINARY, querypb.Type_INT32}, []int64{0}) 151 tables["t1"] = table 152 blob3 := getDbSchemaBlob(t, tables) 153 ddl3 := "alter table t1 add column id3 int" 154 ts3 := ts2 + 100 155 db.AddQuery("select id, pos, ddl, time_updated, schemax from _vt.schema_version where id > 2 order by id asc", &sqltypes.Result{ 156 Fields: fields, 157 Rows: [][]sqltypes.Value{ 158 {sqltypes.NewInt32(3), sqltypes.NewVarBinary(gtid3), sqltypes.NewVarBinary(ddl3), sqltypes.NewInt32(int32(ts3)), sqltypes.NewVarBinary(blob3)}, 159 }, 160 }) 161 require.Nil(t, se.RegisterVersionEvent()) 162 exp3 := `name:"t1" fields:{name:"id1" type:INT32 table:"t1"} fields:{name:"id2" type:VARBINARY table:"t1"} fields:{name:"id3" type:INT32 table:"t1"} p_k_columns:0` 163 tab, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid3) 164 require.NoError(t, err) 165 require.Equal(t, exp3, fmt.Sprintf("%v", tab)) 166 167 tab, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid1) 168 require.NoError(t, err) 169 require.Equal(t, exp1, fmt.Sprintf("%v", tab)) 170 tab, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid2) 171 require.NoError(t, err) 172 require.Equal(t, exp2, fmt.Sprintf("%v", tab)) 173 tab, err = se.GetTableForPos(sqlparser.NewIdentifierCS("t1"), gtid3) 174 require.NoError(t, err) 175 require.Equal(t, exp3, fmt.Sprintf("%v", tab)) 176 }