提交 7cc80d1a 编写于 作者: martianzhang's avatar martianzhang

vendor daily update

上级 34e7d796
...@@ -161,8 +161,6 @@ pingcap-parser: tidb ...@@ -161,8 +161,6 @@ pingcap-parser: tidb
.PHONY: vendor .PHONY: vendor
vendor: vitess pingcap-parser vendor: vitess pingcap-parser
# gometalinter # gometalinter
# 如果有不想改的lint问题可以使用metalinter.sh加黑名单
#@bash doc/example/metalinter.sh
.PHONY: lint .PHONY: lint
lint: build lint: build
@echo "$(CGREEN)Run linter check ...$(CEND)" @echo "$(CGREEN)Run linter check ...$(CEND)"
......
...@@ -78,6 +78,10 @@ soar -h ...@@ -78,6 +78,10 @@ soar -h
### 命令行参数配置DSN ### 命令行参数配置DSN
SOAR 最新版本已经使用`go-sql-driver`替代了`mymysql`,DSN将使用`go-sql-driver`格式并且保持向前兼容,请参考[go-sql-driver](https://github.com/go-sql-driver/mysql#dsn-data-source-name)文档。
**以下DSN格式不再推荐使用**
> 账号密码中如包含特殊符号(如:'@',':','/'等)可在配置文件中设置,存在特殊字符的情况不适合在命令行中使用。目前`soar`只支持 tcp 协议的 MySQL 数据库连接方式,如需要配置本机MySQL环境建议将`localhost`修改为'127.0.0.1',并检查对应的 'user'@'127.0.0.1' 账号是否存在。 > 账号密码中如包含特殊符号(如:'@',':','/'等)可在配置文件中设置,存在特殊字符的情况不适合在命令行中使用。目前`soar`只支持 tcp 协议的 MySQL 数据库连接方式,如需要配置本机MySQL环境建议将`localhost`修改为'127.0.0.1',并检查对应的 'user'@'127.0.0.1' 账号是否存在。
```bash ```bash
......
...@@ -370,7 +370,51 @@ type ColumnOption struct { ...@@ -370,7 +370,51 @@ type ColumnOption struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ColumnOption) Restore(ctx *RestoreCtx) error { func (n *ColumnOption) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") switch n.Tp {
case ColumnOptionNoOption:
return nil
case ColumnOptionPrimaryKey:
ctx.WriteKeyWord("PRIMARY KEY")
case ColumnOptionNotNull:
ctx.WriteKeyWord("NOT NULL")
case ColumnOptionAutoIncrement:
ctx.WriteKeyWord("AUTO_INCREMENT")
case ColumnOptionDefaultValue:
ctx.WriteKeyWord("DEFAULT ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption DefaultValue Expr")
}
case ColumnOptionUniqKey:
ctx.WriteKeyWord("UNIQUE KEY")
case ColumnOptionNull:
ctx.WriteKeyWord("NULL")
case ColumnOptionOnUpdate:
ctx.WriteKeyWord("ON UPDATE ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption ON UPDATE Expr")
}
case ColumnOptionFulltext:
return errors.New("TiDB Parser ignore the `ColumnOptionFulltext` type now")
case ColumnOptionComment:
ctx.WriteKeyWord("COMMENT ")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption COMMENT Expr")
}
case ColumnOptionGenerated:
ctx.WriteKeyWord("GENERATED ALWAYS AS")
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption GENERATED ALWAYS Expr")
}
ctx.WritePlain(")")
case ColumnOptionReference:
if err := n.Refer.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnOption ReferenceDef")
}
default:
return errors.New("An error occurred while splicing ColumnOption")
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -489,13 +533,18 @@ func (n *Constraint) Restore(ctx *RestoreCtx) error { ...@@ -489,13 +533,18 @@ func (n *Constraint) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("UNIQUE KEY") ctx.WriteKeyWord("UNIQUE KEY")
case ConstraintUniqIndex: case ConstraintUniqIndex:
ctx.WriteKeyWord("UNIQUE INDEX") ctx.WriteKeyWord("UNIQUE INDEX")
case ConstraintForeignKey:
ctx.WriteKeyWord("FOREIGN KEY")
case ConstraintFulltext: case ConstraintFulltext:
ctx.WriteKeyWord("FULLTEXT") ctx.WriteKeyWord("FULLTEXT")
} }
if n.Name != "" { if n.Tp == ConstraintForeignKey {
ctx.WriteKeyWord("CONSTRAINT ")
if n.Name != "" {
ctx.WriteName(n.Name)
ctx.WritePlain(" ")
}
ctx.WriteKeyWord("FOREIGN KEY ")
} else if n.Name != "" {
ctx.WritePlain(" ") ctx.WritePlain(" ")
ctx.WriteName(n.Name) ctx.WriteName(n.Name)
} }
...@@ -570,7 +619,22 @@ type ColumnDef struct { ...@@ -570,7 +619,22 @@ type ColumnDef struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ColumnDef) Restore(ctx *RestoreCtx) error { func (n *ColumnDef) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if err := n.Name.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnDef Name")
}
if n.Tp != nil {
ctx.WritePlain(" ")
if err := n.Tp.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing ColumnDef Type")
}
}
for i, options := range n.Options {
ctx.WritePlain(" ")
if err := options.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing ColumnDef ColumnOption: [%v]", i)
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -613,7 +677,73 @@ type CreateTableStmt struct { ...@@ -613,7 +677,73 @@ type CreateTableStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error { func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("CREATE TABLE ")
if n.IfNotExists {
ctx.WriteKeyWord("IF NOT EXISTS ")
}
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Table")
}
ctx.WritePlain(" ")
if n.ReferTable != nil {
ctx.WriteKeyWord("LIKE ")
if err := n.ReferTable.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt ReferTable")
}
}
if lenCols := len(n.Cols); lenCols > 0 {
ctx.WritePlain("(")
for i, col := range n.Cols {
if i > 0 {
ctx.WritePlain(",")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt ColumnDef: [%v]", i)
}
}
for i, constraint := range n.Constraints {
if i > 0 || lenCols >= 1 {
ctx.WritePlain(",")
}
if err := constraint.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt Constraints: [%v]", i)
}
}
ctx.WritePlain(")")
}
for i, option := range n.Options {
ctx.WritePlain(" ")
if err := option.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing CreateTableStmt TableOption: [%v]", i)
}
}
if n.Partition != nil {
ctx.WritePlain(" ")
if err := n.Partition.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Partition")
}
}
if n.Select != nil {
switch n.OnDuplicate {
case OnDuplicateCreateTableSelectError:
ctx.WriteKeyWord(" AS ")
case OnDuplicateCreateTableSelectIgnore:
ctx.WriteKeyWord(" IGNORE AS ")
case OnDuplicateCreateTableSelectReplace:
ctx.WriteKeyWord(" REPLACE AS ")
}
if err := n.Select.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing CreateTableStmt Select")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -822,7 +952,59 @@ type CreateViewStmt struct { ...@@ -822,7 +952,59 @@ type CreateViewStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateViewStmt) Restore(ctx *RestoreCtx) error { func (n *CreateViewStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("CREATE ")
if n.OrReplace {
ctx.WriteKeyWord("OR REPLACE ")
}
ctx.WriteKeyWord("ALGORITHM")
ctx.WritePlain(" = ")
ctx.WriteKeyWord(n.Algorithm.String())
ctx.WriteKeyWord(" DEFINER")
ctx.WritePlain(" = ")
// todo Use n.Definer.Restore(ctx) to replace this part
if n.Definer.CurrentUser {
ctx.WriteKeyWord("current_user")
} else {
ctx.WriteName(n.Definer.Username)
if n.Definer.Hostname != "" {
ctx.WritePlain("@")
ctx.WriteName(n.Definer.Hostname)
}
}
ctx.WriteKeyWord(" SQL SECURITY ")
ctx.WriteKeyWord(n.Security.String())
ctx.WriteKeyWord(" VIEW ")
if err := n.ViewName.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while create CreateViewStmt.ViewName")
}
for i, col := range n.Cols {
if i == 0 {
ctx.WritePlain(" (")
} else {
ctx.WritePlain(",")
}
ctx.WriteName(col.O)
if i == len(n.Cols)-1 {
ctx.WritePlain(")")
}
}
ctx.WriteKeyWord(" AS ")
if err := n.Select.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while create CreateViewStmt.Select")
}
if n.CheckOption != model.CheckOptionCascaded {
ctx.WriteKeyWord(" WITH ")
ctx.WriteKeyWord(n.CheckOption.String())
ctx.WriteKeyWord(" CHECK OPTION")
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -859,7 +1041,36 @@ type CreateIndexStmt struct { ...@@ -859,7 +1041,36 @@ type CreateIndexStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateIndexStmt) Restore(ctx *RestoreCtx) error { func (n *CreateIndexStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("CREATE ")
if n.Unique {
ctx.WriteKeyWord("UNIQUE ")
}
ctx.WriteKeyWord("INDEX ")
ctx.WriteName(n.IndexName)
ctx.WriteKeyWord(" ON ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CreateIndexStmt.Table")
}
ctx.WritePlain(" (")
for i, indexColName := range n.IndexColNames {
if i != 0 {
ctx.WritePlain(", ")
}
if err := indexColName.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateIndexStmt.IndexColNames: [%v]", i)
}
}
ctx.WritePlain(")")
if n.IndexOption.Tp != model.IndexTypeInvalid || n.IndexOption.KeyBlockSize > 0 || n.IndexOption.Comment != "" {
ctx.WritePlain(" ")
if err := n.IndexOption.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CreateIndexStmt.IndexOption")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -986,6 +1197,103 @@ type TableOption struct { ...@@ -986,6 +1197,103 @@ type TableOption struct {
UintValue uint64 UintValue uint64
} }
func (n *TableOption) Restore(ctx *RestoreCtx) error {
switch n.Tp {
case TableOptionEngine:
ctx.WriteKeyWord("ENGINE ")
ctx.WritePlain("= ")
if n.StrValue != "" {
ctx.WritePlain(n.StrValue)
} else {
ctx.WritePlain("''")
}
case TableOptionCharset:
ctx.WriteKeyWord("DEFAULT CHARACTER SET ")
ctx.WritePlain("= ")
ctx.WriteKeyWord(n.StrValue)
case TableOptionCollate:
ctx.WriteKeyWord("DEFAULT COLLATE ")
ctx.WritePlain("= ")
ctx.WriteKeyWord(n.StrValue)
case TableOptionAutoIncrement:
ctx.WriteKeyWord("AUTO_INCREMENT ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionComment:
ctx.WriteKeyWord("COMMENT ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionAvgRowLength:
ctx.WriteKeyWord("AVG_ROW_LENGTH ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionCheckSum:
ctx.WriteKeyWord("CHECKSUM ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionCompression:
ctx.WriteKeyWord("COMPRESSION ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionConnection:
ctx.WriteKeyWord("CONNECTION ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionPassword:
ctx.WriteKeyWord("PASSWORD ")
ctx.WritePlain("= ")
ctx.WriteString(n.StrValue)
case TableOptionKeyBlockSize:
ctx.WriteKeyWord("KEY_BLOCK_SIZE ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionMaxRows:
ctx.WriteKeyWord("MAX_ROWS ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionMinRows:
ctx.WriteKeyWord("MIN_ROWS ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionDelayKeyWrite:
ctx.WriteKeyWord("DELAY_KEY_WRITE ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionRowFormat:
ctx.WriteKeyWord("ROW_FORMAT ")
ctx.WritePlain("= ")
switch n.UintValue {
case RowFormatDefault:
ctx.WriteKeyWord("DEFAULT")
case RowFormatDynamic:
ctx.WriteKeyWord("DYNAMIC")
case RowFormatFixed:
ctx.WriteKeyWord("FIXED")
case RowFormatCompressed:
ctx.WriteKeyWord("COMPRESSED")
case RowFormatRedundant:
ctx.WriteKeyWord("REDUNDANT")
case RowFormatCompact:
ctx.WriteKeyWord("COMPACT")
default:
return errors.Errorf("invalid TableOption: TableOptionRowFormat: %d", n.UintValue)
}
case TableOptionStatsPersistent:
// TODO: not support
ctx.WritePlain(" /* TableOptionStatsPersistent is not supported */ ")
case TableOptionShardRowID:
ctx.WriteKeyWord("SHARD_ROW_ID_BITS ")
ctx.WritePlain("= ")
ctx.WritePlainf("%d", n.UintValue)
case TableOptionPackKeys:
// TODO: not support
ctx.WritePlain(" /* TableOptionPackKeys is not supported */ ")
default:
return errors.Errorf("invalid TableOption: %d", n.Tp)
}
return nil
}
// ColumnPositionType is the type for ColumnPosition. // ColumnPositionType is the type for ColumnPosition.
type ColumnPositionType int type ColumnPositionType int
...@@ -1072,6 +1380,20 @@ const ( ...@@ -1072,6 +1380,20 @@ const (
// See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html#alter-table-concurrency // See https://dev.mysql.com/doc/refman/5.7/en/alter-table.html#alter-table-concurrency
type LockType byte type LockType byte
func (n LockType) String() string {
switch n {
case LockTypeNone:
return "NONE"
case LockTypeDefault:
return "DEFAULT"
case LockTypeShared:
return "SHARED"
case LockTypeExclusive:
return "EXCLUSIVE"
}
return ""
}
// Lock Types. // Lock Types.
const ( const (
LockTypeNone LockType = iota + 1 LockTypeNone LockType = iota + 1
...@@ -1102,7 +1424,159 @@ type AlterTableSpec struct { ...@@ -1102,7 +1424,159 @@ type AlterTableSpec struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error { func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") switch n.Tp {
case AlterTableOption:
switch {
case len(n.Options) == 2 &&
n.Options[0].Tp == TableOptionCharset &&
n.Options[1].Tp == TableOptionCollate:
ctx.WriteKeyWord("CONVERT TO CHARACTER SET ")
ctx.WriteKeyWord(n.Options[0].StrValue)
ctx.WriteKeyWord(" COLLATE ")
ctx.WriteKeyWord(n.Options[1].StrValue)
default:
for i, opt := range n.Options {
if i != 0 {
ctx.WritePlain(", ")
}
if err := opt.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.Options[%d]", i)
}
}
}
case AlterTableAddColumns:
ctx.WriteKeyWord("ADD COLUMN ")
if n.Position != nil && len(n.NewColumns) == 1 {
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.NewColumns[%d]", 0)
}
if n.Position.Tp != ColumnPositionNone {
ctx.WritePlain(" ")
}
if err := n.Position.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position")
}
} else {
ctx.WritePlain("(")
for i, col := range n.NewColumns {
if i != 0 {
ctx.WritePlain(", ")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.NewColumns[%d]", i)
}
}
ctx.WritePlain(")")
}
case AlterTableAddConstraint:
ctx.WriteKeyWord("ADD ")
if err := n.Constraint.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Constraint")
}
case AlterTableDropColumn:
ctx.WriteKeyWord("DROP COLUMN ")
if err := n.OldColumnName.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.OldColumnName")
}
// TODO: RestrictOrCascadeOpt not support
case AlterTableDropPrimaryKey:
ctx.WriteKeyWord("DROP PRIMARY KEY")
case AlterTableDropIndex:
ctx.WriteKeyWord("DROP INDEX ")
ctx.WriteName(n.Name)
case AlterTableDropForeignKey:
ctx.WriteKeyWord("DROP FOREIGN KEY ")
ctx.WriteName(n.Name)
case AlterTableModifyColumn:
ctx.WriteKeyWord("MODIFY COLUMN ")
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]")
}
if n.Position.Tp != ColumnPositionNone {
ctx.WritePlain(" ")
}
if err := n.Position.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position")
}
case AlterTableChangeColumn:
ctx.WriteKeyWord("CHANGE COLUMN ")
if err := n.OldColumnName.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.OldColumnName")
}
ctx.WritePlain(" ")
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]")
}
if n.Position.Tp != ColumnPositionNone {
ctx.WritePlain(" ")
}
if err := n.Position.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.Position")
}
case AlterTableRenameTable:
ctx.WriteKeyWord("RENAME AS ")
if err := n.NewTable.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewTable")
}
case AlterTableAlterColumn:
ctx.WriteKeyWord("ALTER COLUMN ")
if err := n.NewColumns[0].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0]")
}
if len(n.NewColumns[0].Options) == 1 {
ctx.WriteKeyWord("SET DEFAULT ")
if err := n.NewColumns[0].Options[0].Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableSpec.NewColumns[0].Options[0].Expr")
}
} else {
ctx.WriteKeyWord(" DROP DEFAULT")
}
case AlterTableLock:
ctx.WriteKeyWord("LOCK ")
ctx.WritePlain("= ")
ctx.WriteKeyWord(n.LockType.String())
case AlterTableAlgorithm:
// TODO: not support
ctx.WritePlain(" /* AlterTableAlgorithm is not supported */ ")
case AlterTableRenameIndex:
ctx.WriteKeyWord("RENAME INDEX ")
ctx.WriteName(n.FromKey.O)
ctx.WriteKeyWord(" TO ")
ctx.WriteName(n.ToKey.O)
case AlterTableForce:
// TODO: not support
ctx.WritePlain(" /* AlterTableForce is not supported */ ")
case AlterTableAddPartitions:
ctx.WriteKeyWord("ADD PARTITION")
if n.PartDefinitions != nil {
ctx.WritePlain(" (")
for i, def := range n.PartDefinitions {
if i != 0 {
ctx.WritePlain(", ")
}
if err := def.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableSpec.PartDefinitions[%d]", i)
}
}
ctx.WritePlain(")")
} else if n.Num != 0 {
ctx.WriteKeyWord(" PARTITIONS ")
ctx.WritePlainf("%d", n.Num)
}
case AlterTableCoalescePartitions:
ctx.WriteKeyWord("COALESCE PARTITION ")
ctx.WritePlainf("%d", n.Num)
case AlterTableDropPartition:
ctx.WriteKeyWord("DROP PARTITION ")
ctx.WriteName(n.Name)
case AlterTableTruncatePartition:
ctx.WriteKeyWord("TRUNCATE PARTITION ")
ctx.WriteName(n.Name)
default:
// TODO: not support
ctx.WritePlainf(" /* AlterTableType(%d) is not supported */ ", n.Tp)
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1161,7 +1635,21 @@ type AlterTableStmt struct { ...@@ -1161,7 +1635,21 @@ type AlterTableStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *AlterTableStmt) Restore(ctx *RestoreCtx) error { func (n *AlterTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("ALTER TABLE ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterTableStmt.Table")
}
for i, spec := range n.Specs {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
if err := spec.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterTableStmt.Specs[%d]", i)
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1226,6 +1714,28 @@ type PartitionDefinition struct { ...@@ -1226,6 +1714,28 @@ type PartitionDefinition struct {
Comment string Comment string
} }
// Restore implements Node interface.
func (n *PartitionDefinition) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PARTITION ")
ctx.WriteName(n.Name.O)
if n.LessThan != nil {
ctx.WriteKeyWord(" VALUES LESS THAN ")
ctx.WritePlain("(")
for k, less := range n.LessThan {
if err := less.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PartitionDefinition.LessThan[%d]", k)
}
}
ctx.WritePlain(")")
}
if n.Comment != "" {
ctx.WriteKeyWord(" COMMENT ")
ctx.WritePlain("= ")
ctx.WriteString(n.Comment)
}
return nil
}
// PartitionOptions specifies the partition options. // PartitionOptions specifies the partition options.
type PartitionOptions struct { type PartitionOptions struct {
Tp model.PartitionType Tp model.PartitionType
...@@ -1234,3 +1744,52 @@ type PartitionOptions struct { ...@@ -1234,3 +1744,52 @@ type PartitionOptions struct {
Definitions []*PartitionDefinition Definitions []*PartitionDefinition
Num uint64 Num uint64
} }
func (n *PartitionOptions) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("PARTITION BY ")
switch n.Tp {
case model.PartitionTypeRange:
ctx.WriteKeyWord("RANGE ")
case model.PartitionTypeHash:
ctx.WriteKeyWord("HASH ")
case model.PartitionTypeList:
return errors.New("TiDB Parser ignore the `PartitionTypeList` type now")
default:
return errors.Errorf("invalid model.PartitionType: %d", n.Tp)
}
ctx.WritePlain("(")
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PartitionOptions Expr")
}
ctx.WritePlain(") ")
for i, col := range n.ColumnNames {
if i > 0 {
ctx.WritePlain(",")
}
if err := col.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions ColumnName: [%v]", i)
}
}
if n.Num > 0 {
ctx.WriteKeyWord("PARTITIONS ")
ctx.WritePlainf("%d", n.Num)
}
if len(n.Definitions) > 0 {
ctx.WritePlain("(")
for i, def := range n.Definitions {
if i > 0 {
ctx.WritePlain(",")
}
if err := def.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while splicing PartitionOptions Definitions: [%v]", i)
}
}
ctx.WritePlain(")")
}
return nil
}
...@@ -183,7 +183,8 @@ type TableName struct { ...@@ -183,7 +183,8 @@ type TableName struct {
DBInfo *model.DBInfo DBInfo *model.DBInfo
TableInfo *model.TableInfo TableInfo *model.TableInfo
IndexHints []*IndexHint IndexHints []*IndexHint
PartitionNames []model.CIStr
} }
// Restore implements Node interface. // Restore implements Node interface.
...@@ -756,7 +757,110 @@ type SelectStmt struct { ...@@ -756,7 +757,110 @@ type SelectStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *SelectStmt) Restore(ctx *RestoreCtx) error { func (n *SelectStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord("SELECT ")
if n.SelectStmtOpts.Priority > 0 {
ctx.WriteKeyWord(mysql.Priority2Str[n.SelectStmtOpts.Priority])
ctx.WritePlain(" ")
}
if !n.SelectStmtOpts.SQLCache {
ctx.WriteKeyWord("SQL_NO_CACHE ")
}
if n.TableHints != nil && len(n.TableHints) != 0 {
ctx.WritePlain("/*+ ")
for i, tableHint := range n.TableHints {
if err := tableHint.Restore(ctx); err != nil {
errors.Annotatef(err, "An error occurred while restore SelectStmt.TableHints[%d]", i)
}
}
ctx.WritePlain("*/ ")
}
if n.Distinct {
ctx.WriteKeyWord("DISTINCT ")
}
if n.SelectStmtOpts.StraightJoin {
ctx.WriteKeyWord("STRAIGHT_JOIN ")
}
if n.Fields != nil {
for i, field := range n.Fields.Fields {
if i != 0 {
ctx.WritePlain(",")
}
if err := field.Restore(ctx); err != nil {
errors.Annotatef(err, "An error occurred while restore SelectStmt.Fields[%d]", i)
}
}
}
if n.From != nil {
ctx.WriteKeyWord(" FROM ")
if err := n.From.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.From")
}
}
if n.From == nil && n.Where != nil {
ctx.WriteKeyWord(" FROM DUAL")
}
if n.Where != nil {
ctx.WriteKeyWord(" WHERE ")
if err := n.Where.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.Where")
}
}
if n.GroupBy != nil {
ctx.WritePlain(" ")
if err := n.GroupBy.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.GroupBy")
}
}
if n.Having != nil {
ctx.WritePlain(" ")
if err := n.Having.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.Having")
}
}
if n.WindowSpecs != nil {
ctx.WriteKeyWord(" WINDOW ")
for i, windowsSpec := range n.WindowSpecs {
if i != 0 {
ctx.WritePlain(",")
}
if err := windowsSpec.Restore(ctx); err != nil {
errors.Annotatef(err, "An error occurred while restore SelectStmt.WindowSpec[%d]", i)
}
}
}
if n.OrderBy != nil {
ctx.WritePlain(" ")
if err := n.OrderBy.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.OrderBy")
}
}
if n.Limit != nil {
ctx.WritePlain(" ")
if err := n.Limit.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore SelectStmt.Limit")
}
}
switch n.LockTp {
case SelectLockInShareMode:
ctx.WriteKeyWord(" LOCK ")
ctx.WriteKeyWord(n.LockTp.String())
case SelectLockForUpdate:
ctx.WritePlain(" ")
ctx.WriteKeyWord(n.LockTp.String())
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -855,7 +959,24 @@ type UnionSelectList struct { ...@@ -855,7 +959,24 @@ type UnionSelectList struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UnionSelectList) Restore(ctx *RestoreCtx) error { func (n *UnionSelectList) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") for i, selectStmt := range n.Selects {
if i != 0 {
ctx.WriteKeyWord(" UNION ")
if !selectStmt.IsAfterUnionDistinct {
ctx.WriteKeyWord("ALL ")
}
}
if selectStmt.IsInBraces {
ctx.WritePlain("(")
}
if err := selectStmt.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionSelectList.SelectStmt")
}
if selectStmt.IsInBraces {
ctx.WritePlain(")")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -888,7 +1009,24 @@ type UnionStmt struct { ...@@ -888,7 +1009,24 @@ type UnionStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UnionStmt) Restore(ctx *RestoreCtx) error { func (n *UnionStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if err := n.SelectList.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionStmt.SelectList")
}
if n.OrderBy != nil {
ctx.WritePlain(" ")
if err := n.OrderBy.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionStmt.OrderBy")
}
}
if n.Limit != nil {
ctx.WritePlain(" ")
if err := n.Limit.Restore(ctx); err != nil {
errors.Annotate(err, "An error occurred while restore UnionStmt.Limit")
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1037,7 +1175,90 @@ type InsertStmt struct { ...@@ -1037,7 +1175,90 @@ type InsertStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *InsertStmt) Restore(ctx *RestoreCtx) error { func (n *InsertStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if n.IsReplace {
ctx.WriteKeyWord("REPLACE ")
} else {
ctx.WriteKeyWord("INSERT ")
}
switch n.Priority {
case mysql.LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY ")
case mysql.HighPriority:
ctx.WriteKeyWord("HIGH_PRIORITY ")
case mysql.DelayedPriority:
ctx.WriteKeyWord("DELAYED ")
}
if n.IgnoreErr {
ctx.WriteKeyWord("IGNORE ")
}
ctx.WriteKeyWord("INTO ")
if err := n.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore InsertStmt.Table")
}
if n.Columns != nil {
ctx.WritePlain(" (")
for i, v := range n.Columns {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.Columns[%d]", i)
}
}
ctx.WritePlain(")")
}
if n.Lists != nil {
ctx.WriteKeyWord(" VALUES ")
for i, row := range n.Lists {
if i != 0 {
ctx.WritePlain(",")
}
ctx.WritePlain("(")
for j, v := range row {
if j != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.Lists[%d][%d]", i, j)
}
}
ctx.WritePlain(")")
}
}
if n.Select != nil {
switch v := n.Select.(type) {
case *SelectStmt, *UnionStmt:
if err := v.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore InsertStmt.Select")
}
default:
return errors.Errorf("Incorrect type for InsertStmt.Select: %T", v)
}
}
if n.Setlist != nil {
ctx.WriteKeyWord(" SET ")
for i, v := range n.Setlist {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.Setlist[%d]", i)
}
}
}
if n.OnDuplicate != nil {
ctx.WriteKeyWord(" ON DUPLICATE KEY UPDATE ")
for i, v := range n.OnDuplicate {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore InsertStmt.OnDuplicate[%d]", i)
}
}
}
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
...@@ -1311,6 +1532,7 @@ const ( ...@@ -1311,6 +1532,7 @@ const (
ShowMasterStatus ShowMasterStatus
ShowPrivileges ShowPrivileges
ShowErrors ShowErrors
ShowBindings
) )
// ShowStmt is a statement to provide information about databases, tables, columns and so on. // ShowStmt is a statement to provide information about databases, tables, columns and so on.
......
...@@ -158,7 +158,7 @@ func (n *BinaryOperationExpr) Restore(ctx *RestoreCtx) error { ...@@ -158,7 +158,7 @@ func (n *BinaryOperationExpr) Restore(ctx *RestoreCtx) error {
if err := n.L.Restore(ctx); err != nil { if err := n.L.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.L") return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.L")
} }
if err := n.Op.Restore(ctx.In); err != nil { if err := n.Op.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.Op") return errors.Annotate(err, "An error occurred when restore BinaryOperationExpr.Op")
} }
if err := n.R.Restore(ctx); err != nil { if err := n.R.Restore(ctx); err != nil {
...@@ -347,7 +347,12 @@ type SubqueryExpr struct { ...@@ -347,7 +347,12 @@ type SubqueryExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *SubqueryExpr) Restore(ctx *RestoreCtx) error { func (n *SubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WritePlain("(")
if err := n.Query.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore SubqueryExpr.Query")
}
ctx.WritePlain(")")
return nil
} }
// Format the ExprNode into a Writer. // Format the ExprNode into a Writer.
...@@ -388,7 +393,21 @@ type CompareSubqueryExpr struct { ...@@ -388,7 +393,21 @@ type CompareSubqueryExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CompareSubqueryExpr) Restore(ctx *RestoreCtx) error { func (n *CompareSubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") if err := n.L.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.L")
}
if err := n.Op.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.Op")
}
if n.All {
ctx.WriteKeyWord("ALL ")
} else {
ctx.WriteKeyWord("ANY ")
}
if err := n.R.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore CompareSubqueryExpr.R")
}
return nil
} }
// Format the ExprNode into a Writer. // Format the ExprNode into a Writer.
...@@ -615,21 +634,22 @@ func (n *PatternInExpr) Restore(ctx *RestoreCtx) error { ...@@ -615,21 +634,22 @@ func (n *PatternInExpr) Restore(ctx *RestoreCtx) error {
} else { } else {
ctx.WriteKeyWord(" IN ") ctx.WriteKeyWord(" IN ")
} }
ctx.WritePlain("(")
for i, expr := range n.List {
if i != 0 {
ctx.WritePlain(",")
}
if err := expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PatternInExpr.List[%d]", i)
}
}
if n.Sel != nil { if n.Sel != nil {
if err := n.Sel.Restore(ctx); err != nil { if err := n.Sel.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PatternInExpr.Sel") return errors.Annotate(err, "An error occurred while restore PatternInExpr.Sel")
} }
} else {
ctx.WritePlain("(")
for i, expr := range n.List {
if i != 0 {
ctx.WritePlain(",")
}
if err := expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PatternInExpr.List[%d]", i)
}
}
ctx.WritePlain(")")
} }
ctx.WritePlain(")")
return nil return nil
} }
...@@ -817,6 +837,12 @@ func (n *PatternLikeExpr) Restore(ctx *RestoreCtx) error { ...@@ -817,6 +837,12 @@ func (n *PatternLikeExpr) Restore(ctx *RestoreCtx) error {
return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Pattern") return errors.Annotate(err, "An error occurred while restore PatternLikeExpr.Pattern")
} }
escape := string(n.Escape)
if escape != "\\" {
ctx.WriteKeyWord(" ESCAPE ")
ctx.WriteString(escape)
}
return nil return nil
} }
...@@ -1071,7 +1097,7 @@ type UnaryOperationExpr struct { ...@@ -1071,7 +1097,7 @@ type UnaryOperationExpr struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UnaryOperationExpr) Restore(ctx *RestoreCtx) error { func (n *UnaryOperationExpr) Restore(ctx *RestoreCtx) error {
if err := n.Op.Restore(ctx.In); err != nil { if err := n.Op.Restore(ctx); err != nil {
return errors.Trace(err) return errors.Trace(err)
} }
if err := n.V.Restore(ctx); err != nil { if err := n.V.Restore(ctx); err != nil {
......
...@@ -16,6 +16,7 @@ package ast ...@@ -16,6 +16,7 @@ package ast
import ( import (
"fmt" "fmt"
"io" "io"
"strings"
"github.com/pingcap/errors" "github.com/pingcap/errors"
. "github.com/pingcap/parser/format" . "github.com/pingcap/parser/format"
...@@ -340,15 +341,7 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error { ...@@ -340,15 +341,7 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error {
} }
ctx.WriteKeyWord(" USING ") ctx.WriteKeyWord(" USING ")
ctx.WriteKeyWord(n.Args[1].GetType().Charset) ctx.WriteKeyWord(n.Args[1].GetType().Charset)
case "adddate": case "adddate", "subdate", "date_add", "date_sub":
if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
ctx.WritePlain(", ")
if err := n.Args[1].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
case "date_add":
if err := n.Args[0].Restore(ctx); err != nil { if err := n.Args[0].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr") return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
} }
...@@ -413,6 +406,15 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error { ...@@ -413,6 +406,15 @@ func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr") return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
} }
} }
case "timestampdiff", "timestampadd":
ctx.WriteKeyWord(n.Args[0].(ValueExpr).GetString())
for i := 1; i < len(n.Args); {
ctx.WritePlain(", ")
if err := n.Args[i].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FuncCallExpr")
}
i++
}
default: default:
for i, argv := range n.Args { for i, argv := range n.Args {
if i != 0 { if i != 0 {
...@@ -644,12 +646,28 @@ func (n *AggregateFuncExpr) Restore(ctx *RestoreCtx) error { ...@@ -644,12 +646,28 @@ func (n *AggregateFuncExpr) Restore(ctx *RestoreCtx) error {
if n.Distinct { if n.Distinct {
ctx.WriteKeyWord("DISTINCT ") ctx.WriteKeyWord("DISTINCT ")
} }
for i, argv := range n.Args { switch strings.ToLower(n.F) {
if i != 0 { case "group_concat":
ctx.WritePlain(", ") for i := 0; i < len(n.Args)-1; i++ {
if i != 0 {
ctx.WritePlain(", ")
}
if err := n.Args[i].Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args[%d]", i)
}
}
ctx.WriteKeyWord(" SEPARATOR ")
if err := n.Args[len(n.Args)-1].Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AggregateFuncExpr.Args SEPARATOR")
} }
if err := argv.Restore(ctx); err != nil { default:
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args %d", i) for i, argv := range n.Args {
if i != 0 {
ctx.WritePlain(", ")
}
if err := argv.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AggregateFuncExpr.Args[%d]", i)
}
} }
} }
ctx.WritePlain(")") ctx.WritePlain(")")
......
...@@ -44,6 +44,8 @@ var ( ...@@ -44,6 +44,8 @@ var (
_ StmtNode = &UseStmt{} _ StmtNode = &UseStmt{}
_ StmtNode = &FlushStmt{} _ StmtNode = &FlushStmt{}
_ StmtNode = &KillStmt{} _ StmtNode = &KillStmt{}
_ StmtNode = &CreateBindingStmt{}
_ StmtNode = &DropBindingStmt{}
_ Node = &PrivElem{} _ Node = &PrivElem{}
_ Node = &VariableAssignment{} _ Node = &VariableAssignment{}
...@@ -685,6 +687,64 @@ func (n *DropUserStmt) Accept(v Visitor) (Node, bool) { ...@@ -685,6 +687,64 @@ func (n *DropUserStmt) Accept(v Visitor) (Node, bool) {
return v.Leave(n) return v.Leave(n)
} }
// CreateBindingStmt creates sql binding hint.
type CreateBindingStmt struct {
stmtNode
GlobalScope bool
OriginSel StmtNode
HintedSel StmtNode
}
func (n *CreateBindingStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
func (n *CreateBindingStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*CreateBindingStmt)
selnode, ok := n.OriginSel.Accept(v)
if !ok {
return n, false
}
n.OriginSel = selnode.(*SelectStmt)
hintedSelnode, ok := n.HintedSel.Accept(v)
if !ok {
return n, false
}
n.HintedSel = hintedSelnode.(*SelectStmt)
return v.Leave(n)
}
// DropBindingStmt deletes sql binding hint.
type DropBindingStmt struct {
stmtNode
GlobalScope bool
OriginSel StmtNode
}
func (n *DropBindingStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
func (n *DropBindingStmt) Accept(v Visitor) (Node, bool) {
newNode, skipChildren := v.Enter(n)
if skipChildren {
return v.Leave(newNode)
}
n = newNode.(*DropBindingStmt)
selnode, ok := n.OriginSel.Accept(v)
if !ok {
return n, false
}
n.OriginSel = selnode.(*SelectStmt)
return v.Leave(n)
}
// DoStmt is the struct for DO statement. // DoStmt is the struct for DO statement.
type DoStmt struct { type DoStmt struct {
stmtNode stmtNode
...@@ -985,7 +1045,20 @@ type TableOptimizerHint struct { ...@@ -985,7 +1045,20 @@ type TableOptimizerHint struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *TableOptimizerHint) Restore(ctx *RestoreCtx) error { func (n *TableOptimizerHint) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented") ctx.WriteKeyWord(n.HintName.String())
ctx.WritePlain("(")
if n.HintName.L == "max_execution_time" {
ctx.WritePlainf("%d", n.MaxExecutionTime)
} else {
for i, table := range n.Tables {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WriteName(table.String())
}
}
ctx.WritePlain(")")
return nil
} }
// Accept implements Node Accept interface. // Accept implements Node Accept interface.
......
...@@ -19,3 +19,12 @@ jobs: ...@@ -19,3 +19,12 @@ jobs:
- run: - run:
name: "Build & Test" name: "Build & Test"
command: make test command: make test
- run:
name: "Integration Test"
command: |
cd /go/src/github.com/pingcap/
git clone git@github.com:pingcap/tidb.git
cd tidb
rm go.sum
GO111MODULE=on go mod edit -replace github.com/pingcap/parser=github.com/${CIRCLE_PR_USERNAME:-$CIRCLE_PROJECT_USERNAME}/${CIRCLE_PR_REPONAME:-$CIRCLE_PROJECT_REPONAME}@$CIRCLE_BRANCH
make test
...@@ -2,15 +2,15 @@ module github.com/pingcap/parser ...@@ -2,15 +2,15 @@ module github.com/pingcap/parser
require ( require (
github.com/cznic/golex v0.0.0-20181122101858-9c343928389c // indirect github.com/cznic/golex v0.0.0-20181122101858-9c343928389c // indirect
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548
github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186
github.com/cznic/y v0.0.0-20170802143616-045f81c6662a github.com/cznic/y v0.0.0-20170802143616-045f81c6662a
github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8
github.com/pingcap/errors v0.11.0 github.com/pingcap/errors v0.11.0
github.com/pingcap/tidb v0.0.0-20180108134023-971629b9477a github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7
github.com/sirupsen/logrus v1.2.0 github.com/sirupsen/logrus v1.2.0
golang.org/x/text v0.3.0 golang.org/x/text v0.3.0
) )
...@@ -23,12 +23,14 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp ...@@ -23,12 +23,14 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cznic/golex v0.0.0-20181122101858-9c343928389c h1:G8zTsaqyVfIHpgMFcGgdbhHSFhlNc77rAKkhVbQ9kQg= github.com/cznic/golex v0.0.0-20181122101858-9c343928389c h1:G8zTsaqyVfIHpgMFcGgdbhHSFhlNc77rAKkhVbQ9kQg=
github.com/cznic/golex v0.0.0-20181122101858-9c343928389c/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= github.com/cznic/golex v0.0.0-20181122101858-9c343928389c/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc=
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7 h1:y+DH9ARrWiiNBV+6waYP2IPcsRbxdU1qsnycPfShF4c=
github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/cznic/mathutil v0.0.0-20181021201202-eba54fb065b7/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 h1:uWcWCkSP+E1w1z8r082miT+c+9vzg+5UdrgGCo15lMo= github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1 h1:uWcWCkSP+E1w1z8r082miT+c+9vzg+5UdrgGCo15lMo=
github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM= github.com/cznic/parser v0.0.0-20160622100904-31edd927e5b1/go.mod h1:2B43mz36vGZNZEwkWi8ayRSSUXLfjL8OkbzwW4NcPMM=
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65 h1:hxuZop6tSoOi0sxFzoGGYdRqNrPubyaIf9KoBG9tPiE=
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8 h1:LpMLYGyy67BoAFGda1NeOBQwqlv7nUXpm+rIVHGxZZ4=
github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 h1:0rkFMAbn5KBKNpJyHQ6Prb95vIKanmAe62KxsrN+sqA= github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186 h1:0rkFMAbn5KBKNpJyHQ6Prb95vIKanmAe62KxsrN+sqA=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
github.com/cznic/y v0.0.0-20170802143616-045f81c6662a h1:N2rDAvHuM46OGscJkGX4Dw4BBqZgg6mGNGLYs5utVVo= github.com/cznic/y v0.0.0-20170802143616-045f81c6662a h1:N2rDAvHuM46OGscJkGX4Dw4BBqZgg6mGNGLYs5utVVo=
...@@ -119,13 +121,14 @@ github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c/go.mod h1:Ja9XPjot ...@@ -119,13 +121,14 @@ github.com/pingcap/kvproto v0.0.0-20181203065228-c14302da291c/go.mod h1:Ja9XPjot
github.com/pingcap/parser v0.0.0-20190108044100-02812c3c22e7/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/parser v0.0.0-20190108044100-02812c3c22e7/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 h1:/buwGk04aHO5odk/+O8ZOXGs4qkUjYTJ2UpCJXna8NE=
github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E=
github.com/pingcap/tidb v0.0.0-20180108134023-971629b9477a h1:+UaU3bgZJtmgn1IJOWQU63z+HaVNhOfyxT8puMZ32rc= github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319 h1:ltRU5YUxYpW29ywVKnFXIRRTnY6r2cYxauB79L5gU2E=
github.com/pingcap/tidb v0.0.0-20180108134023-971629b9477a/go.mod h1:ytMJRc0YwJxWtwJpuu60xXIXHSTGwi1jhmt3TnxifYw= github.com/pingcap/tidb v0.0.0-20190108123336-c68ee7318319/go.mod h1:qXpdYNt83vgSegvc/TNcxKGiAo4Pa4EtIJl0ka7yGXE=
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible h1:Bsd+NHosPVowEGB3BCx+2d8wUQGDTXSSC5ljeNS6cXo= github.com/pingcap/tidb-tools v2.1.3-0.20190104033906-883b07a04a73+incompatible h1:Ba48wwPwPq5hd1kkQpgua49dqB5cthC2zXVo7fUUDec=
github.com/pingcap/tidb-tools v2.1.1-0.20181218072513-b2235d442b06+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= github.com/pingcap/tidb-tools v2.1.3-0.20190104033906-883b07a04a73+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM=
github.com/pingcap/tipb v0.0.0-20170310053819-1043caee48da/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pingcap/tipb v0.0.0-20170310053819-1043caee48da/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI=
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323 h1:mRKKzRjDNaUNPnAkPAHnRqpNmwNWBX1iA+hxlmvQ93I=
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI=
github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7 h1:wnjdQRhybddDesBVBKyOLUPgDaOFdtqA92pduBgWvVQ=
github.com/pingcap/tipb v0.0.0-20190107072121-abbec73437b7/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
......
...@@ -533,6 +533,8 @@ var tokenMap = map[string]int{ ...@@ -533,6 +533,8 @@ var tokenMap = map[string]int{
"YEAR": yearType, "YEAR": yearType,
"YEAR_MONTH": yearMonth, "YEAR_MONTH": yearMonth,
"ZEROFILL": zerofill, "ZEROFILL": zerofill,
"BINDING": binding,
"BINDINGS": bindings,
} }
// See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details // See https://dev.mysql.com/doc/refman/5.7/en/function-resolution.html for details
......
...@@ -511,6 +511,11 @@ func (m SQLMode) HasNoAutoCreateUserMode() bool { ...@@ -511,6 +511,11 @@ func (m SQLMode) HasNoAutoCreateUserMode() bool {
return m&ModeNoAutoCreateUser == ModeNoAutoCreateUser return m&ModeNoAutoCreateUser == ModeNoAutoCreateUser
} }
// HasAllowInvalidDatesMode detects if 'ALLOW_INVALID_DATES' mode is set in SQLMode
func (m SQLMode) HasAllowInvalidDatesMode() bool {
return m&ModeAllowInvalidDates == ModeAllowInvalidDates
}
// consts for sql modes. // consts for sql modes.
const ( const (
ModeNone SQLMode = 0 ModeNone SQLMode = 0
...@@ -546,6 +551,7 @@ const ( ...@@ -546,6 +551,7 @@ const (
ModeHighNotPrecedence ModeHighNotPrecedence
ModeNoEngineSubstitution ModeNoEngineSubstitution
ModePadCharToFullLength ModePadCharToFullLength
ModeAllowInvalidDates
) )
// FormatSQLModeStr re-format 'SQL_MODE' variable. // FormatSQLModeStr re-format 'SQL_MODE' variable.
...@@ -623,6 +629,7 @@ var Str2SQLMode = map[string]SQLMode{ ...@@ -623,6 +629,7 @@ var Str2SQLMode = map[string]SQLMode{
"HIGH_NOT_PRECEDENCE": ModeHighNotPrecedence, "HIGH_NOT_PRECEDENCE": ModeHighNotPrecedence,
"NO_ENGINE_SUBSTITUTION": ModeNoEngineSubstitution, "NO_ENGINE_SUBSTITUTION": ModeNoEngineSubstitution,
"PAD_CHAR_TO_FULL_LENGTH": ModePadCharToFullLength, "PAD_CHAR_TO_FULL_LENGTH": ModePadCharToFullLength,
"ALLOW_INVALID_DATES": ModeAllowInvalidDates,
} }
// CombinationSQLMode is the special modes that provided as shorthand for combinations of mode values. // CombinationSQLMode is the special modes that provided as shorthand for combinations of mode values.
......
...@@ -915,9 +915,18 @@ const ( ...@@ -915,9 +915,18 @@ const (
ErrWindowFunctionIgnoresFrame = 3599 ErrWindowFunctionIgnoresFrame = 3599
// TiDB self-defined errors. // TiDB self-defined errors.
ErrMemExceedThreshold = 8001 ErrMemExceedThreshold = 8001
ErrForUpdateCantRetry = 8002 ErrForUpdateCantRetry = 8002
ErrAdminCheckTable = 8003 ErrAdminCheckTable = 8003
ErrInvalidPluginID = 8101
ErrInvalidPluginManifest = 8102
ErrInvalidPluginName = 8103
ErrInvalidPluginVersion = 8104
ErrDuplicatePlugin = 8105
ErrInvalidPluginSysVarName = 8106
ErrRequireVersionCheckFail = 8107
ErrUnsupportedReloadPlugin = 8018
ErrUnsupportedReloadPluginVar = 8019
// TiKV/PD errors. // TiKV/PD errors.
ErrPDServerTimeout = 9001 ErrPDServerTimeout = 9001
......
...@@ -916,6 +916,16 @@ var MySQLErrName = map[uint16]string{ ...@@ -916,6 +916,16 @@ var MySQLErrName = map[uint16]string{
ErrForUpdateCantRetry: "[%d] can not retry select for update statement", ErrForUpdateCantRetry: "[%d] can not retry select for update statement",
ErrAdminCheckTable: "TiDB admin check table failed.", ErrAdminCheckTable: "TiDB admin check table failed.",
ErrInvalidPluginID: "Wrong plugin id: %s, valid plugin id is [name]-[version], both name and version should not contain '-'",
ErrInvalidPluginManifest: "Cannot read plugin %s's manifest",
ErrInvalidPluginName: "Plugin load with %s but got wrong name %s",
ErrInvalidPluginVersion: "Plugin load with %s but got %s",
ErrDuplicatePlugin: "Plugin [%s] is redeclared",
ErrInvalidPluginSysVarName: "Plugin %s's sysVar %s must start with its plugin name %s",
ErrRequireVersionCheckFail: "Plugin %s require %s be %v but got %v",
ErrUnsupportedReloadPlugin: "Plugin %s isn't loaded so cannot be reloaded",
ErrUnsupportedReloadPluginVar: "Reload plugin with different sysVar is unsupported %v",
// TiKV/PD errors. // TiKV/PD errors.
ErrPDServerTimeout: "PD server timeout", ErrPDServerTimeout: "PD server timeout",
ErrTiKVServerTimeout: "TiKV server timeout", ErrTiKVServerTimeout: "TiKV server timeout",
......
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
"io" "io"
"github.com/pingcap/errors" "github.com/pingcap/errors"
. "github.com/pingcap/parser/format"
) )
// Op is opcode type. // Op is opcode type.
...@@ -102,9 +103,9 @@ func (o Op) String() string { ...@@ -102,9 +103,9 @@ func (o Op) String() string {
} }
var opsLiteral = map[Op]string{ var opsLiteral = map[Op]string{
LogicAnd: "&&", LogicAnd: " AND ",
LogicOr: "||", LogicOr: " OR ",
LogicXor: "^", LogicXor: " XOR ",
LeftShift: "<<", LeftShift: "<<",
RightShift: ">>", RightShift: ">>",
GE: ">=", GE: ">=",
...@@ -140,9 +141,9 @@ func (o Op) Format(w io.Writer) { ...@@ -140,9 +141,9 @@ func (o Op) Format(w io.Writer) {
} }
// Restore the Op into a Writer // Restore the Op into a Writer
func (o Op) Restore(w io.Writer) error { func (o Op) Restore(ctx *RestoreCtx) error {
if v, ok := opsLiteral[o]; ok { if v, ok := opsLiteral[o]; ok {
fmt.Fprint(w, v) ctx.WriteKeyWord(v)
return nil return nil
} }
return errors.Errorf("Invalid opcode type %d during restoring AST to SQL text", o) return errors.Errorf("Invalid opcode type %d during restoring AST to SQL text", o)
......
...@@ -423,6 +423,8 @@ import ( ...@@ -423,6 +423,8 @@ import (
value "VALUE" value "VALUE"
variables "VARIABLES" variables "VARIABLES"
view "VIEW" view "VIEW"
binding "BINDING"
bindings "BINDINGS"
warnings "WARNINGS" warnings "WARNINGS"
identSQLErrors "ERRORS" identSQLErrors "ERRORS"
week "WEEK" week "WEEK"
...@@ -573,6 +575,7 @@ import ( ...@@ -573,6 +575,7 @@ import (
CreateUserStmt "CREATE User statement" CreateUserStmt "CREATE User statement"
CreateDatabaseStmt "Create Database Statement" CreateDatabaseStmt "Create Database Statement"
CreateIndexStmt "CREATE INDEX statement" CreateIndexStmt "CREATE INDEX statement"
CreateBindingStmt "CREATE BINDING statement"
DoStmt "Do statement" DoStmt "Do statement"
DropDatabaseStmt "DROP DATABASE statement" DropDatabaseStmt "DROP DATABASE statement"
DropIndexStmt "DROP INDEX statement" DropIndexStmt "DROP INDEX statement"
...@@ -580,6 +583,7 @@ import ( ...@@ -580,6 +583,7 @@ import (
DropTableStmt "DROP TABLE statement" DropTableStmt "DROP TABLE statement"
DropUserStmt "DROP USER" DropUserStmt "DROP USER"
DropViewStmt "DROP VIEW statement" DropViewStmt "DROP VIEW statement"
DropBindingStmt "DROP BINDING statement"
DeallocateStmt "Deallocate prepared statement" DeallocateStmt "Deallocate prepared statement"
DeleteFromStmt "DELETE FROM statement" DeleteFromStmt "DELETE FROM statement"
EmptyStmt "empty statement" EmptyStmt "empty statement"
...@@ -723,6 +727,7 @@ import ( ...@@ -723,6 +727,7 @@ import (
PartitionDefinitionListOpt "Partition definition list option" PartitionDefinitionListOpt "Partition definition list option"
PartitionOpt "Partition option" PartitionOpt "Partition option"
PartitionNameList "Partition name list" PartitionNameList "Partition name list"
PartitionNameListOpt "table partition names list optional"
PartitionNumOpt "PARTITION NUM option" PartitionNumOpt "PARTITION NUM option"
PartDefValuesOpt "VALUES {LESS THAN {(expr | value_list) | MAXVALUE} | IN {value_list}" PartDefValuesOpt "VALUES {LESS THAN {(expr | value_list) | MAXVALUE} | IN {value_list}"
PartDefOptionsOpt "PartDefOptionList option" PartDefOptionsOpt "PartDefOptionList option"
...@@ -1084,7 +1089,7 @@ AlterTableSpec: ...@@ -1084,7 +1089,7 @@ AlterTableSpec:
Tp: ast.AlterTableDropPartition, Tp: ast.AlterTableDropPartition,
Name: $3, Name: $3,
} }
} }
| "TRUNCATE" "PARTITION" Identifier | "TRUNCATE" "PARTITION" Identifier
{ {
$$ = &ast.AlterTableSpec{ $$ = &ast.AlterTableSpec{
...@@ -2988,7 +2993,7 @@ UnReservedKeyword: ...@@ -2988,7 +2993,7 @@ UnReservedKeyword:
| "COLLATION" | "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MASTER" | "MAX_ROWS" | "COLLATION" | "COMMENT" | "AVG_ROW_LENGTH" | "CONNECTION" | "CHECKSUM" | "COMPRESSION" | "KEY_BLOCK_SIZE" | "MASTER" | "MAX_ROWS"
| "MIN_ROWS" | "NATIONAL" | "ROW_FORMAT" | "QUARTER" | "GRANTS" | "TRIGGERS" | "DELAY_KEY_WRITE" | "ISOLATION" | "JSON" | "MIN_ROWS" | "NATIONAL" | "ROW_FORMAT" | "QUARTER" | "GRANTS" | "TRIGGERS" | "DELAY_KEY_WRITE" | "ISOLATION" | "JSON"
| "REPEATABLE" | "RESPECT" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES" | "SQL_CACHE" | "INDEXES" | "PROCESSLIST" | "REPEATABLE" | "RESPECT" | "COMMITTED" | "UNCOMMITTED" | "ONLY" | "SERIALIZABLE" | "LEVEL" | "VARIABLES" | "SQL_CACHE" | "INDEXES" | "PROCESSLIST"
| "SQL_NO_CACHE" | "DISABLE" | "ENABLE" | "REVERSE" | "PRIVILEGES" | "NO" | "BINLOG" | "FUNCTION" | "VIEW" | "MODIFY" | "EVENTS" | "PARTITIONS" | "SQL_NO_CACHE" | "DISABLE" | "ENABLE" | "REVERSE" | "PRIVILEGES" | "NO" | "BINLOG" | "FUNCTION" | "VIEW" | "BINDING" | "BINDINGS" | "MODIFY" | "EVENTS" | "PARTITIONS"
| "NONE" | "NULLS" | "SUPER" | "EXCLUSIVE" | "STATS_PERSISTENT" | "ROW_COUNT" | "COALESCE" | "MONTH" | "PROCESS" | "PROFILES" | "NONE" | "NULLS" | "SUPER" | "EXCLUSIVE" | "STATS_PERSISTENT" | "ROW_COUNT" | "COALESCE" | "MONTH" | "PROCESS" | "PROFILES"
| "MICROSECOND" | "MINUTE" | "PLUGINS" | "PRECEDING" | "QUERY" | "QUERIES" | "SECOND" | "SEPARATOR" | "SHARE" | "SHARED" | "SLOW" | "MAX_CONNECTIONS_PER_HOUR" | "MAX_QUERIES_PER_HOUR" | "MAX_UPDATES_PER_HOUR" | "MICROSECOND" | "MINUTE" | "PLUGINS" | "PRECEDING" | "QUERY" | "QUERIES" | "SECOND" | "SEPARATOR" | "SHARE" | "SHARED" | "SLOW" | "MAX_CONNECTIONS_PER_HOUR" | "MAX_QUERIES_PER_HOUR" | "MAX_UPDATES_PER_HOUR"
| "MAX_USER_CONNECTIONS" | "REPLICATION" | "CLIENT" | "SLAVE" | "RELOAD" | "TEMPORARY" | "ROUTINE" | "EVENT" | "ALGORITHM" | "DEFINER" | "INVOKER" | "MERGE" | "TEMPTABLE" | "UNDEFINED" | "SECURITY" | "CASCADED" | "RECOVER" | "MAX_USER_CONNECTIONS" | "REPLICATION" | "CLIENT" | "SLAVE" | "RELOAD" | "TEMPORARY" | "ROUTINE" | "EVENT" | "ALGORITHM" | "DEFINER" | "INVOKER" | "MERGE" | "TEMPTABLE" | "UNDEFINED" | "SECURITY" | "CASCADED" | "RECOVER"
...@@ -4937,11 +4942,12 @@ TableRef: ...@@ -4937,11 +4942,12 @@ TableRef:
} }
TableFactor: TableFactor:
TableName TableAsNameOpt IndexHintListOpt TableName PartitionNameListOpt TableAsNameOpt IndexHintListOpt
{ {
tn := $1.(*ast.TableName) tn := $1.(*ast.TableName)
tn.IndexHints = $3.([]*ast.IndexHint) tn.PartitionNames = $2.([]model.CIStr)
$$ = &ast.TableSource{Source: tn, AsName: $2.(model.CIStr)} tn.IndexHints = $4.([]*ast.IndexHint)
$$ = &ast.TableSource{Source: tn, AsName: $3.(model.CIStr)}
} }
| '(' SelectStmt ')' TableAsName | '(' SelectStmt ')' TableAsName
{ {
...@@ -4959,6 +4965,16 @@ TableFactor: ...@@ -4959,6 +4965,16 @@ TableFactor:
$$ = $2 $$ = $2
} }
PartitionNameListOpt:
/* empty */
{
$$ = []model.CIStr{}
}
| "PARTITION" '(' PartitionNameList ')'
{
$$ = $3
}
TableAsNameOpt: TableAsNameOpt:
{ {
$$ = model.CIStr{} $$ = model.CIStr{}
...@@ -5764,11 +5780,26 @@ AdminStmt: ...@@ -5764,11 +5780,26 @@ AdminStmt:
Index: string($5), Index: string($5),
} }
} }
| "ADMIN" "RESTORE" "TABLE" "BY" "JOB" NumList | "ADMIN" "RESTORE" "TABLE" "BY" "JOB" NUM
{ {
$$ = &ast.AdminStmt{ $$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable, Tp: ast.AdminRestoreTable,
JobIDs: $6.([]int64), JobIDs: []int64{$6.(int64)},
}
}
| "ADMIN" "RESTORE" "TABLE" TableName
{
$$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable,
Tables: []*ast.TableName{$4.(*ast.TableName)},
}
}
| "ADMIN" "RESTORE" "TABLE" TableName NUM
{
$$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable,
Tables: []*ast.TableName{$4.(*ast.TableName)},
JobNumber: $5.(int64),
} }
} }
| "ADMIN" "CLEANUP" "INDEX" TableName Identifier | "ADMIN" "CLEANUP" "INDEX" TableName Identifier
...@@ -6102,6 +6133,13 @@ ShowTargetFilterable: ...@@ -6102,6 +6133,13 @@ ShowTargetFilterable:
GlobalScope: $1.(bool), GlobalScope: $1.(bool),
} }
} }
| GlobalScope "BINDINGS"
{
$$ = &ast.ShowStmt{
Tp: ast.ShowBindings,
GlobalScope: $1.(bool),
}
}
| "COLLATION" | "COLLATION"
{ {
$$ = &ast.ShowStmt{ $$ = &ast.ShowStmt{
...@@ -6277,6 +6315,7 @@ Statement: ...@@ -6277,6 +6315,7 @@ Statement:
| CreateTableStmt | CreateTableStmt
| CreateViewStmt | CreateViewStmt
| CreateUserStmt | CreateUserStmt
| CreateBindingStmt
| DoStmt | DoStmt
| DropDatabaseStmt | DropDatabaseStmt
| DropIndexStmt | DropIndexStmt
...@@ -6284,6 +6323,7 @@ Statement: ...@@ -6284,6 +6323,7 @@ Statement:
| DropViewStmt | DropViewStmt
| DropUserStmt | DropUserStmt
| DropStatsStmt | DropStatsStmt
| DropBindingStmt
| FlushStmt | FlushStmt
| GrantStmt | GrantStmt
| InsertIntoStmt | InsertIntoStmt
...@@ -7285,6 +7325,55 @@ HashString: ...@@ -7285,6 +7325,55 @@ HashString:
$$ = $1 $$ = $1
} }
/*******************************************************************
*
* Create Binding Statement
*
* Example:
* CREATE GLOBAL BINDING FOR select Col1,Col2 from table USING select Col1,Col2 from table use index(Col1)
*******************************************************************/
CreateBindingStmt:
"CREATE" GlobalScope "BINDING" "FOR" SelectStmt "USING" SelectStmt
{
startOffset := parser.startOffset(&yyS[yypt-2])
endOffset := parser.startOffset(&yyS[yypt-1])
selStmt := $5.(*ast.SelectStmt)
selStmt.SetText(strings.TrimSpace(parser.src[startOffset:endOffset]))
startOffset = parser.startOffset(&yyS[yypt])
hintedSelStmt := $7.(*ast.SelectStmt)
hintedSelStmt.SetText(strings.TrimSpace(parser.src[startOffset:]))
x := &ast.CreateBindingStmt {
OriginSel: selStmt,
HintedSel: hintedSelStmt,
GlobalScope: $2.(bool),
}
$$ = x
}
/*******************************************************************
*
* Drop Binding Statement
*
* Example:
* DROP GLOBAL BINDING FOR select Col1,Col2 from table
*******************************************************************/
DropBindingStmt:
"DROP" GlobalScope "BINDING" "FOR" SelectStmt
{
startOffset := parser.startOffset(&yyS[yypt])
selStmt := $5.(*ast.SelectStmt)
selStmt.SetText(strings.TrimSpace(parser.src[startOffset:]))
x := &ast.DropBindingStmt {
OriginSel: selStmt,
GlobalScope: $2.(bool),
}
$$ = x
}
/************************************************************************************* /*************************************************************************************
* Grant statement * Grant statement
* See https://dev.mysql.com/doc/refman/5.7/en/grant.html * See https://dev.mysql.com/doc/refman/5.7/en/grant.html
......
...@@ -82,6 +82,7 @@ const ( ...@@ -82,6 +82,7 @@ const (
ClassJSON ClassJSON
ClassTiKV ClassTiKV
ClassSession ClassSession
ClassPlugin
// Add more as needed. // Add more as needed.
) )
...@@ -109,6 +110,7 @@ var errClz2Str = map[ErrClass]string{ ...@@ -109,6 +110,7 @@ var errClz2Str = map[ErrClass]string{
ClassJSON: "json", ClassJSON: "json",
ClassTiKV: "tikv", ClassTiKV: "tikv",
ClassSession: "session", ClassSession: "session",
ClassPlugin: "plugin",
} }
// String implements fmt.Stringer interface. // String implements fmt.Stringer interface.
......
...@@ -195,6 +195,61 @@ func (ft *FieldType) String() string { ...@@ -195,6 +195,61 @@ func (ft *FieldType) String() string {
return strings.Join(strs, " ") return strings.Join(strs, " ")
} }
// Restore implements Node interface.
func (ft *FieldType) Restore(ctx *format.RestoreCtx) error {
ctx.WriteKeyWord(TypeToStr(ft.Tp, ft.Charset))
switch ft.Tp {
case mysql.TypeEnum, mysql.TypeSet:
ctx.WritePlain("(")
for i, e := range ft.Elems {
if i != 0 {
ctx.WritePlain(",")
}
ctx.WriteString(e)
}
ctx.WritePlain(")")
case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDuration:
if ft.Flen > 0 && ft.Decimal > 0 {
ctx.WritePlainf("(%d)", ft.Decimal)
}
case mysql.TypeDouble, mysql.TypeFloat:
if ft.Flen > 0 && ft.Decimal > 0 {
ctx.WritePlainf("(%d,%d)", ft.Flen, ft.Decimal)
}
case mysql.TypeNewDecimal:
if ft.Flen > 0 && ft.Decimal > 0 {
ctx.WritePlainf("(%d,%d)", ft.Flen, ft.Decimal)
}
case mysql.TypeBit, mysql.TypeShort, mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeVarchar, mysql.TypeString, mysql.TypeVarString:
if ft.Flen > 0 {
ctx.WritePlainf("(%d)", ft.Flen)
}
}
if mysql.HasUnsignedFlag(ft.Flag) {
ctx.WriteKeyWord(" UNSIGNED")
}
if mysql.HasZerofillFlag(ft.Flag) {
ctx.WriteKeyWord(" ZEROFILL")
}
if mysql.HasBinaryFlag(ft.Flag) && ft.Charset != charset.CharsetBin {
ctx.WriteKeyWord(" BINARY")
}
if IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp) {
if ft.Charset != "" && ft.Charset != charset.CharsetBin {
ctx.WriteKeyWord(" CHARACTER SET " + ft.Charset)
}
if ft.Collate != "" && ft.Collate != charset.CharsetBin {
ctx.WriteKeyWord(" COLLATE ")
ctx.WritePlain(ft.Collate)
}
}
return nil
}
// FormatAsCastType is used for write AST back to string. // FormatAsCastType is used for write AST back to string.
func (ft *FieldType) FormatAsCastType(w io.Writer) { func (ft *FieldType) FormatAsCastType(w io.Writer) {
switch ft.Tp { switch ft.Tp {
......
...@@ -47,8 +47,10 @@ type StatementContext struct { ...@@ -47,8 +47,10 @@ type StatementContext struct {
// If IsDDLJobInQueue is true, it means the DDL job is in the queue of storage, and it can be handled by the DDL worker. // If IsDDLJobInQueue is true, it means the DDL job is in the queue of storage, and it can be handled by the DDL worker.
IsDDLJobInQueue bool IsDDLJobInQueue bool
InInsertStmt bool InInsertStmt bool
InUpdateOrDeleteStmt bool InUpdateStmt bool
InDeleteStmt bool
InSelectStmt bool InSelectStmt bool
InLoadDataStmt bool
IgnoreTruncate bool IgnoreTruncate bool
IgnoreZeroInDate bool IgnoreZeroInDate bool
DupKeyAsWarning bool DupKeyAsWarning bool
...@@ -61,6 +63,7 @@ type StatementContext struct { ...@@ -61,6 +63,7 @@ type StatementContext struct {
PadCharToFullLength bool PadCharToFullLength bool
BatchCheck bool BatchCheck bool
InNullRejectCheck bool InNullRejectCheck bool
AllowInvalidDate bool
// mu struct holds variables that change during execution. // mu struct holds variables that change during execution.
mu struct { mu struct {
...@@ -379,3 +382,21 @@ func (sc *StatementContext) GetExecDetails() execdetails.ExecDetails { ...@@ -379,3 +382,21 @@ func (sc *StatementContext) GetExecDetails() execdetails.ExecDetails {
sc.mu.Unlock() sc.mu.Unlock()
return details return details
} }
// ShouldClipToZero indicates whether values less than 0 should be clipped to 0 for unsigned integer types.
// This is the case for `insert`, `update`, `alter table` and `load data infile` statements, when not in strict SQL mode.
// see https://dev.mysql.com/doc/refman/5.7/en/out-of-range-and-overflow.html
func (sc *StatementContext) ShouldClipToZero() bool {
// TODO: Currently altering column of integer to unsigned integer is not supported.
// If it is supported one day, that case should be added here.
return sc.InInsertStmt || sc.InLoadDataStmt
}
// ShouldIgnoreOverflowError indicates whether we should ignore the error when type conversion overflows,
// so we can leave it for further processing like clipping values less than 0 to 0 for unsigned integer types.
func (sc *StatementContext) ShouldIgnoreOverflowError() bool {
if (sc.InInsertStmt && sc.TruncateAsWarning) || sc.InLoadDataStmt {
return true
}
return false
}
...@@ -106,7 +106,11 @@ func ConvertUintToInt(val uint64, upperBound int64, tp byte) (int64, error) { ...@@ -106,7 +106,11 @@ func ConvertUintToInt(val uint64, upperBound int64, tp byte) (int64, error) {
} }
// ConvertIntToUint converts an int value to an uint value. // ConvertIntToUint converts an int value to an uint value.
func ConvertIntToUint(val int64, upperBound uint64, tp byte) (uint64, error) { func ConvertIntToUint(sc *stmtctx.StatementContext, val int64, upperBound uint64, tp byte) (uint64, error) {
if sc.ShouldClipToZero() && val < 0 {
return 0, overflow(val, tp)
}
if uint64(val) > upperBound { if uint64(val) > upperBound {
return upperBound, overflow(val, tp) return upperBound, overflow(val, tp)
} }
...@@ -124,9 +128,12 @@ func ConvertUintToUint(val uint64, upperBound uint64, tp byte) (uint64, error) { ...@@ -124,9 +128,12 @@ func ConvertUintToUint(val uint64, upperBound uint64, tp byte) (uint64, error) {
} }
// ConvertFloatToUint converts a float value to an uint value. // ConvertFloatToUint converts a float value to an uint value.
func ConvertFloatToUint(fval float64, upperBound uint64, tp byte) (uint64, error) { func ConvertFloatToUint(sc *stmtctx.StatementContext, fval float64, upperBound uint64, tp byte) (uint64, error) {
val := RoundFloat(fval) val := RoundFloat(fval)
if val < 0 { if val < 0 {
if sc.ShouldClipToZero() {
return 0, overflow(val, tp)
}
return uint64(int64(val)), overflow(val, tp) return uint64(int64(val)), overflow(val, tp)
} }
...@@ -322,14 +329,12 @@ func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr st ...@@ -322,14 +329,12 @@ func floatStrToIntStr(sc *stmtctx.StatementContext, validFloat string, oriStr st
if intCnt <= 0 { if intCnt <= 0 {
intStr = "0" intStr = "0"
if intCnt == 0 && len(digits) > 0 { if intCnt == 0 && len(digits) > 0 {
dotIdx = -1
intStr = roundIntStr(digits[0], intStr) intStr = roundIntStr(digits[0], intStr)
} }
return intStr, nil return intStr, nil
} }
if intCnt == 1 && (digits[0] == '-' || digits[0] == '+') { if intCnt == 1 && (digits[0] == '-' || digits[0] == '+') {
intStr = "0" intStr = "0"
dotIdx = 0
if len(digits) > 1 { if len(digits) > 1 {
intStr = roundIntStr(digits[1], intStr) intStr = roundIntStr(digits[1], intStr)
} }
...@@ -400,7 +405,7 @@ func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned ...@@ -400,7 +405,7 @@ func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned
return ConvertFloatToInt(f, lBound, uBound, mysql.TypeDouble) return ConvertFloatToInt(f, lBound, uBound, mysql.TypeDouble)
} }
bound := UnsignedUpperBound[mysql.TypeLonglong] bound := UnsignedUpperBound[mysql.TypeLonglong]
u, err := ConvertFloatToUint(f, bound, mysql.TypeDouble) u, err := ConvertFloatToUint(sc, f, bound, mysql.TypeDouble)
return int64(u), errors.Trace(err) return int64(u), errors.Trace(err)
case json.TypeCodeString: case json.TypeCodeString:
return StrToInt(sc, hack.String(j.GetString())) return StrToInt(sc, hack.String(j.GetString()))
...@@ -423,7 +428,7 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6 ...@@ -423,7 +428,7 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6
case json.TypeCodeInt64: case json.TypeCodeInt64:
return float64(j.GetInt64()), nil return float64(j.GetInt64()), nil
case json.TypeCodeUint64: case json.TypeCodeUint64:
u, err := ConvertIntToUint(j.GetInt64(), UnsignedUpperBound[mysql.TypeLonglong], mysql.TypeLonglong) u, err := ConvertIntToUint(sc, j.GetInt64(), UnsignedUpperBound[mysql.TypeLonglong], mysql.TypeLonglong)
return float64(u), errors.Trace(err) return float64(u), errors.Trace(err)
case json.TypeCodeFloat64: case json.TypeCodeFloat64:
return j.GetFloat64(), nil return j.GetFloat64(), nil
......
...@@ -218,6 +218,12 @@ func (d *Datum) SetNull() { ...@@ -218,6 +218,12 @@ func (d *Datum) SetNull() {
d.x = nil d.x = nil
} }
// SetMinNotNull sets datum to minNotNull value.
func (d *Datum) SetMinNotNull() {
d.k = KindMinNotNull
d.x = nil
}
// GetBinaryLiteral gets Bit value // GetBinaryLiteral gets Bit value
func (d *Datum) GetBinaryLiteral() BinaryLiteral { func (d *Datum) GetBinaryLiteral() BinaryLiteral {
return d.b return d.b
...@@ -866,21 +872,21 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) ( ...@@ -866,21 +872,21 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (
) )
switch d.k { switch d.k {
case KindInt64: case KindInt64:
val, err = ConvertIntToUint(d.GetInt64(), upperBound, tp) val, err = ConvertIntToUint(sc, d.GetInt64(), upperBound, tp)
case KindUint64: case KindUint64:
val, err = ConvertUintToUint(d.GetUint64(), upperBound, tp) val, err = ConvertUintToUint(d.GetUint64(), upperBound, tp)
case KindFloat32, KindFloat64: case KindFloat32, KindFloat64:
val, err = ConvertFloatToUint(d.GetFloat64(), upperBound, tp) val, err = ConvertFloatToUint(sc, d.GetFloat64(), upperBound, tp)
case KindString, KindBytes: case KindString, KindBytes:
val, err = StrToUint(sc, d.GetString()) uval, err1 := StrToUint(sc, d.GetString())
if err != nil { if err1 != nil && ErrOverflow.Equal(err1) && !sc.ShouldIgnoreOverflowError() {
return ret, errors.Trace(err) return ret, errors.Trace(err1)
} }
val, err = ConvertUintToUint(val, upperBound, tp) val, err = ConvertUintToUint(uval, upperBound, tp)
if err != nil { if err != nil {
return ret, errors.Trace(err) return ret, errors.Trace(err)
} }
ret.SetUint64(val) err = err1
case KindMysqlTime: case KindMysqlTime:
dec := d.GetMysqlTime().ToNumber() dec := d.GetMysqlTime().ToNumber()
err = dec.Round(dec, 0, ModeHalfEven) err = dec.Round(dec, 0, ModeHalfEven)
...@@ -888,7 +894,7 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) ( ...@@ -888,7 +894,7 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (
if err == nil { if err == nil {
err = err1 err = err1
} }
val, err1 = ConvertIntToUint(ival, upperBound, tp) val, err1 = ConvertIntToUint(sc, ival, upperBound, tp)
if err == nil { if err == nil {
err = err1 err = err1
} }
...@@ -897,18 +903,18 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) ( ...@@ -897,18 +903,18 @@ func (d *Datum) convertToUint(sc *stmtctx.StatementContext, target *FieldType) (
err = dec.Round(dec, 0, ModeHalfEven) err = dec.Round(dec, 0, ModeHalfEven)
ival, err1 := dec.ToInt() ival, err1 := dec.ToInt()
if err1 == nil { if err1 == nil {
val, err = ConvertIntToUint(ival, upperBound, tp) val, err = ConvertIntToUint(sc, ival, upperBound, tp)
} }
case KindMysqlDecimal: case KindMysqlDecimal:
fval, err1 := d.GetMysqlDecimal().ToFloat64() fval, err1 := d.GetMysqlDecimal().ToFloat64()
val, err = ConvertFloatToUint(fval, upperBound, tp) val, err = ConvertFloatToUint(sc, fval, upperBound, tp)
if err == nil { if err == nil {
err = err1 err = err1
} }
case KindMysqlEnum: case KindMysqlEnum:
val, err = ConvertFloatToUint(d.GetMysqlEnum().ToNumber(), upperBound, tp) val, err = ConvertFloatToUint(sc, d.GetMysqlEnum().ToNumber(), upperBound, tp)
case KindMysqlSet: case KindMysqlSet:
val, err = ConvertFloatToUint(d.GetMysqlSet().ToNumber(), upperBound, tp) val, err = ConvertFloatToUint(sc, d.GetMysqlSet().ToNumber(), upperBound, tp)
case KindBinaryLiteral, KindMysqlBit: case KindBinaryLiteral, KindMysqlBit:
val, err = d.GetBinaryLiteral().ToInt(sc) val, err = d.GetBinaryLiteral().ToInt(sc)
case KindMysqlJSON: case KindMysqlJSON:
...@@ -1138,7 +1144,7 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem ...@@ -1138,7 +1144,7 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem
return nil, errors.Trace(err) return nil, errors.Trace(err)
} }
if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 { if !dec.IsZero() && frac > decimal && dec.Compare(&old) != 0 {
if sc.InInsertStmt || sc.InUpdateOrDeleteStmt { if sc.InInsertStmt || sc.InUpdateStmt || sc.InDeleteStmt {
// fix https://github.com/pingcap/tidb/issues/3895 // fix https://github.com/pingcap/tidb/issues/3895
// fix https://github.com/pingcap/tidb/issues/5532 // fix https://github.com/pingcap/tidb/issues/5532
sc.AppendWarning(ErrTruncated) sc.AppendWarning(ErrTruncated)
......
...@@ -217,7 +217,7 @@ func (bj BinaryJSON) objectSearchKey(key []byte) (BinaryJSON, bool) { ...@@ -217,7 +217,7 @@ func (bj BinaryJSON) objectSearchKey(key []byte) (BinaryJSON, bool) {
idx := sort.Search(elemCount, func(i int) bool { idx := sort.Search(elemCount, func(i int) bool {
return bytes.Compare(bj.objectGetKey(i), key) >= 0 return bytes.Compare(bj.objectGetKey(i), key) >= 0
}) })
if idx < elemCount && bytes.Compare(bj.objectGetKey(idx), key) == 0 { if idx < elemCount && bytes.Equal(bj.objectGetKey(idx), key) {
return bj.objectGetVal(idx), true return bj.objectGetVal(idx), true
} }
return BinaryJSON{}, false return BinaryJSON{}, false
......
...@@ -234,6 +234,23 @@ func (d *MyDecimal) removeLeadingZeros() (wordIdx int, digitsInt int) { ...@@ -234,6 +234,23 @@ func (d *MyDecimal) removeLeadingZeros() (wordIdx int, digitsInt int) {
return return
} }
func (d *MyDecimal) removeTrailingZeros() (lastWordIdx int, digitsFrac int) {
digitsFrac = int(d.digitsFrac)
i := ((digitsFrac - 1) % digitsPerWord) + 1
lastWordIdx = digitsToWords(int(d.digitsInt)) + digitsToWords(int(d.digitsFrac))
for digitsFrac > 0 && d.wordBuf[lastWordIdx-1] == 0 {
digitsFrac -= i
i = digitsPerWord
lastWordIdx--
}
if digitsFrac > 0 {
digitsFrac -= countTrailingZeroes(9-((digitsFrac-1)%digitsPerWord), d.wordBuf[lastWordIdx-1])
} else {
digitsFrac = 0
}
return
}
// ToString converts decimal to its printable string representation without rounding. // ToString converts decimal to its printable string representation without rounding.
// //
// RETURN VALUE // RETURN VALUE
...@@ -1212,6 +1229,26 @@ func (d *MyDecimal) ToBin(precision, frac int) ([]byte, error) { ...@@ -1212,6 +1229,26 @@ func (d *MyDecimal) ToBin(precision, frac int) ([]byte, error) {
return bin, err return bin, err
} }
// ToHashKey removes the leading and trailing zeros and generates a hash key.
// Two Decimals dec0 and dec1 with different fraction will generate the same hash keys if dec0.Compare(dec1) == 0.
func (d *MyDecimal) ToHashKey() ([]byte, error) {
_, digitsInt := d.removeLeadingZeros()
_, digitsFrac := d.removeTrailingZeros()
prec := digitsInt + digitsFrac
if prec == 0 { // zeroDecimal
prec = 1
}
buf, err := d.ToBin(prec, digitsFrac)
if err == ErrTruncated {
// This err is caused by shorter digitsFrac;
// After removing the trailing zeros from a Decimal,
// so digitsFrac may be less than the real digitsFrac of the Decimal,
// thus ErrTruncated may be raised, we can ignore it here.
err = nil
}
return buf, err
}
// PrecisionAndFrac returns the internal precision and frac number. // PrecisionAndFrac returns the internal precision and frac number.
func (d *MyDecimal) PrecisionAndFrac() (precision, frac int) { func (d *MyDecimal) PrecisionAndFrac() (precision, frac int) {
frac = int(d.digitsFrac) frac = int(d.digitsFrac)
...@@ -1326,7 +1363,6 @@ func (d *MyDecimal) FromBin(bin []byte, precision, frac int) (binSize int, err e ...@@ -1326,7 +1363,6 @@ func (d *MyDecimal) FromBin(bin []byte, precision, frac int) (binSize int, err e
*d = zeroMyDecimal *d = zeroMyDecimal
return binSize, ErrBadNumber return binSize, ErrBadNumber
} }
wordIdx++
} }
if d.digitsInt == 0 && d.digitsFrac == 0 { if d.digitsInt == 0 && d.digitsFrac == 0 {
...@@ -1760,7 +1796,7 @@ func DecimalMul(from1, from2, to *MyDecimal) error { ...@@ -1760,7 +1796,7 @@ func DecimalMul(from1, from2, to *MyDecimal) error {
wordsFracTo = wordsFrac1 + wordsFrac2 wordsFracTo = wordsFrac1 + wordsFrac2
idx1 = wordsInt1 idx1 = wordsInt1
idx2 = wordsInt2 idx2 = wordsInt2
idxTo = 0 idxTo int
tmp1 = wordsIntTo tmp1 = wordsIntTo
tmp2 = wordsFracTo tmp2 = wordsFracTo
) )
...@@ -1991,7 +2027,6 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error { ...@@ -1991,7 +2027,6 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error {
idxTo++ idxTo++
digitsIntTo++ digitsIntTo++
} }
digitsIntTo++
} }
i = digitsToWords(prec1) i = digitsToWords(prec1)
len1 := i + digitsToWords(2*frac2+fracIncr+1) + 1 len1 := i + digitsToWords(2*frac2+fracIncr+1) + 1
...@@ -2003,7 +2038,7 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error { ...@@ -2003,7 +2038,7 @@ func doDivMod(from1, from2, to, mod *MyDecimal, fracIncr int) error {
copy(tmp1, from1.wordBuf[idx1:idx1+i]) copy(tmp1, from1.wordBuf[idx1:idx1+i])
start1 := 0 start1 := 0
stop1 := len1 var stop1 int
start2 := idx2 start2 := idx2
stop2 := idx2 + digitsToWords(prec2) - 1 stop2 := idx2 + digitsToWords(prec2) - 1
......
...@@ -232,8 +232,7 @@ func (v weekBehaviour) test(flag weekBehaviour) bool { ...@@ -232,8 +232,7 @@ func (v weekBehaviour) test(flag weekBehaviour) bool {
} }
func weekMode(mode int) weekBehaviour { func weekMode(mode int) weekBehaviour {
var weekFormat weekBehaviour weekFormat := weekBehaviour(mode & 7)
weekFormat = weekBehaviour(mode & 7)
if (weekFormat & weekBehaviourMondayFirst) == 0 { if (weekFormat & weekBehaviourMondayFirst) == 0 {
weekFormat ^= weekBehaviourFirstWeekday weekFormat ^= weekBehaviourFirstWeekday
} }
......
...@@ -474,18 +474,20 @@ func (t *Time) FromPackedUint(packed uint64) error { ...@@ -474,18 +474,20 @@ func (t *Time) FromPackedUint(packed uint64) error {
// FIXME: See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date // FIXME: See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date
func (t *Time) check(sc *stmtctx.StatementContext) error { func (t *Time) check(sc *stmtctx.StatementContext) error {
allowZeroInDate := false allowZeroInDate := false
allowInvalidDate := false
// We should avoid passing sc as nil here as far as possible. // We should avoid passing sc as nil here as far as possible.
if sc != nil { if sc != nil {
allowZeroInDate = sc.IgnoreZeroInDate allowZeroInDate = sc.IgnoreZeroInDate
allowInvalidDate = sc.AllowInvalidDate
} }
var err error var err error
switch t.Type { switch t.Type {
case mysql.TypeTimestamp: case mysql.TypeTimestamp:
err = checkTimestampType(sc, t.Time) err = checkTimestampType(sc, t.Time)
case mysql.TypeDatetime: case mysql.TypeDatetime:
err = checkDatetimeType(t.Time, allowZeroInDate) err = checkDatetimeType(t.Time, allowZeroInDate, allowInvalidDate)
case mysql.TypeDate: case mysql.TypeDate:
err = checkDateType(t.Time, allowZeroInDate) err = checkDateType(t.Time, allowZeroInDate, allowInvalidDate)
} }
return errors.Trace(err) return errors.Trace(err)
} }
...@@ -1344,7 +1346,7 @@ func TimeFromDays(num int64) Time { ...@@ -1344,7 +1346,7 @@ func TimeFromDays(num int64) Time {
} }
} }
func checkDateType(t MysqlTime, allowZeroInDate bool) error { func checkDateType(t MysqlTime, allowZeroInDate, allowInvalidDate bool) error {
year, month, day := t.Year(), t.Month(), t.Day() year, month, day := t.Year(), t.Month(), t.Day()
if year == 0 && month == 0 && day == 0 { if year == 0 && month == 0 && day == 0 {
return nil return nil
...@@ -1358,7 +1360,7 @@ func checkDateType(t MysqlTime, allowZeroInDate bool) error { ...@@ -1358,7 +1360,7 @@ func checkDateType(t MysqlTime, allowZeroInDate bool) error {
return errors.Trace(err) return errors.Trace(err)
} }
if err := checkMonthDay(year, month, day); err != nil { if err := checkMonthDay(year, month, day, allowInvalidDate); err != nil {
return errors.Trace(err) return errors.Trace(err)
} }
...@@ -1377,17 +1379,19 @@ func checkDateRange(t MysqlTime) error { ...@@ -1377,17 +1379,19 @@ func checkDateRange(t MysqlTime) error {
return nil return nil
} }
func checkMonthDay(year, month, day int) error { func checkMonthDay(year, month, day int, allowInvalidDate bool) error {
if month < 0 || month > 12 { if month < 0 || month > 12 {
return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(month)) return errors.Trace(ErrInvalidTimeFormat.GenWithStackByArgs(month))
} }
maxDay := 31 maxDay := 31
if month > 0 { if !allowInvalidDate {
maxDay = maxDaysInMonth[month-1] if month > 0 {
} maxDay = maxDaysInMonth[month-1]
if month == 2 && year%4 != 0 { }
maxDay = 28 if month == 2 && year%4 != 0 {
maxDay = 28
}
} }
if day < 0 || day > maxDay { if day < 0 || day > maxDay {
...@@ -1427,8 +1431,8 @@ func checkTimestampType(sc *stmtctx.StatementContext, t MysqlTime) error { ...@@ -1427,8 +1431,8 @@ func checkTimestampType(sc *stmtctx.StatementContext, t MysqlTime) error {
return nil return nil
} }
func checkDatetimeType(t MysqlTime, allowZeroInDate bool) error { func checkDatetimeType(t MysqlTime, allowZeroInDate, allowInvalidDate bool) error {
if err := checkDateType(t, allowZeroInDate); err != nil { if err := checkDateType(t, allowZeroInDate, allowInvalidDate); err != nil {
return errors.Trace(err) return errors.Trace(err)
} }
...@@ -2027,10 +2031,7 @@ func (t *Time) StrToDate(sc *stmtctx.StatementContext, date, format string) bool ...@@ -2027,10 +2031,7 @@ func (t *Time) StrToDate(sc *stmtctx.StatementContext, date, format string) bool
t.Time = tm t.Time = tm
t.Type = mysql.TypeDatetime t.Type = mysql.TypeDatetime
if t.check(sc) != nil { return t.check(sc) == nil
return false
}
return true
} }
// mysqlTimeFix fixes the MysqlTime use the values in the context. // mysqlTimeFix fixes the MysqlTime use the values in the context.
......
...@@ -53,13 +53,13 @@ type CommitDetails struct { ...@@ -53,13 +53,13 @@ type CommitDetails struct {
func (d ExecDetails) String() string { func (d ExecDetails) String() string {
parts := make([]string, 0, 6) parts := make([]string, 0, 6)
if d.ProcessTime > 0 { if d.ProcessTime > 0 {
parts = append(parts, fmt.Sprintf("process_time:%v", d.ProcessTime)) parts = append(parts, fmt.Sprintf("process_time:%vs", d.ProcessTime.Seconds()))
} }
if d.WaitTime > 0 { if d.WaitTime > 0 {
parts = append(parts, fmt.Sprintf("wait_time:%v", d.WaitTime)) parts = append(parts, fmt.Sprintf("wait_time:%vs", d.WaitTime.Seconds()))
} }
if d.BackoffTime > 0 { if d.BackoffTime > 0 {
parts = append(parts, fmt.Sprintf("backoff_time:%v", d.BackoffTime)) parts = append(parts, fmt.Sprintf("backoff_time:%vs", d.BackoffTime.Seconds()))
} }
if d.RequestCount > 0 { if d.RequestCount > 0 {
parts = append(parts, fmt.Sprintf("request_count:%d", d.RequestCount)) parts = append(parts, fmt.Sprintf("request_count:%d", d.RequestCount))
...@@ -73,23 +73,23 @@ func (d ExecDetails) String() string { ...@@ -73,23 +73,23 @@ func (d ExecDetails) String() string {
commitDetails := d.CommitDetail commitDetails := d.CommitDetail
if commitDetails != nil { if commitDetails != nil {
if commitDetails.PrewriteTime > 0 { if commitDetails.PrewriteTime > 0 {
parts = append(parts, fmt.Sprintf("prewrite_time:%v", commitDetails.PrewriteTime)) parts = append(parts, fmt.Sprintf("prewrite_time:%vs", commitDetails.PrewriteTime.Seconds()))
} }
if commitDetails.CommitTime > 0 { if commitDetails.CommitTime > 0 {
parts = append(parts, fmt.Sprintf("commit_time:%v", commitDetails.CommitTime)) parts = append(parts, fmt.Sprintf("commit_time:%vs", commitDetails.CommitTime.Seconds()))
} }
if commitDetails.GetCommitTsTime > 0 { if commitDetails.GetCommitTsTime > 0 {
parts = append(parts, fmt.Sprintf("get_commit_ts_time:%v", commitDetails.GetCommitTsTime)) parts = append(parts, fmt.Sprintf("get_commit_ts_time:%vs", commitDetails.GetCommitTsTime.Seconds()))
} }
if commitDetails.TotalBackoffTime > 0 { if commitDetails.TotalBackoffTime > 0 {
parts = append(parts, fmt.Sprintf("total_backoff_time:%v", commitDetails.TotalBackoffTime)) parts = append(parts, fmt.Sprintf("total_backoff_time:%vs", commitDetails.TotalBackoffTime.Seconds()))
} }
resolveLockTime := atomic.LoadInt64(&commitDetails.ResolveLockTime) resolveLockTime := atomic.LoadInt64(&commitDetails.ResolveLockTime)
if resolveLockTime > 0 { if resolveLockTime > 0 {
parts = append(parts, fmt.Sprintf("resolve_lock_time:%d", time.Duration(resolveLockTime))) parts = append(parts, fmt.Sprintf("resolve_lock_time:%vs", time.Duration(resolveLockTime).Seconds()))
} }
if commitDetails.LocalLatchTime > 0 { if commitDetails.LocalLatchTime > 0 {
parts = append(parts, fmt.Sprintf("local_latch_wait_time:%v", commitDetails.LocalLatchTime)) parts = append(parts, fmt.Sprintf("local_latch_wait_time:%vs", commitDetails.LocalLatchTime.Seconds()))
} }
if commitDetails.WriteKeys > 0 { if commitDetails.WriteKeys > 0 {
parts = append(parts, fmt.Sprintf("write_keys:%d", commitDetails.WriteKeys)) parts = append(parts, fmt.Sprintf("write_keys:%d", commitDetails.WriteKeys))
......
...@@ -111,106 +111,106 @@ ...@@ -111,106 +111,106 @@
"revisionTime": "2018-10-24T15:10:47Z" "revisionTime": "2018-10-24T15:10:47Z"
}, },
{ {
"checksumSHA1": "DJypl3jfSRspsBR2fc6eyBktkq4=", "checksumSHA1": "cOEqkxoki8WzzrAKFDP1GvSufH4=",
"path": "github.com/pingcap/parser", "path": "github.com/pingcap/parser",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "+IqkkjB5E83Q1mUjZ1V+75iHocA=", "checksumSHA1": "jTB3MZ/p6/PeJDX5P0tw7C97J2I=",
"path": "github.com/pingcap/parser/ast", "path": "github.com/pingcap/parser/ast",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=", "checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=",
"path": "github.com/pingcap/parser/auth", "path": "github.com/pingcap/parser/auth",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=", "checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset", "path": "github.com/pingcap/parser/charset",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=", "checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=",
"path": "github.com/pingcap/parser/format", "path": "github.com/pingcap/parser/format",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "ZADwr2/PcEd9VI3XF9OvN4HkJ+8=", "checksumSHA1": "ZADwr2/PcEd9VI3XF9OvN4HkJ+8=",
"path": "github.com/pingcap/parser/model", "path": "github.com/pingcap/parser/model",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "ge+W5BLlgqKIlvmappsPTLgVJLk=", "checksumSHA1": "poSWMsB1ZV4Pi33qMq7Wb1mLmZ0=",
"path": "github.com/pingcap/parser/mysql", "path": "github.com/pingcap/parser/mysql",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "mxpiJJ3b08I0o0Sd2rJLYMwz7uw=", "checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=",
"path": "github.com/pingcap/parser/opcode", "path": "github.com/pingcap/parser/opcode",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "XvnUllvwMYd6HrMvMiKnn4cGN2M=", "checksumSHA1": "TF2rMYy9ewgZpFsJb+jaGXXqZqc=",
"path": "github.com/pingcap/parser/terror", "path": "github.com/pingcap/parser/terror",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "CpuZhpMNeho4tIFPwY2GUDvuEfQ=", "checksumSHA1": "sCYsaxxXBau10NOc5tuYQEtmAu0=",
"path": "github.com/pingcap/parser/types", "path": "github.com/pingcap/parser/types",
"revision": "35fab0be7fca9ea7f7b5350af83a8d1e2775abe4", "revision": "0321c0fc2a7b5bf3d019ac753e70b808961d4194",
"revisionTime": "2019-01-08T10:41:42Z" "revisionTime": "2019-01-16T08:50:57Z"
}, },
{ {
"checksumSHA1": "MxoLdFWi8nwd0uqTJnYqw+JaDAY=", "checksumSHA1": "uOrWw9c47zwN6COxonFJ0t2IMcM=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx", "path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "1PFyexjkPlACP5S2pRrT6TsjcQ0=", "checksumSHA1": "SxNV0h7Hb44wjJFvFmQ8daMSHyI=",
"path": "github.com/pingcap/tidb/types", "path": "github.com/pingcap/tidb/types",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "DWVD7+ygtT66IQ+cqXmMJ5OVqUk=", "checksumSHA1": "7PiTQPW4ftgZIg8KBGCHZjdc0hE=",
"path": "github.com/pingcap/tidb/types/json", "path": "github.com/pingcap/tidb/types/json",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=", "checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=",
"path": "github.com/pingcap/tidb/types/parser_driver", "path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "SS7twHZofFKr8w/pwIKmkp3u5qU=", "checksumSHA1": "OOig47D9TSVOUAYkNj2yJok1Hmo=",
"path": "github.com/pingcap/tidb/util/execdetails", "path": "github.com/pingcap/tidb/util/execdetails",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=", "checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=",
"path": "github.com/pingcap/tidb/util/hack", "path": "github.com/pingcap/tidb/util/hack",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=", "checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory", "path": "github.com/pingcap/tidb/util/memory",
"revision": "c68ee7318319b34fbad53d5abf18275b0273ae41", "revision": "47ea05d01781be5f1e751a68d4b5576f0fc0783d",
"revisionTime": "2019-01-08T12:33:36Z" "revisionTime": "2019-01-16T10:02:55Z"
}, },
{ {
"checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=", "checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=",
...@@ -407,62 +407,62 @@ ...@@ -407,62 +407,62 @@
{ {
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=", "checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2", "path": "vitess.io/vitess/go/bytes2",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=", "checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"path": "vitess.io/vitess/go/hack", "path": "vitess.io/vitess/go/hack",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=", "checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"path": "vitess.io/vitess/go/sqltypes", "path": "vitess.io/vitess/go/sqltypes",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "ntFIQYkBS51G6y+FEkjFW40+HOU=", "checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=",
"path": "vitess.io/vitess/go/vt/log", "path": "vitess.io/vitess/go/vt/log",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "HHIcl3lpWkzLARkkNv94fVaObjo=", "checksumSHA1": "HHIcl3lpWkzLARkkNv94fVaObjo=",
"path": "vitess.io/vitess/go/vt/proto/query", "path": "vitess.io/vitess/go/vt/proto/query",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=", "checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=",
"path": "vitess.io/vitess/go/vt/proto/topodata", "path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "tNNlcSFFnlOauS2hXnrz/zA/wfk=", "checksumSHA1": "tNNlcSFFnlOauS2hXnrz/zA/wfk=",
"path": "vitess.io/vitess/go/vt/proto/vtgate", "path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=", "checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc", "path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "IDe+9Bn42lZVsuoYO/epdguiErk=", "checksumSHA1": "3yiiEdMrUONYMNI84Bs/KONvW94=",
"path": "vitess.io/vitess/go/vt/sqlparser", "path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
}, },
{ {
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=", "checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors", "path": "vitess.io/vitess/go/vt/vterrors",
"revision": "42f5c760cca59b18c4ea877284f36eb0be7d6468", "revision": "360d5cdb70a8fe85321a6ddde39a632883b7b4e3",
"revisionTime": "2019-01-06T20:12:04Z" "revisionTime": "2019-01-16T07:27:56Z"
} }
], ],
"rootPath": "github.com/XiaoMi/soar" "rootPath": "github.com/XiaoMi/soar"
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
package log package log
import "github.com/golang/glog" import (
"flag"
"github.com/golang/glog"
)
// Level is used with V() to test log verbosity. // Level is used with V() to test log verbosity.
type Level = glog.Level type Level = glog.Level
...@@ -52,3 +55,7 @@ var ( ...@@ -52,3 +55,7 @@ var (
// FatalDepth formats arguments like fmt.Print and uses depth to choose which call frame to log. // FatalDepth formats arguments like fmt.Print and uses depth to choose which call frame to log.
FatalDepth = glog.FatalDepth FatalDepth = glog.FatalDepth
) )
func init() {
flag.Uint64Var(&glog.MaxSize, "log_rotate_max_size", glog.MaxSize, "size in bytes at which logs are rotated (glog.MaxSize)")
}
...@@ -31,6 +31,7 @@ import ( ...@@ -31,6 +31,7 @@ import (
) )
// These constants are used to identify the SQL statement type. // These constants are used to identify the SQL statement type.
// Changing this list will require reviewing all calls to Preview.
const ( const (
StmtSelect = iota StmtSelect = iota
StmtStream StmtStream
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册