vitess.io/vitess@v0.16.2/go/test/endtoend/vtgate/sequence/seq_test.go (about) 1 /* 2 Copyright 2019 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 sequence 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "os" 24 "strings" 25 "testing" 26 27 "vitess.io/vitess/go/test/endtoend/utils" 28 29 "github.com/stretchr/testify/assert" 30 31 "github.com/stretchr/testify/require" 32 33 "vitess.io/vitess/go/mysql" 34 "vitess.io/vitess/go/test/endtoend/cluster" 35 ) 36 37 var ( 38 clusterInstance *cluster.LocalProcessCluster 39 cell = "zone1" 40 hostname = "localhost" 41 unshardedKs = "uks" 42 unshardedSQLSchema = ` 43 create table sequence_test( 44 id bigint, 45 val varchar(16), 46 primary key(id) 47 )Engine=InnoDB; 48 49 create table sequence_test_seq ( 50 id int default 0, 51 next_id bigint default null, 52 cache bigint default null, 53 primary key(id) 54 ) comment 'vitess_sequence' Engine=InnoDB; 55 56 CREATE TABLE id_seq ( id INT, next_id BIGINT, cache BIGINT, PRIMARY KEY(id)) comment 'vitess_sequence'; 57 58 INSERT INTO id_seq (id, next_id, cache) values (0, 1, 1000); 59 60 ` 61 62 unshardedVSchema = ` 63 { 64 "sharded":false, 65 "vindexes": { 66 "hash_index": { 67 "type": "hash" 68 } 69 }, 70 "tables": { 71 "sequence_test":{ 72 "auto_increment":{ 73 "column" : "id", 74 "sequence" : "sequence_test_seq" 75 }, 76 "column_vindexes": [ 77 { 78 "column": "id", 79 "name": "hash_index" 80 } 81 ] 82 }, 83 "sequence_test_seq": { 84 "type": "sequence" 85 }, 86 "id_seq": { 87 "type": "sequence" 88 } 89 } 90 } 91 ` 92 93 shardedKeyspaceName = `sks` 94 95 shardedSQLSchema = ` 96 CREATE TABLE ` + "`dotted.tablename`" + ` ( 97 id BIGINT NOT NULL, 98 c1 DOUBLE NOT NULL, 99 c2 BIGINT, 100 PRIMARY KEY (id), 101 UNIQUE KEY (c1, c2) 102 ); 103 104 CREATE TABLE lookup_vindex ( 105 c1 DOUBLE NOT NULL, 106 c2 BIGINT, 107 keyspace_id BLOB, 108 UNIQUE KEY (c1, c2) 109 ); 110 111 CREATE TABLE allDefaults ( 112 id bigint NOT NULL, 113 foo varchar(255), 114 primary key (id) 115 );` 116 117 shardedVSchema = ` 118 { 119 "sharded": true, 120 "vindexes": { 121 "lookup_vindex": { 122 "type": "consistent_lookup", 123 "params": { 124 "from": "c1,c2", 125 "table": "lookup_vindex", 126 "to": "keyspace_id" 127 }, 128 "owner": "dotted.tablename" 129 }, 130 "hash": { 131 "type": "hash" 132 } 133 }, 134 "tables": { 135 "dotted.tablename": { 136 "columnVindexes": [ 137 { 138 "column": "id", 139 "name": "hash" 140 }, 141 { 142 "name": "lookup_vindex", 143 "columns": [ "c1", "c2" ] 144 } 145 ], 146 "autoIncrement": { 147 "column": "id", 148 "sequence": "id_seq" 149 } 150 }, 151 "allDefaults": { 152 "columnVindexes": [ 153 { 154 "column": "id", 155 "name": "hash" 156 } 157 ], 158 "autoIncrement": { 159 "column": "id", 160 "sequence": "id_seq" 161 } 162 }, 163 "lookup_vindex": { 164 "columnVindexes": [ 165 { 166 "column": "c1", 167 "name": "hash" 168 } 169 ] 170 } 171 } 172 }` 173 ) 174 175 func TestMain(m *testing.M) { 176 defer cluster.PanicHandler(nil) 177 flag.Parse() 178 179 exitCode := func() int { 180 clusterInstance = cluster.NewCluster(cell, hostname) 181 defer clusterInstance.Teardown() 182 183 // Start topo server 184 if err := clusterInstance.StartTopo(); err != nil { 185 return 1 186 } 187 188 // Start keyspace 189 uKeyspace := &cluster.Keyspace{ 190 Name: unshardedKs, 191 SchemaSQL: unshardedSQLSchema, 192 VSchema: unshardedVSchema, 193 } 194 if err := clusterInstance.StartUnshardedKeyspace(*uKeyspace, 1, false); err != nil { 195 return 1 196 } 197 198 sKeyspace := &cluster.Keyspace{ 199 Name: shardedKeyspaceName, 200 SchemaSQL: shardedSQLSchema, 201 VSchema: shardedVSchema, 202 } 203 if err := clusterInstance.StartKeyspace(*sKeyspace, []string{"-80", "80-"}, 1, false); err != nil { 204 return 1 205 } 206 207 // Start vtgate 208 if err := clusterInstance.StartVtgate(); err != nil { 209 return 1 210 } 211 212 return m.Run() 213 }() 214 os.Exit(exitCode) 215 } 216 217 func TestSeq(t *testing.T) { 218 defer cluster.PanicHandler(t) 219 ctx := context.Background() 220 vtParams := mysql.ConnParams{ 221 Host: "localhost", 222 Port: clusterInstance.VtgateMySQLPort, 223 } 224 conn, err := mysql.Connect(ctx, &vtParams) 225 require.Nil(t, err) 226 defer conn.Close() 227 228 //Initialize seq table 229 utils.Exec(t, conn, "insert into sequence_test_seq(id, next_id, cache) values(0,1,10)") 230 231 //Insert 4 values in the main table 232 utils.Exec(t, conn, "insert into sequence_test(val) values('a'), ('b') ,('c'), ('d')") 233 234 // Test select calls to main table and verify expected id. 235 qr := utils.Exec(t, conn, "select id, val from sequence_test where id=4") 236 if got, want := fmt.Sprintf("%v", qr.Rows), `[[INT64(4) VARCHAR("d")]]`; got != want { 237 t.Errorf("select:\n%v want\n%v", got, want) 238 } 239 240 // Test next available seq id from cache 241 qr = utils.Exec(t, conn, "select next 1 values from sequence_test_seq") 242 if got, want := fmt.Sprintf("%v", qr.Rows), `[[INT64(5)]]`; got != want { 243 t.Errorf("select:\n%v want\n%v", got, want) 244 } 245 246 // Test next_id from seq table which should be the increased by cache value(id+cache) 247 qr = utils.Exec(t, conn, "select next_id from sequence_test_seq") 248 if got, want := fmt.Sprintf("%v", qr.Rows), `[[INT64(11)]]`; got != want { 249 t.Errorf("select:\n%v want\n%v", got, want) 250 } 251 252 // Test insert with no auto-inc 253 utils.Exec(t, conn, "insert into sequence_test(id, val) values(6, 'f')") 254 qr = utils.Exec(t, conn, "select * from sequence_test") 255 if got, want := fmt.Sprintf("%v", qr.Rows), `[[INT64(1) VARCHAR("a")] [INT64(2) VARCHAR("b")] [INT64(3) VARCHAR("c")] [INT64(4) VARCHAR("d")] [INT64(6) VARCHAR("f")]]`; got != want { 256 t.Errorf("select:\n%v want\n%v", got, want) 257 } 258 259 // Next insert will fail as we have corrupted the sequence 260 utils.Exec(t, conn, "begin") 261 _, err = conn.ExecuteFetch("insert into sequence_test(val) values('g')", 1000, false) 262 utils.Exec(t, conn, "rollback") 263 want := "Duplicate entry" 264 if err == nil || !strings.Contains(err.Error(), want) { 265 t.Errorf("wrong insert: %v, must contain %s", err, want) 266 } 267 268 utils.Exec(t, conn, "DELETE FROM sequence_test_seq") 269 qr = utils.Exec(t, conn, "select * from sequence_test_seq") 270 if got, want := fmt.Sprintf("%v", qr.Rows), `[]`; got != want { 271 t.Errorf("select:\n%v want\n%v", got, want) 272 } 273 } 274 275 func TestDotTableSeq(t *testing.T) { 276 defer cluster.PanicHandler(t) 277 ctx := context.Background() 278 vtParams := mysql.ConnParams{ 279 Host: "localhost", 280 Port: clusterInstance.VtgateMySQLPort, 281 DbName: shardedKeyspaceName, 282 } 283 conn, err := mysql.Connect(ctx, &vtParams) 284 require.NoError(t, err) 285 defer conn.Close() 286 287 _, err = conn.ExecuteFetch("insert into `dotted.tablename` (c1,c2) values (10,10)", 1000, true) 288 require.NoError(t, err) 289 290 _, err = conn.ExecuteFetch("insert into `dotted.tablename` (c1,c2) values (10,10)", 1000, true) 291 require.Error(t, err) 292 mysqlErr := err.(*mysql.SQLError) 293 assert.Equal(t, 1062, mysqlErr.Num) 294 assert.Equal(t, "23000", mysqlErr.State) 295 assert.Contains(t, mysqlErr.Message, "Duplicate entry") 296 } 297 298 func TestInsertAllDefaults(t *testing.T) { 299 defer cluster.PanicHandler(t) 300 ctx := context.Background() 301 vtParams := mysql.ConnParams{ 302 Host: "localhost", 303 Port: clusterInstance.VtgateMySQLPort, 304 DbName: shardedKeyspaceName, 305 } 306 conn, err := mysql.Connect(ctx, &vtParams) 307 require.NoError(t, err) 308 defer conn.Close() 309 310 // inserting into a table that has default values for all columns works well 311 utils.Exec(t, conn, `insert into allDefaults () values ()`) 312 result := utils.Exec(t, conn, `select * from uks.id_seq`) 313 assert.Equal(t, 1, len(result.Rows)) 314 315 // inserting into a table that does not have default values for all columns fails 316 _, err = conn.ExecuteFetch("insert into lookup_vindex () values ()", 0, false) 317 require.Error(t, err) 318 }