diff --git a/executor/admin_test.go b/executor/admin_test.go index 40220e8aee3cc..b60ef73e30184 100644 --- a/executor/admin_test.go +++ b/executor/admin_test.go @@ -19,6 +19,7 @@ import ( . "github.com/pingcap/check" "github.com/pingcap/parser/model" "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/meta/autoid" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/mock" @@ -514,3 +515,45 @@ func (s *testSuite) TestAdminCheckPrimaryIndex(c *C) { tk.MustExec("insert into t values(1, 1, 1), (9223372036854775807, 2, 2);") tk.MustExec("admin check index t idx;") } + +func (s *testSuite) TestAdminShowNextID(c *C) { + step := int64(10) + autoIDStep := autoid.GetStep() + autoid.SetStep(step) + defer autoid.SetStep(autoIDStep) + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("create table t(id int, c int)") + // Start handle is 1. + r := tk.MustQuery("admin show t next_row_id") + r.Check(testkit.Rows("test t _tidb_rowid 1")) + // Row ID is step + 1. + tk.MustExec("insert into t values(1, 1)") + r = tk.MustQuery("admin show t next_row_id") + r.Check(testkit.Rows("test t _tidb_rowid 11")) + // Row ID is original + step. + for i := 0; i < int(step); i++ { + tk.MustExec("insert into t values(10000, 1)") + } + r = tk.MustQuery("admin show t next_row_id") + r.Check(testkit.Rows("test t _tidb_rowid 21")) + + // test for a table with the primary key + tk.MustExec("create table tt(id int primary key auto_increment, c int)") + // Start handle is 1. + r = tk.MustQuery("admin show tt next_row_id") + r.Check(testkit.Rows("test tt id 1")) + // After rebasing auto ID, row ID is 20 + step + 1. + tk.MustExec("insert into tt values(20, 1)") + r = tk.MustQuery("admin show tt next_row_id") + r.Check(testkit.Rows("test tt id 31")) + // test for renaming the table + tk.MustExec("create database test1") + tk.MustExec("rename table test.tt to test1.tt") + tk.MustExec("use test1") + r = tk.MustQuery("admin show tt next_row_id") + r.Check(testkit.Rows("test1 tt id 31")) + tk.MustExec("insert test1.tt values ()") + r = tk.MustQuery("admin show tt next_row_id") + r.Check(testkit.Rows("test1 tt id 41")) +} diff --git a/executor/aggregate_test.go b/executor/aggregate_test.go index c0c7d7ffb4a6f..fe453a659c3e9 100644 --- a/executor/aggregate_test.go +++ b/executor/aggregate_test.go @@ -240,7 +240,7 @@ func (s *testSuite) TestAggregation(c *C) { result = tk.MustQuery("select count(*) from information_schema.columns") // When adding new memory columns in information_schema, please update this variable. - columnCountOfAllInformationSchemaTables := "757" + columnCountOfAllInformationSchemaTables := "759" result.Check(testkit.Rows(columnCountOfAllInformationSchemaTables)) tk.MustExec("drop table if exists t1") diff --git a/executor/builder.go b/executor/builder.go index b74806a3ae419..ba530a4993f33 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -112,6 +112,8 @@ func (b *executorBuilder) build(p plannercore.Plan) Executor { return b.buildSelectLock(v) case *plannercore.CancelDDLJobs: return b.buildCancelDDLJobs(v) + case *plannercore.ShowNextRowID: + return b.buildShowNextRowID(v) case *plannercore.ShowDDL: return b.buildShowDDL(v) case *plannercore.ShowDDLJobs: @@ -185,6 +187,14 @@ func (b *executorBuilder) buildCancelDDLJobs(v *plannercore.CancelDDLJobs) Execu return e } +func (b *executorBuilder) buildShowNextRowID(v *plannercore.ShowNextRowID) Executor { + e := &ShowNextRowIDExec{ + baseExecutor: newBaseExecutor(b.ctx, v.Schema(), v.ExplainID()), + tblName: v.TableName, + } + return e +} + func (b *executorBuilder) buildShowDDL(v *plannercore.ShowDDL) Executor { // We get DDLInfo here because for Executors that returns result set, // next will be called after transaction has been committed. diff --git a/executor/executor.go b/executor/executor.go index b03af3671ddea..b1d3dc8793986 100644 --- a/executor/executor.go +++ b/executor/executor.go @@ -55,6 +55,7 @@ var ( _ Executor = &ProjectionExec{} _ Executor = &SelectionExec{} _ Executor = &SelectLockExec{} + _ Executor = &ShowNextRowIDExec{} _ Executor = &ShowDDLExec{} _ Executor = &ShowDDLJobsExec{} _ Executor = &ShowDDLJobQueriesExec{} @@ -200,6 +201,43 @@ func (e *CancelDDLJobsExec) Next(ctx context.Context, chk *chunk.Chunk) error { return nil } +// ShowNextRowIDExec represents a show the next row ID executor. +type ShowNextRowIDExec struct { + baseExecutor + tblName *ast.TableName + done bool +} + +// Next implements the Executor Next interface. +func (e *ShowNextRowIDExec) Next(ctx context.Context, chk *chunk.Chunk) error { + chk.Reset() + if e.done { + return nil + } + is := domain.GetDomain(e.ctx).InfoSchema() + tbl, err := is.TableByName(e.tblName.Schema, e.tblName.Name) + if err != nil { + return errors.Trace(err) + } + colName := model.ExtraHandleName + for _, col := range tbl.Meta().Columns { + if mysql.HasAutoIncrementFlag(col.Flag) { + colName = col.Name + break + } + } + nextGlobalID, err := tbl.Allocator(e.ctx).NextGlobalAutoID(tbl.Meta().ID) + if err != nil { + return errors.Trace(err) + } + chk.AppendString(0, e.tblName.Schema.O) + chk.AppendString(1, e.tblName.Name.O) + chk.AppendString(2, colName.O) + chk.AppendInt64(3, nextGlobalID) + e.done = true + return nil +} + // ShowDDLExec represents a show DDL executor. type ShowDDLExec struct { baseExecutor diff --git a/go.mod b/go.mod index 9928c48f12789..3906a25895fc2 100644 --- a/go.mod +++ b/go.mod @@ -1,71 +1,30 @@ module github.com/pingcap/tidb require ( - cloud.google.com/go v0.31.0 // indirect github.com/BurntSushi/toml v0.3.1 - github.com/Shopify/sarama v1.19.0 // indirect - github.com/Shopify/toxiproxy v2.1.3+incompatible // indirect - github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7 // indirect github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 // indirect github.com/blacktear23/go-proxyprotocol v0.0.0-20171102103907-62e368e1c470 - github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3 // indirect - github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292 // indirect github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect - github.com/coreos/bbolt v1.3.1-coreos.6 // indirect github.com/coreos/etcd v3.3.10+incompatible - github.com/coreos/go-semver v0.2.0 // indirect - github.com/coreos/go-systemd v0.0.0-20181031085051-9002847aa142 // indirect - github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect - github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4 // indirect github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 - github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 // indirect github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 - github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 // indirect - github.com/cznic/y v0.0.0-20170802143616-045f81c6662a // indirect - github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/eapache/go-resiliency v1.1.0 // indirect - github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect - github.com/eapache/queue v0.0.0-20180227141424-093482f3f8ce // indirect - github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect github.com/etcd-io/gofail v0.0.0-20180808172546-51ce9a71510a - github.com/ghodss/yaml v1.0.0 // indirect github.com/go-sql-driver/mysql v0.0.0-20170715192408-3955978caca4 github.com/gogo/protobuf v1.1.1 // indirect - github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff // indirect - github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3 // indirect github.com/golang/protobuf v1.2.0 github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c - github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 - github.com/gorilla/websocket v1.2.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 - github.com/grpc-ecosystem/grpc-gateway v1.5.1 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jonboulle/clockwork v0.1.0 // indirect github.com/juju/errors v0.0.0-20181012004132-a4583d0a56ea // indirect - github.com/juju/loggo v0.0.0-20180524022052-584905176618 // indirect - github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073 // indirect github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 - github.com/kr/pretty v0.1.0 // indirect - github.com/kr/pty v1.1.3 // indirect - github.com/mattn/go-shellwords v1.0.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect - github.com/montanaflynn/stats v0.0.0-20180911141734-db72e6cae808 // indirect - github.com/myesui/uuid v1.0.0 // indirect - github.com/ngaut/log v0.0.0-20180314031856-b8e36e7ba5ac // indirect github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7 github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef - github.com/onsi/gomega v1.4.2 // indirect github.com/opentracing/basictracer-go v1.0.0 github.com/opentracing/opentracing-go v1.0.2 - github.com/petar/GoLLRB v0.0.0-20130427215148-53be0d36a84c // indirect - github.com/pierrec/lz4 v2.0.5+incompatible // indirect - github.com/pierrec/xxHash v0.1.1 // indirect github.com/pingcap/check v0.0.0-20171206051426-1c287c953996 - github.com/pingcap/errcode v0.0.0-20180921232412-a1a7271709d9 // indirect github.com/pingcap/errors v0.11.0 github.com/pingcap/goleveldb v0.0.0-20171020122428-b9ff6c35079e github.com/pingcap/kvproto v0.0.0-20181105061835-1b5d69cd1d26 @@ -78,44 +37,14 @@ require ( github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 github.com/prometheus/common v0.0.0-20181020173914-7e9e6cabbd39 // indirect github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d // indirect - github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a // indirect github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 // indirect - github.com/satori/go.uuid v1.2.0 // indirect - github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect github.com/sirupsen/logrus v1.2.0 - github.com/soheilhy/cmux v0.1.4 // indirect github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 - github.com/spf13/cobra v0.0.2 // indirect - github.com/spf13/pflag v1.0.1 // indirect - github.com/syndtr/goleveldb v0.0.0-20180815032940-ae2bd5eed72d // indirect - github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect github.com/twinj/uuid v1.0.0 - github.com/uber-go/atomic v1.3.2 // indirect github.com/uber/jaeger-client-go v2.15.0+incompatible github.com/uber/jaeger-lib v1.5.0 // indirect - github.com/ugorji/go v1.1.1 // indirect - github.com/unrolled/render v0.0.0-20180914162206-b9786414de4d // indirect - github.com/urfave/negroni v1.0.0 // indirect - github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 // indirect - go.uber.org/atomic v1.3.2 // indirect - go.uber.org/multierr v1.1.0 // indirect - go.uber.org/zap v1.8.0 // indirect - golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 // indirect - golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 // indirect golang.org/x/net v0.0.0-20181029044818-c44066c5c816 - golang.org/x/oauth2 v0.0.0-20181031022657-8527f56f7107 // indirect - golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc // indirect golang.org/x/text v0.3.0 - golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2 // indirect - golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563 // indirect - google.golang.org/appengine v1.2.0 // indirect - google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2 // indirect google.golang.org/grpc v1.16.0 - gopkg.in/airbrake/gobrake.v2 v2.0.9 // indirect - gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect - gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2 // indirect - gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 - gopkg.in/stretchr/testify.v1 v1.2.2 // indirect - honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3 // indirect ) diff --git a/go.sum b/go.sum index 41f1dd3fdb6c2..02271d68a0a68 100644 --- a/go.sum +++ b/go.sum @@ -204,6 +204,7 @@ github.com/pingcap/pd v2.0.5+incompatible h1:nUTetzzM/tLbd03DoMB76AAvI57oYftNib9 github.com/pingcap/pd v2.0.5+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= 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 v0.0.0-20181105182855-379ee5b1915a/go.mod h1:tq1TVnaDUrh46KbB+oJA34Ob3eMbinTopWVzhX5Rj94= github.com/pingcap/tidb v2.0.8+incompatible/go.mod h1:I8C6jrPINP2rrVunTRd7C9fRRhQrtR43S1/CL5ix/yQ= github.com/pingcap/tidb-tools v0.0.0-20181025073300-5db58e3b7e66 h1:auCqWgjgklL7o7c3Pj5PaSOAd9hBZd3OwEyvGSEStnA= github.com/pingcap/tidb-tools v0.0.0-20181025073300-5db58e3b7e66/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= @@ -296,6 +297,8 @@ github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 h1:MPPkRncZLN9Kh4MEFmbnK4h3BD7AUmskWv2+EeZJCCs= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/zimulala/parser v0.0.0-20181108115726-650caa67be64 h1:QYGszvB1bmVsjvH6Id0AAnYXK9KUzSlbD8sbfaSf+Rw= +github.com/zimulala/parser v0.0.0-20181108115726-650caa67be64/go.mod h1:G69sWhUqZ6QkeOjLFa/d9eJsBxH7Y/JhkqOyvz1gZ3M= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= @@ -305,6 +308,7 @@ go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20150218234220-1351f936d976/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180503215945-1f94bef427e3 h1:+U/hI4i24Enhs+2BEMCN7wg16uT6entqa2mTg/PUKB8= golang.org/x/crypto v0.0.0-20180503215945-1f94bef427e3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16 h1:y6ce7gCWtnH+m3dCjzQ1PCuwl28DDIc3VNnvY29DlIA= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -326,6 +330,7 @@ golang.org/x/sys v0.0.0-20180501092740-78d5f264b493/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180510032850-7dfd1290c791 h1:fFK3O68ywqxh9kSJokoTlNlK0NSLZ66TYEOB+yqcOVs= golang.org/x/sys v0.0.0-20180510032850-7dfd1290c791/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181030150119-7e31e0c00fa0 h1:biUuj9O+0+XckRUCDzjoOGm6yFV5c0IHbm1ODP3e4Zw= @@ -348,6 +353,7 @@ google.golang.org/genproto v0.0.0-20170711235230-b0a3dcfcd1a9/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20170815003206-6b7d9516179c/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180427144745-86e600f69ee4 h1:0rk3/gV3HbvCeUzVMhdxV3TEVKMVPDnayjN7sYRmcxY= google.golang.org/genproto v0.0.0-20180427144745-86e600f69ee4/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2 h1:67iHsV9djwGdZpdZNbLuQj6FOzCaZe3w+vhLjn5AcFA= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index bf850652505d9..bdb3e49eee580 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -61,6 +61,12 @@ type ShowDDLJobQueries struct { JobIDs []int64 } +// ShowNextRowID is for showing the next global row ID. +type ShowNextRowID struct { + baseSchemaProducer + TableName *ast.TableName +} + // CheckTable is used for checking table data, built from the 'admin check table' statement. type CheckTable struct { baseSchemaProducer diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 88c746a528821..d1934c86b5d40 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -503,6 +503,10 @@ func (b *PlanBuilder) buildAdmin(as *ast.AdminStmt) (Plan, error) { p := &ChecksumTable{Tables: as.Tables} p.SetSchema(buildChecksumTableSchema()) ret = p + case ast.AdminShowNextRowID: + p := &ShowNextRowID{TableName: as.Tables[0]} + p.SetSchema(buildShowNextRowID()) + ret = p case ast.AdminShowDDL: p := &ShowDDL{} p.SetSchema(buildShowDDLFields()) @@ -762,6 +766,15 @@ func (b *PlanBuilder) buildAnalyze(as *ast.AnalyzeTableStmt) (Plan, error) { return b.buildAnalyzeTable(as) } +func buildShowNextRowID() *expression.Schema { + schema := expression.NewSchema(make([]*expression.Column, 0, 4)...) + schema.Append(buildColumn("", "DB_NAME", mysql.TypeVarchar, mysql.MaxDatabaseNameLength)) + schema.Append(buildColumn("", "TABLE_NAME", mysql.TypeVarchar, mysql.MaxTableNameLength)) + schema.Append(buildColumn("", "COLUMN_NAME", mysql.TypeVarchar, mysql.MaxColumnNameLength)) + schema.Append(buildColumn("", "NEXT_GLOBAL_ROW_ID", mysql.TypeLonglong, 4)) + return schema +} + func buildShowDDLFields() *expression.Schema { schema := expression.NewSchema(make([]*expression.Column, 0, 4)...) schema.Append(buildColumn("", "SCHEMA_VER", mysql.TypeLonglong, 4))