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

update vendor after chinese lunar new year

上级 9baca3f7
......@@ -4,6 +4,10 @@
TiDB SQL Parser
## How to use it
See [https://godoc.org/github.com/pingcap/parser](https://godoc.org/github.com/pingcap/parser)
## How to update parser for TiDB
Assuming that you want to file a PR (pull request) to TiDB, and your PR includes a change in the parser, follow these steps to update the parser in TiDB.
......@@ -21,25 +25,13 @@ Suppose the forked repository is `https://github.com/your-repo/parser`.
### Step 2: Make your parser changes take effect in TiDB and run CI
1. In your TiDB repository, modify the `go.mod` file, remove `github.com/pingcap/parser` from the `require` instruction, and add a new line at the end of the file like this:
```
replace github.com/pingcap/parser => github.com/your-repo/parser v0.0.0-20181102150703-4acd198f5092
```
This change tells TiDB to use the modified parser from your repository. You can just use below command to replace the dependent parser version:
1. In your TiDB repository, execute the `replace` instruction to make your parser changes take effect:
```
GO111MODULE=on go mod edit -replace github.com/pingcap/parser=github.com/your-repo/parser@your-branch
```
2. You can get correct version information by running this command in your TiDB directory:
```
GO111MODULE=on go get -u github.com/your-repo/parser@master
```
If some error is reported, you can ignore it and still edit the `go.mod` file manually.
2. `make dev` to run CI in TiDB.
3. File a PR to TiDB.
......
......@@ -1408,7 +1408,80 @@ type DeleteStmt struct {
// Restore implements Node interface.
func (n *DeleteStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DELETE ")
if n.TableHints != nil && len(n.TableHints) != 0 {
ctx.WritePlain("/*+ ")
for i, tableHint := range n.TableHints {
if err := tableHint.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore UpdateStmt.TableHints[%d]", i)
}
}
ctx.WritePlain("*/ ")
}
switch n.Priority {
case mysql.LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY ")
}
if n.Quick {
ctx.WriteKeyWord("QUICK ")
}
if n.IgnoreErr {
ctx.WriteKeyWord("IGNORE ")
}
if n.IsMultiTable { // Multiple-Table Syntax
if n.BeforeFrom {
if err := n.Tables.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.Tables")
}
ctx.WriteKeyWord(" FROM ")
if err := n.TableRefs.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.TableRefs")
}
} else {
ctx.WriteKeyWord("FROM ")
if err := n.Tables.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.Tables")
}
ctx.WriteKeyWord(" USING ")
if err := n.TableRefs.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.TableRefs")
}
}
} else { // Single-Table Syntax
ctx.WriteKeyWord("FROM ")
if err := n.TableRefs.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.TableRefs")
}
}
if n.Where != nil {
ctx.WriteKeyWord(" WHERE ")
if err := n.Where.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.Where")
}
}
if n.Order != nil {
ctx.WritePlain(" ")
if err := n.Order.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.Order")
}
}
if n.Limit != nil {
ctx.WritePlain(" ")
if err := n.Limit.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore DeleteStmt.Limit")
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -1425,11 +1498,13 @@ func (n *DeleteStmt) Accept(v Visitor) (Node, bool) {
}
n.TableRefs = node.(*TableRefsClause)
node, ok = n.Tables.Accept(v)
if !ok {
return n, false
if n.Tables != nil {
node, ok = n.Tables.Accept(v)
if !ok {
return n, false
}
n.Tables = node.(*DeleteTableList)
}
n.Tables = node.(*DeleteTableList)
if n.Where != nil {
node, ok = n.Where.Accept(v)
......@@ -1473,7 +1548,69 @@ type UpdateStmt struct {
// Restore implements Node interface.
func (n *UpdateStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("UPDATE ")
if n.TableHints != nil && len(n.TableHints) != 0 {
ctx.WritePlain("/*+ ")
for i, tableHint := range n.TableHints {
if err := tableHint.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore UpdateStmt.TableHints[%d]", i)
}
}
ctx.WritePlain("*/ ")
}
switch n.Priority {
case mysql.LowPriority:
ctx.WriteKeyWord("LOW_PRIORITY ")
}
if n.IgnoreErr {
ctx.WriteKeyWord("IGNORE ")
}
if err := n.TableRefs.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occur while restore UpdateStmt.TableRefs")
}
ctx.WriteKeyWord(" SET ")
for i, assignment := range n.List {
if i != 0 {
ctx.WritePlain(", ")
}
if err := assignment.Column.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occur while restore UpdateStmt.List[%d].Column", i)
}
ctx.WritePlain("=")
if err := assignment.Expr.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occur while restore UpdateStmt.List[%d].Expr", i)
}
}
if n.Where != nil {
ctx.WriteKeyWord(" WHERE ")
if err := n.Where.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occur while restore UpdateStmt.Where")
}
}
if n.Order != nil {
ctx.WritePlain(" ")
if err := n.Order.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occur while restore UpdateStmt.Order")
}
}
if n.Limit != nil {
ctx.WritePlain(" ")
if err := n.Limit.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occur while restore UpdateStmt.Limit")
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -1661,18 +1798,6 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
}
return nil
}
restoreUserName := func() error {
if n.User.CurrentUser {
ctx.WriteKeyWord("CURRENT_USER")
} else {
ctx.WriteString(n.User.Username)
if n.User.Hostname != "" {
ctx.WritePlain("@")
ctx.WriteString(n.User.Hostname)
}
}
return nil
}
ctx.WriteKeyWord("SHOW ")
switch n.Tp {
......@@ -1694,12 +1819,16 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteName(n.DBName)
case ShowCreateUser:
ctx.WriteKeyWord("CREATE USER ")
restoreUserName()
if err := n.User.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ShowStmt.User")
}
case ShowGrants:
ctx.WriteKeyWord("GRANTS")
if n.User != nil {
ctx.WriteKeyWord(" FOR ")
restoreUserName()
if err := n.User.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ShowStmt.User")
}
}
case ShowMasterStatus:
ctx.WriteKeyWord("MASTER STATUS")
......
......@@ -93,6 +93,18 @@ type AuthOption struct {
// TODO: support auth_plugin
}
// Restore implements Node interface.
func (n *AuthOption) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("IDENTIFIED BY ")
if n.ByAuthString {
ctx.WriteString(n.AuthString)
} else {
ctx.WriteKeyWord("PASSWORD ")
ctx.WriteString(n.HashString)
}
return nil
}
// TraceStmt is a statement to trace what sql actually does at background.
type TraceStmt struct {
stmtNode
......@@ -134,7 +146,32 @@ type ExplainStmt struct {
// Restore implements Node interface.
func (n *ExplainStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
if showStmt, ok := n.Stmt.(*ShowStmt); ok {
ctx.WriteKeyWord("DESC ")
if err := showStmt.Table.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Table")
}
if showStmt.Column != nil {
ctx.WritePlain(" ")
if err := showStmt.Column.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExplainStmt.ShowStmt.Column")
}
}
return nil
}
ctx.WriteKeyWord("EXPLAIN ")
if n.Analyze {
ctx.WriteKeyWord("ANALYZE ")
} else {
ctx.WriteKeyWord("FORMAT ")
ctx.WritePlain("= ")
ctx.WriteString(n.Format)
ctx.WritePlain(" ")
}
if err := n.Stmt.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore ExplainStmt.Stmt")
}
return nil
}
// Accept implements Node Accept interface.
......@@ -165,7 +202,20 @@ type PrepareStmt struct {
// Restore implements Node interface.
func (n *PrepareStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("PREPARE ")
ctx.WriteName(n.Name)
ctx.WriteKeyWord(" FROM ")
if n.SQLText != "" {
ctx.WriteString(n.SQLText)
return nil
}
if n.SQLVar != nil {
if err := n.SQLVar.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore PrepareStmt.SQLVar")
}
return nil
}
return errors.New("An error occurred while restore PrepareStmt")
}
// Accept implements Node Accept interface.
......@@ -195,7 +245,9 @@ type DeallocateStmt struct {
// Restore implements Node interface.
func (n *DeallocateStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DEALLOCATE PREPARE ")
ctx.WriteName(n.Name)
return nil
}
// Accept implements Node Accept interface.
......@@ -228,7 +280,20 @@ type ExecuteStmt struct {
// Restore implements Node interface.
func (n *ExecuteStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("EXECUTE ")
ctx.WriteName(n.Name)
if len(n.UsingVars) > 0 {
ctx.WriteKeyWord(" USING ")
for i, val := range n.UsingVars {
if i != 0 {
ctx.WritePlain(",")
}
if err := val.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore ExecuteStmt.UsingVars index %d", i)
}
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -280,7 +345,9 @@ type BinlogStmt struct {
// Restore implements Node interface.
func (n *BinlogStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("BINLOG ")
ctx.WriteString(n.Str)
return nil
}
// Accept implements Node Accept interface.
......@@ -385,7 +452,33 @@ type VariableAssignment struct {
// Restore implements Node interface.
func (n *VariableAssignment) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
if n.IsSystem {
ctx.WritePlain("@@")
if n.IsGlobal {
ctx.WriteKeyWord("GLOBAL")
} else {
ctx.WriteKeyWord("SESSION")
}
ctx.WritePlain(".")
} else if n.Name != SetNames {
ctx.WriteKeyWord("@")
}
if n.Name == SetNames {
ctx.WriteKeyWord("NAMES ")
} else {
ctx.WriteName(n.Name)
ctx.WritePlain("=")
}
if err := n.Value.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore VariableAssignment.Value")
}
if n.ExtendValue != nil {
ctx.WriteKeyWord(" COLLATE ")
if err := n.ExtendValue.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore VariableAssignment.ExtendValue")
}
}
return nil
}
// Accept implements Node interface.
......@@ -426,7 +519,34 @@ type FlushStmt struct {
// Restore implements Node interface.
func (n *FlushStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("FLUSH ")
if n.NoWriteToBinLog {
ctx.WriteKeyWord("NO_WRITE_TO_BINLOG ")
}
switch n.Tp {
case FlushTables:
ctx.WriteKeyWord("TABLES")
for i, v := range n.Tables {
if i == 0 {
ctx.WritePlain(" ")
} else {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore FlushStmt.Tables[%d]", i)
}
}
if n.ReadLock {
ctx.WriteKeyWord(" WITH READ LOCK")
}
case FlushPrivileges:
ctx.WriteKeyWord("PRIVILEGES")
case FlushStatus:
ctx.WriteKeyWord("STATUS")
default:
return errors.New("Unsupported type of FlushTables")
}
return nil
}
// Accept implements Node Accept interface.
......@@ -461,7 +581,15 @@ type KillStmt struct {
// Restore implements Node interface.
func (n *KillStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("KILL")
if n.TiDBExtension {
ctx.WriteKeyWord(" TIDB")
}
if n.Query {
ctx.WriteKeyWord(" QUERY")
}
ctx.WritePlainf(" %d", n.ConnectionID)
return nil
}
// Accept implements Node Accept interface.
......@@ -483,7 +611,16 @@ type SetStmt struct {
// Restore implements Node interface.
func (n *SetStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("SET ")
for i, v := range n.Variables {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore SetStmt.Variables[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -535,7 +672,16 @@ type SetPwdStmt struct {
// Restore implements Node interface.
func (n *SetPwdStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("SET PASSWORD")
if n.User != nil {
ctx.WriteKeyWord(" FOR ")
if err := n.User.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore SetPwdStmt.User")
}
}
ctx.WritePlain("=")
ctx.WriteString(n.Password)
return nil
}
// SecureText implements SensitiveStatement interface.
......@@ -559,28 +705,42 @@ type UserSpec struct {
AuthOpt *AuthOption
}
// Restore implements Node interface.
func (n *UserSpec) Restore(ctx *RestoreCtx) error {
if err := n.User.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore UserSpec.User")
}
if n.AuthOpt != nil {
ctx.WritePlain(" ")
if err := n.AuthOpt.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore UserSpec.AuthOpt")
}
}
return nil
}
// SecurityString formats the UserSpec without password information.
func (u *UserSpec) SecurityString() string {
func (n *UserSpec) SecurityString() string {
withPassword := false
if opt := u.AuthOpt; opt != nil {
if opt := n.AuthOpt; opt != nil {
if len(opt.AuthString) > 0 || len(opt.HashString) > 0 {
withPassword = true
}
}
if withPassword {
return fmt.Sprintf("{%s password = ***}", u.User)
return fmt.Sprintf("{%s password = ***}", n.User)
}
return u.User.String()
return n.User.String()
}
// EncodedPassword returns the encoded password (which is the real data mysql.user).
// The boolean value indicates input's password format is legal or not.
func (u *UserSpec) EncodedPassword() (string, bool) {
if u.AuthOpt == nil {
func (n *UserSpec) EncodedPassword() (string, bool) {
if n.AuthOpt == nil {
return "", true
}
opt := u.AuthOpt
opt := n.AuthOpt
if opt.ByAuthString {
return auth.EncodePassword(opt.AuthString), true
}
......@@ -603,7 +763,19 @@ type CreateUserStmt struct {
// Restore implements Node interface.
func (n *CreateUserStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("CREATE USER ")
if n.IfNotExists {
ctx.WriteKeyWord("IF NOT EXISTS ")
}
for i, v := range n.Specs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore CreateUserStmt.Specs[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -639,7 +811,26 @@ type AlterUserStmt struct {
// Restore implements Node interface.
func (n *AlterUserStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("ALTER USER ")
if n.IfExists {
ctx.WriteKeyWord("IF EXISTS ")
}
if n.CurrentAuth != nil {
ctx.WriteKeyWord("USER")
ctx.WritePlain("() ")
if err := n.CurrentAuth.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AlterUserStmt.CurrentAuth")
}
}
for i, v := range n.Specs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AlterUserStmt.Specs[%d]", i)
}
}
return nil
}
// SecureText implements SensitiveStatement interface.
......@@ -674,7 +865,19 @@ type DropUserStmt struct {
// Restore implements Node interface.
func (n *DropUserStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DROP USER ")
if n.IfExists {
ctx.WriteKeyWord("IF EXISTS ")
}
for i, v := range n.UserList {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore DropUserStmt.UserList[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -754,7 +957,16 @@ type DoStmt struct {
// Restore implements Node interface.
func (n *DoStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("DO ")
for i, v := range n.Exprs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore DoStmt.Exprs[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -831,6 +1043,30 @@ type ShowSlow struct {
Kind ShowSlowKind
}
// Restore implements Node interface.
func (n *ShowSlow) Restore(ctx *RestoreCtx) error {
switch n.Tp {
case ShowSlowRecent:
ctx.WriteKeyWord("RECENT ")
case ShowSlowTop:
ctx.WriteKeyWord("TOP ")
switch n.Kind {
case ShowSlowKindDefault:
// do nothing
case ShowSlowKindInternal:
ctx.WriteKeyWord("INTERNAL ")
case ShowSlowKindAll:
ctx.WriteKeyWord("ALL ")
default:
return errors.New("Unsupported kind of ShowSlowTop")
}
default:
return errors.New("Unsupported type of ShowSlow")
}
ctx.WritePlainf("%d", n.Count)
return nil
}
// AdminStmt is the struct for Admin statement.
type AdminStmt struct {
stmtNode
......@@ -847,7 +1083,112 @@ type AdminStmt struct {
// Restore implements Node interface.
func (n *AdminStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
restoreTables := func() error {
for i, v := range n.Tables {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore AdminStmt.Tables[%d]", i)
}
}
return nil
}
restoreJobIDs := func() {
for i, v := range n.JobIDs {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WritePlainf("%d", v)
}
}
ctx.WriteKeyWord("ADMIN ")
switch n.Tp {
case AdminShowDDL:
ctx.WriteKeyWord("SHOW DDL")
case AdminShowDDLJobs:
ctx.WriteKeyWord("SHOW DDL JOBS")
if n.JobNumber != 0 {
ctx.WritePlainf(" %d", n.JobNumber)
}
case AdminShowNextRowID:
ctx.WriteKeyWord("SHOW ")
if err := restoreTables(); err != nil {
return err
}
ctx.WriteKeyWord(" NEXT_ROW_ID")
case AdminCheckTable:
ctx.WriteKeyWord("CHECK TABLE ")
if err := restoreTables(); err != nil {
return err
}
case AdminCheckIndex:
ctx.WriteKeyWord("CHECK INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
case AdminRecoverIndex:
ctx.WriteKeyWord("RECOVER INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
case AdminRestoreTable:
ctx.WriteKeyWord("RESTORE TABLE ")
if n.JobIDs != nil {
ctx.WriteKeyWord("BY JOB ")
restoreJobIDs()
} else {
if err := restoreTables(); err != nil {
return err
}
if n.JobNumber != 0 {
ctx.WritePlainf(" %d", n.JobNumber)
}
}
case AdminCleanupIndex:
ctx.WriteKeyWord("CLEANUP INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
case AdminCheckIndexRange:
ctx.WriteKeyWord("CHECK INDEX ")
if err := restoreTables(); err != nil {
return err
}
ctx.WritePlainf(" %s", n.Index)
if n.HandleRanges != nil {
ctx.WritePlain(" ")
for i, v := range n.HandleRanges {
if i != 0 {
ctx.WritePlain(", ")
}
ctx.WritePlainf("(%d,%d)", v.Begin, v.End)
}
}
case AdminChecksumTable:
ctx.WriteKeyWord("CHECKSUM TABLE ")
if err := restoreTables(); err != nil {
return err
}
case AdminCancelDDLJobs:
ctx.WriteKeyWord("CANCEL DDL JOBS ")
restoreJobIDs()
case AdminShowDDLJobQueries:
ctx.WriteKeyWord("SHOW DDL JOB QUERIES ")
restoreJobIDs()
case AdminShowSlow:
ctx.WriteKeyWord("SHOW SLOW ")
if err := n.ShowSlow.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore AdminStmt.ShowSlow")
}
default:
return errors.New("Unsupported AdminStmt type")
}
return nil
}
// Accept implements Node Accept interface.
......@@ -879,7 +1220,65 @@ type PrivElem struct {
// Restore implements Node interface.
func (n *PrivElem) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
switch n.Priv {
case 0:
// Do nothing for types that have no effect.
// Actually this should not happen since there is no way to determine its type.
return errors.New("Cannot determine privilege type")
case mysql.AllPriv:
ctx.WriteKeyWord("ALL")
case mysql.AlterPriv:
ctx.WriteKeyWord("ALTER")
case mysql.CreatePriv:
ctx.WriteKeyWord("CREATE")
case mysql.CreateUserPriv:
ctx.WriteKeyWord("CREATE USER")
case mysql.TriggerPriv:
ctx.WriteKeyWord("TRIGGER")
case mysql.DeletePriv:
ctx.WriteKeyWord("DELETE")
case mysql.DropPriv:
ctx.WriteKeyWord("DROP")
case mysql.ProcessPriv:
ctx.WriteKeyWord("PROCESS")
case mysql.ExecutePriv:
ctx.WriteKeyWord("EXECUTE")
case mysql.IndexPriv:
ctx.WriteKeyWord("INDEX")
case mysql.InsertPriv:
ctx.WriteKeyWord("INSERT")
case mysql.SelectPriv:
ctx.WriteKeyWord("SELECT")
case mysql.SuperPriv:
ctx.WriteKeyWord("SUPER")
case mysql.ShowDBPriv:
ctx.WriteKeyWord("SHOW DATABASES")
case mysql.UpdatePriv:
ctx.WriteKeyWord("UPDATE")
case mysql.GrantPriv:
ctx.WriteKeyWord("GRANT OPTION")
case mysql.ReferencesPriv:
ctx.WriteKeyWord("REFERENCES")
case mysql.CreateViewPriv:
ctx.WriteKeyWord("CREATE VIEW")
case mysql.ShowViewPriv:
ctx.WriteKeyWord("SHOW VIEW")
default:
return errors.New("Unsupported privilege type")
}
if n.Cols != nil {
ctx.WritePlain(" (")
for i, v := range n.Cols {
if i != 0 {
ctx.WritePlain(",")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore PrivElem.Cols[%d]", i)
}
}
ctx.WritePlain(")")
}
return nil
}
// Accept implements Node Accept interface.
......@@ -909,6 +1308,19 @@ const (
ObjectTypeTable
)
// Restore implements Node interface.
func (n ObjectTypeType) Restore(ctx *RestoreCtx) error {
switch n {
case ObjectTypeNone:
// do nothing
case ObjectTypeTable:
ctx.WriteKeyWord("TABLE ")
default:
return errors.New("Unsupported object type")
}
return nil
}
// GrantLevelType is the type for grant level.
type GrantLevelType int
......@@ -930,6 +1342,28 @@ type GrantLevel struct {
TableName string
}
// Restore implements Node interface.
func (n *GrantLevel) Restore(ctx *RestoreCtx) error {
switch n.Level {
case GrantLevelDB:
if n.DBName == "" {
ctx.WritePlain("*")
} else {
ctx.WriteName(n.DBName)
ctx.WritePlain(".*")
}
case GrantLevelGlobal:
ctx.WritePlain("*.*")
case GrantLevelTable:
if n.DBName != "" {
ctx.WriteName(n.DBName)
ctx.WritePlain(".")
}
ctx.WriteName(n.TableName)
}
return nil
}
// RevokeStmt is the struct for REVOKE statement.
type RevokeStmt struct {
stmtNode
......@@ -942,7 +1376,32 @@ type RevokeStmt struct {
// Restore implements Node interface.
func (n *RevokeStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("REVOKE ")
for i, v := range n.Privs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Privs[%d]", i)
}
}
ctx.WriteKeyWord(" ON ")
if err := n.ObjectType.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore RevokeStmt.ObjectType")
}
if err := n.Level.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore RevokeStmt.Level")
}
ctx.WriteKeyWord(" FROM ")
for i, v := range n.Users {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore RevokeStmt.Users[%d]", i)
}
}
return nil
}
// Accept implements Node Accept interface.
......@@ -975,7 +1434,35 @@ type GrantStmt struct {
// Restore implements Node interface.
func (n *GrantStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
ctx.WriteKeyWord("GRANT ")
for i, v := range n.Privs {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.Privs[%d]", i)
}
}
ctx.WriteKeyWord(" ON ")
if err := n.ObjectType.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore GrantStmt.ObjectType")
}
if err := n.Level.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore GrantStmt.Level")
}
ctx.WriteKeyWord(" TO ")
for i, v := range n.Users {
if i != 0 {
ctx.WritePlain(", ")
}
if err := v.Restore(ctx); err != nil {
return errors.Annotatef(err, "An error occurred while restore GrantStmt.Users[%d]", i)
}
}
if n.WithGrant {
ctx.WriteKeyWord(" WITH GRANT OPTION")
}
return nil
}
// SecureText implements SensitiveStatement interface.
......
......@@ -20,6 +20,7 @@ import (
"fmt"
"github.com/pingcap/errors"
. "github.com/pingcap/parser/format"
"github.com/pingcap/parser/terror"
)
......@@ -32,6 +33,20 @@ type UserIdentity struct {
AuthHostname string // Match in privs system (i.e. could be a wildcard)
}
// Restore implements Node interface.
func (user *UserIdentity) Restore(ctx *RestoreCtx) error {
if user.CurrentUser {
ctx.WriteKeyWord("CURRENT_USER")
} else {
ctx.WriteName(user.Username)
if user.Hostname != "" {
ctx.WritePlain("@")
ctx.WriteName(user.Hostname)
}
}
return nil
}
// String converts UserIdentity to the format user@host.
func (user *UserIdentity) String() string {
// TODO: Escape username and hostname.
......
version: 2
jobs:
build:
build-ut:
docker:
- image: golang:1.11
working_directory: /go/src/github.com/pingcap/parser
......@@ -19,12 +19,36 @@ jobs:
- run:
name: "Build & 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_SHA1
make test
build-integration:
docker:
- image: golang:1.11
working_directory: /go/src/github.com/pingcap/parser
steps:
- checkout
- run:
name: "Verify parser.go is up-to-date"
command: |
mv parser.go parser.go.committed
make parser
diff -u parser.go.committed parser.go
- run:
name: "Check code format"
command: make fmt
- run:
name: "Build"
command: make
- 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_SHA1
make test
workflows:
version: 2
build_and_test:
jobs:
- build-ut
- build-integration
\ No newline at end of file
......@@ -16,6 +16,7 @@ package parser
import (
"bytes"
"fmt"
"strconv"
"strings"
"unicode"
"unicode/utf8"
......@@ -50,6 +51,10 @@ type Scanner struct {
// It may break the compatibility when support those keywords,
// because some application may already use them as identifiers.
supportWindowFunc bool
// lastScanOffset indicates last offset returned by scan().
// It's used to substring sql in syntax error message.
lastScanOffset int
}
type specialCommentScanner interface {
......@@ -123,17 +128,14 @@ func (s *Scanner) stmtText() string {
// Scanner satisfies yyLexer interface which need this function.
func (s *Scanner) Errorf(format string, a ...interface{}) {
str := fmt.Sprintf(format, a...)
col := s.r.p.Col
startPos := s.stmtStartPos
if s.r.s[startPos] == '\n' {
startPos++
col--
}
val := s.r.s[startPos:]
val := s.r.s[s.lastScanOffset:]
var lenStr = ""
if len(val) > 2048 {
lenStr = "(total length " + strconv.Itoa(len(val)) + ")"
val = val[:2048]
}
err := fmt.Errorf("line %d column %d near \"%s\"%s (total length %d)", s.r.p.Line, col, val, str, len(s.r.s))
err := fmt.Errorf("line %d column %d near \"%s\"%s %s",
s.r.p.Line, s.r.p.Col, val, str, lenStr)
s.errs = append(s.errs, err)
}
......@@ -144,6 +146,7 @@ func (s *Scanner) Errorf(format string, a ...interface{}) {
// return invalid tells parser that scanner meets illegal character.
func (s *Scanner) Lex(v *yySymType) int {
tok, pos, lit := s.scan()
s.lastScanOffset = pos.Offset
v.offset = pos.Offset
v.ident = lit
if tok == identifier {
......
......@@ -17,7 +17,6 @@ import (
"strings"
"github.com/pingcap/parser/charset"
"github.com/pingcap/tidb/util/hack"
)
func isLetter(ch rune) bool {
......@@ -372,6 +371,7 @@ var tokenMap = map[string]int{
"ON": on,
"ONLY": only,
"OPTION": option,
"OPTIONALLY": optionally,
"OR": or,
"ORDER": order,
"OUTER": outer,
......@@ -634,9 +634,9 @@ func (s *Scanner) isTokenIdentifier(lit string, offset int) int {
return tok
}
}
tok, ok := tokenMap[hack.String(data)]
tok, ok := tokenMap[string(data)]
if !ok && s.supportWindowFunc {
tok = windowFuncTokenMap[hack.String(data)]
tok = windowFuncTokenMap[string(data)]
}
return tok
}
......
......@@ -62,6 +62,13 @@ func (s SchemaState) String() string {
}
}
const (
// ColumnInfoVersion0 means the column info version is 0.
ColumnInfoVersion0 = uint64(0)
// ColumnInfoVersion1 means the column info version is 1.
ColumnInfoVersion1 = uint64(1)
)
// ColumnInfo provides meta data describing of a table column.
type ColumnInfo struct {
ID int64 `json:"id"`
......@@ -76,6 +83,12 @@ type ColumnInfo struct {
types.FieldType `json:"type"`
State SchemaState `json:"state"`
Comment string `json:"comment"`
// Version means the version of the column info.
// Version = 0: For OriginDefaultValue and DefaultValue of timestamp column will stores the default time in system time zone.
// That is a bug if multiple TiDB servers in different system time zone.
// Version = 1: For OriginDefaultValue and DefaultValue of timestamp column will stores the default time in UTC time zone.
// This will fix bug in version 0. For compatibility with version 0, we add version field in column info struct.
Version uint64 `json:"version"`
}
// Clone clones ColumnInfo.
......
......@@ -218,6 +218,10 @@ const (
ExecutePriv
// IndexPriv is the privilege to create/drop index.
IndexPriv
// CreateViewPriv is the privilege to create view.
CreateViewPriv
// ShowViewPriv is the privilege to show create view.
ShowViewPriv
// AllPriv is the privilege for all actions.
AllPriv
)
......@@ -277,6 +281,8 @@ var Priv2UserCol = map[PrivilegeType]string{
AlterPriv: "Alter_priv",
ExecutePriv: "Execute_priv",
IndexPriv: "Index_priv",
CreateViewPriv: "Create_view_priv",
ShowViewPriv: "Show_view_priv",
}
// Command2Str is the command information to command name.
......@@ -333,10 +339,12 @@ var Col2PrivType = map[string]PrivilegeType{
"Alter_priv": AlterPriv,
"Execute_priv": ExecutePriv,
"Index_priv": IndexPriv,
"Create_view_priv": CreateViewPriv,
"Show_view_priv": ShowViewPriv,
}
// AllGlobalPrivs is all the privileges in global scope.
var AllGlobalPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, ProcessPriv, GrantPriv, ReferencesPriv, AlterPriv, ShowDBPriv, SuperPriv, ExecutePriv, IndexPriv, CreateUserPriv, TriggerPriv}
var AllGlobalPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, ProcessPriv, GrantPriv, ReferencesPriv, AlterPriv, ShowDBPriv, SuperPriv, ExecutePriv, IndexPriv, CreateUserPriv, TriggerPriv, CreateViewPriv, ShowViewPriv}
// Priv2Str is the map for privilege to string.
var Priv2Str = map[PrivilegeType]string{
......@@ -356,38 +364,44 @@ var Priv2Str = map[PrivilegeType]string{
AlterPriv: "Alter",
ExecutePriv: "Execute",
IndexPriv: "Index",
CreateViewPriv: "Create View",
ShowViewPriv: "Show View",
}
// Priv2SetStr is the map for privilege to string.
var Priv2SetStr = map[PrivilegeType]string{
CreatePriv: "Create",
SelectPriv: "Select",
InsertPriv: "Insert",
UpdatePriv: "Update",
DeletePriv: "Delete",
DropPriv: "Drop",
GrantPriv: "Grant",
AlterPriv: "Alter",
ExecutePriv: "Execute",
IndexPriv: "Index",
CreatePriv: "Create",
SelectPriv: "Select",
InsertPriv: "Insert",
UpdatePriv: "Update",
DeletePriv: "Delete",
DropPriv: "Drop",
GrantPriv: "Grant",
AlterPriv: "Alter",
ExecutePriv: "Execute",
IndexPriv: "Index",
CreateViewPriv: "Create View",
ShowViewPriv: "Show View",
}
// SetStr2Priv is the map for privilege set string to privilege type.
var SetStr2Priv = map[string]PrivilegeType{
"Create": CreatePriv,
"Select": SelectPriv,
"Insert": InsertPriv,
"Update": UpdatePriv,
"Delete": DeletePriv,
"Drop": DropPriv,
"Grant": GrantPriv,
"Alter": AlterPriv,
"Execute": ExecutePriv,
"Index": IndexPriv,
"Create": CreatePriv,
"Select": SelectPriv,
"Insert": InsertPriv,
"Update": UpdatePriv,
"Delete": DeletePriv,
"Drop": DropPriv,
"Grant": GrantPriv,
"Alter": AlterPriv,
"Execute": ExecutePriv,
"Index": IndexPriv,
"Create View": CreateViewPriv,
"Show View": ShowViewPriv,
}
// AllDBPrivs is all the privileges in database scope.
var AllDBPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, ExecutePriv, IndexPriv}
var AllDBPrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, ExecutePriv, IndexPriv, CreateViewPriv, ShowViewPriv}
// AllTablePrivs is all the privileges in table scope.
var AllTablePrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, IndexPriv}
......
......@@ -79,7 +79,7 @@ var MySQLErrName = map[uint16]string{
ErrDupKeyName: "Duplicate key name '%-.192s'",
ErrDupEntry: "Duplicate entry '%-.192s' for key %d",
ErrWrongFieldSpec: "Incorrect column specifier for column '%-.192s'",
ErrParse: "%s near '%-.80s' at line %d",
ErrParse: "%s %s",
ErrEmptyQuery: "Query was empty",
ErrNonuniqTable: "Not unique table/alias: '%-.192s'",
ErrInvalidDefault: "Invalid default value for '%-.192s'",
......
......@@ -188,6 +188,7 @@ import (
nvarcharType "NVARCHAR"
on "ON"
option "OPTION"
optionally "OPTIONALLY"
or "OR"
order "ORDER"
outer "OUTER"
......@@ -4363,6 +4364,10 @@ TableName:
{
$$ = &ast.TableName{Schema:model.NewCIStr($1), Name:model.NewCIStr($3)}
}
| Identifier '.' '*'
{
$$ = &ast.TableName{Name:model.NewCIStr($1)}
}
TableNameList:
TableName
......@@ -5799,7 +5804,7 @@ AdminStmt:
$$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable,
Tables: []*ast.TableName{$4.(*ast.TableName)},
JobNumber: $5.(int64),
JobNumber: $5.(int64),
}
}
| "ADMIN" "CLEANUP" "INDEX" TableName Identifier
......@@ -7546,11 +7551,11 @@ PrivType:
}
| "CREATE" "VIEW"
{
$$ = mysql.PrivilegeType(0)
$$ = mysql.CreateViewPriv
}
| "SHOW" "VIEW"
{
$$ = mysql.PrivilegeType(0)
$$ = mysql.ShowViewPriv
}
| "CREATE" "ROUTINE"
{
......@@ -7720,6 +7725,10 @@ Enclosed:
{
$$ = ""
}
| "OPTIONALLY" "ENCLOSED" "BY" stringLit
{
$$ = $4
}
| "ENCLOSED" "BY" stringLit
{
$$ = $3
......
......@@ -14,6 +14,7 @@
package parser
import (
"fmt"
"math"
"regexp"
"strconv"
......@@ -159,7 +160,7 @@ func ParseErrorWith(errstr string, lineno int) error {
if len(errstr) > mysql.ErrTextLength {
errstr = errstr[:mysql.ErrTextLength]
}
return ErrParse.GenWithStackByArgs(mysql.MySQLErrName[mysql.ErrSyntax], errstr, lineno)
return fmt.Errorf("near '%-.80s' at line %d", errstr, lineno)
}
// The select statement is not at the end of the whole statement, if the last
......
......@@ -408,7 +408,8 @@ func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned
u, err := ConvertFloatToUint(sc, f, bound, mysql.TypeDouble)
return int64(u), errors.Trace(err)
case json.TypeCodeString:
return StrToInt(sc, hack.String(j.GetString()))
str := string(hack.String(j.GetString()))
return StrToInt(sc, str)
}
return 0, errors.New("Unknown type code in JSON")
}
......@@ -433,7 +434,8 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6
case json.TypeCodeFloat64:
return j.GetFloat64(), nil
case json.TypeCodeString:
return StrToFloat(sc, hack.String(j.GetString()))
str := string(hack.String(j.GetString()))
return StrToFloat(sc, str)
}
return 0, errors.New("Unknown type code in JSON")
}
......
......@@ -170,7 +170,7 @@ func (d *Datum) SetFloat32(f float32) {
// GetString gets string value.
func (d *Datum) GetString() string {
return hack.String(d.b)
return string(hack.String(d.b))
}
// SetString sets string value.
......@@ -271,7 +271,8 @@ func (d *Datum) SetMysqlDuration(b Duration) {
// GetMysqlEnum gets Enum value
func (d *Datum) GetMysqlEnum() Enum {
return Enum{Value: uint64(d.i), Name: hack.String(d.b)}
str := string(hack.String(d.b))
return Enum{Value: uint64(d.i), Name: str}
}
// SetMysqlEnum sets Enum value
......@@ -284,7 +285,8 @@ func (d *Datum) SetMysqlEnum(b Enum) {
// GetMysqlSet gets Set value
func (d *Datum) GetMysqlSet() Set {
return Set{Value: uint64(d.i), Name: hack.String(d.b)}
str := string(hack.String(d.b))
return Set{Value: uint64(d.i), Name: str}
}
// SetMysqlSet sets Set value
......@@ -579,7 +581,8 @@ func (d *Datum) compareString(sc *stmtctx.StatementContext, s string) (int, erro
}
func (d *Datum) compareBytes(sc *stmtctx.StatementContext, b []byte) (int, error) {
return d.compareString(sc, hack.String(b))
str := string(hack.String(b))
return d.compareString(sc, str)
}
func (d *Datum) compareMysqlDecimal(sc *stmtctx.StatementContext, dec *MyDecimal) (int, error) {
......@@ -1169,18 +1172,19 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem
func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) {
var (
ret Datum
y int64
err error
fromStr bool
ret Datum
y int64
err error
adjust bool
)
switch d.k {
case KindString, KindBytes:
y, err = StrToInt(sc, d.GetString())
s := d.GetString()
y, err = StrToInt(sc, s)
if err != nil {
return ret, errors.Trace(err)
}
fromStr = true
adjust = len(s) < 4
case KindMysqlTime:
y = int64(d.GetMysqlTime().Time.Year())
case KindMysqlDuration:
......@@ -1192,7 +1196,7 @@ func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldTy
}
y = ret.GetInt64()
}
y, err = AdjustYear(y, fromStr)
y, err = AdjustYear(y, adjust)
if err != nil {
return invalidConv(d, target.Tp)
}
......
......@@ -19,6 +19,7 @@ import (
"encoding/hex"
"fmt"
"sort"
"strconv"
"unicode/utf8"
"unsafe"
......@@ -54,11 +55,18 @@ func (bj BinaryJSON) Type() string {
}
}
// Quote is for JSON_QUOTE
func (bj BinaryJSON) Quote() string {
str := hack.String(bj.GetString())
return strconv.Quote(string(str))
}
// Unquote is for JSON_UNQUOTE.
func (bj BinaryJSON) Unquote() (string, error) {
switch bj.TypeCode {
case TypeCodeString:
s, err := unquoteString(hack.String(bj.GetString()))
tmp := string(hack.String(bj.GetString()))
s, err := unquoteString(tmp)
if err != nil {
return "", errors.Trace(err)
}
......
......@@ -119,7 +119,56 @@ func (t MysqlTime) GoTime(loc *gotime.Location) (gotime.Time, error) {
// IsLeapYear returns if it's leap year.
func (t MysqlTime) IsLeapYear() bool {
return (t.year%4 == 0 && t.year%100 != 0) || t.year%400 == 0
return isLeapYear(t.year)
}
func isLeapYear(year uint16) bool {
return (year%4 == 0 && year%100 != 0) || year%400 == 0
}
var daysByMonth = [12]int{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
// GetLastDay returns the last day of the month
func GetLastDay(year, month int) int {
var day = 0
if month > 0 && month <= 12 {
day = daysByMonth[month-1]
}
if month == 2 && isLeapYear(uint16(year)) {
day = 29
}
return day
}
func getFixDays(year, month, day int, ot gotime.Time) int {
if (year != 0 || month != 0) && day == 0 {
od := ot.Day()
t := ot.AddDate(year, month, day)
td := t.Day()
if od != td {
tm := int(t.Month()) - 1
tMax := GetLastDay(t.Year(), tm)
dd := tMax - od
return dd
}
}
return 0
}
// AddDate fix gap between mysql and golang api
// When we execute select date_add('2018-01-31',interval 1 month) in mysql we got 2018-02-28
// but in tidb we got 2018-03-03.
// Dig it and we found it's caused by golang api time.Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time ,
// it says October 32 converts to November 1 ,it conflits with mysql.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-add
func AddDate(year, month, day int64, ot gotime.Time) (nt gotime.Time) {
df := getFixDays(int(year), int(month), int(day), ot)
if df != 0 {
nt = ot.AddDate(int(year), int(month), df)
} else {
nt = ot.AddDate(int(year), int(month), int(day))
}
return nt
}
func calcTimeFromSec(to *MysqlTime, seconds, microseconds int) {
......
......@@ -791,8 +791,8 @@ func adjustYear(y int) int {
}
// AdjustYear is used for adjusting year and checking its validation.
func AdjustYear(y int64, fromStr bool) (int64, error) {
if y == 0 && !fromStr {
func AdjustYear(y int64, shouldAdjust bool) (int64, error) {
if y == 0 && !shouldAdjust {
return y, nil
}
y = int64(adjustYear(int(y)))
......
......@@ -18,9 +18,13 @@ import (
"unsafe"
)
// String converts slice to string without copy.
// Use at your own risk.
func String(b []byte) (s string) {
// MutableString can be used as string via string(MutableString) without performance loss.
type MutableString string
// String converts slice to MutableString without copy.
// The MutableString can be converts to string without copy.
// Use it at your own risk.
func String(b []byte) (s MutableString) {
if len(b) == 0 {
return ""
}
......
......@@ -111,106 +111,106 @@
"revisionTime": "2018-10-24T15:10:47Z"
},
{
"checksumSHA1": "g4MBFiIkIQ8l4DWYGu60F8jPamQ=",
"checksumSHA1": "MZWBKlzvcvOO6ORrDX//cN1qMyw=",
"path": "github.com/pingcap/parser",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "n+s4Mdz2iK2Bm5LtsGr1vE6KE6A=",
"checksumSHA1": "qPX1edrnPa/EtgVB8IfB5KStU+U=",
"path": "github.com/pingcap/parser/ast",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=",
"checksumSHA1": "npMzF75Vg7tO28nM3MNFq7ciqRY=",
"path": "github.com/pingcap/parser/auth",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=",
"path": "github.com/pingcap/parser/format",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "ZADwr2/PcEd9VI3XF9OvN4HkJ+8=",
"checksumSHA1": "AqNgtzIGY8g7Ojd9ofE8EtKW2mk=",
"path": "github.com/pingcap/parser/model",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "0YvCqsNHKFZEA7vfi3Fq+eYkjW4=",
"checksumSHA1": "4A/BJa0ZcUlrUay8dYVsweGgnZA=",
"path": "github.com/pingcap/parser/mysql",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=",
"path": "github.com/pingcap/parser/opcode",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "TF2rMYy9ewgZpFsJb+jaGXXqZqc=",
"path": "github.com/pingcap/parser/terror",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "sCYsaxxXBau10NOc5tuYQEtmAu0=",
"path": "github.com/pingcap/parser/types",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade",
"revisionTime": "2019-01-20T15:33:11Z"
"revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-02-12T07:36:55Z"
},
{
"checksumSHA1": "uOrWw9c47zwN6COxonFJ0t2IMcM=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "kENit8Wf5S1qoj0HVt2GIgH1khI=",
"checksumSHA1": "IJSv0YocnSmIZRpgQJ1pLtHL8vY=",
"path": "github.com/pingcap/tidb/types",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "7PiTQPW4ftgZIg8KBGCHZjdc0hE=",
"checksumSHA1": "fPdBwAtPVKOr7YAyOMnRxyHixoM=",
"path": "github.com/pingcap/tidb/types/json",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=",
"path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "OOig47D9TSVOUAYkNj2yJok1Hmo=",
"path": "github.com/pingcap/tidb/util/execdetails",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=",
"checksumSHA1": "RdbHgQWMHjRtKjqPcTX81k1V3sw=",
"path": "github.com/pingcap/tidb/util/hack",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70",
"revisionTime": "2019-01-20T14:44:10Z"
"revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-02-12T09:47:48Z"
},
{
"checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=",
......@@ -407,62 +407,62 @@
{
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"path": "vitess.io/vitess/go/hack",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"path": "vitess.io/vitess/go/sqltypes",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=",
"path": "vitess.io/vitess/go/vt/log",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "quYYG+uo3v5HIKvG4QQtRhLC0HY=",
"path": "vitess.io/vitess/go/vt/proto/query",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=",
"path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "tNNlcSFFnlOauS2hXnrz/zA/wfk=",
"checksumSHA1": "1gA4wbQ2DiVjeLJauYSQiuBJiE0=",
"path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "3yiiEdMrUONYMNI84Bs/KONvW94=",
"checksumSHA1": "O/ukE4Sl85Une3Km+fk0zWdaw1k=",
"path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
},
{
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665",
"revisionTime": "2019-01-19T07:50:08Z"
"revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-02-12T02:13:30Z"
}
],
"rootPath": "github.com/XiaoMi/soar"
......
......@@ -2803,7 +2803,7 @@ var xxx_messageInfo_ResolveTransactionResponse proto.InternalMessageInfo
// SplitQuery takes a "SELECT" query and generates a list of queries called
// "query-parts". Each query-part consists of the original query with an
// added WHERE clause that restricts the query-part to operate only on
// rows whose values in the the columns listed in the "split_column" field
// rows whose values in the columns listed in the "split_column" field
// of the request (see below) are in a particular range.
//
// It is guaranteed that the set of rows obtained from
......
......@@ -1031,8 +1031,8 @@ type ColumnType struct {
// Generic field options.
NotNull BoolVal
Autoincrement BoolVal
Default *SQLVal
OnUpdate *SQLVal
Default Expr
OnUpdate Expr
Comment *SQLVal
// Numeric field options
......@@ -1170,6 +1170,8 @@ func (ct *ColumnType) SQLType() querypb.Type {
return sqltypes.Uint64
}
return sqltypes.Int64
case keywordStrings[BOOL], keywordStrings[BOOLEAN]:
return sqltypes.Uint8
case keywordStrings[TEXT]:
return sqltypes.Text
case keywordStrings[TINYTEXT]:
......@@ -2151,34 +2153,36 @@ type Expr interface {
SQLNode
}
func (*AndExpr) iExpr() {}
func (*OrExpr) iExpr() {}
func (*NotExpr) iExpr() {}
func (*ParenExpr) iExpr() {}
func (*ComparisonExpr) iExpr() {}
func (*RangeCond) iExpr() {}
func (*IsExpr) iExpr() {}
func (*ExistsExpr) iExpr() {}
func (*SQLVal) iExpr() {}
func (*NullVal) iExpr() {}
func (BoolVal) iExpr() {}
func (*ColName) iExpr() {}
func (ValTuple) iExpr() {}
func (*Subquery) iExpr() {}
func (ListArg) iExpr() {}
func (*BinaryExpr) iExpr() {}
func (*UnaryExpr) iExpr() {}
func (*IntervalExpr) iExpr() {}
func (*CollateExpr) iExpr() {}
func (*FuncExpr) iExpr() {}
func (*CaseExpr) iExpr() {}
func (*ValuesFuncExpr) iExpr() {}
func (*ConvertExpr) iExpr() {}
func (*SubstrExpr) iExpr() {}
func (*ConvertUsingExpr) iExpr() {}
func (*MatchExpr) iExpr() {}
func (*GroupConcatExpr) iExpr() {}
func (*Default) iExpr() {}
func (*AndExpr) iExpr() {}
func (*OrExpr) iExpr() {}
func (*NotExpr) iExpr() {}
func (*ParenExpr) iExpr() {}
func (*ComparisonExpr) iExpr() {}
func (*RangeCond) iExpr() {}
func (*IsExpr) iExpr() {}
func (*ExistsExpr) iExpr() {}
func (*SQLVal) iExpr() {}
func (*NullVal) iExpr() {}
func (BoolVal) iExpr() {}
func (*ColName) iExpr() {}
func (ValTuple) iExpr() {}
func (*Subquery) iExpr() {}
func (ListArg) iExpr() {}
func (*BinaryExpr) iExpr() {}
func (*UnaryExpr) iExpr() {}
func (*IntervalExpr) iExpr() {}
func (*CollateExpr) iExpr() {}
func (*FuncExpr) iExpr() {}
func (*TimestampFuncExpr) iExpr() {}
func (*CurTimeFuncExpr) iExpr() {}
func (*CaseExpr) iExpr() {}
func (*ValuesFuncExpr) iExpr() {}
func (*ConvertExpr) iExpr() {}
func (*SubstrExpr) iExpr() {}
func (*ConvertUsingExpr) iExpr() {}
func (*MatchExpr) iExpr() {}
func (*GroupConcatExpr) iExpr() {}
func (*Default) iExpr() {}
// ReplaceExpr finds the from expression from root
// and replaces it with to. If from matches root,
......@@ -2379,6 +2383,32 @@ func (node *ComparisonExpr) replace(from, to Expr) bool {
return replaceExprs(from, to, &node.Left, &node.Right, &node.Escape)
}
// IsImpossible returns true if the comparison in the expression can never evaluate to true.
// Note that this is not currently exhaustive to ALL impossible comparisons.
func (node *ComparisonExpr) IsImpossible() bool {
var left, right *SQLVal
var ok bool
if left, ok = node.Left.(*SQLVal); !ok {
return false
}
if right, ok = node.Right.(*SQLVal); !ok {
return false
}
if node.Operator == NotEqualStr && left.Type == right.Type {
if len(left.Val) != len(right.Val) {
return false
}
for i := range left.Val {
if left.Val[i] != right.Val[i] {
return false
}
}
return true
}
return false
}
// RangeCond represents a BETWEEN or a NOT BETWEEN expression.
type RangeCond struct {
Operator string
......@@ -2842,6 +2872,66 @@ func (node *IntervalExpr) replace(from, to Expr) bool {
return replaceExprs(from, to, &node.Expr)
}
// TimestampFuncExpr represents the function and arguments for TIMESTAMP{ADD,DIFF} functions.
type TimestampFuncExpr struct {
Name string
Expr1 Expr
Expr2 Expr
Unit string
}
// Format formats the node.
func (node *TimestampFuncExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%s(%s, %v, %v)", node.Name, node.Unit, node.Expr1, node.Expr2)
}
func (node *TimestampFuncExpr) walkSubtree(visit Visit) error {
if node == nil {
return nil
}
return Walk(
visit,
node.Expr1,
node.Expr2,
)
}
func (node *TimestampFuncExpr) replace(from, to Expr) bool {
if replaceExprs(from, to, &node.Expr1) {
return true
}
if replaceExprs(from, to, &node.Expr2) {
return true
}
return false
}
// CurTimeFuncExpr represents the function and arguments for CURRENT DATE/TIME functions
// supported functions are documented in the grammar
type CurTimeFuncExpr struct {
Name ColIdent
Fsp Expr // fractional seconds precision, integer from 0 to 6
}
// Format formats the node.
func (node *CurTimeFuncExpr) Format(buf *TrackedBuffer) {
buf.Myprintf("%s(%v)", node.Name.String(), node.Fsp)
}
func (node *CurTimeFuncExpr) walkSubtree(visit Visit) error {
if node == nil {
return nil
}
return Walk(
visit,
node.Fsp,
)
}
func (node *CurTimeFuncExpr) replace(from, to Expr) bool {
return replaceExprs(from, to, &node.Fsp)
}
// CollateExpr represents dynamic collate operator.
type CollateExpr struct {
Expr Expr
......
......@@ -75,6 +75,7 @@ func skipToEnd(yylex interface{}) {
expr Expr
exprs Exprs
boolVal BoolVal
sqlVal *SQLVal
colTuple ColTuple
values Values
valTuple ValTuple
......@@ -95,7 +96,7 @@ func skipToEnd(yylex interface{}) {
TableSpec *TableSpec
columnType ColumnType
colKeyOpt ColumnKeyOption
optVal *SQLVal
optVal Expr
LengthScaleOption LengthScaleOption
columnDefinition *ColumnDefinition
indexDefinition *IndexDefinition
......@@ -193,6 +194,7 @@ func skipToEnd(yylex interface{}) {
%token <bytes> CONVERT CAST
%token <bytes> SUBSTR SUBSTRING
%token <bytes> GROUP_CONCAT SEPARATOR
%token <bytes> TIMESTAMPADD TIMESTAMPDIFF
// Match
%token <bytes> MATCH AGAINST BOOLEAN LANGUAGE WITH QUERY EXPANSION
......@@ -228,7 +230,7 @@ func skipToEnd(yylex interface{}) {
%type <str> compare
%type <ins> insert_data
%type <expr> value value_expression num_val
%type <expr> function_call_keyword function_call_nonkeyword function_call_generic function_call_conflict
%type <expr> function_call_keyword function_call_nonkeyword function_call_generic function_call_conflict func_datetime_precision
%type <str> is_suffix
%type <colTuple> col_tuple
%type <exprs> expression_list
......@@ -273,7 +275,8 @@ func skipToEnd(yylex interface{}) {
%type <convertType> convert_type
%type <columnType> column_type
%type <columnType> int_type decimal_type numeric_type time_type char_type spatial_type
%type <optVal> length_opt column_default_opt column_comment_opt on_update_opt
%type <sqlVal> length_opt column_comment_opt
%type <optVal> column_default_opt on_update_opt
%type <str> charset_opt collate_opt
%type <boolVal> unsigned_opt zero_fill_opt
%type <LengthScaleOption> float_length_opt decimal_length_opt
......@@ -702,6 +705,14 @@ int_type:
{
$$ = ColumnType{Type: string($1)}
}
| BOOL
{
$$ = ColumnType{Type: string($1)}
}
| BOOLEAN
{
$$ = ColumnType{Type: string($1)}
}
| TINYINT
{
$$ = ColumnType{Type: string($1)}
......@@ -964,46 +975,18 @@ column_default_opt:
{
$$ = nil
}
| DEFAULT STRING
{
$$ = NewStrVal($2)
}
| DEFAULT INTEGRAL
{
$$ = NewIntVal($2)
}
| DEFAULT FLOAT
{
$$ = NewFloatVal($2)
}
| DEFAULT NULL
{
$$ = NewValArg($2)
}
| DEFAULT CURRENT_TIMESTAMP
{
$$ = NewValArg($2)
}
| DEFAULT CURRENT_TIMESTAMP '(' ')'
{
$$ = NewValArg($2)
}
| DEFAULT BIT_LITERAL
| DEFAULT value_expression
{
$$ = NewBitVal($2)
$$ = $2
}
on_update_opt:
{
$$ = nil
}
| ON UPDATE CURRENT_TIMESTAMP
{
$$ = NewValArg($3)
}
| ON UPDATE CURRENT_TIMESTAMP '(' ')'
| ON UPDATE function_call_nonkeyword
{
$$ = NewValArg($3)
$$ = $3
}
auto_increment_opt:
......@@ -2537,47 +2520,91 @@ function_call_keyword:
Dedicated grammar rules are needed because of the special syntax
*/
function_call_nonkeyword:
CURRENT_TIMESTAMP func_datetime_precision_opt
CURRENT_TIMESTAMP func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("current_timestamp")}
}
| UTC_TIMESTAMP func_datetime_precision_opt
| UTC_TIMESTAMP func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("utc_timestamp")}
}
| UTC_TIME func_datetime_precision_opt
| UTC_TIME func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("utc_time")}
}
| UTC_DATE func_datetime_precision_opt
/* doesn't support fsp */
| UTC_DATE func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("utc_date")}
}
// now
| LOCALTIME func_datetime_precision_opt
| LOCALTIME func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("localtime")}
}
// now
| LOCALTIMESTAMP func_datetime_precision_opt
| LOCALTIMESTAMP func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("localtimestamp")}
}
// curdate
| CURRENT_DATE func_datetime_precision_opt
/* doesn't support fsp */
| CURRENT_DATE func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("current_date")}
}
// curtime
| CURRENT_TIME func_datetime_precision_opt
| CURRENT_TIME func_datetime_opt
{
$$ = &FuncExpr{Name:NewColIdent("current_time")}
}
// these functions can also be called with an optional argument
| CURRENT_TIMESTAMP func_datetime_precision
{
$$ = &CurTimeFuncExpr{Name:NewColIdent("current_timestamp"), Fsp:$2}
}
| UTC_TIMESTAMP func_datetime_precision
{
$$ = &CurTimeFuncExpr{Name:NewColIdent("utc_timestamp"), Fsp:$2}
}
| UTC_TIME func_datetime_precision
{
$$ = &CurTimeFuncExpr{Name:NewColIdent("utc_time"), Fsp:$2}
}
// now
| LOCALTIME func_datetime_precision
{
$$ = &CurTimeFuncExpr{Name:NewColIdent("localtime"), Fsp:$2}
}
// now
| LOCALTIMESTAMP func_datetime_precision
{
$$ = &CurTimeFuncExpr{Name:NewColIdent("localtimestamp"), Fsp:$2}
}
// curtime
| CURRENT_TIME func_datetime_precision
{
$$ = &CurTimeFuncExpr{Name:NewColIdent("current_time"), Fsp:$2}
}
| TIMESTAMPADD openb sql_id ',' value_expression ',' value_expression closeb
{
$$ = &TimestampFuncExpr{Name:string("timestampadd"), Unit:$3.String(), Expr1:$5, Expr2:$7}
}
| TIMESTAMPDIFF openb sql_id ',' value_expression ',' value_expression closeb
{
$$ = &TimestampFuncExpr{Name:string("timestampdiff"), Unit:$3.String(), Expr1:$5, Expr2:$7}
}
func_datetime_precision_opt:
func_datetime_opt:
/* empty */
| openb closeb
func_datetime_precision:
openb value_expression closeb
{
$$ = $2
}
/*
Function calls using non reserved keywords with *normal* syntax forms. Because
the names are non-reserved, they need a dedicated rule so as not to conflict
......@@ -3237,6 +3264,8 @@ reserved_keyword:
| STRAIGHT_JOIN
| TABLE
| THEN
| TIMESTAMPADD
| TIMESTAMPDIFF
| TO
| TRUE
| UNION
......@@ -3267,6 +3296,7 @@ non_reserved_keyword:
| BIT
| BLOB
| BOOL
| BOOLEAN
| CASCADE
| CHAR
| CHARACTER
......
......@@ -357,6 +357,8 @@ var keywords = map[string]int{
"then": THEN,
"time": TIME,
"timestamp": TIMESTAMP,
"timestampadd": TIMESTAMPADD,
"timestampdiff": TIMESTAMPDIFF,
"tinyblob": TINYBLOB,
"tinyint": TINYINT,
"tinytext": TINYTEXT,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册