Files
tidb/executor/show_test.go

488 lines
22 KiB
Go

// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.
package executor_test
import (
"context"
"fmt"
. "github.com/pingcap/check"
"github.com/pingcap/errors"
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/executor"
plannercore "github.com/pingcap/tidb/planner/core"
"github.com/pingcap/tidb/session"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/util/testkit"
"github.com/pingcap/tidb/util/testutil"
)
func (s *testSuite2) TestShowVisibility(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("create database showdatabase")
tk.MustExec("use showdatabase")
tk.MustExec("create table t1 (id int)")
tk.MustExec("create table t2 (id int)")
tk.MustExec(`create user 'show'@'%'`)
tk.MustExec(`flush privileges`)
tk1 := testkit.NewTestKit(c, s.store)
se, err := session.CreateSession4Test(s.store)
c.Assert(err, IsNil)
c.Assert(se.Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil), IsTrue)
tk1.Se = se
// No ShowDatabases privilege, this user would see nothing except INFORMATION_SCHEMA.
tk.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA"))
// After grant, the user can see the database.
tk.MustExec(`grant select on showdatabase.t1 to 'show'@'%'`)
tk.MustExec(`flush privileges`)
tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA", "showdatabase"))
// The user can see t1 but not t2.
tk1.MustExec("use showdatabase")
tk1.MustQuery("show tables").Check(testkit.Rows("t1"))
// After revoke, show database result should be just except INFORMATION_SCHEMA.
tk.MustExec(`revoke select on showdatabase.t1 from 'show'@'%'`)
tk.MustExec(`flush privileges`)
tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA"))
// Grant any global privilege would make show databases available.
tk.MustExec(`grant CREATE on *.* to 'show'@'%'`)
tk.MustExec(`flush privileges`)
rows := tk1.MustQuery("show databases").Rows()
c.Assert(len(rows), GreaterEqual, 2) // At least INFORMATION_SCHEMA and showdatabase
tk.MustExec(`drop user 'show'@'%'`)
tk.MustExec("drop database showdatabase")
}
func (s *testSuite2) TestShowDatabasesInfoSchemaFirst(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA"))
tk.MustExec(`create user 'show'@'%'`)
tk.MustExec(`flush privileges`)
tk.MustExec(`create database AAAA`)
tk.MustExec(`create database BBBB`)
tk.MustExec(`grant select on AAAA.* to 'show'@'%'`)
tk.MustExec(`grant select on BBBB.* to 'show'@'%'`)
tk.MustExec(`flush privileges`)
tk1 := testkit.NewTestKit(c, s.store)
se, err := session.CreateSession4Test(s.store)
c.Assert(err, IsNil)
c.Assert(se.Auth(&auth.UserIdentity{Username: "show", Hostname: "%"}, nil, nil), IsTrue)
tk1.Se = se
tk1.MustQuery("show databases").Check(testkit.Rows("INFORMATION_SCHEMA", "AAAA", "BBBB"))
tk.MustExec(`drop user 'show'@'%'`)
tk.MustExec(`drop database AAAA`)
tk.MustExec(`drop database BBBB`)
}
// mockSessionManager is a mocked session manager that wraps one session
// it returns only this session's current process info as processlist for test.
type mockSessionManager struct {
session.Session
}
// Kill implements the SessionManager.Kill interface.
func (msm *mockSessionManager) Kill(cid uint64, query bool) {
}
func (s *testSuite2) TestShowWarnings(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
testSQL := `create table if not exists show_warnings (a int)`
tk.MustExec(testSQL)
tk.MustExec("set @@sql_mode=''")
tk.MustExec("insert show_warnings values ('a')")
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1265|Data Truncated"))
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1265|Data Truncated"))
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))
// Test Warning level 'Error'
testSQL = `create table show_warnings (a int)`
tk.Exec(testSQL)
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Error|1050|Table 'test.show_warnings' already exists"))
tk.MustQuery("select @@error_count").Check(testutil.RowsWithSep("|", "1"))
// Test Warning level 'Note'
testSQL = `create table show_warnings_2 (a int)`
tk.MustExec(testSQL)
testSQL = `create table if not exists show_warnings_2 like show_warnings`
tk.Exec(testSQL)
c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(1))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Note|1050|Table 'test.show_warnings_2' already exists"))
tk.MustQuery("select @@warning_count").Check(testutil.RowsWithSep("|", "1"))
tk.MustQuery("select @@warning_count").Check(testutil.RowsWithSep("|", "0"))
}
func (s *testSuite2) TestShowErrors(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
testSQL := `create table if not exists show_errors (a int)`
tk.MustExec(testSQL)
testSQL = `create table show_errors (a int)`
tk.Exec(testSQL)
tk.MustQuery("show errors").Check(testutil.RowsWithSep("|", "Error|1050|Table 'test.show_errors' already exists"))
}
func (s *testSuite2) TestIssue3641(c *C) {
tk := testkit.NewTestKit(c, s.store)
_, err := tk.Exec("show tables;")
c.Assert(err.Error(), Equals, plannercore.ErrNoDB.Error())
_, err = tk.Exec("show table status;")
c.Assert(err.Error(), Equals, plannercore.ErrNoDB.Error())
}
// TestShow2 is moved from session_test
func (s *testSuite2) TestShow2(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("set global autocommit=0")
tk1 := testkit.NewTestKit(c, s.store)
tk1.MustQuery("show global variables where variable_name = 'autocommit'").Check(testkit.Rows("autocommit 0"))
tk.MustExec("set global autocommit = 1")
tk2 := testkit.NewTestKit(c, s.store)
// TODO: In MySQL, the result is "autocommit ON".
tk2.MustQuery("show global variables where variable_name = 'autocommit'").Check(testkit.Rows("autocommit 1"))
// TODO: Specifying the charset for national char/varchar should not be supported.
tk.MustExec("drop table if exists test_full_column")
tk.MustExec(`create table test_full_column(
c_int int,
c_float float,
c_bit bit,
c_bool bool,
c_char char(1) charset ascii collate ascii_bin,
c_nchar national char(1) charset ascii collate ascii_bin,
c_binary binary,
c_varchar varchar(1) charset ascii collate ascii_bin,
c_nvarchar national varchar(1) charset ascii collate ascii_bin,
c_varbinary varbinary(1),
c_year year,
c_date date,
c_time time,
c_datetime datetime,
c_timestamp timestamp,
c_blob blob,
c_tinyblob tinyblob,
c_mediumblob mediumblob,
c_longblob longblob,
c_text text charset ascii collate ascii_bin,
c_tinytext tinytext charset ascii collate ascii_bin,
c_mediumtext mediumtext charset ascii collate ascii_bin,
c_longtext longtext charset ascii collate ascii_bin,
c_json json,
c_enum enum('1') charset ascii collate ascii_bin,
c_set set('1') charset ascii collate ascii_bin
);`)
tk.MustQuery(`show full columns from test_full_column`).Check(testkit.Rows(
"" +
"c_int int(11) <nil> YES <nil> select,insert,update,references ]\n" +
"[c_float float <nil> YES <nil> select,insert,update,references ]\n" +
"[c_bit bit(1) <nil> YES <nil> select,insert,update,references ]\n" +
"[c_bool tinyint(1) <nil> YES <nil> select,insert,update,references ]\n" +
"[c_char char(1) ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_nchar char(1) ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_binary binary(1) <nil> YES <nil> select,insert,update,references ]\n" +
"[c_varchar varchar(1) ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_nvarchar varchar(1) ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_varbinary varbinary(1) <nil> YES <nil> select,insert,update,references ]\n" +
"[c_year year(4) <nil> YES <nil> select,insert,update,references ]\n" +
"[c_date date <nil> YES <nil> select,insert,update,references ]\n" +
"[c_time time <nil> YES <nil> select,insert,update,references ]\n" +
"[c_datetime datetime <nil> YES <nil> select,insert,update,references ]\n" +
"[c_timestamp timestamp <nil> YES <nil> select,insert,update,references ]\n" +
"[c_blob blob <nil> YES <nil> select,insert,update,references ]\n" +
"[c_tinyblob tinyblob <nil> YES <nil> select,insert,update,references ]\n" +
"[c_mediumblob mediumblob <nil> YES <nil> select,insert,update,references ]\n" +
"[c_longblob longblob <nil> YES <nil> select,insert,update,references ]\n" +
"[c_text text ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_tinytext tinytext ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_mediumtext mediumtext ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_longtext longtext ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_json json <nil> YES <nil> select,insert,update,references ]\n" +
"[c_enum enum('1') ascii_bin YES <nil> select,insert,update,references ]\n" +
"[c_set set('1') ascii_bin YES <nil> select,insert,update,references "))
tk.MustExec("drop table if exists test_full_column")
tk.MustExec("drop table if exists t")
tk.MustExec(`create table if not exists t (c int) comment '注释'`)
tk.MustExec("create or replace definer='root'@'localhost' view v as select * from t")
tk.MustQuery(`show columns from t`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,<nil>,"))
tk.MustQuery(`describe t`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,<nil>,"))
tk.MustQuery(`show columns from v`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,<nil>,"))
tk.MustQuery(`describe v`).Check(testutil.RowsWithSep(",", "c,int(11),YES,,<nil>,"))
tk.MustQuery("show collation where Charset = 'utf8' and Collation = 'utf8_bin'").Check(testutil.RowsWithSep(",", "utf8_bin,utf8,83,Yes,Yes,1"))
tk.MustQuery("show tables").Check(testkit.Rows("t", "v"))
tk.MustQuery("show full tables").Check(testkit.Rows("t BASE TABLE", "v VIEW"))
ctx := tk.Se.(sessionctx.Context)
is := domain.GetDomain(ctx).InfoSchema()
tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
c.Assert(err, IsNil)
createTime := model.TSConvert2Time(tblInfo.Meta().UpdateTS).Format("2006-01-02 15:04:05")
// The Hostname is the actual host
tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"))
r := tk.MustQuery("show table status from test like 't'")
r.Check(testkit.Rows(fmt.Sprintf("t InnoDB 10 Compact 0 0 0 0 0 0 0 %s <nil> <nil> utf8mb4_bin 注释", createTime)))
tk.MustQuery("show databases like 'test'").Check(testkit.Rows("test"))
tk.MustExec(`grant all on *.* to 'root'@'%'`)
tk.MustQuery("show grants").Check(testkit.Rows(`GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'`))
tk.MustQuery("show grants for current_user()").Check(testkit.Rows(`GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'`))
tk.MustQuery("show grants for current_user").Check(testkit.Rows(`GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'`))
}
func (s *testSuite2) TestShow3(c *C) {
tk := testkit.NewTestKit(c, s.store)
// Create a new user.
tk.MustExec(`CREATE USER 'test_show_create_user'@'%' IDENTIFIED BY 'root';`)
tk.MustQuery("show create user 'test_show_create_user'@'%'").
Check(testkit.Rows(`CREATE USER 'test_show_create_user'@'%' IDENTIFIED WITH 'mysql_native_password' AS '*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK`))
tk.MustExec(`CREATE USER 'test_show_create_user'@'localhost' IDENTIFIED BY 'test';`)
tk.MustQuery("show create user 'test_show_create_user'@'localhost';").
Check(testkit.Rows(`CREATE USER 'test_show_create_user'@'localhost' IDENTIFIED WITH 'mysql_native_password' AS '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29' REQUIRE NONE PASSWORD EXPIRE DEFAULT ACCOUNT UNLOCK`))
// Case: the user exists but the host portion doesn't match
err := tk.QueryToErr("show create user 'test_show_create_user'@'asdf';")
c.Assert(err.Error(), Equals, executor.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'test_show_create_user'@'asdf'").Error())
// Case: a user that doesn't exist
err = tk.QueryToErr("show create user 'aaa'@'localhost';")
c.Assert(err.Error(), Equals, executor.ErrCannotUser.GenWithStackByArgs("SHOW CREATE USER", "'aaa'@'localhost'").Error())
}
func (s *testSuite2) TestUnprivilegedShow(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("CREATE DATABASE testshow")
tk.MustExec("USE testshow")
tk.MustExec("CREATE TABLE t1 (a int)")
tk.MustExec("CREATE TABLE t2 (a int)")
tk.MustExec(`CREATE USER 'lowprivuser'`) // no grants
tk.MustExec(`FLUSH PRIVILEGES`)
tk.Se.Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890"))
rs, err := tk.Exec("SHOW TABLE STATUS FROM testshow")
c.Assert(err, IsNil)
c.Assert(rs, NotNil)
tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"))
tk.MustExec("GRANT ALL ON testshow.t1 TO 'lowprivuser'")
tk.MustExec(`FLUSH PRIVILEGES`)
tk.Se.Auth(&auth.UserIdentity{Username: "lowprivuser", Hostname: "192.168.0.1", AuthUsername: "lowprivuser", AuthHostname: "%"}, nil, []byte("012345678901234567890"))
ctx := tk.Se.(sessionctx.Context)
is := domain.GetDomain(ctx).InfoSchema()
tblInfo, err := is.TableByName(model.NewCIStr("testshow"), model.NewCIStr("t1"))
c.Assert(err, IsNil)
createTime := model.TSConvert2Time(tblInfo.Meta().UpdateTS).Format("2006-01-02 15:04:05")
tk.MustQuery("show table status from testshow").Check(testkit.Rows(fmt.Sprintf("t1 InnoDB 10 Compact 0 0 0 0 0 0 0 %s <nil> <nil> utf8mb4_bin ", createTime)))
}
func (s *testSuite2) TestCollation(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
rs, err := tk.Exec("show collation;")
c.Assert(err, IsNil)
fields := rs.Fields()
c.Assert(fields[0].Column.Tp, Equals, mysql.TypeVarchar)
c.Assert(fields[1].Column.Tp, Equals, mysql.TypeVarchar)
c.Assert(fields[2].Column.Tp, Equals, mysql.TypeLonglong)
c.Assert(fields[3].Column.Tp, Equals, mysql.TypeVarchar)
c.Assert(fields[4].Column.Tp, Equals, mysql.TypeVarchar)
c.Assert(fields[5].Column.Tp, Equals, mysql.TypeLonglong)
}
func (s *testSuite2) TestShowTableStatus(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec(`drop table if exists t;`)
tk.MustExec(`create table t(a bigint);`)
tk.Se.Auth(&auth.UserIdentity{Username: "root", Hostname: "192.168.0.1", AuthUsername: "root", AuthHostname: "%"}, nil, []byte("012345678901234567890"))
// It's not easy to test the result contents because every time the test runs, "Create_time" changed.
tk.MustExec("show table status;")
rs, err := tk.Exec("show table status;")
c.Assert(errors.ErrorStack(err), Equals, "")
c.Assert(rs, NotNil)
rows, err := session.GetRows4Test(context.Background(), tk.Se, rs)
c.Assert(errors.ErrorStack(err), Equals, "")
err = rs.Close()
c.Assert(errors.ErrorStack(err), Equals, "")
for i := range rows {
row := rows[i]
c.Assert(row.GetString(0), Equals, "t")
c.Assert(row.GetString(1), Equals, "InnoDB")
c.Assert(row.GetInt64(2), Equals, int64(10))
c.Assert(row.GetString(3), Equals, "Compact")
}
tk.MustExec(`drop table if exists tp;`)
tk.MustExec(`create table tp (a int)
partition by range(a)
( partition p0 values less than (10),
partition p1 values less than (20),
partition p2 values less than (maxvalue)
);`)
rs, err = tk.Exec("show table status from test like 'tp';")
c.Assert(errors.ErrorStack(err), Equals, "")
rows, err = session.GetRows4Test(context.Background(), tk.Se, rs)
c.Assert(errors.ErrorStack(err), Equals, "")
c.Assert(rows[0].GetString(16), Equals, "partitioned")
}
func (s *testSuite2) TestShowSlow(c *C) {
tk := testkit.NewTestKit(c, s.store)
// The test result is volatile, because
// 1. Slow queries is stored in domain, which may be affected by other tests.
// 2. Collecting slow queries is a asynchronous process, check immediately may not get the expected result.
// 3. Make slow query like "select sleep(1)" would slow the CI.
// So, we just cover the code but do not check the result.
tk.MustQuery(`admin show slow recent 3`)
tk.MustQuery(`admin show slow top 3`)
tk.MustQuery(`admin show slow top internal 3`)
tk.MustQuery(`admin show slow top all 3`)
}
func (s *testSuite2) TestShowOpenTables(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustQuery("show open tables")
tk.MustQuery("show open tables in test")
}
func (s *testSuite2) TestShowCreateTable(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1(a int,b int)")
tk.MustExec("drop view if exists v1")
tk.MustExec("create or replace definer=`root`@`127.0.0.1` view v1 as select * from t1")
tk.MustQuery("show create table v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a`, `b`) AS select * from t1 "))
tk.MustQuery("show create view v1").Check(testutil.RowsWithSep("|", "v1|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v1` (`a`, `b`) AS select * from t1 "))
tk.MustExec("drop view v1")
tk.MustExec("drop table t1")
tk.MustExec("drop view if exists v")
tk.MustExec("create or replace definer=`root`@`127.0.0.1` view v as select JSON_MERGE('{}', '{}') as col;")
tk.MustQuery("show create view v").Check(testutil.RowsWithSep("|", "v|CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`127.0.0.1` SQL SECURITY DEFINER VIEW `v` (`col`) AS select JSON_MERGE('{}', '{}') as col; "))
tk.MustExec("drop view if exists v")
// For issue #9211
tk.MustExec("create table t(c int, b int as (c + 1))ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;")
tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `c` int(11) DEFAULT NULL,\n"+
" `b` int(11) GENERATED ALWAYS AS (`c` + 1) VIRTUAL\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
))
tk.MustExec("drop table t")
tk.MustExec("create table t(c int, b int as (c + 1) not null)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;")
tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `c` int(11) DEFAULT NULL,\n"+
" `b` int(11) GENERATED ALWAYS AS (`c` + 1) VIRTUAL NOT NULL\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
))
tk.MustExec("drop table t")
tk.MustExec("create table t ( a char(10) charset utf8 collate utf8_bin, b char(10) as (rtrim(a)));")
tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `a` char(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n"+
" `b` char(10) GENERATED ALWAYS AS (rtrim(`a`)) VIRTUAL\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
))
tk.MustExec("drop table t")
tk.MustExec(`drop table if exists different_charset`)
tk.MustExec(`create table different_charset(ch1 varchar(10) charset utf8, ch2 varchar(10) charset binary);`)
tk.MustQuery(`show create table different_charset`).Check(testutil.RowsWithSep("|",
""+
"different_charset CREATE TABLE `different_charset` (\n"+
" `ch1` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,\n"+
" `ch2` varbinary(10) DEFAULT NULL\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
))
tk.MustExec("create table t (a int, b int) shard_row_id_bits = 4 pre_split_regions=3;")
tk.MustQuery("show create table `t`").Check(testutil.RowsWithSep("|",
""+
"t CREATE TABLE `t` (\n"+
" `a` int(11) DEFAULT NULL,\n"+
" `b` int(11) DEFAULT NULL\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin/*!90000 SHARD_ROW_ID_BITS=4 PRE_SPLIT_REGIONS=3 */",
))
tk.MustExec("drop table t")
}
func (s *testSuite2) TestShowEscape(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists `t``abl\"e`")
tk.MustExec("create table `t``abl\"e`(`c``olum\"n` int(11) primary key)")
tk.MustQuery("show create table `t``abl\"e`").Check(testutil.RowsWithSep("|",
""+
"t`abl\"e CREATE TABLE `t``abl\"e` (\n"+
" `c``olum\"n` int(11) NOT NULL,\n"+
" PRIMARY KEY (`c``olum\"n`)\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
))
// ANSI_QUOTES will change the SHOW output
tk.MustExec("set @old_sql_mode=@@sql_mode")
tk.MustExec("set sql_mode=ansi_quotes")
tk.MustQuery("show create table \"t`abl\"\"e\"").Check(testutil.RowsWithSep("|",
""+
"t`abl\"e CREATE TABLE \"t`abl\"\"e\" (\n"+
" \"c`olum\"\"n\" int(11) NOT NULL,\n"+
" PRIMARY KEY (\"c`olum\"\"n\")\n"+
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin",
))
tk.MustExec("rename table \"t`abl\"\"e\" to t")
tk.MustExec("set sql_mode=@old_sql_mode")
}