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

update vendor after chinese lunar new year

上级 9baca3f7
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
TiDB SQL Parser 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 ## 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. 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`. ...@@ -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 ### 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: 1. In your TiDB repository, execute the `replace` instruction to make your parser changes take effect:
```
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:
``` ```
GO111MODULE=on go mod edit -replace github.com/pingcap/parser=github.com/your-repo/parser@your-branch 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: 2. `make dev` to run CI in TiDB.
```
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.
3. File a PR to TiDB. 3. File a PR to TiDB.
......
...@@ -1408,7 +1408,80 @@ type DeleteStmt struct { ...@@ -1408,7 +1408,80 @@ type DeleteStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *DeleteStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -1425,11 +1498,13 @@ func (n *DeleteStmt) Accept(v Visitor) (Node, bool) { ...@@ -1425,11 +1498,13 @@ func (n *DeleteStmt) Accept(v Visitor) (Node, bool) {
} }
n.TableRefs = node.(*TableRefsClause) n.TableRefs = node.(*TableRefsClause)
node, ok = n.Tables.Accept(v) if n.Tables != nil {
if !ok { node, ok = n.Tables.Accept(v)
return n, false if !ok {
return n, false
}
n.Tables = node.(*DeleteTableList)
} }
n.Tables = node.(*DeleteTableList)
if n.Where != nil { if n.Where != nil {
node, ok = n.Where.Accept(v) node, ok = n.Where.Accept(v)
...@@ -1473,7 +1548,69 @@ type UpdateStmt struct { ...@@ -1473,7 +1548,69 @@ type UpdateStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *UpdateStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -1661,18 +1798,6 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error { ...@@ -1661,18 +1798,6 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
} }
return nil 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 ") ctx.WriteKeyWord("SHOW ")
switch n.Tp { switch n.Tp {
...@@ -1694,12 +1819,16 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error { ...@@ -1694,12 +1819,16 @@ func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteName(n.DBName) ctx.WriteName(n.DBName)
case ShowCreateUser: case ShowCreateUser:
ctx.WriteKeyWord("CREATE USER ") 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: case ShowGrants:
ctx.WriteKeyWord("GRANTS") ctx.WriteKeyWord("GRANTS")
if n.User != nil { if n.User != nil {
ctx.WriteKeyWord(" FOR ") 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: case ShowMasterStatus:
ctx.WriteKeyWord("MASTER STATUS") ctx.WriteKeyWord("MASTER STATUS")
......
...@@ -93,6 +93,18 @@ type AuthOption struct { ...@@ -93,6 +93,18 @@ type AuthOption struct {
// TODO: support auth_plugin // 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. // TraceStmt is a statement to trace what sql actually does at background.
type TraceStmt struct { type TraceStmt struct {
stmtNode stmtNode
...@@ -134,7 +146,32 @@ type ExplainStmt struct { ...@@ -134,7 +146,32 @@ type ExplainStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ExplainStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -165,7 +202,20 @@ type PrepareStmt struct { ...@@ -165,7 +202,20 @@ type PrepareStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *PrepareStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -195,7 +245,9 @@ type DeallocateStmt struct { ...@@ -195,7 +245,9 @@ type DeallocateStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *DeallocateStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -228,7 +280,20 @@ type ExecuteStmt struct { ...@@ -228,7 +280,20 @@ type ExecuteStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *ExecuteStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -280,7 +345,9 @@ type BinlogStmt struct { ...@@ -280,7 +345,9 @@ type BinlogStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *BinlogStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -385,7 +452,33 @@ type VariableAssignment struct { ...@@ -385,7 +452,33 @@ type VariableAssignment struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *VariableAssignment) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node interface.
...@@ -426,7 +519,34 @@ type FlushStmt struct { ...@@ -426,7 +519,34 @@ type FlushStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *FlushStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -461,7 +581,15 @@ type KillStmt struct { ...@@ -461,7 +581,15 @@ type KillStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *KillStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -483,7 +611,16 @@ type SetStmt struct { ...@@ -483,7 +611,16 @@ type SetStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *SetStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -535,7 +672,16 @@ type SetPwdStmt struct { ...@@ -535,7 +672,16 @@ type SetPwdStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *SetPwdStmt) Restore(ctx *RestoreCtx) error { 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. // SecureText implements SensitiveStatement interface.
...@@ -559,28 +705,42 @@ type UserSpec struct { ...@@ -559,28 +705,42 @@ type UserSpec struct {
AuthOpt *AuthOption 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. // SecurityString formats the UserSpec without password information.
func (u *UserSpec) SecurityString() string { func (n *UserSpec) SecurityString() string {
withPassword := false withPassword := false
if opt := u.AuthOpt; opt != nil { if opt := n.AuthOpt; opt != nil {
if len(opt.AuthString) > 0 || len(opt.HashString) > 0 { if len(opt.AuthString) > 0 || len(opt.HashString) > 0 {
withPassword = true withPassword = true
} }
} }
if withPassword { 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). // EncodedPassword returns the encoded password (which is the real data mysql.user).
// The boolean value indicates input's password format is legal or not. // The boolean value indicates input's password format is legal or not.
func (u *UserSpec) EncodedPassword() (string, bool) { func (n *UserSpec) EncodedPassword() (string, bool) {
if u.AuthOpt == nil { if n.AuthOpt == nil {
return "", true return "", true
} }
opt := u.AuthOpt opt := n.AuthOpt
if opt.ByAuthString { if opt.ByAuthString {
return auth.EncodePassword(opt.AuthString), true return auth.EncodePassword(opt.AuthString), true
} }
...@@ -603,7 +763,19 @@ type CreateUserStmt struct { ...@@ -603,7 +763,19 @@ type CreateUserStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *CreateUserStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -639,7 +811,26 @@ type AlterUserStmt struct { ...@@ -639,7 +811,26 @@ type AlterUserStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *AlterUserStmt) Restore(ctx *RestoreCtx) error { 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. // SecureText implements SensitiveStatement interface.
...@@ -674,7 +865,19 @@ type DropUserStmt struct { ...@@ -674,7 +865,19 @@ type DropUserStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *DropUserStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -754,7 +957,16 @@ type DoStmt struct { ...@@ -754,7 +957,16 @@ type DoStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *DoStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -831,6 +1043,30 @@ type ShowSlow struct { ...@@ -831,6 +1043,30 @@ type ShowSlow struct {
Kind ShowSlowKind 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. // AdminStmt is the struct for Admin statement.
type AdminStmt struct { type AdminStmt struct {
stmtNode stmtNode
...@@ -847,7 +1083,112 @@ type AdminStmt struct { ...@@ -847,7 +1083,112 @@ type AdminStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *AdminStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -879,7 +1220,65 @@ type PrivElem struct { ...@@ -879,7 +1220,65 @@ type PrivElem struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *PrivElem) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -909,6 +1308,19 @@ const ( ...@@ -909,6 +1308,19 @@ const (
ObjectTypeTable 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. // GrantLevelType is the type for grant level.
type GrantLevelType int type GrantLevelType int
...@@ -930,6 +1342,28 @@ type GrantLevel struct { ...@@ -930,6 +1342,28 @@ type GrantLevel struct {
TableName string 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. // RevokeStmt is the struct for REVOKE statement.
type RevokeStmt struct { type RevokeStmt struct {
stmtNode stmtNode
...@@ -942,7 +1376,32 @@ type RevokeStmt struct { ...@@ -942,7 +1376,32 @@ type RevokeStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *RevokeStmt) Restore(ctx *RestoreCtx) error { 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. // Accept implements Node Accept interface.
...@@ -975,7 +1434,35 @@ type GrantStmt struct { ...@@ -975,7 +1434,35 @@ type GrantStmt struct {
// Restore implements Node interface. // Restore implements Node interface.
func (n *GrantStmt) Restore(ctx *RestoreCtx) error { 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. // SecureText implements SensitiveStatement interface.
......
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"github.com/pingcap/errors" "github.com/pingcap/errors"
. "github.com/pingcap/parser/format"
"github.com/pingcap/parser/terror" "github.com/pingcap/parser/terror"
) )
...@@ -32,6 +33,20 @@ type UserIdentity struct { ...@@ -32,6 +33,20 @@ type UserIdentity struct {
AuthHostname string // Match in privs system (i.e. could be a wildcard) 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. // String converts UserIdentity to the format user@host.
func (user *UserIdentity) String() string { func (user *UserIdentity) String() string {
// TODO: Escape username and hostname. // TODO: Escape username and hostname.
......
version: 2 version: 2
jobs: jobs:
build: build-ut:
docker: docker:
- image: golang:1.11 - image: golang:1.11
working_directory: /go/src/github.com/pingcap/parser working_directory: /go/src/github.com/pingcap/parser
...@@ -19,12 +19,36 @@ jobs: ...@@ -19,12 +19,36 @@ jobs:
- run: - run:
name: "Build & Test" name: "Build & Test"
command: make test command: make test
- run: build-integration:
name: "Integration Test" docker:
command: | - image: golang:1.11
cd /go/src/github.com/pingcap/ working_directory: /go/src/github.com/pingcap/parser
git clone git@github.com:pingcap/tidb.git steps:
cd tidb - checkout
rm go.sum - run:
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 name: "Verify parser.go is up-to-date"
make test 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 ...@@ -16,6 +16,7 @@ package parser
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"strconv"
"strings" "strings"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
...@@ -50,6 +51,10 @@ type Scanner struct { ...@@ -50,6 +51,10 @@ type Scanner struct {
// It may break the compatibility when support those keywords, // It may break the compatibility when support those keywords,
// because some application may already use them as identifiers. // because some application may already use them as identifiers.
supportWindowFunc bool supportWindowFunc bool
// lastScanOffset indicates last offset returned by scan().
// It's used to substring sql in syntax error message.
lastScanOffset int
} }
type specialCommentScanner interface { type specialCommentScanner interface {
...@@ -123,17 +128,14 @@ func (s *Scanner) stmtText() string { ...@@ -123,17 +128,14 @@ func (s *Scanner) stmtText() string {
// Scanner satisfies yyLexer interface which need this function. // Scanner satisfies yyLexer interface which need this function.
func (s *Scanner) Errorf(format string, a ...interface{}) { func (s *Scanner) Errorf(format string, a ...interface{}) {
str := fmt.Sprintf(format, a...) str := fmt.Sprintf(format, a...)
col := s.r.p.Col val := s.r.s[s.lastScanOffset:]
startPos := s.stmtStartPos var lenStr = ""
if s.r.s[startPos] == '\n' {
startPos++
col--
}
val := s.r.s[startPos:]
if len(val) > 2048 { if len(val) > 2048 {
lenStr = "(total length " + strconv.Itoa(len(val)) + ")"
val = val[:2048] 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) s.errs = append(s.errs, err)
} }
...@@ -144,6 +146,7 @@ func (s *Scanner) Errorf(format string, a ...interface{}) { ...@@ -144,6 +146,7 @@ func (s *Scanner) Errorf(format string, a ...interface{}) {
// return invalid tells parser that scanner meets illegal character. // return invalid tells parser that scanner meets illegal character.
func (s *Scanner) Lex(v *yySymType) int { func (s *Scanner) Lex(v *yySymType) int {
tok, pos, lit := s.scan() tok, pos, lit := s.scan()
s.lastScanOffset = pos.Offset
v.offset = pos.Offset v.offset = pos.Offset
v.ident = lit v.ident = lit
if tok == identifier { if tok == identifier {
......
...@@ -17,7 +17,6 @@ import ( ...@@ -17,7 +17,6 @@ import (
"strings" "strings"
"github.com/pingcap/parser/charset" "github.com/pingcap/parser/charset"
"github.com/pingcap/tidb/util/hack"
) )
func isLetter(ch rune) bool { func isLetter(ch rune) bool {
...@@ -372,6 +371,7 @@ var tokenMap = map[string]int{ ...@@ -372,6 +371,7 @@ var tokenMap = map[string]int{
"ON": on, "ON": on,
"ONLY": only, "ONLY": only,
"OPTION": option, "OPTION": option,
"OPTIONALLY": optionally,
"OR": or, "OR": or,
"ORDER": order, "ORDER": order,
"OUTER": outer, "OUTER": outer,
...@@ -634,9 +634,9 @@ func (s *Scanner) isTokenIdentifier(lit string, offset int) int { ...@@ -634,9 +634,9 @@ func (s *Scanner) isTokenIdentifier(lit string, offset int) int {
return tok return tok
} }
} }
tok, ok := tokenMap[hack.String(data)] tok, ok := tokenMap[string(data)]
if !ok && s.supportWindowFunc { if !ok && s.supportWindowFunc {
tok = windowFuncTokenMap[hack.String(data)] tok = windowFuncTokenMap[string(data)]
} }
return tok return tok
} }
......
...@@ -62,6 +62,13 @@ func (s SchemaState) String() string { ...@@ -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. // ColumnInfo provides meta data describing of a table column.
type ColumnInfo struct { type ColumnInfo struct {
ID int64 `json:"id"` ID int64 `json:"id"`
...@@ -76,6 +83,12 @@ type ColumnInfo struct { ...@@ -76,6 +83,12 @@ type ColumnInfo struct {
types.FieldType `json:"type"` types.FieldType `json:"type"`
State SchemaState `json:"state"` State SchemaState `json:"state"`
Comment string `json:"comment"` 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. // Clone clones ColumnInfo.
......
...@@ -218,6 +218,10 @@ const ( ...@@ -218,6 +218,10 @@ const (
ExecutePriv ExecutePriv
// IndexPriv is the privilege to create/drop index. // IndexPriv is the privilege to create/drop index.
IndexPriv 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 is the privilege for all actions.
AllPriv AllPriv
) )
...@@ -277,6 +281,8 @@ var Priv2UserCol = map[PrivilegeType]string{ ...@@ -277,6 +281,8 @@ var Priv2UserCol = map[PrivilegeType]string{
AlterPriv: "Alter_priv", AlterPriv: "Alter_priv",
ExecutePriv: "Execute_priv", ExecutePriv: "Execute_priv",
IndexPriv: "Index_priv", IndexPriv: "Index_priv",
CreateViewPriv: "Create_view_priv",
ShowViewPriv: "Show_view_priv",
} }
// Command2Str is the command information to command name. // Command2Str is the command information to command name.
...@@ -333,10 +339,12 @@ var Col2PrivType = map[string]PrivilegeType{ ...@@ -333,10 +339,12 @@ var Col2PrivType = map[string]PrivilegeType{
"Alter_priv": AlterPriv, "Alter_priv": AlterPriv,
"Execute_priv": ExecutePriv, "Execute_priv": ExecutePriv,
"Index_priv": IndexPriv, "Index_priv": IndexPriv,
"Create_view_priv": CreateViewPriv,
"Show_view_priv": ShowViewPriv,
} }
// AllGlobalPrivs is all the privileges in global scope. // 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. // Priv2Str is the map for privilege to string.
var Priv2Str = map[PrivilegeType]string{ var Priv2Str = map[PrivilegeType]string{
...@@ -356,38 +364,44 @@ var Priv2Str = map[PrivilegeType]string{ ...@@ -356,38 +364,44 @@ var Priv2Str = map[PrivilegeType]string{
AlterPriv: "Alter", AlterPriv: "Alter",
ExecutePriv: "Execute", ExecutePriv: "Execute",
IndexPriv: "Index", IndexPriv: "Index",
CreateViewPriv: "Create View",
ShowViewPriv: "Show View",
} }
// Priv2SetStr is the map for privilege to string. // Priv2SetStr is the map for privilege to string.
var Priv2SetStr = map[PrivilegeType]string{ var Priv2SetStr = map[PrivilegeType]string{
CreatePriv: "Create", CreatePriv: "Create",
SelectPriv: "Select", SelectPriv: "Select",
InsertPriv: "Insert", InsertPriv: "Insert",
UpdatePriv: "Update", UpdatePriv: "Update",
DeletePriv: "Delete", DeletePriv: "Delete",
DropPriv: "Drop", DropPriv: "Drop",
GrantPriv: "Grant", GrantPriv: "Grant",
AlterPriv: "Alter", AlterPriv: "Alter",
ExecutePriv: "Execute", ExecutePriv: "Execute",
IndexPriv: "Index", IndexPriv: "Index",
CreateViewPriv: "Create View",
ShowViewPriv: "Show View",
} }
// SetStr2Priv is the map for privilege set string to privilege type. // SetStr2Priv is the map for privilege set string to privilege type.
var SetStr2Priv = map[string]PrivilegeType{ var SetStr2Priv = map[string]PrivilegeType{
"Create": CreatePriv, "Create": CreatePriv,
"Select": SelectPriv, "Select": SelectPriv,
"Insert": InsertPriv, "Insert": InsertPriv,
"Update": UpdatePriv, "Update": UpdatePriv,
"Delete": DeletePriv, "Delete": DeletePriv,
"Drop": DropPriv, "Drop": DropPriv,
"Grant": GrantPriv, "Grant": GrantPriv,
"Alter": AlterPriv, "Alter": AlterPriv,
"Execute": ExecutePriv, "Execute": ExecutePriv,
"Index": IndexPriv, "Index": IndexPriv,
"Create View": CreateViewPriv,
"Show View": ShowViewPriv,
} }
// AllDBPrivs is all the privileges in database scope. // 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. // AllTablePrivs is all the privileges in table scope.
var AllTablePrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, IndexPriv} var AllTablePrivs = []PrivilegeType{SelectPriv, InsertPriv, UpdatePriv, DeletePriv, CreatePriv, DropPriv, GrantPriv, AlterPriv, IndexPriv}
......
...@@ -79,7 +79,7 @@ var MySQLErrName = map[uint16]string{ ...@@ -79,7 +79,7 @@ var MySQLErrName = map[uint16]string{
ErrDupKeyName: "Duplicate key name '%-.192s'", ErrDupKeyName: "Duplicate key name '%-.192s'",
ErrDupEntry: "Duplicate entry '%-.192s' for key %d", ErrDupEntry: "Duplicate entry '%-.192s' for key %d",
ErrWrongFieldSpec: "Incorrect column specifier for column '%-.192s'", ErrWrongFieldSpec: "Incorrect column specifier for column '%-.192s'",
ErrParse: "%s near '%-.80s' at line %d", ErrParse: "%s %s",
ErrEmptyQuery: "Query was empty", ErrEmptyQuery: "Query was empty",
ErrNonuniqTable: "Not unique table/alias: '%-.192s'", ErrNonuniqTable: "Not unique table/alias: '%-.192s'",
ErrInvalidDefault: "Invalid default value for '%-.192s'", ErrInvalidDefault: "Invalid default value for '%-.192s'",
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -188,6 +188,7 @@ import ( ...@@ -188,6 +188,7 @@ import (
nvarcharType "NVARCHAR" nvarcharType "NVARCHAR"
on "ON" on "ON"
option "OPTION" option "OPTION"
optionally "OPTIONALLY"
or "OR" or "OR"
order "ORDER" order "ORDER"
outer "OUTER" outer "OUTER"
...@@ -4363,6 +4364,10 @@ TableName: ...@@ -4363,6 +4364,10 @@ TableName:
{ {
$$ = &ast.TableName{Schema:model.NewCIStr($1), Name:model.NewCIStr($3)} $$ = &ast.TableName{Schema:model.NewCIStr($1), Name:model.NewCIStr($3)}
} }
| Identifier '.' '*'
{
$$ = &ast.TableName{Name:model.NewCIStr($1)}
}
TableNameList: TableNameList:
TableName TableName
...@@ -5799,7 +5804,7 @@ AdminStmt: ...@@ -5799,7 +5804,7 @@ AdminStmt:
$$ = &ast.AdminStmt{ $$ = &ast.AdminStmt{
Tp: ast.AdminRestoreTable, Tp: ast.AdminRestoreTable,
Tables: []*ast.TableName{$4.(*ast.TableName)}, Tables: []*ast.TableName{$4.(*ast.TableName)},
JobNumber: $5.(int64), JobNumber: $5.(int64),
} }
} }
| "ADMIN" "CLEANUP" "INDEX" TableName Identifier | "ADMIN" "CLEANUP" "INDEX" TableName Identifier
...@@ -7546,11 +7551,11 @@ PrivType: ...@@ -7546,11 +7551,11 @@ PrivType:
} }
| "CREATE" "VIEW" | "CREATE" "VIEW"
{ {
$$ = mysql.PrivilegeType(0) $$ = mysql.CreateViewPriv
} }
| "SHOW" "VIEW" | "SHOW" "VIEW"
{ {
$$ = mysql.PrivilegeType(0) $$ = mysql.ShowViewPriv
} }
| "CREATE" "ROUTINE" | "CREATE" "ROUTINE"
{ {
...@@ -7720,6 +7725,10 @@ Enclosed: ...@@ -7720,6 +7725,10 @@ Enclosed:
{ {
$$ = "" $$ = ""
} }
| "OPTIONALLY" "ENCLOSED" "BY" stringLit
{
$$ = $4
}
| "ENCLOSED" "BY" stringLit | "ENCLOSED" "BY" stringLit
{ {
$$ = $3 $$ = $3
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
package parser package parser
import ( import (
"fmt"
"math" "math"
"regexp" "regexp"
"strconv" "strconv"
...@@ -159,7 +160,7 @@ func ParseErrorWith(errstr string, lineno int) error { ...@@ -159,7 +160,7 @@ func ParseErrorWith(errstr string, lineno int) error {
if len(errstr) > mysql.ErrTextLength { if len(errstr) > mysql.ErrTextLength {
errstr = 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 // 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 ...@@ -408,7 +408,8 @@ func ConvertJSONToInt(sc *stmtctx.StatementContext, j json.BinaryJSON, unsigned
u, err := ConvertFloatToUint(sc, 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())) str := string(hack.String(j.GetString()))
return StrToInt(sc, str)
} }
return 0, errors.New("Unknown type code in JSON") return 0, errors.New("Unknown type code in JSON")
} }
...@@ -433,7 +434,8 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6 ...@@ -433,7 +434,8 @@ func ConvertJSONToFloat(sc *stmtctx.StatementContext, j json.BinaryJSON) (float6
case json.TypeCodeFloat64: case json.TypeCodeFloat64:
return j.GetFloat64(), nil return j.GetFloat64(), nil
case json.TypeCodeString: 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") return 0, errors.New("Unknown type code in JSON")
} }
......
...@@ -170,7 +170,7 @@ func (d *Datum) SetFloat32(f float32) { ...@@ -170,7 +170,7 @@ func (d *Datum) SetFloat32(f float32) {
// GetString gets string value. // GetString gets string value.
func (d *Datum) GetString() string { func (d *Datum) GetString() string {
return hack.String(d.b) return string(hack.String(d.b))
} }
// SetString sets string value. // SetString sets string value.
...@@ -271,7 +271,8 @@ func (d *Datum) SetMysqlDuration(b Duration) { ...@@ -271,7 +271,8 @@ func (d *Datum) SetMysqlDuration(b Duration) {
// GetMysqlEnum gets Enum value // GetMysqlEnum gets Enum value
func (d *Datum) GetMysqlEnum() Enum { 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 // SetMysqlEnum sets Enum value
...@@ -284,7 +285,8 @@ func (d *Datum) SetMysqlEnum(b Enum) { ...@@ -284,7 +285,8 @@ func (d *Datum) SetMysqlEnum(b Enum) {
// GetMysqlSet gets Set value // GetMysqlSet gets Set value
func (d *Datum) GetMysqlSet() Set { 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 // SetMysqlSet sets Set value
...@@ -579,7 +581,8 @@ func (d *Datum) compareString(sc *stmtctx.StatementContext, s string) (int, erro ...@@ -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) { 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) { func (d *Datum) compareMysqlDecimal(sc *stmtctx.StatementContext, dec *MyDecimal) (int, error) {
...@@ -1169,18 +1172,19 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem ...@@ -1169,18 +1172,19 @@ func ProduceDecWithSpecifiedTp(dec *MyDecimal, tp *FieldType, sc *stmtctx.Statem
func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) { func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldType) (Datum, error) {
var ( var (
ret Datum ret Datum
y int64 y int64
err error err error
fromStr bool adjust bool
) )
switch d.k { switch d.k {
case KindString, KindBytes: case KindString, KindBytes:
y, err = StrToInt(sc, d.GetString()) s := d.GetString()
y, err = StrToInt(sc, s)
if err != nil { if err != nil {
return ret, errors.Trace(err) return ret, errors.Trace(err)
} }
fromStr = true adjust = len(s) < 4
case KindMysqlTime: case KindMysqlTime:
y = int64(d.GetMysqlTime().Time.Year()) y = int64(d.GetMysqlTime().Time.Year())
case KindMysqlDuration: case KindMysqlDuration:
...@@ -1192,7 +1196,7 @@ func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldTy ...@@ -1192,7 +1196,7 @@ func (d *Datum) convertToMysqlYear(sc *stmtctx.StatementContext, target *FieldTy
} }
y = ret.GetInt64() y = ret.GetInt64()
} }
y, err = AdjustYear(y, fromStr) y, err = AdjustYear(y, adjust)
if err != nil { if err != nil {
return invalidConv(d, target.Tp) return invalidConv(d, target.Tp)
} }
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"sort" "sort"
"strconv"
"unicode/utf8" "unicode/utf8"
"unsafe" "unsafe"
...@@ -54,11 +55,18 @@ func (bj BinaryJSON) Type() string { ...@@ -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. // Unquote is for JSON_UNQUOTE.
func (bj BinaryJSON) Unquote() (string, error) { func (bj BinaryJSON) Unquote() (string, error) {
switch bj.TypeCode { switch bj.TypeCode {
case TypeCodeString: case TypeCodeString:
s, err := unquoteString(hack.String(bj.GetString())) tmp := string(hack.String(bj.GetString()))
s, err := unquoteString(tmp)
if err != nil { if err != nil {
return "", errors.Trace(err) return "", errors.Trace(err)
} }
......
...@@ -119,7 +119,56 @@ func (t MysqlTime) GoTime(loc *gotime.Location) (gotime.Time, error) { ...@@ -119,7 +119,56 @@ func (t MysqlTime) GoTime(loc *gotime.Location) (gotime.Time, error) {
// IsLeapYear returns if it's leap year. // IsLeapYear returns if it's leap year.
func (t MysqlTime) IsLeapYear() bool { 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) { func calcTimeFromSec(to *MysqlTime, seconds, microseconds int) {
......
...@@ -791,8 +791,8 @@ func adjustYear(y int) int { ...@@ -791,8 +791,8 @@ func adjustYear(y int) int {
} }
// AdjustYear is used for adjusting year and checking its validation. // AdjustYear is used for adjusting year and checking its validation.
func AdjustYear(y int64, fromStr bool) (int64, error) { func AdjustYear(y int64, shouldAdjust bool) (int64, error) {
if y == 0 && !fromStr { if y == 0 && !shouldAdjust {
return y, nil return y, nil
} }
y = int64(adjustYear(int(y))) y = int64(adjustYear(int(y)))
......
...@@ -18,9 +18,13 @@ import ( ...@@ -18,9 +18,13 @@ import (
"unsafe" "unsafe"
) )
// String converts slice to string without copy. // MutableString can be used as string via string(MutableString) without performance loss.
// Use at your own risk. type MutableString string
func String(b []byte) (s 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 { if len(b) == 0 {
return "" return ""
} }
......
...@@ -111,106 +111,106 @@ ...@@ -111,106 +111,106 @@
"revisionTime": "2018-10-24T15:10:47Z" "revisionTime": "2018-10-24T15:10:47Z"
}, },
{ {
"checksumSHA1": "g4MBFiIkIQ8l4DWYGu60F8jPamQ=", "checksumSHA1": "MZWBKlzvcvOO6ORrDX//cN1qMyw=",
"path": "github.com/pingcap/parser", "path": "github.com/pingcap/parser",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "n+s4Mdz2iK2Bm5LtsGr1vE6KE6A=", "checksumSHA1": "qPX1edrnPa/EtgVB8IfB5KStU+U=",
"path": "github.com/pingcap/parser/ast", "path": "github.com/pingcap/parser/ast",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=", "checksumSHA1": "npMzF75Vg7tO28nM3MNFq7ciqRY=",
"path": "github.com/pingcap/parser/auth", "path": "github.com/pingcap/parser/auth",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=", "checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset", "path": "github.com/pingcap/parser/charset",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=", "checksumSHA1": "ohLJW2u9NJEzYIJL/AjOqcuKfMY=",
"path": "github.com/pingcap/parser/format", "path": "github.com/pingcap/parser/format",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "ZADwr2/PcEd9VI3XF9OvN4HkJ+8=", "checksumSHA1": "AqNgtzIGY8g7Ojd9ofE8EtKW2mk=",
"path": "github.com/pingcap/parser/model", "path": "github.com/pingcap/parser/model",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "0YvCqsNHKFZEA7vfi3Fq+eYkjW4=", "checksumSHA1": "4A/BJa0ZcUlrUay8dYVsweGgnZA=",
"path": "github.com/pingcap/parser/mysql", "path": "github.com/pingcap/parser/mysql",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=", "checksumSHA1": "olapD16WCMBU9vrA5PtlERGFfXw=",
"path": "github.com/pingcap/parser/opcode", "path": "github.com/pingcap/parser/opcode",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "TF2rMYy9ewgZpFsJb+jaGXXqZqc=", "checksumSHA1": "TF2rMYy9ewgZpFsJb+jaGXXqZqc=",
"path": "github.com/pingcap/parser/terror", "path": "github.com/pingcap/parser/terror",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "sCYsaxxXBau10NOc5tuYQEtmAu0=", "checksumSHA1": "sCYsaxxXBau10NOc5tuYQEtmAu0=",
"path": "github.com/pingcap/parser/types", "path": "github.com/pingcap/parser/types",
"revision": "05caf0a5ea61e774cd7c6694aa774b05d182bade", "revision": "03c401199829fbfd5d456c5e1e6a96c97b5ac447",
"revisionTime": "2019-01-20T15:33:11Z" "revisionTime": "2019-02-12T07:36:55Z"
}, },
{ {
"checksumSHA1": "uOrWw9c47zwN6COxonFJ0t2IMcM=", "checksumSHA1": "uOrWw9c47zwN6COxonFJ0t2IMcM=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx", "path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"checksumSHA1": "kENit8Wf5S1qoj0HVt2GIgH1khI=", "checksumSHA1": "IJSv0YocnSmIZRpgQJ1pLtHL8vY=",
"path": "github.com/pingcap/tidb/types", "path": "github.com/pingcap/tidb/types",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"checksumSHA1": "7PiTQPW4ftgZIg8KBGCHZjdc0hE=", "checksumSHA1": "fPdBwAtPVKOr7YAyOMnRxyHixoM=",
"path": "github.com/pingcap/tidb/types/json", "path": "github.com/pingcap/tidb/types/json",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=", "checksumSHA1": "yKeU1hJFc7X3afXESYV0Wz5ZPXQ=",
"path": "github.com/pingcap/tidb/types/parser_driver", "path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"checksumSHA1": "OOig47D9TSVOUAYkNj2yJok1Hmo=", "checksumSHA1": "OOig47D9TSVOUAYkNj2yJok1Hmo=",
"path": "github.com/pingcap/tidb/util/execdetails", "path": "github.com/pingcap/tidb/util/execdetails",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=", "checksumSHA1": "RdbHgQWMHjRtKjqPcTX81k1V3sw=",
"path": "github.com/pingcap/tidb/util/hack", "path": "github.com/pingcap/tidb/util/hack",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=", "checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory", "path": "github.com/pingcap/tidb/util/memory",
"revision": "818ec911c5abb2eeaabb1d094cf0eadc9ecc0b70", "revision": "c8554f826d1b5073365d6e8f7e68bcddbd6faf27",
"revisionTime": "2019-01-20T14:44:10Z" "revisionTime": "2019-02-12T09:47:48Z"
}, },
{ {
"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": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=", "checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"path": "vitess.io/vitess/go/hack", "path": "vitess.io/vitess/go/hack",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=", "checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"path": "vitess.io/vitess/go/sqltypes", "path": "vitess.io/vitess/go/sqltypes",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=", "checksumSHA1": "vAIRxI6MHsq3x1hLQwIyw5AvqtI=",
"path": "vitess.io/vitess/go/vt/log", "path": "vitess.io/vitess/go/vt/log",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "quYYG+uo3v5HIKvG4QQtRhLC0HY=", "checksumSHA1": "quYYG+uo3v5HIKvG4QQtRhLC0HY=",
"path": "vitess.io/vitess/go/vt/proto/query", "path": "vitess.io/vitess/go/vt/proto/query",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=", "checksumSHA1": "YLWTmL+rvz0htn0niRMrIUI6rKc=",
"path": "vitess.io/vitess/go/vt/proto/topodata", "path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "tNNlcSFFnlOauS2hXnrz/zA/wfk=", "checksumSHA1": "1gA4wbQ2DiVjeLJauYSQiuBJiE0=",
"path": "vitess.io/vitess/go/vt/proto/vtgate", "path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=", "checksumSHA1": "qz32abYdmm9NfKTc++K0l1EvXXM=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc", "path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "3yiiEdMrUONYMNI84Bs/KONvW94=", "checksumSHA1": "O/ukE4Sl85Une3Km+fk0zWdaw1k=",
"path": "vitess.io/vitess/go/vt/sqlparser", "path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
}, },
{ {
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=", "checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors", "path": "vitess.io/vitess/go/vt/vterrors",
"revision": "dbef792951a40d6ac55f4d58fe50c7ce8e4fc665", "revision": "46205087f71b84d75cf0eaeabb5d59bbca8d8be1",
"revisionTime": "2019-01-19T07:50:08Z" "revisionTime": "2019-02-12T02:13:30Z"
} }
], ],
"rootPath": "github.com/XiaoMi/soar" "rootPath": "github.com/XiaoMi/soar"
......
...@@ -2803,7 +2803,7 @@ var xxx_messageInfo_ResolveTransactionResponse proto.InternalMessageInfo ...@@ -2803,7 +2803,7 @@ var xxx_messageInfo_ResolveTransactionResponse proto.InternalMessageInfo
// SplitQuery takes a "SELECT" query and generates a list of queries called // SplitQuery takes a "SELECT" query and generates a list of queries called
// "query-parts". Each query-part consists of the original query with an // "query-parts". Each query-part consists of the original query with an
// added WHERE clause that restricts the query-part to operate only on // 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. // of the request (see below) are in a particular range.
// //
// It is guaranteed that the set of rows obtained from // It is guaranteed that the set of rows obtained from
......
...@@ -1031,8 +1031,8 @@ type ColumnType struct { ...@@ -1031,8 +1031,8 @@ type ColumnType struct {
// Generic field options. // Generic field options.
NotNull BoolVal NotNull BoolVal
Autoincrement BoolVal Autoincrement BoolVal
Default *SQLVal Default Expr
OnUpdate *SQLVal OnUpdate Expr
Comment *SQLVal Comment *SQLVal
// Numeric field options // Numeric field options
...@@ -1170,6 +1170,8 @@ func (ct *ColumnType) SQLType() querypb.Type { ...@@ -1170,6 +1170,8 @@ func (ct *ColumnType) SQLType() querypb.Type {
return sqltypes.Uint64 return sqltypes.Uint64
} }
return sqltypes.Int64 return sqltypes.Int64
case keywordStrings[BOOL], keywordStrings[BOOLEAN]:
return sqltypes.Uint8
case keywordStrings[TEXT]: case keywordStrings[TEXT]:
return sqltypes.Text return sqltypes.Text
case keywordStrings[TINYTEXT]: case keywordStrings[TINYTEXT]:
...@@ -2151,34 +2153,36 @@ type Expr interface { ...@@ -2151,34 +2153,36 @@ type Expr interface {
SQLNode SQLNode
} }
func (*AndExpr) iExpr() {} func (*AndExpr) iExpr() {}
func (*OrExpr) iExpr() {} func (*OrExpr) iExpr() {}
func (*NotExpr) iExpr() {} func (*NotExpr) iExpr() {}
func (*ParenExpr) iExpr() {} func (*ParenExpr) iExpr() {}
func (*ComparisonExpr) iExpr() {} func (*ComparisonExpr) iExpr() {}
func (*RangeCond) iExpr() {} func (*RangeCond) iExpr() {}
func (*IsExpr) iExpr() {} func (*IsExpr) iExpr() {}
func (*ExistsExpr) iExpr() {} func (*ExistsExpr) iExpr() {}
func (*SQLVal) iExpr() {} func (*SQLVal) iExpr() {}
func (*NullVal) iExpr() {} func (*NullVal) iExpr() {}
func (BoolVal) iExpr() {} func (BoolVal) iExpr() {}
func (*ColName) iExpr() {} func (*ColName) iExpr() {}
func (ValTuple) iExpr() {} func (ValTuple) iExpr() {}
func (*Subquery) iExpr() {} func (*Subquery) iExpr() {}
func (ListArg) iExpr() {} func (ListArg) iExpr() {}
func (*BinaryExpr) iExpr() {} func (*BinaryExpr) iExpr() {}
func (*UnaryExpr) iExpr() {} func (*UnaryExpr) iExpr() {}
func (*IntervalExpr) iExpr() {} func (*IntervalExpr) iExpr() {}
func (*CollateExpr) iExpr() {} func (*CollateExpr) iExpr() {}
func (*FuncExpr) iExpr() {} func (*FuncExpr) iExpr() {}
func (*CaseExpr) iExpr() {} func (*TimestampFuncExpr) iExpr() {}
func (*ValuesFuncExpr) iExpr() {} func (*CurTimeFuncExpr) iExpr() {}
func (*ConvertExpr) iExpr() {} func (*CaseExpr) iExpr() {}
func (*SubstrExpr) iExpr() {} func (*ValuesFuncExpr) iExpr() {}
func (*ConvertUsingExpr) iExpr() {} func (*ConvertExpr) iExpr() {}
func (*MatchExpr) iExpr() {} func (*SubstrExpr) iExpr() {}
func (*GroupConcatExpr) iExpr() {} func (*ConvertUsingExpr) iExpr() {}
func (*Default) iExpr() {} func (*MatchExpr) iExpr() {}
func (*GroupConcatExpr) iExpr() {}
func (*Default) iExpr() {}
// ReplaceExpr finds the from expression from root // ReplaceExpr finds the from expression from root
// and replaces it with to. If from matches root, // and replaces it with to. If from matches root,
...@@ -2379,6 +2383,32 @@ func (node *ComparisonExpr) replace(from, to Expr) bool { ...@@ -2379,6 +2383,32 @@ func (node *ComparisonExpr) replace(from, to Expr) bool {
return replaceExprs(from, to, &node.Left, &node.Right, &node.Escape) 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. // RangeCond represents a BETWEEN or a NOT BETWEEN expression.
type RangeCond struct { type RangeCond struct {
Operator string Operator string
...@@ -2842,6 +2872,66 @@ func (node *IntervalExpr) replace(from, to Expr) bool { ...@@ -2842,6 +2872,66 @@ func (node *IntervalExpr) replace(from, to Expr) bool {
return replaceExprs(from, to, &node.Expr) 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. // CollateExpr represents dynamic collate operator.
type CollateExpr struct { type CollateExpr struct {
Expr Expr Expr Expr
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
...@@ -75,6 +75,7 @@ func skipToEnd(yylex interface{}) { ...@@ -75,6 +75,7 @@ func skipToEnd(yylex interface{}) {
expr Expr expr Expr
exprs Exprs exprs Exprs
boolVal BoolVal boolVal BoolVal
sqlVal *SQLVal
colTuple ColTuple colTuple ColTuple
values Values values Values
valTuple ValTuple valTuple ValTuple
...@@ -95,7 +96,7 @@ func skipToEnd(yylex interface{}) { ...@@ -95,7 +96,7 @@ func skipToEnd(yylex interface{}) {
TableSpec *TableSpec TableSpec *TableSpec
columnType ColumnType columnType ColumnType
colKeyOpt ColumnKeyOption colKeyOpt ColumnKeyOption
optVal *SQLVal optVal Expr
LengthScaleOption LengthScaleOption LengthScaleOption LengthScaleOption
columnDefinition *ColumnDefinition columnDefinition *ColumnDefinition
indexDefinition *IndexDefinition indexDefinition *IndexDefinition
...@@ -193,6 +194,7 @@ func skipToEnd(yylex interface{}) { ...@@ -193,6 +194,7 @@ func skipToEnd(yylex interface{}) {
%token <bytes> CONVERT CAST %token <bytes> CONVERT CAST
%token <bytes> SUBSTR SUBSTRING %token <bytes> SUBSTR SUBSTRING
%token <bytes> GROUP_CONCAT SEPARATOR %token <bytes> GROUP_CONCAT SEPARATOR
%token <bytes> TIMESTAMPADD TIMESTAMPDIFF
// Match // Match
%token <bytes> MATCH AGAINST BOOLEAN LANGUAGE WITH QUERY EXPANSION %token <bytes> MATCH AGAINST BOOLEAN LANGUAGE WITH QUERY EXPANSION
...@@ -228,7 +230,7 @@ func skipToEnd(yylex interface{}) { ...@@ -228,7 +230,7 @@ func skipToEnd(yylex interface{}) {
%type <str> compare %type <str> compare
%type <ins> insert_data %type <ins> insert_data
%type <expr> value value_expression num_val %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 <str> is_suffix
%type <colTuple> col_tuple %type <colTuple> col_tuple
%type <exprs> expression_list %type <exprs> expression_list
...@@ -273,7 +275,8 @@ func skipToEnd(yylex interface{}) { ...@@ -273,7 +275,8 @@ func skipToEnd(yylex interface{}) {
%type <convertType> convert_type %type <convertType> convert_type
%type <columnType> column_type %type <columnType> column_type
%type <columnType> int_type decimal_type numeric_type time_type char_type spatial_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 <str> charset_opt collate_opt
%type <boolVal> unsigned_opt zero_fill_opt %type <boolVal> unsigned_opt zero_fill_opt
%type <LengthScaleOption> float_length_opt decimal_length_opt %type <LengthScaleOption> float_length_opt decimal_length_opt
...@@ -702,6 +705,14 @@ int_type: ...@@ -702,6 +705,14 @@ int_type:
{ {
$$ = ColumnType{Type: string($1)} $$ = ColumnType{Type: string($1)}
} }
| BOOL
{
$$ = ColumnType{Type: string($1)}
}
| BOOLEAN
{
$$ = ColumnType{Type: string($1)}
}
| TINYINT | TINYINT
{ {
$$ = ColumnType{Type: string($1)} $$ = ColumnType{Type: string($1)}
...@@ -964,46 +975,18 @@ column_default_opt: ...@@ -964,46 +975,18 @@ column_default_opt:
{ {
$$ = nil $$ = nil
} }
| DEFAULT STRING | DEFAULT value_expression
{
$$ = 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
{ {
$$ = NewBitVal($2) $$ = $2
} }
on_update_opt: on_update_opt:
{ {
$$ = nil $$ = nil
} }
| ON UPDATE CURRENT_TIMESTAMP | ON UPDATE function_call_nonkeyword
{
$$ = NewValArg($3)
}
| ON UPDATE CURRENT_TIMESTAMP '(' ')'
{ {
$$ = NewValArg($3) $$ = $3
} }
auto_increment_opt: auto_increment_opt:
...@@ -2537,47 +2520,91 @@ function_call_keyword: ...@@ -2537,47 +2520,91 @@ function_call_keyword:
Dedicated grammar rules are needed because of the special syntax Dedicated grammar rules are needed because of the special syntax
*/ */
function_call_nonkeyword: function_call_nonkeyword:
CURRENT_TIMESTAMP func_datetime_precision_opt CURRENT_TIMESTAMP func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("current_timestamp")} $$ = &FuncExpr{Name:NewColIdent("current_timestamp")}
} }
| UTC_TIMESTAMP func_datetime_precision_opt | UTC_TIMESTAMP func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("utc_timestamp")} $$ = &FuncExpr{Name:NewColIdent("utc_timestamp")}
} }
| UTC_TIME func_datetime_precision_opt | UTC_TIME func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("utc_time")} $$ = &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")} $$ = &FuncExpr{Name:NewColIdent("utc_date")}
} }
// now // now
| LOCALTIME func_datetime_precision_opt | LOCALTIME func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("localtime")} $$ = &FuncExpr{Name:NewColIdent("localtime")}
} }
// now // now
| LOCALTIMESTAMP func_datetime_precision_opt | LOCALTIMESTAMP func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("localtimestamp")} $$ = &FuncExpr{Name:NewColIdent("localtimestamp")}
} }
// curdate // curdate
| CURRENT_DATE func_datetime_precision_opt /* doesn't support fsp */
| CURRENT_DATE func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("current_date")} $$ = &FuncExpr{Name:NewColIdent("current_date")}
} }
// curtime // curtime
| CURRENT_TIME func_datetime_precision_opt | CURRENT_TIME func_datetime_opt
{ {
$$ = &FuncExpr{Name:NewColIdent("current_time")} $$ = &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 */ /* empty */
| openb closeb | openb closeb
func_datetime_precision:
openb value_expression closeb
{
$$ = $2
}
/* /*
Function calls using non reserved keywords with *normal* syntax forms. Because 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 the names are non-reserved, they need a dedicated rule so as not to conflict
...@@ -3237,6 +3264,8 @@ reserved_keyword: ...@@ -3237,6 +3264,8 @@ reserved_keyword:
| STRAIGHT_JOIN | STRAIGHT_JOIN
| TABLE | TABLE
| THEN | THEN
| TIMESTAMPADD
| TIMESTAMPDIFF
| TO | TO
| TRUE | TRUE
| UNION | UNION
...@@ -3267,6 +3296,7 @@ non_reserved_keyword: ...@@ -3267,6 +3296,7 @@ non_reserved_keyword:
| BIT | BIT
| BLOB | BLOB
| BOOL | BOOL
| BOOLEAN
| CASCADE | CASCADE
| CHAR | CHAR
| CHARACTER | CHARACTER
......
...@@ -357,6 +357,8 @@ var keywords = map[string]int{ ...@@ -357,6 +357,8 @@ var keywords = map[string]int{
"then": THEN, "then": THEN,
"time": TIME, "time": TIME,
"timestamp": TIMESTAMP, "timestamp": TIMESTAMP,
"timestampadd": TIMESTAMPADD,
"timestampdiff": TIMESTAMPDIFF,
"tinyblob": TINYBLOB, "tinyblob": TINYBLOB,
"tinyint": TINYINT, "tinyint": TINYINT,
"tinytext": TINYTEXT, "tinytext": TINYTEXT,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册