From 7721265ae08085b6a11befe1d79ddbb7c751d3e5 Mon Sep 17 00:00:00 2001 From: hustjieke Date: Tue, 24 Sep 2019 18:03:14 +0800 Subject: [PATCH] planner: fix column name with no quote when scatter to backends #489 [summary] When scatter sql to backends, the column name should be with quote '`' e.g.: create table db.t(`key` int primary key, `col` int); For the ddl with rename table, we remove all quotes '`' to uniform standars. e.g.: alter table t1 rename t2. [test case] src/planner/ddl_plan_test.go src/planner/ddl_test.go src/executor/ddl_executor_test.go [patch codecov] src/planner/ddl_plan.go 95.1% coverage: 89.8% of statements --- src/executor/ddl_executor_test.go | 23 +-- src/planner/ddl_plan.go | 330 +++++++++++++++++------------- src/planner/ddl_plan_test.go | 118 +++++------ src/proxy/ddl.go | 3 + src/proxy/ddl_test.go | 53 +---- src/router/frm.go | 2 +- 6 files changed, 246 insertions(+), 283 deletions(-) diff --git a/src/executor/ddl_executor_test.go b/src/executor/ddl_executor_test.go index 151951ab..99cda1e8 100644 --- a/src/executor/ddl_executor_test.go +++ b/src/executor/ddl_executor_test.go @@ -29,7 +29,7 @@ func TestDDLExecutor(t *testing.T) { // Create scatter and query handler. scatter, fakedbs, cleanup := backend.MockScatter(log, 10) defer cleanup() - fakedbs.AddQueryPattern("create table `sbtest`.`A.*", fakedb.Result3) + fakedbs.AddQueryPattern("create table sbtest.A.*", fakedb.Result3) fakedbs.AddQueryPattern("create database.*", fakedb.Result3) route, cleanup := router.MockNewRouter(log) @@ -58,25 +58,4 @@ func TestDDLExecutor(t *testing.T) { assert.Nil(t, err) } } - - // create database - { - query := "create database sbtest" - node, err := sqlparser.Parse(query) - assert.Nil(t, err) - - plan := planner.NewDDLPlan(log, database, query, node.(*sqlparser.DDL), route) - err = plan.Build() - assert.Nil(t, err) - - txn, err := scatter.CreateTransaction() - assert.Nil(t, err) - defer txn.Finish() - executor := NewDDLExecutor(log, plan, txn) - { - ctx := xcontext.NewResultContext() - err := executor.Execute(ctx) - assert.Nil(t, err) - } - } } diff --git a/src/planner/ddl_plan.go b/src/planner/ddl_plan.go index 81c91ffb..05bf50ed 100644 --- a/src/planner/ddl_plan.go +++ b/src/planner/ddl_plan.go @@ -12,7 +12,6 @@ import ( "encoding/json" "errors" "fmt" - "regexp" "strings" "router" @@ -66,162 +65,215 @@ func NewDDLPlan(log *xlog.Log, database string, query string, node *sqlparser.DD } } -// Build used to build DDL distributed querys. -// sqlparser.DDL is a simple grammar ast, it just parses database and table name in the prefix. -func (p *DDLPlan) Build() error { +// checkUnsupportedOperations used to check whether we do unsupported operations when shardtype is HASH/LIST. +func (p *DDLPlan) checkUnsupportedOperations(database, table string) error { node := p.node - - switch node.Action { - case sqlparser.CreateDBStr: - p.ReqMode = xcontext.ReqScatter - return nil - default: - table := node.Table.Name.String() - database := p.database - if !node.Table.Qualifier.IsEmpty() { - database = node.Table.Qualifier.String() - } - - // Get the shard key. - shardKey, err := p.router.ShardKey(database, table) - if err != nil { - return err - } - // Unsupported operations check if shardtype is HASH. - if shardKey != "" { - switch node.Action { - case sqlparser.AlterDropColumnStr: - if shardKey == node.DropColumnName { - return errors.New("unsupported: cannot.drop.the.column.on.shard.key") - } - case sqlparser.AlterModifyColumnStr: - if shardKey == node.ModifyColumnDef.Name.String() { - return errors.New("unsupported: cannot.modify.the.column.on.shard.key") - } - // constraint check in column definition - if node.ModifyColumnDef.Type.PrimaryKeyOpt == sqlparser.ColKeyPrimary || - node.ModifyColumnDef.Type.UniqueKeyOpt == sqlparser.ColKeyUniqueKey { + // Get the shard key. + shardKey, err := p.router.ShardKey(database, table) + if err != nil { + return err + } + // Unsupported operations check when shardtype is HASH/LIST. + if shardKey != "" { + switch node.Action { + case sqlparser.AlterDropColumnStr: + if shardKey == node.DropColumnName { + return errors.New("unsupported: cannot.drop.the.column.on.shard.key") + } + case sqlparser.AlterModifyColumnStr: + if shardKey == node.ModifyColumnDef.Name.String() { + return errors.New("unsupported: cannot.modify.the.column.on.shard.key") + } + // constraint check in column definition + if node.ModifyColumnDef.Type.PrimaryKeyOpt == sqlparser.ColKeyPrimary || + node.ModifyColumnDef.Type.UniqueKeyOpt == sqlparser.ColKeyUniqueKey { + err := fmt.Sprintf("The unique/primary constraint should be only defined on the sharding key column[%s]", shardKey) + return errors.New(err) + } + case sqlparser.AlterAddColumnStr: + // constraint check in column definition + for _, col := range node.TableSpec.Columns { + if col.Type.PrimaryKeyOpt == sqlparser.ColKeyPrimary || + col.Type.UniqueKeyOpt == sqlparser.ColKeyUniqueKey { err := fmt.Sprintf("The unique/primary constraint should be only defined on the sharding key column[%s]", shardKey) return errors.New(err) } - case sqlparser.AlterAddColumnStr: - //constraint check in column definition - for _, col := range node.TableSpec.Columns { - if col.Type.PrimaryKeyOpt == sqlparser.ColKeyPrimary || - col.Type.UniqueKeyOpt == sqlparser.ColKeyUniqueKey { - err := fmt.Sprintf("The unique/primary constraint should be only defined on the sharding key column[%s]", shardKey) - return errors.New(err) - } - } - // constraint check in index definition - for _, index := range node.TableSpec.Indexes { - info := index.Info - if info.Unique || info.Primary { - err := fmt.Sprintf("The unique/primary constraint should be only defined on the sharding key column[%s]", shardKey) - return errors.New(err) - } + } + // constraint check in index definition + for _, index := range node.TableSpec.Indexes { + info := index.Info + if info.Unique || info.Primary { + err := fmt.Sprintf("The unique/primary constraint should be only defined on the sharding key column[%s]", shardKey) + return errors.New(err) } } } + } + return nil +} - segments, err := p.router.Lookup(database, table, nil, nil) - if err != nil { - return err +// commonImpl used to build distributed querys for create/alter ... +func (p *DDLPlan) commonImpl() error { + oldNode := p.node + oldTable := oldNode.Table.Name.String() + database := p.database + if !oldNode.Table.Qualifier.IsEmpty() { + database = oldNode.Table.Qualifier.String() + } + if err := p.checkUnsupportedOperations(database, oldTable); err != nil { + return err + } + + segments, err := p.router.Lookup(database, oldTable, nil, nil) + if err != nil { + return err + } + for _, segment := range segments { + // Rewrite ddl ast, replace oldTable to segment table(new table) and format a new query + newNode := *oldNode + newTable := segment.Table + buf := sqlparser.NewTrackedBuffer(nil) + newNode.Table = sqlparser.TableName{ + Name: sqlparser.NewTableIdent(newTable), + Qualifier: sqlparser.NewTableIdent(database), } - for _, segment := range segments { - var query string - - orgSegTable := segment.Table - var rawQuery string - var re *regexp.Regexp - var segTable string - if node.Table.Qualifier.IsEmpty() { - segTable = fmt.Sprintf("`%s`.`%s`", database, orgSegTable) - rawQuery = strings.Replace(p.RawQuery, "`", "", -1) - // \b: https://www.regular-expressions.info/wordboundaries.html - re, _ = regexp.Compile(fmt.Sprintf(`\b(%s)\b`, table)) - } else { - segTable = fmt.Sprintf("`%s`.`%s`", database, orgSegTable) - newTable := fmt.Sprintf("%s.%s", database, table) - rawQuery = strings.Replace(p.RawQuery, "`", "", -1) - re, _ = regexp.Compile(fmt.Sprintf(`\b(%s)\b`, newTable)) - } + newNode.NewName = newNode.Table + newNode.Format(buf) + newQuery := buf.String() - // avoid the name of the column is the same as the table name, eg, issues/438 - // just replace the first place. - var count = 0 - var occurrence = 1 - query = re.ReplaceAllStringFunc(rawQuery, func(m string) string { - count = count + 1 - if count == occurrence { - return segTable - } - return m - }) - - if node.Action == sqlparser.RenameStr { - var segQuery string - var segToTable string - var re *regexp.Regexp - pos := strings.Index(query, segTable) - pos += len(segTable) - - if !node.NewName.Qualifier.IsEmpty() { - toDatabase := node.NewName.Qualifier.String() - if toDatabase != database { - err := fmt.Sprintf("unsupported: Database is not equal[%s:%s]", database, toDatabase) - return errors.New(err) - } - } + tuple := xcontext.QueryTuple{ + Query: newQuery, + Backend: segment.Backend, + Range: segment.Range.String(), + } + p.Querys = append(p.Querys, tuple) + } + return nil +} - toTable := node.NewName.Name.String() - // just to the shardtable, the suffix with "_0001" is valid - if shardKey != "" { - splits := strings.SplitN(orgSegTable, "_", -1) - suffix := splits[len(splits)-1] - segToTable = toTable + "_" + suffix - } else { - segToTable = toTable - } +// dropTblImpl used to build distributed querys for drop table tbl1, tbl2 ... +func (p *DDLPlan) dropTblImpl() error { + oldNode := p.node + oldTable := oldNode.Table.Name.String() + database := p.database + if !oldNode.Table.Qualifier.IsEmpty() { + database = oldNode.Table.Qualifier.String() + } - if node.NewName.Qualifier.IsEmpty() { - segToTable = fmt.Sprintf("`%s`.`%s`", database, segToTable) - segQuery = strings.Replace(query[pos:], "`", "", -1) - // \b: https://www.regular-expressions.info/wordboundaries.html - re, _ = regexp.Compile(fmt.Sprintf(`\b(%s)\b`, toTable)) - } else { - segToTable = fmt.Sprintf("`%s`.`%s`", database, segToTable) - newToTable := fmt.Sprintf("%s.%s", database, toTable) - segQuery = strings.Replace(query[pos:], "`", "", -1) - re, _ = regexp.Compile(fmt.Sprintf(`\b(%s)\b`, newToTable)) - } + segments, err := p.router.Lookup(database, oldTable, nil, nil) + if err != nil { + return err + } + for _, segment := range segments { + // Rewrite ddl ast, replace oldTable to segment table(new table) and format a new query + newNode := *oldNode + newTable := segment.Table + buf := sqlparser.NewTrackedBuffer(nil) + // Now we just drop a table once a time, here can be optimized with proxy/ddl.go in the future + newNode.Tables = sqlparser.TableNames{ + sqlparser.TableName{ + Name: sqlparser.NewTableIdent(newTable), + Qualifier: sqlparser.NewTableIdent(database), + }, + } + newNode.Format(buf) + newQuery := buf.String() + p.log.Error("grynewQ:%v", newQuery) - // avoid the name of the column is the same as the table name, eg, issues/438 - // just replace the first place. - var count = 0 - var occurrence = 1 - toQuery := re.ReplaceAllStringFunc(segQuery, func(m string) string { - count = count + 1 - if count == occurrence { - return segToTable - } - return m - }) - - query = query[:pos] + toQuery - } + tuple := xcontext.QueryTuple{ + Query: newQuery, + Backend: segment.Backend, + Range: segment.Range.String(), + } + p.Querys = append(p.Querys, tuple) + } + return nil +} - tuple := xcontext.QueryTuple{ - Query: query, - Backend: segment.Backend, - Range: segment.Range.String(), - } - p.Querys = append(p.Querys, tuple) +// renameImpl used to build distributed querys for rename oldTbl to newTbl ... +func (p *DDLPlan) renameImpl() error { + oldNode := p.node + // Check if fromDatabase and toDatabase is same or not. + fromDatabase := p.database + if !oldNode.Table.Qualifier.IsEmpty() { + fromDatabase = oldNode.Table.Qualifier.String() + } + if toDatabase := oldNode.NewName.Qualifier.String(); toDatabase != "" && toDatabase != fromDatabase { + // toDatabase must equal to fromDatabase if not empty + err := fmt.Sprintf("unsupported: Database is not equal[%s:%s]", fromDatabase, toDatabase) + return errors.New(err) + } + + oldFromTable := oldNode.Table.Name.String() + oldToTable := oldNode.NewName.Name.String() + segments, err := p.router.Lookup(fromDatabase, oldFromTable, nil, nil) + if err != nil { + return err + } + + for _, segment := range segments { + // Get newFromTable and newToTable + newFromTable := segment.Table + var newToTable string + shardKey, err := p.router.ShardKey(fromDatabase, oldFromTable) + if err != nil { + return err + } + if shardKey != "" { + // just to the shardtable, the suffix with "_0001" is valid + splits := strings.SplitN(segment.Table, "_", -1) + suffix := splits[len(splits)-1] + newToTable = oldToTable + "_" + suffix + } else { + newToTable = oldToTable + } + + // Rewrite rename ast, replace oldFromTable to newFromTable and oldToTable to newToTable, then format to a new query + newNode := *oldNode + buf := sqlparser.NewTrackedBuffer(nil) + newNode.Table = sqlparser.TableName{ + Name: sqlparser.NewTableIdent(newFromTable), + Qualifier: sqlparser.NewTableIdent(fromDatabase), + } + newNode.NewName = sqlparser.TableName{ + Name: sqlparser.NewTableIdent(newToTable), + Qualifier: sqlparser.NewTableIdent(fromDatabase), + } + newNode.Format(buf) + newQuery := buf.String() + + tuple := xcontext.QueryTuple{ + Query: newQuery, + Backend: segment.Backend, + Range: segment.Range.String(), } + p.Querys = append(p.Querys, tuple) } return nil } +// Build used to build DDL distributed querys. +// sqlparser.DDL is a simple grammar ast, it just parses database and table name in the prefix. +// In our sql syntax in sql.y, alter will be changed to rename in case next: +// ALTER ignore_opt TABLE table_name RENAME to_opt table_name +// { +// Change this to a rename statement +// $$ = &DDL{Action: RenameStr, Table: $4, NewName: $7} +// } +func (p *DDLPlan) Build() error { + var err error + + switch p.node.Action { + case sqlparser.DropTableStr: + err = p.dropTblImpl() + case sqlparser.RenameStr: + err = p.renameImpl() + default: + err = p.commonImpl() + } + return err +} + // Type returns the type of the plan. func (p *DDLPlan) Type() PlanType { return p.typ @@ -241,6 +293,8 @@ func (p *DDLPlan) JSON() string { RawQuery: p.RawQuery, Partitions: parts, } + // If exp include escape, json will add '\' before it. + // e.g.: "\n\t tbl \n" will be "\\n\\t tbl \\n" bout, err := json.MarshalIndent(exp, "", "\t") if err != nil { return err.Error() diff --git a/src/planner/ddl_plan_test.go b/src/planner/ddl_plan_test.go index 3b342a6d..209fdee0 100644 --- a/src/planner/ddl_plan_test.go +++ b/src/planner/ddl_plan_test.go @@ -20,18 +20,18 @@ import ( func TestDDLPlan1(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"create table A(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table G(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`G`(a int)\",\n\t\t\t\"Backend\": \"backend1\",\n\t\t\t\"Range\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`G`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table S(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`S`(a int)\",\n\t\t\t\"Backend\": \"backend1\",\n\t\t\t\"Range\": \"\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table A engine = tokudb\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` engine = tokudb\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` engine = tokudb\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` engine = tokudb\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` engine = tokudb\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create index idx_a on A(a)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on `sbtest`.`A0`(a)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on `sbtest`.`A2`(a)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on `sbtest`.`A4`(a)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on `sbtest`.`A8`(a)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"drop index idx_a on sbtest.A\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on `sbtest`.`A0`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on `sbtest`.`A2`\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on `sbtest`.`A4`\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on `sbtest`.`A8`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table A add column(b int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` add column(b int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` add column(b int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` add column(b int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` add column(b int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table sbtest.A add column(b int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` add column(b int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` add column(b int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` add column(b int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` add column(b int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table sbtest.A add column(b int, c varchar(100))\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` add column(b int, c varchar(100))\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` add column(b int, c varchar(100))\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` add column(b int, c varchar(100))\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` add column(b int, c varchar(100))\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table A modify column b int\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` modify column b int\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` modify column b int\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` modify column b int\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` modify column b int\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table A drop column b\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` drop column b\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` drop column b\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` drop column b\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` drop column b\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"truncate table A\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"truncate table `sbtest`.`A0`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"truncate table `sbtest`.`A2`\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"truncate table `sbtest`.`A4`\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"truncate table `sbtest`.`A8`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table A(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table G(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.G (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend1\",\n\t\t\t\"Range\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.G (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table S(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.S (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend1\",\n\t\t\t\"Range\": \"\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table A engine = tokudb\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 engine = tokudb\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 engine = tokudb\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 engine = tokudb\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 engine = tokudb\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create index idx_a on A(a)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on sbtest.A0\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on sbtest.A2\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on sbtest.A4\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_a on sbtest.A8\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"drop index idx_a on sbtest.A\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on sbtest.A0\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on sbtest.A2\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on sbtest.A4\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop index idx_a on sbtest.A8\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table A add column(b int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table sbtest.A add column(b int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 add column (\\n\\t`b` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table sbtest.A add column(b int, c varchar(100))\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 add column (\\n\\t`b` int,\\n\\t`c` varchar(100)\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 add column (\\n\\t`b` int,\\n\\t`c` varchar(100)\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 add column (\\n\\t`b` int,\\n\\t`c` varchar(100)\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 add column (\\n\\t`b` int,\\n\\t`c` varchar(100)\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table A modify column b int\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 modify column `b` int\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 modify column `b` int\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 modify column `b` int\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 modify column `b` int\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table A drop column b\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 drop column `b`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 drop column `b`\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 drop column `b`\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 drop column `b`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"truncate table A\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"truncate table sbtest.A0\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"truncate table sbtest.A2\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"truncate table sbtest.A4\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"truncate table sbtest.A8\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", } querys := []string{ @@ -89,7 +89,7 @@ func TestDDLPlan1(t *testing.T) { func TestDROPPlan(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"drop table sbtest.A\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"drop table `sbtest`.`A0`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop table `sbtest`.`A2`\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop table `sbtest`.`A4`\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop table `sbtest`.`A8`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"drop table sbtest.A\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"drop table sbtest.A0\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop table sbtest.A2\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop table sbtest.A4\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"drop table sbtest.A8\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", } querys := []string{ @@ -202,45 +202,9 @@ func TestDDLAlterError(t *testing.T) { } } -func TestDDLPlanScatter(t *testing.T) { - results := []string{ - `{ - "RawQuery": "create database A" -}`, - } - querys := []string{ - "create database A", - } - - log := xlog.NewStdLog(xlog.Level(xlog.PANIC)) - database := "sbtest" - - route, cleanup := router.MockNewRouter(log) - defer cleanup() - - err := route.AddForTest(database, router.MockTableAConfig()) - assert.Nil(t, err) - for i, query := range querys { - node, err := sqlparser.Parse(query) - assert.Nil(t, err) - plan := NewDDLPlan(log, database, query, node.(*sqlparser.DDL), route) - - // plan build - { - err := plan.Build() - assert.Nil(t, err) - - want := results[i] - got := plan.JSON() - log.Debug(got) - assert.Equal(t, want, got) - } - } -} - func TestDDLPlanCreateIndexWithTableNameIssue10(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"create index idx_A_id on A(a)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on `sbtest`.`A0`(a)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on `sbtest`.`A2`(a)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on `sbtest`.`A4`(a)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on `sbtest`.`A8`(a)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create index idx_A_id on A(a)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on sbtest.A0\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on sbtest.A2\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on sbtest.A4\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create index idx_A_id on sbtest.A8\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", } querys := []string{ @@ -281,13 +245,13 @@ func TestDDLPlanCreateIndexWithTableNameIssue10(t *testing.T) { func TestDDLPlanWithQuote(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"create table `A`(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table A(`a` int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table A(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table sbtest.A(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table sbtest.`A`(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table `sbtest`.A(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table `sbtest`.`A`(a int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(a int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(a int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(a int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(a int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table sbtest.A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table sbtest.A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table sbtest.A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table sbtest.A (\\n\\t`a` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`a` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", } querys := []string{ @@ -312,7 +276,9 @@ func TestDDLPlanWithQuote(t *testing.T) { log.Debug("%v", query) node, err := sqlparser.Parse(query) assert.Nil(t, err) - plan := NewDDLPlan(log, database, query, node.(*sqlparser.DDL), route) + ddl := node.(*sqlparser.DDL) + // After sqlparser.String(ddl), we`ll get sql like: "create table A (\n\t`a` int\n)" + plan := NewDDLPlan(log, database, sqlparser.String(ddl), node.(*sqlparser.DDL), route) // plan build { @@ -327,11 +293,11 @@ func TestDDLPlanWithQuote(t *testing.T) { func TestDDLPlanWithSameColumn(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"CREATE table A(A int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A0`(A int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A2`(A int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A4`(A int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A8`(A int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"CREATE table `A`(A int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A0`(A int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A2`(A int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A4`(A int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"CREATE table `sbtest`.`A8`(A int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"create table sbtest.A(A int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A0`(A int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A2`(A int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A4`(A int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table `sbtest`.`A8`(A int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table A add column(A int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` add column(A int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` add column(A int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` add column(A int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` add column(A int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table sbtest.A add column(A int)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A0` add column(A int)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A2` add column(A int)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A4` add column(A int)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`A8` add column(A int)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table A (\\n\\t`A` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table A (\\n\\t`A` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"create table sbtest.A (\\n\\t`A` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A0 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A2 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A4 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"create table sbtest.A8 (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table A add column (\\n\\t`A` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table sbtest.A add column (\\n\\t`A` int\\n)\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A0 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A2 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend2\",\n\t\t\t\"Range\": \"[2-4)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A4 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend4\",\n\t\t\t\"Range\": \"[4-8)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table sbtest.A8 add column (\\n\\t`A` int\\n)\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[8-4096)\"\n\t\t}\n\t]\n}", } querys := []string{ @@ -354,7 +320,9 @@ func TestDDLPlanWithSameColumn(t *testing.T) { log.Debug("%v", query) node, err := sqlparser.Parse(query) assert.Nil(t, err) - plan := NewDDLPlan(log, database, query, node.(*sqlparser.DDL), route) + ddl := node.(*sqlparser.DDL) + // After sqlparser.String(ddl), we`ll get sql like: "create table A (\n\t`a` int\n)" + plan := NewDDLPlan(log, database, sqlparser.String(ddl), node.(*sqlparser.DDL), route) // plan build { @@ -369,13 +337,16 @@ func TestDDLPlanWithSameColumn(t *testing.T) { func TestDDLPlanWithRename(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"alter table R rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table sbtest.R rename sbtest.RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table sbtest.R rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table R rename sbtest.RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table `R` rename `sbtest`.`RR`\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table `R` rename `sbtest`.RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", - "{\n\t\"RawQuery\": \"alter table `R` rename sbtest.`RR`\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0000` rename `sbtest`.`RR_0000`\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`R_0008` rename `sbtest`.`RR_0008`\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table R rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table sbtest.R rename sbtest.RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table sbtest.R rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table R rename sbtest.RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table `R` rename `sbtest`.`RR`\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table `R` rename `sbtest`.RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table `R` rename sbtest.`RR`\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table `sbtest`.`R` rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table `sbtest`.R rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table sbtest.`R` rename RR\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0000 to sbtest.RR_0000\",\n\t\t\t\"Backend\": \"backend0\",\n\t\t\t\"Range\": \"[0-2)\"\n\t\t},\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.R_0008 to sbtest.RR_0008\",\n\t\t\t\"Backend\": \"backend8\",\n\t\t\t\"Range\": \"[2-4096)\"\n\t\t}\n\t]\n}", } querys := []string{ @@ -386,6 +357,9 @@ func TestDDLPlanWithRename(t *testing.T) { "alter table `R` rename `sbtest`.`RR`", "alter table `R` rename `sbtest`.RR", "alter table `R` rename sbtest.`RR`", + "alter table `sbtest`.`R` rename RR", + "alter table `sbtest`.R rename RR", + "alter table sbtest.`R` rename RR", } log := xlog.NewStdLog(xlog.Level(xlog.PANIC)) @@ -415,7 +389,7 @@ func TestDDLPlanWithRename(t *testing.T) { func TestDDLPlanWithRenameNoshard(t *testing.T) { results := []string{ - "{\n\t\"RawQuery\": \"alter table S rename S_S\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"alter table `sbtest`.`S` rename `sbtest`.`S_S`\",\n\t\t\t\"Backend\": \"backend1\",\n\t\t\t\"Range\": \"\"\n\t\t}\n\t]\n}", + "{\n\t\"RawQuery\": \"alter table S rename S_S\",\n\t\"Partitions\": [\n\t\t{\n\t\t\t\"Query\": \"rename table sbtest.S to sbtest.S_S\",\n\t\t\t\"Backend\": \"backend1\",\n\t\t\t\"Range\": \"\"\n\t\t}\n\t]\n}", } querys := []string{ diff --git a/src/proxy/ddl.go b/src/proxy/ddl.go index eff8798e..7c692b84 100644 --- a/src/proxy/ddl.go +++ b/src/proxy/ddl.go @@ -280,6 +280,9 @@ func (spanner *Spanner) handleDDL(session *driver.Session, query string, node *s } } + // After sqlparser.String(ddl), the quote '`' in table name will be removed, but the colName with quote '`' will be reserved. e.g.: + // sql: create table `db`.`tbl`(`col` int .... + // after string(): create table db.tbl(`col` int .... r, err := spanner.ExecuteDDL(session, database, sqlparser.String(ddl), node) if err != nil { // Try to drop table. diff --git a/src/proxy/ddl_test.go b/src/proxy/ddl_test.go index b2ea9a88..c2670d49 100644 --- a/src/proxy/ddl_test.go +++ b/src/proxy/ddl_test.go @@ -473,8 +473,8 @@ func TestProxyDropTables(t *testing.T) { fakedbs.AddQueryPattern("show tables from .*", &sqltypes.Result{}) fakedbs.AddQueryPattern("create .*", &sqltypes.Result{}) fakedbs.AddQueryPattern("alter table .*", &sqltypes.Result{}) - fakedbs.AddQueryPattern("drop table `db1`.*", &sqltypes.Result{}) - fakedbs.AddQueryPattern("drop table `db2`.*", &sqltypes.Result{}) + fakedbs.AddQueryPattern("drop table db1.*", &sqltypes.Result{}) + fakedbs.AddQueryPattern("drop table db2.*", &sqltypes.Result{}) fakedbs.AddQueryPattern("truncate table .*", &sqltypes.Result{}) } @@ -1240,7 +1240,7 @@ func TestProxyDDLAlterRename(t *testing.T) { { fakedbs.AddQueryPattern("use .*", &sqltypes.Result{}) fakedbs.AddQueryPattern("create .*", &sqltypes.Result{}) - fakedbs.AddQueryPattern("alter table .*", &sqltypes.Result{}) + fakedbs.AddQueryPattern("rename table .*", &sqltypes.Result{}) } // create database. @@ -1275,53 +1275,6 @@ func TestProxyDDLAlterRename(t *testing.T) { } } -func TestProxyDDLAlterRename2(t *testing.T) { - log := xlog.NewStdLog(xlog.Level(xlog.PANIC)) - fakedbs, proxy, cleanup := MockProxy(log) - defer cleanup() - address := proxy.Address() - - // fakedbs. - { - fakedbs.AddQueryPattern("use .*", &sqltypes.Result{}) - fakedbs.AddQueryPattern("create .*", &sqltypes.Result{}) - //fakedbs.AddQueryPattern("alter table .*", &sqltypes.Result{}) - } - - querys := []string{ - "create table t1(id int, b int) partition by hash(id)", - } - - // create sbtest table. - { - client, err := driver.NewConn("mock", "mock", address, "", "utf8") - assert.Nil(t, err) - query := "create database test" - _, err = client.FetchAll(query, -1) - assert.Nil(t, err) - } - - { - client, err := driver.NewConn("mock", "mock", address, "test", "utf8") - assert.Nil(t, err) - for _, query := range querys { - _, err = client.FetchAll(query, -1) - assert.Nil(t, err) - } - } - - { - fakedbs.AddQueryErrorPattern("alter table .*", errors.New("mock.mysql.alter.table.error")) - client, err := driver.NewConn("mock", "mock", address, "test", "utf8") - assert.Nil(t, err) - query := "alter table t1 rename t2" - _, err = client.FetchAll(query, -1) - want := "mock.mysql.alter.table.error (errno 1105) (sqlstate HY000)" - got := err.Error() - assert.Equal(t, want, got) - } -} - func TestProxyDDLCreateTableDistributed(t *testing.T) { log := xlog.NewStdLog(xlog.Level(xlog.PANIC)) fakedbs, proxy, cleanup := MockProxy(log) diff --git a/src/router/frm.go b/src/router/frm.go index ecde8ae1..1118281f 100644 --- a/src/router/frm.go +++ b/src/router/frm.go @@ -54,7 +54,7 @@ func (r *Router) removeTableFrmData(db string, table string) error { log := r.log dir := path.Join(r.metadir, db) file := path.Join(dir, fmt.Sprintf("%s.json", table)) - log.Warning("frm.remove.file[%v].for.[db:%s, table:%s]", db, table, file) + log.Warning("frm.remove.file[%v].for.[db:%s, table:%s]", file, db, table) return os.Remove(file) }