func (ts *testSuite) TestConstraintNames(c *C) { se, _ := tidb.CreateSession(ts.store) ctx := se.(context.Context) schemaName := model.NewCIStr("test_constraint") tblName := model.NewCIStr("t") tbIdent := table.Ident{ Schema: schemaName, Name: tblName, } err := sessionctx.GetDomain(ctx).DDL().CreateSchema(ctx, tbIdent.Schema) c.Assert(err, IsNil) tbStmt := statement("create table t (a int, b int, index a (a, b), index a (a))").(*stmts.CreateTableStmt) err = sessionctx.GetDomain(ctx).DDL().CreateTable(ctx, tbIdent, tbStmt.Cols, tbStmt.Constraints) c.Assert(err, NotNil) tbStmt = statement("create table t (a int, b int, index A (a, b), index (a))").(*stmts.CreateTableStmt) err = sessionctx.GetDomain(ctx).DDL().CreateTable(ctx, tbIdent, tbStmt.Cols, tbStmt.Constraints) c.Assert(err, IsNil) tbl, err := sessionctx.GetDomain(ctx).InfoSchema().TableByName(schemaName, tblName) indices := tbl.Indices() c.Assert(len(indices), Equals, 2) c.Assert(indices[0].Name.O, Equals, "A") c.Assert(indices[1].Name.O, Equals, "a_2") err = sessionctx.GetDomain(ctx).DDL().DropSchema(ctx, tbIdent.Schema) c.Assert(err, IsNil) }
// CreateSession creates a new session environment. func CreateSession(store kv.Storage) (Session, error) { s := &session{ values: make(map[fmt.Stringer]interface{}), store: store, sid: atomic.AddInt64(&sessionID, 1), debugInfos: make(map[string]interface{}), maxRetryCnt: 10, parser: parser.New(), } domain, err := domap.Get(store) if err != nil { return nil, errors.Trace(err) } sessionctx.BindDomain(s, domain) variable.BindSessionVars(s) variable.GetSessionVars(s).SetStatusFlag(mysql.ServerStatusAutocommit, true) // session implements variable.GlobalVarAccessor. Bind it to ctx. variable.BindGlobalVarAccessor(s, s) // session implements autocommit.Checker. Bind it to ctx autocommit.BindAutocommitChecker(s, s) sessionMu.Lock() defer sessionMu.Unlock() ver := getStoreBootstrapVersion(store) if ver == notBootstrapped { // if no bootstrap and storage is remote, we must use a little lease time to // bootstrap quickly, after bootstrapped, we will reset the lease time. // TODO: Using a bootstap tool for doing this may be better later. if !localstore.IsLocalStore(store) { sessionctx.GetDomain(s).SetLease(chooseMinLease(100*time.Millisecond, schemaLease)) } s.SetValue(context.Initing, true) bootstrap(s) s.ClearValue(context.Initing) if !localstore.IsLocalStore(store) { sessionctx.GetDomain(s).SetLease(schemaLease) } finishBootstrap(store) } else if ver < currentBootstrapVersion { s.SetValue(context.Initing, true) upgrade(s) s.ClearValue(context.Initing) } // TODO: Add auth here privChecker := &privileges.UserPrivileges{} privilege.BindPrivilegeChecker(s, privChecker) return s, nil }
func (s *testDBSuite) TestTruncateTable(c *C) { defer testleak.AfterTest(c) store, err := tidb.NewStore("memory://truncate_table") c.Assert(err, IsNil) tk := testkit.NewTestKit(c, store) tk.MustExec("use test") tk.MustExec("create table t (c1 int, c2 int)") tk.MustExec("insert t values (1, 1), (2, 2)") ctx := tk.Se.(context.Context) is := sessionctx.GetDomain(ctx).InfoSchema() oldTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) c.Assert(err, IsNil) oldTblID := oldTblInfo.Meta().ID tk.MustExec("truncate table t") tk.MustExec("insert t values (3, 3), (4, 4)") tk.MustQuery("select * from t").Check(testkit.Rows("3 3", "4 4")) is = sessionctx.GetDomain(ctx).InfoSchema() newTblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t")) c.Assert(err, IsNil) c.Assert(newTblInfo.Meta().ID, Greater, oldTblID) // verify that the old table data has been deleted by background worker. tablePrefix := tablecodec.EncodeTablePrefix(oldTblID) hasOldTableData := true for i := 0; i < 30; i++ { err = kv.RunInNewTxn(store, false, func(txn kv.Transaction) error { it, err1 := txn.Seek(tablePrefix) if err1 != nil { return err1 } if !it.Valid() { hasOldTableData = false } else { hasOldTableData = it.Key().HasPrefix(tablePrefix) } it.Close() return nil }) c.Assert(err, IsNil) if !hasOldTableData { break } time.Sleep(time.Millisecond * 100) } c.Assert(hasOldTableData, IsFalse) }
func (s *session) checkSchemaValid() error { var ts uint64 if s.txn != nil { ts = s.txn.StartTS() } else { s.schemaVerInCurrTxn = 0 } var err error var currSchemaVer int64 for i := 0; i < schemaExpiredRetryTimes; i++ { currSchemaVer, err = sessionctx.GetDomain(s).SchemaValidity.Check(ts, s.schemaVerInCurrTxn) if err == nil { if s.txn == nil { s.schemaVerInCurrTxn = currSchemaVer } return nil } log.Infof("schema version original %d, current %d, sleep time %v", s.schemaVerInCurrTxn, currSchemaVer, checkSchemaValiditySleepTime) if terror.ErrorEqual(err, domain.ErrInfoSchemaChanged) { break } time.Sleep(checkSchemaValiditySleepTime) } return errors.Trace(err) }
// Compile compiles an ast.StmtNode to a stmt.Statement. // If it is supported to use new plan and executer, it optimizes the node to // a plan, and we wrap the plan in an adapter as stmt.Statement. // If it is not supported, the node will be converted to old statement. func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (stmt.Statement, error) { if optimizer.IsSupported(node) { ast.SetFlag(node) if err := optimizer.Validate(node, false); err != nil { return nil, errors.Trace(err) } is := sessionctx.GetDomain(ctx).InfoSchema() if err := optimizer.ResolveName(node, is, ctx); err != nil { return nil, errors.Trace(err) } p, err := optimizer.Optimize(ctx, node) if err != nil { return nil, errors.Trace(err) } sa := &statementAdapter{ is: is, plan: p, } return sa, nil } c.converter = &converter.Converter{} s, err := c.converter.Convert(node) if err != nil { return nil, errors.Trace(err) } return s, nil }
func (s *testDBSuite) SetUpSuite(c *C) { trySkipDBTest(c) var err error s.schemaName = "test_db" uri := "memory://test" s.store, err = tidb.NewStore(uri) c.Assert(err, IsNil) s.db, err = sql.Open("tidb", fmt.Sprintf("%s/%s", uri, s.schemaName)) c.Assert(err, IsNil) s.s, err = tidb.CreateSession(s.store) c.Assert(err, IsNil) s.mustExec(c, "create table t1 (c1 int, c2 int, c3 int, primary key(c1))") s.mustExec(c, "create table t2 (c1 int, c2 int, c3 int)") // set proper schema lease s.lease = 500 * time.Millisecond ctx := s.s.(context.Context) sessionctx.GetDomain(ctx).SetLease(s.lease) }
func (s *ShowPlan) fetchShowDatabases(ctx context.Context) error { dbs := sessionctx.GetDomain(ctx).InfoSchema().AllSchemaNames() // TODO: let information_schema be the first database sort.Strings(dbs) m := map[interface{}]interface{}{} for _, d := range dbs { if s.Pattern != nil { s.Pattern.Expr = expression.Value{Val: d} } else if s.Where != nil { m[expression.ExprEvalIdentFunc] = func(name string) (interface{}, error) { if strings.EqualFold(name, "Database") { return d, nil } return nil, errors.Errorf("unknown field %s", name) } } match, err := s.evalCondition(ctx, m) if err != nil { return errors.Trace(err) } if !match { continue } s.rows = append(s.rows, &plan.Row{Data: []interface{}{d}}) } return nil }
func (s *ShowPlan) fetchShowTables(ctx context.Context) error { is := sessionctx.GetDomain(ctx).InfoSchema() dbName := model.NewCIStr(s.DBName) if !is.SchemaExists(dbName) { return errors.Errorf("Can not find DB: %s", dbName) } // sort for tables var tableNames []string for _, v := range is.SchemaTables(dbName) { tableNames = append(tableNames, v.TableName().L) } sort.Strings(tableNames) for _, v := range tableNames { data := []interface{}{v} if s.Full { // TODO: support "VIEW" later if we have supported view feature. // now, just use "BASE TABLE". data = append(data, "BASE TABLE") } s.rows = append(s.rows, &plan.Row{Data: data}) } return nil }
// Compile compiles an ast.StmtNode to a stmt.Statement. // If it is supported to use new plan and executer, it optimizes the node to // a plan, and we wrap the plan in an adapter as stmt.Statement. // If it is not supported, the node will be converted to old statement. func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (stmt.Statement, error) { if optimizer.IsSupported(node) { ast.SetFlag(node) is := sessionctx.GetDomain(ctx).InfoSchema() if err := optimizer.Preprocess(node, is, ctx); err != nil { return nil, errors.Trace(err) } // Validate should be after NameResolve. if err := optimizer.Validate(node, false); err != nil { return nil, errors.Trace(err) } sb := NewSubQueryBuilder(is) p, err := optimizer.Optimize(ctx, node, sb) if err != nil { return nil, errors.Trace(err) } sa := &statementAdapter{ is: is, plan: p, } return sa, nil } c.converter = &converter.Converter{} s, err := c.converter.Convert(node) if err != nil { return nil, errors.Trace(err) } return s, nil }
// Exec implements the stmt.Statement Exec interface. func (s *CreateIndexStmt) Exec(ctx context.Context) (rset.Recordset, error) { err := sessionctx.GetDomain(ctx).DDL().CreateIndex(ctx, s.TableIdent.Full(ctx), s.Unique, model.NewCIStr(s.IndexName), s.IndexColNames) if err != nil { return nil, errors.Trace(err) } return nil, nil }
func (s *testBinlogSuite) SetUpSuite(c *C) { logLevel := os.Getenv("log_level") log.SetLevelByString(logLevel) store, err := tikv.NewMockTikvStore() c.Assert(err, IsNil) s.store = store tidb.SetSchemaLease(0) s.unixFile = "/tmp/mock-binlog-pump" os.Remove(s.unixFile) l, err := net.Listen("unix", s.unixFile) c.Assert(err, IsNil) s.serv = grpc.NewServer() s.pump = new(mockBinlogPump) binlog.RegisterPumpServer(s.serv, s.pump) go s.serv.Serve(l) opt := grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout("unix", addr, timeout) }) clientCon, err := grpc.Dial(s.unixFile, opt, grpc.WithInsecure()) c.Assert(err, IsNil) c.Assert(clientCon, NotNil) binloginfo.PumpClient = binlog.NewPumpClient(clientCon) s.tk = testkit.NewTestKit(c, s.store) s.tk.MustExec("use test") domain := sessionctx.GetDomain(s.tk.Se.(context.Context)) s.ddl = domain.DDL() }
func (s *session) Execute(sql string) ([]ast.RecordSet, error) { if err := s.checkSchemaValidOrRollback(); err != nil { return nil, errors.Trace(err) } charset, collation := getCtxCharsetInfo(s) rawStmts, err := s.ParseSQL(sql, charset, collation) if err != nil { log.Warnf("compiling %s, error: %v", sql, err) return nil, errors.Trace(err) } var rs []ast.RecordSet ph := sessionctx.GetDomain(s).PerfSchema() for i, rst := range rawStmts { st, err1 := Compile(s, rst) if err1 != nil { log.Errorf("Syntax error: %s", sql) log.Errorf("Error occurs at %s.", err1) return nil, errors.Trace(err1) } id := variable.GetSessionVars(s).ConnectionID s.stmtState = ph.StartStatement(sql, id, perfschema.CallerNameSessionExecute, rawStmts[i]) r, err := runStmt(s, st) ph.EndStatement(s.stmtState) if err != nil { log.Warnf("session:%v, err:%v", s, err) return nil, errors.Trace(err) } if r != nil { rs = append(rs, r) } } return rs, nil }
func (ts *testSuite) TestUniqueIndexMultipleNullEntries(c *C) { _, err := ts.se.Execute("CREATE TABLE test.t (a int primary key auto_increment, b varchar(255) unique)") c.Assert(err, IsNil) ctx := ts.se.(context.Context) dom := sessionctx.GetDomain(ctx) tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) c.Assert(err, IsNil) c.Assert(tb.Meta().ID, Greater, int64(0)) c.Assert(tb.Meta().Name.L, Equals, "t") c.Assert(tb.Meta(), NotNil) c.Assert(tb.Indices(), NotNil) c.Assert(string(tb.FirstKey()), Not(Equals), "") c.Assert(string(tb.IndexPrefix()), Not(Equals), "") c.Assert(string(tb.RecordPrefix()), Not(Equals), "") c.Assert(tables.FindIndexByColName(tb, "b"), NotNil) autoid, err := tb.AllocAutoID() c.Assert(err, IsNil) c.Assert(autoid, Greater, int64(0)) _, err = tb.AddRecord(ctx, types.MakeDatums(1, nil)) c.Assert(err, IsNil) _, err = tb.AddRecord(ctx, types.MakeDatums(2, nil)) c.Assert(err, IsNil) _, err = ts.se.Execute("drop table test.t") c.Assert(err, IsNil) }
func (ts *testInfoBinderSuite) TestInfoBinder(c *C) { store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory) c.Assert(err, IsNil) defer store.Close() testKit := testkit.NewTestKit(c, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 int)") domain := sessionctx.GetDomain(testKit.Se.(context.Context)) src := "SELECT c1 from t" l := parser.NewLexer(src) c.Assert(parser.YYParse(l), Equals, 0) stmts := l.Stmts() c.Assert(len(stmts), Equals, 1) v := &optimizer.InfoBinder{ Info: domain.InfoSchema(), DefaultSchema: model.NewCIStr("test"), } selectStmt := stmts[0].(*ast.SelectStmt) selectStmt.Accept(v) verifier := &binderVerifier{ c: c, } selectStmt.Accept(verifier) }
// Open returns a new connection to the database. The name is a string in a // driver-specific format. // // Open may return a cached connection (one previously closed), but doing so is // unnecessary; the sql package maintains a pool of idle connections for // efficient re-use. // // The returned connection is only used by one goroutine at a time. func (d *sqlDriver) Open(name string) (driver.Conn, error) { store, err := NewStore(name) if err != nil { return nil, errors.Trace(err) } driver := &sqlDriver{} switch { case strings.HasPrefix(name, "file://"): name = name[len("file://"):] case strings.HasPrefix(name, "memory://"): name = name[len("memory://"):] } name = filepath.Clean(name) if name == "" || name == "." || name == string(os.PathSeparator) { return nil, errors.Errorf("invalid DB name %q", name) } sess, err := CreateSession(store) if err != nil { return nil, errors.Trace(err) } s := sess.(*session) defer d.lock()() DBName := model.NewCIStr(name[strings.LastIndex(name, "/")+1:]) domain := sessionctx.GetDomain(s) if !domain.InfoSchema().SchemaExists(DBName) { err = domain.DDL().CreateSchema(s, DBName) if err != nil { return nil, errors.Trace(err) } } return newDriverConn(s, driver, DBName.O) }
// Exec implements the stmt.Statement Exec interface. func (s *DropDatabaseStmt) Exec(ctx context.Context) (rset.Recordset, error) { err := sessionctx.GetDomain(ctx).DDL().DropSchema(ctx, model.NewCIStr(s.Name)) if terror.ErrorEqual(err, ddl.ErrNotExists) && s.IfExists { err = nil } return nil, errors.Trace(err) }
// Next implements Executor Next interface. func (e *CheckTableExec) Next() (*Row, error) { if e.done { return nil, nil } dbName := model.NewCIStr(db.GetCurrentSchema(e.ctx)) is := sessionctx.GetDomain(e.ctx).InfoSchema() for _, t := range e.tables { tb, err := is.TableByName(dbName, t.Name) if err != nil { return nil, errors.Trace(err) } for _, idx := range tb.Indices() { txn, err := e.ctx.GetTxn(false) if err != nil { return nil, errors.Trace(err) } err = inspectkv.CompareIndexData(txn, tb, idx) if err != nil { return nil, errors.Errorf("%v err:%v", t.Name, err) } } } e.done = true return nil, nil }
func (ts *testNameResolverSuite) TestNameResolver(c *C) { store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory) c.Assert(err, IsNil) defer store.Close() testKit := testkit.NewTestKit(c, store) testKit.MustExec("use test") testKit.MustExec("create table t1 (c1 int, c2 int)") testKit.MustExec("create table t2 (c1 int, c2 int)") testKit.MustExec("create table t3 (c1 int, c2 int)") ctx := testKit.Se.(context.Context) domain := sessionctx.GetDomain(ctx) db.BindCurrentSchema(ctx, "test") for _, tc := range resolverTestCases { node, err := parser.ParseOneStmt(tc.src, "", "") c.Assert(err, IsNil) resolveErr := plan.ResolveName(node, domain.InfoSchema(), ctx) if tc.valid { c.Assert(resolveErr, IsNil) verifier := &resolverVerifier{c: c, src: tc.src} node.Accept(verifier) } else { c.Assert(resolveErr, NotNil, Commentf("%s", tc.src)) } } }
// Open returns a new connection to the database. // // The dsn must be a URL format 'engine://path/dbname?params'. // Engine is the storage name registered with RegisterStore. // Path is the storage specific format. // Params is key-value pairs split by '&', optional params are storage specific. // Examples: // goleveldb://relative/path/test // boltdb:///absolute/path/test // hbase://zk1,zk2,zk3/hbasetbl/test?tso=zk // // Open may return a cached connection (one previously closed), but doing so is // unnecessary; the sql package maintains a pool of idle connections for // efficient re-use. // // The returned connection is only used by one goroutine at a time. func (d *sqlDriver) Open(dsn string) (driver.Conn, error) { storePath, dbName, err := parseDriverDSN(dsn) if err != nil { return nil, errors.Trace(err) } store, err := NewStore(storePath) if err != nil { return nil, errors.Trace(err) } sess, err := CreateSession(store) if err != nil { return nil, errors.Trace(err) } s := sess.(*session) d.lock() defer d.unlock() DBName := model.NewCIStr(dbName) domain := sessionctx.GetDomain(s) cs := &coldef.CharsetOpt{ Chs: "utf8", Col: "utf8_bin", } if !domain.InfoSchema().SchemaExists(DBName) { err = domain.DDL().CreateSchema(s, DBName, cs) if err != nil { return nil, errors.Trace(err) } } driver := &sqlDriver{} return newDriverConn(s, driver, DBName.O) }
func (ts *testSuite) TestTypes(c *C) { _, err := ts.se.Execute("CREATE TABLE test.t (c1 tinyint, c2 smallint, c3 int, c4 bigint, c5 text, c6 blob, c7 varchar(64), c8 time, c9 timestamp not null default CURRENT_TIMESTAMP, c10 decimal)") c.Assert(err, IsNil) ctx := ts.se.(context.Context) dom := sessionctx.GetDomain(ctx) _, err = dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) c.Assert(err, IsNil) _, err = ts.se.Execute("insert test.t values (1, 2, 3, 4, '5', '6', '7', '10:10:10', null, 1.4)") c.Assert(err, IsNil) rs, err := ts.se.Execute("select * from test.t where c1 = 1") row, err := rs[0].FirstRow() c.Assert(err, IsNil) c.Assert(row, NotNil) _, err = ts.se.Execute("drop table test.t") c.Assert(err, IsNil) _, err = ts.se.Execute("CREATE TABLE test.t (c1 tinyint unsigned, c2 smallint unsigned, c3 int unsigned, c4 bigint unsigned, c5 double)") c.Assert(err, IsNil) _, err = ts.se.Execute("insert test.t values (1, 2, 3, 4, 5)") c.Assert(err, IsNil) rs, err = ts.se.Execute("select * from test.t where c1 = 1") row, err = rs[0].FirstRow() c.Assert(err, IsNil) c.Assert(row, NotNil) _, err = ts.se.Execute("drop table test.t") c.Assert(err, IsNil) }
// Compile compiles an ast.StmtNode to a stmt.Statement. // If it is supported to use new plan and executer, it optimizes the node to // a plan, and we wrap the plan in an adapter as stmt.Statement. // If it is not supported, the node will be converted to old statement. func (c *Compiler) Compile(ctx context.Context, node ast.StmtNode) (ast.Statement, error) { ast.SetFlag(node) if _, ok := node.(*ast.UpdateStmt); ok { sVars := variable.GetSessionVars(ctx) sVars.InUpdateStmt = true defer func() { sVars.InUpdateStmt = false }() } is := sessionctx.GetDomain(ctx).InfoSchema() if err := plan.Preprocess(node, is, ctx); err != nil { return nil, errors.Trace(err) } // Validate should be after NameResolve. if err := plan.Validate(node, false); err != nil { return nil, errors.Trace(err) } sb := NewSubQueryBuilder(is) p, err := plan.Optimize(ctx, node, sb, is) if err != nil { return nil, errors.Trace(err) } _, isDDL := node.(ast.DDLNode) sa := &statement{ is: is, plan: p, text: node.Text(), isDDL: isDDL, } return sa, nil }
// Exec implements the stmt.Statement Exec interface. func (s *DropIndexStmt) Exec(ctx context.Context) (rset.Recordset, error) { err := sessionctx.GetDomain(ctx).DDL().DropIndex(ctx, s.TableIdent.Full(ctx), model.NewCIStr(s.IndexName)) if (terror.ErrorEqual(err, ddl.ErrNotExists) || terror.DatabaseNotExists.Equal(err)) && s.IfExists { err = nil } return nil, errors.Trace(err) }
// Exec implements the stmt.Statement Exec interface. func (s *UseStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { dbname := model.NewCIStr(s.DBName) if !sessionctx.GetDomain(ctx).InfoSchema().SchemaExists(dbname) { return nil, errors.ErrDatabaseNotExist } db.BindCurrentSchema(ctx, dbname.O) return nil, nil }
func (e *DDLExec) executeDropIndex(s *ast.DropIndexStmt) error { ti := ast.Ident{Schema: s.Table.Schema, Name: s.Table.Name} err := sessionctx.GetDomain(e.ctx).DDL().DropIndex(e.ctx, ti, model.NewCIStr(s.IndexName)) if (infoschema.ErrDatabaseNotExists.Equal(err) || infoschema.ErrTableNotExists.Equal(err)) && s.IfExists { err = nil } return errors.Trace(err) }
func (s *testDBSuite) TestUpdateMultipleTable(c *C) { defer testleak.AfterTest(c) store, err := tidb.NewStore("memory://update_multiple_table") c.Assert(err, IsNil) tk := testkit.NewTestKit(c, store) tk.MustExec("use test") tk.MustExec("create table t1 (c1 int, c2 int)") tk.MustExec("insert t1 values (1, 1), (2, 2)") tk.MustExec("create table t2 (c1 int, c2 int)") tk.MustExec("insert t2 values (1, 3), (2, 5)") ctx := tk.Se.(context.Context) domain := sessionctx.GetDomain(ctx) is := domain.InfoSchema() db, ok := is.SchemaByName(model.NewCIStr("test")) c.Assert(ok, IsTrue) t1Tbl, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("t1")) c.Assert(err, IsNil) t1Info := t1Tbl.Meta() // Add a new column in write only state. newColumn := &model.ColumnInfo{ ID: 100, Name: model.NewCIStr("c3"), Offset: 2, DefaultValue: 9, FieldType: *types.NewFieldType(mysql.TypeLonglong), State: model.StateWriteOnly, } t1Info.Columns = append(t1Info.Columns, newColumn) kv.RunInNewTxn(store, false, func(txn kv.Transaction) error { m := meta.NewMeta(txn) _, err = m.GenSchemaVersion() c.Assert(err, IsNil) c.Assert(m.UpdateTable(db.ID, t1Info), IsNil) return nil }) err = domain.Reload() c.Assert(err, IsNil) tk.MustExec("update t1, t2 set t1.c1 = 8, t2.c2 = 10 where t1.c2 = t2.c1") tk.MustQuery("select * from t1").Check(testkit.Rows("8 1", "8 2")) tk.MustQuery("select * from t2").Check(testkit.Rows("1 10", "2 10")) newColumn.State = model.StatePublic kv.RunInNewTxn(store, false, func(txn kv.Transaction) error { m := meta.NewMeta(txn) _, err = m.GenSchemaVersion() c.Assert(err, IsNil) c.Assert(m.UpdateTable(db.ID, t1Info), IsNil) return nil }) err = domain.Reload() c.Assert(err, IsNil) tk.MustQuery("select * from t1").Check(testkit.Rows("8 1 9", "8 2 9")) }
func (ts *testTypeInferrerSuite) TestInterType(c *C) { store, err := tidb.NewStore(tidb.EngineGoLevelDBMemory) c.Assert(err, IsNil) defer store.Close() testKit := testkit.NewTestKit(c, store) testKit.MustExec("use test") testKit.MustExec("create table t (c1 int, c2 double, c3 text)") cases := []struct { expr string tp byte }{ {"c1", mysql.TypeLong}, {"+1", mysql.TypeLonglong}, {"-1", mysql.TypeLonglong}, {"-'1'", mysql.TypeDouble}, {"~1", mysql.TypeLonglong}, {"!true", mysql.TypeLonglong}, {"c1 is true", mysql.TypeLonglong}, {"c2 is null", mysql.TypeLonglong}, {"cast(1 as decimal)", mysql.TypeNewDecimal}, {"1 and 1", mysql.TypeLonglong}, {"1 or 1", mysql.TypeLonglong}, {"1 xor 1", mysql.TypeLonglong}, {"'1' & 2", mysql.TypeLonglong}, {"'1' | 2", mysql.TypeLonglong}, {"'1' ^ 2", mysql.TypeLonglong}, {"'1' << 1", mysql.TypeLonglong}, {"'1' >> 1", mysql.TypeLonglong}, {"1 + '1'", mysql.TypeDouble}, {"1 + 1.1", mysql.TypeNewDecimal}, {"1 div 2", mysql.TypeLonglong}, {"1 > any (select 1)", mysql.TypeLonglong}, {"exists (select 1)", mysql.TypeLonglong}, {"1 in (2, 3)", mysql.TypeLonglong}, {"'abc' like 'abc'", mysql.TypeLonglong}, {"'abc' rlike 'abc'", mysql.TypeLonglong}, {"(1+1)", mysql.TypeLonglong}, } for _, ca := range cases { ctx := testKit.Se.(context.Context) stmts, err := tidb.Parse(ctx, "select "+ca.expr+" from t") c.Assert(err, IsNil) c.Assert(stmts, HasLen, 1) stmt := stmts[0].(*ast.SelectStmt) is := sessionctx.GetDomain(ctx).InfoSchema() err = optimizer.ResolveName(stmt, is, ctx) c.Assert(err, IsNil) optimizer.InferType(stmt) tp := stmt.GetResultFields()[0].Column.Tp c.Assert(tp, Equals, ca.tp, Commentf("for %s", ca.expr)) } }
// For execute prepare statement in binary protocol func (s *session) PrepareStmt(sql string) (stmtID uint32, paramCount int, fields []*field.ResultField, err error) { prepareExec := &executor.PrepareExec{ IS: sessionctx.GetDomain(s).InfoSchema(), Ctx: s, SQLText: sql, } prepareExec.DoPrepare() return prepareExec.ID, prepareExec.ParamCount, prepareExec.ResultFields, prepareExec.Err }
func (s *testSuite) TestAdmin(c *C) { defer testleak.AfterTest(c)() tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") tk.MustExec("drop table if exists admin_test") tk.MustExec("create table admin_test (c1 int, c2 int, c3 int default 1, index (c1))") tk.MustExec("insert admin_test (c1) values (1),(2),(NULL)") r, err := tk.Exec("admin show ddl") c.Assert(err, IsNil) row, err := r.Next() c.Assert(err, IsNil) c.Assert(row.Data, HasLen, 6) txn, err := s.store.Begin() c.Assert(err, IsNil) ddlInfo, err := inspectkv.GetDDLInfo(txn) c.Assert(err, IsNil) c.Assert(row.Data[0].GetInt64(), Equals, ddlInfo.SchemaVer) rowOwnerInfos := strings.Split(row.Data[1].GetString(), ",") ownerInfos := strings.Split(ddlInfo.Owner.String(), ",") c.Assert(rowOwnerInfos[0], Equals, ownerInfos[0]) c.Assert(row.Data[2].GetString(), Equals, "") bgInfo, err := inspectkv.GetBgDDLInfo(txn) c.Assert(err, IsNil) c.Assert(row.Data[3].GetInt64(), Equals, bgInfo.SchemaVer) rowOwnerInfos = strings.Split(row.Data[4].GetString(), ",") ownerInfos = strings.Split(bgInfo.Owner.String(), ",") c.Assert(rowOwnerInfos[0], Equals, ownerInfos[0]) c.Assert(row.Data[5].GetString(), Equals, "") row, err = r.Next() c.Assert(err, IsNil) c.Assert(row, IsNil) // check table test tk.MustExec("create table admin_test1 (c1 int, c2 int default 1, index (c1))") tk.MustExec("insert admin_test1 (c1) values (21),(22)") r, err = tk.Exec("admin check table admin_test, admin_test1") c.Assert(err, IsNil) c.Assert(r, IsNil) // error table name r, err = tk.Exec("admin check table admin_test_error") c.Assert(err, NotNil) // different index values ctx := tk.Se.(context.Context) domain := sessionctx.GetDomain(ctx) is := domain.InfoSchema() c.Assert(is, NotNil) tb, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("admin_test")) c.Assert(err, IsNil) c.Assert(tb.Indices(), HasLen, 1) _, err = tb.Indices()[0].Create(txn, types.MakeDatums(int64(10)), 1) c.Assert(err, IsNil) err = txn.Commit() c.Assert(err, IsNil) r, err = tk.Exec("admin check table admin_test") c.Assert(err, NotNil) }
func (ts *testSuite) TestBasic(c *C) { _, err := ts.se.Execute("CREATE TABLE test.t (a int primary key auto_increment, b varchar(255) unique)") c.Assert(err, IsNil) ctx := ts.se.(context.Context) dom := sessionctx.GetDomain(ctx) tb, err := dom.InfoSchema().TableByName(model.NewCIStr("test"), model.NewCIStr("t")) c.Assert(err, IsNil) c.Assert(tb.TableID(), Greater, int64(0)) c.Assert(tb.TableName().L, Equals, "t") c.Assert(tb.Meta(), NotNil) c.Assert(tb.Indices(), NotNil) c.Assert(tb.FirstKey(), Not(Equals), "") c.Assert(tb.IndexPrefix(), Not(Equals), "") c.Assert(tb.KeyPrefix(), Not(Equals), "") c.Assert(tb.FindIndexByColName("b"), NotNil) autoid, err := tb.AllocAutoID() c.Assert(err, IsNil) c.Assert(autoid, Greater, int64(0)) rid, err := tb.AddRecord(ctx, []interface{}{1, "abc"}) c.Assert(err, IsNil) c.Assert(rid, Greater, int64(0)) row, err := tb.Row(ctx, rid) c.Assert(err, IsNil) c.Assert(len(row), Equals, 2) c.Assert(row[0].(int64), Equals, int64(1)) _, err = tb.AddRecord(ctx, []interface{}{1, "aba"}) c.Assert(err, NotNil) _, err = tb.AddRecord(ctx, []interface{}{2, "abc"}) c.Assert(err, NotNil) c.Assert(tb.UpdateRecord(ctx, rid, []interface{}{1, "abc"}, []interface{}{1, "cba"}, []bool{false, true}), IsNil) tb.IterRecords(ctx, tb.FirstKey(), tb.Cols(), func(h int64, data []interface{}, cols []*column.Col) (bool, error) { return true, nil }) c.Assert(tb.RemoveRowAllIndex(ctx, rid, []interface{}{1, "cba"}), IsNil) c.Assert(tb.RemoveRow(ctx, rid), IsNil) // Make sure there is index data in the storage. prefix := tb.IndexPrefix() cnt, err := countEntriesWithPrefix(ctx, prefix) c.Assert(err, IsNil) //c.Assert(cnt, Greater, 0) // it is not a correct assert, because after fix issue 463, there is no index in the table anymore c.Assert(cnt, Equals, 0) c.Assert(tb.Truncate(ctx), IsNil) // Make sure index data is also removed after tb.Truncate(). cnt, err = countEntriesWithPrefix(ctx, prefix) c.Assert(err, IsNil) c.Assert(cnt, Equals, 0) _, err = ts.se.Execute("drop table test.t") c.Assert(err, IsNil) }
func (s *testDBSuite) testGetTable(c *C, name string) table.Table { ctx := s.s.(context.Context) domain := sessionctx.GetDomain(ctx) // Make sure the table schema is the new schema. err := domain.MustReload() c.Assert(err, IsNil) tbl, err := domain.InfoSchema().TableByName(model.NewCIStr(s.schemaName), model.NewCIStr(name)) c.Assert(err, IsNil) return tbl }