Skip to content

Commit

Permalink
planner,executor: support show create database if not exists syntax (
Browse files Browse the repository at this point in the history
…#8926)

<!--
Thank you for contributing to TiDB! Please read TiDB's [CONTRIBUTING](https://github.com/pingcap/tidb/blob/master/CONTRIBUTING.md) document **BEFORE** filing this PR.
-->

### What problem does this PR solve? <!--add issue link with summary if exists-->

pingcap/parser#147
pingcap/parser#148

MySQL compatibility: `show create database if not exists` syntax

See: https://dev.mysql.com/doc/refman/5.7/en/show-create-database.html

MySQL

```
MariaDB [(none)]> show create database b2;
+----------+----------------------------------------------------------------+
| Database | Create Database                                                |
+----------+----------------------------------------------------------------+
| b2       | CREATE DATABASE `b2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+----------------------------------------------------------------+
1 row in set (0.002 sec)

MariaDB [(none)]> show create database if not exists b2;
+----------+-----------------------------------------------------------------------------------------+
| Database | Create Database                                                                         |
+----------+-----------------------------------------------------------------------------------------+
| b2       | CREATE DATABASE /*!32312 IF NOT EXISTS*/ `b2` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+-----------------------------------------------------------------------------------------+
1 row in set (0.000 sec)
```

TiDB
```
MySQL [b1]> show create batabase b2;
ERROR 1105 (HY000): line 1 column 20 near " b2" (total length 23)
MySQL [b1]> show create database b2;
+----------+-----------------------------------------------------------------+
| Database | Create Database                                                 |
+----------+-----------------------------------------------------------------+
| b2       | CREATE DATABASE `b2` /* !40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.000 sec)

MySQL [b1]> show create database if not exists b2;
ERROR 1105 (HY000): line 1 column 23 near " not exists b2" (total length 37)
```

### What is changed and how it works?

Insert `/*!32312 IF NOT EXISTS*/` before shema name when statement contains `if not exists`

### Check List <!--REMOVE the items that are not applicable-->

Tests <!-- At least one of them must be included. -->

 - Unit test

Code changes

Side effects

Related changes

 - Need to cherry-pick to the release branch

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/pingcap/tidb/8926)
<!-- Reviewable:end -->
  • Loading branch information
lonng authored Jan 4, 2019
1 parent cef6e75 commit e0b30fe
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 20 deletions.
1 change: 1 addition & 0 deletions executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ func (b *executorBuilder) buildShow(v *plannercore.Show) Executor {
Table: v.Table,
Column: v.Column,
User: v.User,
IfNotExists: v.IfNotExists,
Flag: v.Flag,
Full: v.Full,
GlobalScope: v.GlobalScope,
Expand Down
6 changes: 5 additions & 1 deletion executor/seqtest/seq_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,11 @@ func (s *seqTestSuite) TestShow(c *C) {
tk.MustExec(testSQL)
testSQL = "show create database show_test_DB;"
tk.MustQuery(testSQL).Check(testutil.RowsWithSep("|",
"show_test_DB|CREATE DATABASE `show_test_DB` /* !40100 DEFAULT CHARACTER SET utf8mb4 */",
"show_test_DB|CREATE DATABASE `show_test_DB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */",
))
testSQL = "show create database if not exists show_test_DB;"
tk.MustQuery(testSQL).Check(testutil.RowsWithSep("|",
"show_test_DB|CREATE DATABASE /*!32312 IF NOT EXISTS*/ `show_test_DB` /*!40100 DEFAULT CHARACTER SET utf8mb4 */",
))

tk.MustExec("use show_test_DB")
Expand Down
23 changes: 14 additions & 9 deletions executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ import (
type ShowExec struct {
baseExecutor

Tp ast.ShowStmtType // Databases/Tables/Columns/....
DBName model.CIStr
Table *ast.TableName // Used for showing columns.
Column *ast.ColumnName // Used for `desc table column`.
Flag int // Some flag parsed from sql, such as FULL.
Full bool
User *auth.UserIdentity // Used for show grants.
Tp ast.ShowStmtType // Databases/Tables/Columns/....
DBName model.CIStr
Table *ast.TableName // Used for showing columns.
Column *ast.ColumnName // Used for `desc table column`.
Flag int // Some flag parsed from sql, such as FULL.
Full bool
User *auth.UserIdentity // Used for show grants.
IfNotExists bool // Used for `show create database if not exists`

// GlobalScope is used by show variables
GlobalScope bool
Expand Down Expand Up @@ -764,9 +765,13 @@ func (e *ShowExec) fetchShowCreateDatabase() error {
sqlMode := e.ctx.GetSessionVars().SQLMode

var buf bytes.Buffer
fmt.Fprintf(&buf, "CREATE DATABASE %s", escape(db.Name, sqlMode))
var ifNotExists string
if e.IfNotExists {
ifNotExists = "/*!32312 IF NOT EXISTS*/ "
}
fmt.Fprintf(&buf, "CREATE DATABASE %s%s", ifNotExists, escape(db.Name, sqlMode))
if s := db.Charset; len(s) > 0 {
fmt.Fprintf(&buf, " /* !40100 DEFAULT CHARACTER SET %s */", s)
fmt.Fprintf(&buf, " /*!40100 DEFAULT CHARACTER SET %s */", s)
}

e.appendRow([]interface{}{db.Name.O, buf.String()})
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
github.com/pingcap/gofail v0.0.0-20181217135706-6a951c1e42c3
github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e
github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c
github.com/pingcap/parser v0.0.0-20190103075927-c065c7404641
github.com/pingcap/parser v0.0.0-20190103131433-5d5a6dd34655
github.com/pingcap/pd v2.1.0-rc.4+incompatible
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e h1:P73/4dPCL96rG
github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw=
github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c h1:Qf5St5XGwKgKQLar9lEXoeO0hJMVaFBj3JqvFguWtVg=
github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c/go.mod h1:Ja9XPjot9q4/3JyCZodnWDGNXt4pKemhIYCvVJM7P24=
github.com/pingcap/parser v0.0.0-20190103075927-c065c7404641 h1:KTGU8kr2wY+FRiHHs8I5lp385b+OzYnbOr3/tPVw7mU=
github.com/pingcap/parser v0.0.0-20190103075927-c065c7404641/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/parser v0.0.0-20190103131433-5d5a6dd34655 h1:nAGxJRuzO6T7mL/uAaOOZSVl9x+Vmy6cTYuzQjFDRw4=
github.com/pingcap/parser v0.0.0-20190103131433-5d5a6dd34655/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA=
github.com/pingcap/pd v2.1.0-rc.4+incompatible h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE=
github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E=
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible h1:Bsd+NHosPVowEGB3BCx+2d8wUQGDTXSSC5ljeNS6cXo=
Expand Down
15 changes: 8 additions & 7 deletions planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,14 @@ type Deallocate struct {
type Show struct {
baseSchemaProducer

Tp ast.ShowStmtType // Databases/Tables/Columns/....
DBName string
Table *ast.TableName // Used for showing columns.
Column *ast.ColumnName // Used for `desc table column`.
Flag int // Some flag parsed from sql, such as FULL.
Full bool
User *auth.UserIdentity // Used for show grants.
Tp ast.ShowStmtType // Databases/Tables/Columns/....
DBName string
Table *ast.TableName // Used for showing columns.
Column *ast.ColumnName // Used for `desc table column`.
Flag int // Some flag parsed from sql, such as FULL.
Full bool
User *auth.UserIdentity // Used for show grants.
IfNotExists bool // Used for `show create database if not exists`

Conditions []expression.Expression

Expand Down
1 change: 1 addition & 0 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,7 @@ func (b *PlanBuilder) buildShow(show *ast.ShowStmt) (Plan, error) {
Flag: show.Flag,
Full: show.Full,
User: show.User,
IfNotExists: show.IfNotExists,
GlobalScope: show.GlobalScope,
}.Init(b.ctx)
switch showTp := show.Tp; showTp {
Expand Down

0 comments on commit e0b30fe

Please sign in to comment.