diff --git a/go/mysql/endtoend/schema_change_test.go b/go/mysql/endtoend/schema_change_test.go deleted file mode 100644 index a9e72aaef5b..00000000000 --- a/go/mysql/endtoend/schema_change_test.go +++ /dev/null @@ -1,139 +0,0 @@ -/* -Copyright 2021 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package endtoend - -import ( - "context" - "fmt" - "strings" - "testing" - - "vitess.io/vitess/go/constants/sidecar" - "vitess.io/vitess/go/vt/sqlparser" - - "github.com/stretchr/testify/require" - - "vitess.io/vitess/go/mysql" -) - -var ctx = context.Background() - -const ( - createUserTable = `create table vttest.product (id bigint(20) primary key, name char(10) CHARACTER SET utf8 COLLATE utf8_unicode_ci, created bigint(20))` - dropTestTable = `drop table if exists product` -) - -func TestChangeSchemaIsNoticed(t *testing.T) { - conn, err := mysql.Connect(ctx, &connParams) - require.NoError(t, err) - defer conn.Close() - - clearQuery := sqlparser.BuildParsedQuery(mysql.ClearSchemaCopy, sidecar.GetIdentifier()).Query - insertQuery := sqlparser.BuildParsedQuery(mysql.InsertIntoSchemaCopy, sidecar.GetIdentifier()).Query - detectQuery := sqlparser.BuildParsedQuery(mysql.DetectSchemaChange, sidecar.GetIdentifier()).Query - - tests := []struct { - name string - changeQ string - }{{ - name: "add column", - changeQ: "alter table vttest.product add column phone VARCHAR(15)", - }, { - name: "rename column", - changeQ: "alter table vttest.product change name firstname char(10)", - }, { - name: "change column type", - changeQ: "alter table vttest.product change name name char(100)", - }, { - name: "remove column", - changeQ: "alter table vttest.product drop column name", - }, { - name: "remove last column", - changeQ: "alter table vttest.product drop column created", - }, { - name: "remove table", - changeQ: "drop table product", - }, { - name: "create table", - changeQ: `create table vttest.new_table (id bigint(20) primary key)`, - }, { - name: "change character set", - changeQ: "alter table vttest.product change name name char(10) CHARACTER SET utf8mb4", - }, { - name: "change collation", - changeQ: "alter table vttest.product change name name char(10) COLLATE utf8_unicode_520_ci", - }, { - name: "drop PK", - changeQ: "alter table vttest.product drop primary key", - }, { - name: "change PK", - changeQ: "alter table vttest.product drop primary key, add primary key (name)", - }, { - name: "two tables changes", - changeQ: "create table vttest.new_table2 (id bigint(20) primary key);alter table vttest.product drop column name", - }} - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - // reset schemacopy - _, err := conn.ExecuteFetch(clearQuery, 1000, true) - require.NoError(t, err) - _, err = conn.ExecuteFetch(dropTestTable, 1000, true) - require.NoError(t, err) - _, err = conn.ExecuteFetch(createUserTable, 1000, true) - require.NoError(t, err) - rs, err := conn.ExecuteFetch(insertQuery, 1000, true) - require.NoError(t, err) - require.NotZero(t, rs.RowsAffected) - - // make sure no changes are detected - rs, err = conn.ExecuteFetch(detectQuery, 1000, true) - require.NoError(t, err) - require.Empty(t, rs.Rows) - - for _, q := range strings.Split(test.changeQ, ";") { - // make the schema change - _, err = conn.ExecuteFetch(q, 1000, true) - require.NoError(t, err) - } - - // make sure the change is detected - rs, err = conn.ExecuteFetch(detectQuery, 1000, true) - require.NoError(t, err) - require.NotEmpty(t, rs.Rows) - - var tables []string - for _, row := range rs.Rows { - apa := sqlparser.NewStrLiteral(row[0].ToString()) - tables = append(tables, "table_name = "+sqlparser.String(apa)) - } - tableNamePredicates := strings.Join(tables, " OR ") - del := fmt.Sprintf("%s AND %s", clearQuery, tableNamePredicates) - upd := fmt.Sprintf("%s AND %s", insertQuery, tableNamePredicates) - - _, err = conn.ExecuteFetch(del, 1000, true) - require.NoError(t, err) - _, err = conn.ExecuteFetch(upd, 1000, true) - require.NoError(t, err) - - // make sure the change is detected - rs, err = conn.ExecuteFetch(detectQuery, 1000, true) - require.NoError(t, err) - require.Empty(t, rs.Rows) - }) - } -} diff --git a/go/mysql/schema.go b/go/mysql/schema.go index 933ce657c3a..d0b9bfe2e79 100644 --- a/go/mysql/schema.go +++ b/go/mysql/schema.go @@ -35,33 +35,6 @@ const ( // ShowRowsRead is the query used to find the number of rows read. ShowRowsRead = "show status like 'Innodb_rows_read'" - // DetectSchemaChange query detects if there is any schema change from previous copy. - DetectSchemaChange = ` -SELECT DISTINCT table_name -FROM ( - SELECT table_name, column_name, ordinal_position, character_set_name, collation_name, data_type, column_key - FROM information_schema.columns - WHERE table_schema = database() - - UNION ALL - - SELECT table_name, column_name, ordinal_position, character_set_name, collation_name, data_type, column_key - FROM %s.schemacopy - WHERE table_schema = database() -) _inner -GROUP BY table_name, column_name, ordinal_position, character_set_name, collation_name, data_type, column_key -HAVING COUNT(*) = 1 -` - - // ClearSchemaCopy query clears the schemacopy table. - ClearSchemaCopy = `delete from %s.schemacopy where table_schema = database()` - - // InsertIntoSchemaCopy query copies over the schema information from information_schema.columns table. - InsertIntoSchemaCopy = `insert %s.schemacopy -select table_schema, table_name, column_name, ordinal_position, character_set_name, collation_name, data_type, column_key -from information_schema.columns -where table_schema = database()` - // GetColumnNamesQueryPatternForTable is used for mocking queries in unit tests GetColumnNamesQueryPatternForTable = `SELECT COLUMN_NAME.*TABLE_NAME.*%s.*` ) diff --git a/go/test/endtoend/vreplication/sidecardb_test.go b/go/test/endtoend/vreplication/sidecardb_test.go index cea74626659..d2a4ec6df07 100644 --- a/go/test/endtoend/vreplication/sidecardb_test.go +++ b/go/test/endtoend/vreplication/sidecardb_test.go @@ -38,7 +38,7 @@ var ddls1, ddls2 []string func init() { sidecarDBTables = []string{"copy_state", "dt_participant", "dt_state", "heartbeat", "post_copy_action", "redo_state", - "redo_statement", "reparent_journal", "resharding_journal", "schema_migrations", "schema_version", "schemacopy", "tables", + "redo_statement", "reparent_journal", "resharding_journal", "schema_migrations", "schema_version", "tables", "vdiff", "vdiff_log", "vdiff_table", "views", "vreplication", "vreplication_log"} numSidecarDBTables = len(sidecarDBTables) ddls1 = []string{ diff --git a/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go b/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go index 1a37dfb5cf7..257dd7238f3 100644 --- a/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go +++ b/go/test/endtoend/vtgate/schematracker/unsharded/st_unsharded_test.go @@ -120,12 +120,7 @@ func TestNewUnshardedTable(t *testing.T) { require.NoError(t, err) defer conn.Close() - vtgateVersion, err := cluster.GetMajorVersion("vtgate") - require.NoError(t, err) - expected := `[[VARCHAR("dual")] [VARCHAR("main")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("main")]]` - } + expected := `[[VARCHAR("main")]]` // ensuring our initial table "main" is in the schema utils.AssertMatchesWithTimeout(t, conn, @@ -138,10 +133,7 @@ func TestNewUnshardedTable(t *testing.T) { // create a new table which is not part of the VSchema utils.Exec(t, conn, `create table new_table_tracked(id bigint, name varchar(100), primary key(id)) Engine=InnoDB`) - expected = `[[VARCHAR("dual")] [VARCHAR("main")] [VARCHAR("new_table_tracked")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("main")] [VARCHAR("new_table_tracked")]]` - } + expected = `[[VARCHAR("main")] [VARCHAR("new_table_tracked")]]` // waiting for the vttablet's schema_reload interval to kick in utils.AssertMatchesWithTimeout(t, conn, @@ -176,10 +168,7 @@ func TestNewUnshardedTable(t *testing.T) { utils.Exec(t, conn, `drop table new_table_tracked`) // waiting for the vttablet's schema_reload interval to kick in - expected = `[[VARCHAR("dual")] [VARCHAR("main")]]` - if vtgateVersion >= 17 { - expected = `[[VARCHAR("main")]]` - } + expected = `[[VARCHAR("main")]]` utils.AssertMatchesWithTimeout(t, conn, "SHOW VSCHEMA TABLES", expected, @@ -187,3 +176,55 @@ func TestNewUnshardedTable(t *testing.T) { 30*time.Second, "new_table_tracked not in vschema tables") } + +// TestCaseSensitiveSchemaTracking tests that schema tracking is case-sensitive. +// This test only works on Linux (and not on Windows and Mac) since it has a case-sensitive file system, so it allows +// creating two tables having the same name differing only in casing, but other operating systems don't. +// More information at https://dev.mysql.com/doc/refman/8.0/en/identifier-case-sensitivity.html#:~:text=Table%20names%20are%20stored%20in,lowercase%20on%20storage%20and%20lookup. +func TestCaseSensitiveSchemaTracking(t *testing.T) { + utils.SkipIfBinaryIsBelowVersion(t, 19, "vttablet") + defer cluster.PanicHandler(t) + + // create a sql connection + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.NoError(t, err) + defer conn.Close() + + // ensuring our initial table "main" is in the schema + utils.AssertMatchesWithTimeout(t, conn, + "SHOW VSCHEMA TABLES", + `[[VARCHAR("main")]]`, + 100*time.Millisecond, + 30*time.Second, + "initial tables not found in vschema") + + // Now we create two tables with the same name differing only in casing t1 and T1. + // For both of them we'll have different schema's and verify that we can read the data after schema tracking kicks in. + utils.Exec(t, conn, `create table t1(id bigint, primary key(id)) Engine=InnoDB`) + utils.Exec(t, conn, `create table T1(col bigint, col2 bigint, primary key(col)) Engine=InnoDB`) + + // Wait for schema tracking to be caught up + utils.AssertMatchesWithTimeout(t, conn, + "SHOW VSCHEMA TABLES", + `[[VARCHAR("T1")] [VARCHAR("main")] [VARCHAR("t1")]]`, + 100*time.Millisecond, + 30*time.Second, + "schema tracking didn't track both the tables") + + // Run DMLs + utils.Exec(t, conn, `insert into t1(id) values(0),(1)`) + utils.Exec(t, conn, `insert into T1(col, col2) values(0,0),(1,1)`) + + // Verify the tables are queryable + utils.AssertMatchesWithTimeout(t, conn, + `select * from t1`, `[[INT64(0)] [INT64(1)]]`, + 100*time.Millisecond, + 30*time.Second, + "could not query expected rows in t1 through vtgate") + utils.AssertMatchesWithTimeout(t, conn, + `select * from T1`, `[[INT64(0) INT64(0)] [INT64(1) INT64(1)]]`, + 100*time.Millisecond, + 30*time.Second, + "could not query expected rows in T1 through vtgate") +} diff --git a/go/vt/sidecardb/schema/schemaengine/tables.sql b/go/vt/sidecardb/schema/schemaengine/tables.sql index 00fd0194d67..3aadc7c9635 100644 --- a/go/vt/sidecardb/schema/schemaengine/tables.sql +++ b/go/vt/sidecardb/schema/schemaengine/tables.sql @@ -16,8 +16,8 @@ limitations under the License. CREATE TABLE IF NOT EXISTS tables ( - TABLE_SCHEMA varchar(64) NOT NULL, - TABLE_NAME varchar(64) NOT NULL, + TABLE_SCHEMA varchar(64) CHARACTER SET `utf8mb3` COLLATE `utf8mb3_bin` NOT NULL, + TABLE_NAME varchar(64) CHARACTER SET `utf8mb3` COLLATE `utf8mb3_bin` NOT NULL, CREATE_STATEMENT longtext, CREATE_TIME BIGINT, PRIMARY KEY (TABLE_SCHEMA, TABLE_NAME) diff --git a/go/vt/sidecardb/schema/schemaengine/views.sql b/go/vt/sidecardb/schema/schemaengine/views.sql index 1fee077202f..dd242e6567f 100644 --- a/go/vt/sidecardb/schema/schemaengine/views.sql +++ b/go/vt/sidecardb/schema/schemaengine/views.sql @@ -16,8 +16,8 @@ limitations under the License. CREATE TABLE IF NOT EXISTS views ( - TABLE_SCHEMA varchar(64) NOT NULL, - TABLE_NAME varchar(64) NOT NULL, + TABLE_SCHEMA varchar(64) CHARACTER SET `utf8mb3` COLLATE `utf8mb3_bin` NOT NULL, + TABLE_NAME varchar(64) CHARACTER SET `utf8mb3` COLLATE `utf8mb3_bin` NOT NULL, CREATE_STATEMENT longtext, VIEW_DEFINITION longtext NOT NULL, PRIMARY KEY (TABLE_SCHEMA, TABLE_NAME) diff --git a/go/vt/sidecardb/schema/schematracker/schemacopy.sql b/go/vt/sidecardb/schema/schematracker/schemacopy.sql deleted file mode 100644 index 296bb34df14..00000000000 --- a/go/vt/sidecardb/schema/schematracker/schemacopy.sql +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright 2023 The Vitess Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -CREATE TABLE IF NOT EXISTS schemacopy -( - `table_schema` varchar(64) NOT NULL, - `table_name` varchar(64) NOT NULL, - `column_name` varchar(64) NOT NULL, - `ordinal_position` bigint unsigned NOT NULL, - `character_set_name` varchar(32) DEFAULT NULL, - `collation_name` varchar(32) DEFAULT NULL, - `data_type` varchar(64) NOT NULL, - `column_key` varchar(3) NOT NULL, - PRIMARY KEY (`table_schema`, `table_name`, `ordinal_position`) -) ENGINE = InnoDB diff --git a/go/vt/vtgate/schema/tracker_test.go b/go/vt/vtgate/schema/tracker_test.go index 7b60278cbbf..1ee1aee6a0f 100644 --- a/go/vt/vtgate/schema/tracker_test.go +++ b/go/vt/vtgate/schema/tracker_test.go @@ -174,9 +174,9 @@ func TestTableTracking(t *testing.T) { // initial load of view - kept empty }, { "t1": "create table t1(id bigint primary key, name varchar(50), email varchar(50) not null default 'a@b.com')", - "t2": "create table t2(id varchar(50) primary key)", + "T1": "create table T1(id varchar(50) primary key)", }, { - "t2": "create table t2(id varchar(50) primary key, name varchar(50))", + "T1": "create table T1(id varchar(50) primary key, name varchar(50))", "t3": "create table t3(id datetime primary key)", }, { "t4": "create table t4(name varchar(50) primary key)", @@ -189,18 +189,18 @@ func TestTableTracking(t *testing.T) { }, }, { testName: "new tables", - updTbl: []string{"t1", "t2"}, + updTbl: []string{"t1", "T1"}, expTbl: map[string][]vindexes.Column{ "prior": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_INT32, CollationName: "binary", Nullable: true}}, "t1": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_INT64, CollationName: "binary", Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("email"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: false, Default: &sqlparser.Literal{Val: "a@b.com"}}}, - "t2": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, + "T1": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, }, }, { - testName: "delete prior, updated t2 and new t3", - updTbl: []string{"prior", "t2", "t3"}, + testName: "delete prior, updated T1 and new t3", + updTbl: []string{"prior", "T1", "t3"}, expTbl: map[string][]vindexes.Column{ "t1": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_INT64, CollationName: "binary", Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("email"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: false, Default: &sqlparser.Literal{Val: "a@b.com"}}}, - "t2": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, + "T1": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, "t3": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_DATETIME, CollationName: "binary", Size: 0, Nullable: true}}, }, }, { @@ -208,7 +208,7 @@ func TestTableTracking(t *testing.T) { updTbl: []string{"t4"}, expTbl: map[string][]vindexes.Column{ "t1": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_INT64, CollationName: "binary", Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("email"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: false, Default: &sqlparser.Literal{Val: "a@b.com"}}}, - "t2": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, + "T1": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}, {Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, "t3": {{Name: sqlparser.NewIdentifierCI("id"), Type: querypb.Type_DATETIME, CollationName: "binary", Size: 0, Nullable: true}}, "t4": {{Name: sqlparser.NewIdentifierCI("name"), Type: querypb.Type_VARCHAR, Size: 50, Nullable: true}}, }, @@ -225,9 +225,9 @@ func TestViewsTracking(t *testing.T) { "prior": "create view prior as select 1 from tbl", }, { "t1": "create view t1 as select 1 from tbl1", - "t2": "create view t2 as select 1 from tbl2", + "V1": "create view V1 as select 1 from tbl2", }, { - "t2": "create view t2 as select 1,2 from tbl2", + "V1": "create view V1 as select 1,2 from tbl2", "t3": "create view t3 as select 1 from tbl3", }, { "t4": "create view t4 as select 1 from tbl4", @@ -238,25 +238,25 @@ func TestViewsTracking(t *testing.T) { expView: map[string]string{ "prior": "select 1 from tbl"}, }, { - testName: "new view t1, t2", - updView: []string{"t1", "t2"}, + testName: "new view t1, V1", + updView: []string{"t1", "V1"}, expView: map[string]string{ "t1": "select 1 from tbl1", - "t2": "select 1 from tbl2", + "V1": "select 1 from tbl2", "prior": "select 1 from tbl"}, }, { - testName: "delete prior, updated t2 and new t3", - updView: []string{"prior", "t2", "t3"}, + testName: "delete prior, updated V1 and new t3", + updView: []string{"prior", "V1", "t3"}, expView: map[string]string{ "t1": "select 1 from tbl1", - "t2": "select 1, 2 from tbl2", + "V1": "select 1, 2 from tbl2", "t3": "select 1 from tbl3"}, }, { testName: "new t4", updView: []string{"t4"}, expView: map[string]string{ "t1": "select 1 from tbl1", - "t2": "select 1, 2 from tbl2", + "V1": "select 1, 2 from tbl2", "t3": "select 1 from tbl3", "t4": "select 1 from tbl4"}, }} diff --git a/go/vt/vtgate/schema/update_controller_flaky_test.go b/go/vt/vtgate/schema/update_controller_flaky_test.go index 971389af822..597705963b8 100644 --- a/go/vt/vtgate/schema/update_controller_flaky_test.go +++ b/go/vt/vtgate/schema/update_controller_flaky_test.go @@ -60,6 +60,16 @@ func TestMultipleUpdatesFromDifferentShards(t *testing.T) { }}, updateTables: []string{"a", "b"}, signalExpected: 1, + }, { + inputs: []input{{ + shard: "0", + tablesUpdates: []string{"a"}, + }, { + shard: "0", + tablesUpdates: []string{"A"}, + }}, + updateTables: []string{"a", "A"}, + signalExpected: 1, }, { inputs: []input{{ shard: "0", @@ -205,6 +215,11 @@ func TestViewsUpdates(t *testing.T) { inputs: []input{{shard: "0", viewUpdates: []string{"a"}}, {shard: "0", viewUpdates: []string{"b"}}}, updateViews: []string{"a", "b"}, signalExpected: 1, + }, { + desc: "received different view updates from shards - case sensitive names", + inputs: []input{{shard: "0", viewUpdates: []string{"a"}}, {shard: "0", viewUpdates: []string{"A"}}}, + updateViews: []string{"a", "A"}, + signalExpected: 1, }, { desc: "delay between inputs - different signals from each input", inputs: []input{{shard: "0", viewUpdates: []string{"a"}}, {shard: "0", viewUpdates: []string{"b"}}}, diff --git a/go/vt/vttablet/endtoend/views_test.go b/go/vt/vttablet/endtoend/views_test.go index 4ef70345180..99a28b0f215 100644 --- a/go/vt/vttablet/endtoend/views_test.go +++ b/go/vt/vttablet/endtoend/views_test.go @@ -70,7 +70,7 @@ func TestCreateViewDDL(t *testing.T) { qr, err := client.Execute(qSelAllRows, nil) require.NoError(t, err) require.Equal(t, - "[[VARCHAR(\"vttest\") VARCHAR(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`eid` AS `eid`,`vitess_a`.`id` AS `id`,`vitess_a`.`name` AS `name`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", + "[[VARBINARY(\"vttest\") VARBINARY(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`eid` AS `eid`,`vitess_a`.`id` AS `id`,`vitess_a`.`name` AS `name`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", fmt.Sprintf("%v", qr.Rows)) // view already exists. This should fail. @@ -86,7 +86,7 @@ func TestCreateViewDDL(t *testing.T) { qr, err = client.Execute(qSelAllRows, nil) require.NoError(t, err) require.Equal(t, - "[[VARCHAR(\"vttest\") VARCHAR(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`id` AS `id`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", + "[[VARBINARY(\"vttest\") VARBINARY(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`id` AS `id`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", fmt.Sprintf("%v", qr.Rows)) } @@ -132,7 +132,7 @@ func TestAlterViewDDL(t *testing.T) { qr, err := client.Execute(qSelAllRows, nil) require.NoError(t, err) require.Equal(t, - "[[VARCHAR(\"vttest\") VARCHAR(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`eid` AS `eid`,`vitess_a`.`id` AS `id`,`vitess_a`.`name` AS `name`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", + "[[VARBINARY(\"vttest\") VARBINARY(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`eid` AS `eid`,`vitess_a`.`id` AS `id`,`vitess_a`.`name` AS `name`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", fmt.Sprintf("%v", qr.Rows)) // view exists, should PASS @@ -144,7 +144,7 @@ func TestAlterViewDDL(t *testing.T) { qr, err = client.Execute(qSelAllRows, nil) require.NoError(t, err) require.Equal(t, - "[[VARCHAR(\"vttest\") VARCHAR(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`id` AS `id`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", + "[[VARBINARY(\"vttest\") VARBINARY(\"vitess_view\") TEXT(\"CREATE ALGORITHM=UNDEFINED DEFINER=`vt_dba`@`localhost` SQL SECURITY DEFINER VIEW `vitess_view` AS select `vitess_a`.`id` AS `id`,`vitess_a`.`foo` AS `foo` from `vitess_a`\")]]", fmt.Sprintf("%v", qr.Rows)) } diff --git a/go/vt/vttablet/tabletserver/health_streamer.go b/go/vt/vttablet/tabletserver/health_streamer.go index 88304da4bec..8ff6834aeaf 100644 --- a/go/vt/vttablet/tabletserver/health_streamer.go +++ b/go/vt/vttablet/tabletserver/health_streamer.go @@ -20,25 +20,19 @@ import ( "context" "fmt" "io" - "strings" "sync" "sync/atomic" "time" "github.com/spf13/pflag" - "vitess.io/vitess/go/constants/sidecar" - vtschema "vitess.io/vitess/go/vt/schema" "vitess.io/vitess/go/vt/vttablet/tabletserver/schema" - "vitess.io/vitess/go/vt/servenv" - "vitess.io/vitess/go/vt/sqlparser" - "vitess.io/vitess/go/vt/dbconfigs" + "vitess.io/vitess/go/vt/servenv" "vitess.io/vitess/go/history" - "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/vt/log" querypb "vitess.io/vitess/go/vt/proto/query" topodatapb "vitess.io/vitess/go/vt/proto/topodata" @@ -371,14 +365,6 @@ func (hs *healthStreamer) reload(full map[string]*schema.Table, created, altered } } - // Reload the tables and views. - // This stores the data that is used by VTGates upto v17. So, we can remove this reload of - // tables and views in v19. - err = hs.reloadTables(ctx, conn.Conn, tables) - if err != nil { - return err - } - // no change detected if len(tables) == 0 && len(views) == 0 { return nil @@ -393,41 +379,3 @@ func (hs *healthStreamer) reload(full map[string]*schema.Table, created, altered return nil } - -func (hs *healthStreamer) reloadTables(ctx context.Context, conn *connpool.Conn, tableNames []string) error { - if len(tableNames) == 0 { - return nil - } - var escapedTableNames []string - for _, tableName := range tableNames { - escapedTblName := sqlparser.String(sqlparser.NewStrLiteral(tableName)) - escapedTableNames = append(escapedTableNames, escapedTblName) - } - - tableNamePredicate := fmt.Sprintf("table_name IN (%s)", strings.Join(escapedTableNames, ", ")) - del := fmt.Sprintf("%s AND %s", sqlparser.BuildParsedQuery(mysql.ClearSchemaCopy, sidecar.GetIdentifier()).Query, tableNamePredicate) - upd := fmt.Sprintf("%s AND %s", sqlparser.BuildParsedQuery(mysql.InsertIntoSchemaCopy, sidecar.GetIdentifier()).Query, tableNamePredicate) - - // Reload the schema in a transaction. - _, err := conn.Exec(ctx, "begin", 1, false) - if err != nil { - return err - } - defer conn.Exec(ctx, "rollback", 1, false) - - _, err = conn.Exec(ctx, del, 1, false) - if err != nil { - return err - } - - _, err = conn.Exec(ctx, upd, 1, false) - if err != nil { - return err - } - - _, err = conn.Exec(ctx, "commit", 1, false) - if err != nil { - return err - } - return nil -} diff --git a/go/vt/vttablet/tabletserver/health_streamer_test.go b/go/vt/vttablet/tabletserver/health_streamer_test.go index 1a7a1392efb..c0f63ab3b96 100644 --- a/go/vt/vttablet/tabletserver/health_streamer_test.go +++ b/go/vt/vttablet/tabletserver/health_streamer_test.go @@ -29,7 +29,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" - "vitess.io/vitess/go/constants/sidecar" "vitess.io/vitess/go/mysql" "vitess.io/vitess/go/mysql/collations" "vitess.io/vitess/go/mysql/fakesqldb" @@ -231,8 +230,6 @@ func TestReloadSchema(t *testing.T) { target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} configs := config.DB - db.AddQueryPattern(sqlparser.BuildParsedQuery(mysql.ClearSchemaCopy, sidecar.GetIdentifier()).Query+".*", &sqltypes.Result{}) - db.AddQueryPattern(sqlparser.BuildParsedQuery(mysql.InsertIntoSchemaCopy, sidecar.GetIdentifier()).Query+".*", &sqltypes.Result{}) db.AddQueryPattern("SELECT UNIX_TIMESTAMP()"+".*", sqltypes.MakeTestResult( sqltypes.MakeTestFields( "UNIX_TIMESTAMP(now())", @@ -345,8 +342,6 @@ func TestReloadView(t *testing.T) { target := &querypb.Target{TabletType: topodatapb.TabletType_PRIMARY} configs := config.DB - db.AddQueryPattern(sqlparser.BuildParsedQuery(mysql.ClearSchemaCopy, sidecar.GetIdentifier()).Query+".*", &sqltypes.Result{}) - db.AddQueryPattern(sqlparser.BuildParsedQuery(mysql.InsertIntoSchemaCopy, sidecar.GetIdentifier()).Query+".*", &sqltypes.Result{}) db.AddQueryPattern("SELECT UNIX_TIMESTAMP()"+".*", sqltypes.MakeTestResult( sqltypes.MakeTestFields( "UNIX_TIMESTAMP(now())", diff --git a/go/vt/vttablet/tabletserver/schema/engine_test.go b/go/vt/vttablet/tabletserver/schema/engine_test.go index 0e9f0dd9162..ebd2d5a325e 100644 --- a/go/vt/vttablet/tabletserver/schema/engine_test.go +++ b/go/vt/vttablet/tabletserver/schema/engine_test.go @@ -1189,23 +1189,23 @@ func TestEngineReload(t *testing.T) { } // MySQL unix timestamp query. db.AddQuery("SELECT UNIX_TIMESTAMP()", sqltypes.MakeTestResult(sqltypes.MakeTestFields("UNIX_TIMESTAMP", "int64"), "987654326")) - // Table t2 is updated, t3 is created and t4 is deleted. - // View v2 is updated, v3 is created and v4 is deleted. + // Table t2 is updated, T2 is created and t4 is deleted. + // View v2 is updated, V2 is created and v4 is deleted. db.AddQuery(conn.BaseShowTables(), sqltypes.MakeTestResult(sqltypes.MakeTestFields("table_name|table_type|unix_timestamp(create_time)|table_comment", "varchar|varchar|int64|varchar"), "t1|BASE_TABLE|123456789|", "t2|BASE_TABLE|123456790|", - "t3|BASE_TABLE|123456789|", + "T2|BASE_TABLE|123456789|", "v1|VIEW|123456789|", "v2|VIEW|123456789|", - "v3|VIEW|123456789|", + "V2|VIEW|123456789|", )) // Detecting view changes. - // According to the database, v2, v3, v4, and v5 require updating. + // According to the database, v2, V2, v4, and v5 require updating. db.AddQuery(fmt.Sprintf(detectViewChange, sidecar.GetIdentifier()), sqltypes.MakeTestResult(sqltypes.MakeTestFields("table_name", "varchar"), "v2", - "v3", + "V2", "v4", "v5", )) @@ -1224,7 +1224,7 @@ func TestEngineReload(t *testing.T) { "Innodb_rows_read|35")) // Queries to load the tables' information. - for _, tableName := range []string{"t2", "t3", "v2", "v3"} { + for _, tableName := range []string{"t2", "T2", "v2", "V2"} { db.AddQuery(fmt.Sprintf(`SELECT COLUMN_NAME as column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'fakesqldb' AND TABLE_NAME = '%s' @@ -1238,12 +1238,12 @@ func TestEngineReload(t *testing.T) { db.AddQuery(mysql.BaseShowPrimary, sqltypes.MakeTestResult(mysql.ShowPrimaryFields, "t1|col1", "t2|col1", - "t3|col1", + "T2|col1", )) // Queries for reloading the tables' information. { - for _, tableName := range []string{"t2", "t3"} { + for _, tableName := range []string{"t2", "T2"} { db.AddQuery(fmt.Sprintf(`show create table %s`, tableName), sqltypes.MakeTestResult(sqltypes.MakeTestFields("Table | Create Table", "varchar|varchar"), fmt.Sprintf("%v|create_table_%v", tableName, tableName))) @@ -1252,41 +1252,41 @@ func TestEngineReload(t *testing.T) { db.AddQuery("commit", &sqltypes.Result{}) db.AddQuery("rollback", &sqltypes.Result{}) // We are adding both the variants of the delete statements that we can see in the test, since the deleted tables are initially stored as a map, the order is not defined. - db.AddQuery("delete from _vt.`tables` where TABLE_SCHEMA = database() and TABLE_NAME in ('t5', 't4', 't3', 't2')", &sqltypes.Result{}) - db.AddQuery("delete from _vt.`tables` where TABLE_SCHEMA = database() and TABLE_NAME in ('t4', 't5', 't3', 't2')", &sqltypes.Result{}) + db.AddQuery("delete from _vt.`tables` where TABLE_SCHEMA = database() and TABLE_NAME in ('t5', 't4', 'T2', 't2')", &sqltypes.Result{}) + db.AddQuery("delete from _vt.`tables` where TABLE_SCHEMA = database() and TABLE_NAME in ('t4', 't5', 'T2', 't2')", &sqltypes.Result{}) db.AddQuery("insert into _vt.`tables`(TABLE_SCHEMA, TABLE_NAME, CREATE_STATEMENT, CREATE_TIME) values (database(), 't2', 'create_table_t2', 123456790)", &sqltypes.Result{}) - db.AddQuery("insert into _vt.`tables`(TABLE_SCHEMA, TABLE_NAME, CREATE_STATEMENT, CREATE_TIME) values (database(), 't3', 'create_table_t3', 123456789)", &sqltypes.Result{}) + db.AddQuery("insert into _vt.`tables`(TABLE_SCHEMA, TABLE_NAME, CREATE_STATEMENT, CREATE_TIME) values (database(), 'T2', 'create_table_T2', 123456789)", &sqltypes.Result{}) } // Queries for reloading the views' information. { - for _, tableName := range []string{"v2", "v3"} { + for _, tableName := range []string{"v2", "V2"} { db.AddQuery(fmt.Sprintf(`show create table %s`, tableName), sqltypes.MakeTestResult(sqltypes.MakeTestFields(" View | Create View | character_set_client | collation_connection", "varchar|varchar|varchar|varchar"), fmt.Sprintf("%v|create_table_%v|utf8mb4|utf8mb4_0900_ai_ci", tableName, tableName))) } // We are adding both the variants of the select statements that we can see in the test, since the deleted views are initially stored as a map, the order is not defined. - db.AddQuery("select table_name, view_definition from information_schema.views where table_schema = database() and table_name in ('v4', 'v5', 'v3', 'v2')", + db.AddQuery("select table_name, view_definition from information_schema.views where table_schema = database() and table_name in ('v4', 'v5', 'V2', 'v2')", sqltypes.MakeTestResult(sqltypes.MakeTestFields("table_name|view_definition", "varchar|varchar"), "v2|select_v2", - "v3|select_v3", + "V2|select_V2", )) - db.AddQuery("select table_name, view_definition from information_schema.views where table_schema = database() and table_name in ('v5', 'v4', 'v3', 'v2')", + db.AddQuery("select table_name, view_definition from information_schema.views where table_schema = database() and table_name in ('v5', 'v4', 'V2', 'v2')", sqltypes.MakeTestResult(sqltypes.MakeTestFields("table_name|view_definition", "varchar|varchar"), "v2|select_v2", - "v3|select_v3", + "V2|select_V2", )) // We are adding both the variants of the delete statements that we can see in the test, since the deleted views are initially stored as a map, the order is not defined. - db.AddQuery("delete from _vt.views where TABLE_SCHEMA = database() and TABLE_NAME in ('v4', 'v5', 'v3', 'v2')", &sqltypes.Result{}) - db.AddQuery("delete from _vt.views where TABLE_SCHEMA = database() and TABLE_NAME in ('v5', 'v4', 'v3', 'v2')", &sqltypes.Result{}) + db.AddQuery("delete from _vt.views where TABLE_SCHEMA = database() and TABLE_NAME in ('v4', 'v5', 'V2', 'v2')", &sqltypes.Result{}) + db.AddQuery("delete from _vt.views where TABLE_SCHEMA = database() and TABLE_NAME in ('v5', 'v4', 'V2', 'v2')", &sqltypes.Result{}) db.AddQuery("insert into _vt.views(TABLE_SCHEMA, TABLE_NAME, CREATE_STATEMENT, VIEW_DEFINITION) values (database(), 'v2', 'create_table_v2', 'select_v2')", &sqltypes.Result{}) - db.AddQuery("insert into _vt.views(TABLE_SCHEMA, TABLE_NAME, CREATE_STATEMENT, VIEW_DEFINITION) values (database(), 'v3', 'create_table_v3', 'select_v3')", &sqltypes.Result{}) + db.AddQuery("insert into _vt.views(TABLE_SCHEMA, TABLE_NAME, CREATE_STATEMENT, VIEW_DEFINITION) values (database(), 'V2', 'create_table_V2', 'select_V2')", &sqltypes.Result{}) } // Verify the list of created, altered and dropped tables seen. se.RegisterNotifier("test", func(full map[string]*Table, created, altered, dropped []*Table) { - require.ElementsMatch(t, extractNamesFromTablesList(created), []string{"t3", "v3"}) + require.ElementsMatch(t, extractNamesFromTablesList(created), []string{"T2", "V2"}) require.ElementsMatch(t, extractNamesFromTablesList(altered), []string{"t2", "v2"}) require.ElementsMatch(t, extractNamesFromTablesList(dropped), []string{"t4", "v4", "t5", "v5"}) }, false)