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

daily update

上级 45a48465
......@@ -257,7 +257,7 @@ func parseDSN(odbc string, d *dsn) *dsn {
if d != nil {
// 原来有个判断,后来判断条件被删除了就导致第一次addr无论如何都会被修改。所以这边先注释掉
//addr = d.Addr
// addr = d.Addr
user = d.User
password = d.Password
schema = d.Schema
......@@ -273,27 +273,24 @@ func parseDSN(odbc string, d *dsn) *dsn {
var userInfo, hostInfo, query string
// DSN 格式匹配
if res := regexp.MustCompile(`^(.*)@(.*?)/(.*?)($|\?)(.*)`).FindStringSubmatch(odbc); len(res) > 5 {
// userInfo@hostInfo/database
if res := regexp.MustCompile( `^(.*)@(.*?)/(.*?)($|\?)(.*)`).FindStringSubmatch(odbc); len(res) > 5 {
userInfo = res[1]
hostInfo = res[2]
schema = res[3]
query = res[5]
// hostInfo/database
} else if res := regexp.MustCompile(`^(.*)/(.*?)($|\?)(.*)`).FindStringSubmatch(odbc); len(res) > 4 {
// hostInfo/database
hostInfo = res[1]
schema = res[2]
query = res[4]
// userInfo@hostInfo
} else if res := regexp.MustCompile(`^(.*)@(.*?)($|\?)(.*)`).FindStringSubmatch(odbc); len(res) > 4 {
// userInfo@hostInfo
userInfo = res[1]
hostInfo = res[2]
query = res[4]
// hostInfo
} else {
// hostInfo
hostInfo = odbc
}
......@@ -301,7 +298,7 @@ func parseDSN(odbc string, d *dsn) *dsn {
if userInfo != "" {
user = strings.Split(userInfo, ":")[0]
// 防止密码中含有与用户名相同的字符, 所以用正则替换, 剩下的就是密码
password = strings.TrimLeft(regexp.MustCompile("^" + user).ReplaceAllString(userInfo, ""), ":")
password = strings.TrimLeft(regexp.MustCompile("^"+user).ReplaceAllString(userInfo, ""), ":")
}
// 解析主机信息
......@@ -310,13 +307,13 @@ func parseDSN(odbc string, d *dsn) *dsn {
if host == "" {
host = "127.0.0.1"
}
if port == ""{
if port == "" {
port = "3306"
}
addr = host + ":" + port
// 解析查询字符串
if (query != "") {
if query != "" {
params := strings.Split(query, "&")
for _, f := range params {
attr := strings.Split(f, "=")
......
......@@ -17,7 +17,6 @@ package ast
import (
"io"
"strings"
"github.com/pingcap/parser/model"
"github.com/pingcap/parser/types"
......@@ -27,7 +26,7 @@ import (
// Interfaces embed Node should have 'Node' name suffix.
type Node interface {
// Restore returns the sql text from ast tree
Restore(sb *strings.Builder) error
Restore(ctx *RestoreCtx) error
// Accept accepts Visitor to visit itself.
// The returned node should replace original node.
// ok returns false to stop visiting.
......
......@@ -14,8 +14,6 @@
package ast
import (
"strings"
"github.com/pingcap/errors"
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/model"
......@@ -65,15 +63,17 @@ type DatabaseOption struct {
Value string
}
// Restore implements Recoverable interface.
func (n *DatabaseOption) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DatabaseOption) Restore(ctx *RestoreCtx) error {
switch n.Tp {
case DatabaseOptionCharset:
sb.WriteString("CHARACTER SET = ")
sb.WriteString(n.Value)
ctx.WriteKeyWord("CHARACTER SET")
ctx.WritePlain(" = ")
ctx.WritePlain(n.Value)
case DatabaseOptionCollate:
sb.WriteString("COLLATE = ")
sb.WriteString(n.Value)
ctx.WriteKeyWord("COLLATE")
ctx.WritePlain(" = ")
ctx.WritePlain(n.Value)
default:
return errors.Errorf("invalid DatabaseOptionType: %d", n.Tp)
}
......@@ -90,16 +90,16 @@ type CreateDatabaseStmt struct {
Options []*DatabaseOption
}
// Restore implements Recoverable interface.
func (n *CreateDatabaseStmt) Restore(sb *strings.Builder) error {
sb.WriteString("CREATE DATABASE ")
// Restore implements Node interface.
func (n *CreateDatabaseStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("CREATE DATABASE ")
if n.IfNotExists {
sb.WriteString("IF NOT EXISTS ")
ctx.WriteKeyWord("IF NOT EXISTS ")
}
WriteName(sb, n.Name)
ctx.WriteName(n.Name)
for _, option := range n.Options {
sb.WriteString(" ")
err := option.Restore(sb)
ctx.WritePlain(" ")
err := option.Restore(ctx)
if err != nil {
return errors.Trace(err)
}
......@@ -126,13 +126,13 @@ type DropDatabaseStmt struct {
Name string
}
// Restore implements Recoverable interface.
func (n *DropDatabaseStmt) Restore(sb *strings.Builder) error {
sb.WriteString("DROP DATABASE ")
// Restore implements Node interface.
func (n *DropDatabaseStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("DROP DATABASE ")
if n.IfExists {
sb.WriteString("IF EXISTS ")
ctx.WriteKeyWord("IF EXISTS ")
}
WriteName(sb, n.Name)
ctx.WriteName(n.Name)
return nil
}
......@@ -154,8 +154,8 @@ type IndexColName struct {
Length int
}
// Restore implements Recoverable interface.
func (n *IndexColName) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *IndexColName) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -185,8 +185,8 @@ type ReferenceDef struct {
OnUpdate *OnUpdateOpt
}
// Restore implements Recoverable interface.
func (n *ReferenceDef) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ReferenceDef) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -255,8 +255,8 @@ type OnDeleteOpt struct {
ReferOpt ReferOptionType
}
// Restore implements Recoverable interface.
func (n *OnDeleteOpt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *OnDeleteOpt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -276,8 +276,8 @@ type OnUpdateOpt struct {
ReferOpt ReferOptionType
}
// Restore implements Recoverable interface.
func (n *OnUpdateOpt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *OnUpdateOpt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -325,8 +325,8 @@ type ColumnOption struct {
Refer *ReferenceDef
}
// Restore implements Recoverable interface.
func (n *ColumnOption) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ColumnOption) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -361,8 +361,8 @@ type IndexOption struct {
Comment string
}
// Restore implements Recoverable interface.
func (n *IndexOption) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *IndexOption) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -406,8 +406,8 @@ type Constraint struct {
Option *IndexOption // Index Options
}
// Restore implements Recoverable interface.
func (n *Constraint) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *Constraint) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -451,8 +451,8 @@ type ColumnDef struct {
Options []*ColumnOption
}
// Restore implements Recoverable interface.
func (n *ColumnDef) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ColumnDef) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -494,8 +494,8 @@ type CreateTableStmt struct {
Select ResultSetNode
}
// Restore implements Recoverable interface.
func (n *CreateTableStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CreateTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -553,8 +553,8 @@ type DropTableStmt struct {
IsView bool
}
// Restore implements Recoverable interface.
func (n *DropTableStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DropTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -588,8 +588,8 @@ type RenameTableStmt struct {
TableToTables []*TableToTable
}
// Restore implements Recoverable interface.
func (n *RenameTableStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *RenameTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -629,8 +629,8 @@ type TableToTable struct {
NewTable *TableName
}
// Restore implements Recoverable interface.
func (n *TableToTable) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TableToTable) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -669,8 +669,8 @@ type CreateViewStmt struct {
CheckOption model.ViewCheckOption
}
// Restore implements Recoverable interface.
func (n *CreateViewStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CreateViewStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -706,8 +706,8 @@ type CreateIndexStmt struct {
IndexOption *IndexOption
}
// Restore implements Recoverable interface.
func (n *CreateIndexStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CreateIndexStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -750,8 +750,8 @@ type DropIndexStmt struct {
Table *TableName
}
// Restore implements Recoverable interface.
func (n *DropIndexStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DropIndexStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -843,8 +843,8 @@ type ColumnPosition struct {
RelativeColumn *ColumnName
}
// Restore implements Recoverable interface.
func (n *ColumnPosition) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ColumnPosition) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -925,8 +925,8 @@ type AlterTableSpec struct {
Num uint64
}
// Restore implements Recoverable interface.
func (n *AlterTableSpec) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *AlterTableSpec) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -984,8 +984,8 @@ type AlterTableStmt struct {
Specs []*AlterTableSpec
}
// Restore implements Recoverable interface.
func (n *AlterTableStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *AlterTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1019,8 +1019,8 @@ type TruncateTableStmt struct {
Table *TableName
}
// Restore implements Recoverable interface.
func (n *TruncateTableStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TruncateTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......
......@@ -14,8 +14,6 @@
package ast
import (
"strings"
"github.com/pingcap/errors"
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/model"
......@@ -85,8 +83,8 @@ type Join struct {
StraightJoin bool
}
// Restore implements Recoverable interface.
func (n *Join) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *Join) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -133,16 +131,16 @@ type TableName struct {
IndexHints []*IndexHint
}
// Restore implements Recoverable interface.
func (n *TableName) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TableName) Restore(ctx *RestoreCtx) error {
if n.Schema.String() != "" {
WriteName(sb, n.Schema.String())
sb.WriteString(".")
ctx.WriteName(n.Schema.String())
ctx.WritePlain(".")
}
WriteName(sb, n.Name.String())
ctx.WriteName(n.Name.String())
for _, value := range n.IndexHints {
sb.WriteString(" ")
if err := value.Restore(sb); err != nil {
ctx.WritePlain(" ")
if err := value.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while splicing IndexHints")
}
}
......@@ -178,7 +176,7 @@ type IndexHint struct {
}
// IndexHint Restore (The const field uses switch to facilitate understanding)
func (n *IndexHint) Restore(sb *strings.Builder) error {
func (n *IndexHint) Restore(ctx *RestoreCtx) error {
indexHintType := ""
switch n.HintType {
case 1:
......@@ -204,17 +202,16 @@ func (n *IndexHint) Restore(sb *strings.Builder) error {
default: // Prevent accidents
return errors.New("IndexHintScope has an error while matching")
}
sb.WriteString(indexHintType)
sb.WriteString(indexHintScope)
sb.WriteString(" (")
ctx.WriteKeyWord(indexHintType)
ctx.WriteKeyWord(indexHintScope)
ctx.WritePlain(" (")
for i, value := range n.IndexNames {
if i > 0 {
sb.WriteString(", ")
ctx.WritePlain(", ")
}
WriteName(sb, value.O)
ctx.WriteName(value.O)
}
sb.WriteString(")")
ctx.WritePlain(")")
return nil
}
......@@ -235,8 +232,8 @@ type DeleteTableList struct {
Tables []*TableName
}
// Restore implements Recoverable interface.
func (n *DeleteTableList) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DeleteTableList) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -266,8 +263,8 @@ type OnCondition struct {
Expr ExprNode
}
// Restore implements Recoverable interface.
func (n *OnCondition) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *OnCondition) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -298,8 +295,8 @@ type TableSource struct {
AsName model.CIStr
}
// Restore implements Recoverable interface.
func (n *TableSource) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TableSource) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -349,8 +346,8 @@ type WildCardField struct {
Schema model.CIStr
}
// Restore implements Recoverable interface.
func (n *WildCardField) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *WildCardField) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -384,8 +381,8 @@ type SelectField struct {
Auxiliary bool
}
// Restore implements Recoverable interface.
func (n *SelectField) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *SelectField) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -413,8 +410,8 @@ type FieldList struct {
Fields []*SelectField
}
// Restore implements Recoverable interface.
func (n *FieldList) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *FieldList) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -442,8 +439,8 @@ type TableRefsClause struct {
TableRefs *Join
}
// Restore implements Recoverable interface.
func (n *TableRefsClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TableRefsClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -470,8 +467,8 @@ type ByItem struct {
Desc bool
}
// Restore implements Recoverable interface.
func (n *ByItem) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ByItem) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -496,8 +493,8 @@ type GroupByClause struct {
Items []*ByItem
}
// Restore implements Recoverable interface.
func (n *GroupByClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *GroupByClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -524,8 +521,8 @@ type HavingClause struct {
Expr ExprNode
}
// Restore implements Recoverable interface.
func (n *HavingClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *HavingClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -551,8 +548,8 @@ type OrderByClause struct {
ForUnion bool
}
// Restore implements Recoverable interface.
func (n *OrderByClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *OrderByClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -609,8 +606,8 @@ type SelectStmt struct {
IsInBraces bool
}
// Restore implements Recoverable interface.
func (n *SelectStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *SelectStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -708,8 +705,8 @@ type UnionSelectList struct {
Selects []*SelectStmt
}
// Restore implements Recoverable interface.
func (n *UnionSelectList) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *UnionSelectList) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -741,8 +738,8 @@ type UnionStmt struct {
Limit *Limit
}
// Restore implements Recoverable interface.
func (n *UnionStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *UnionStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -786,8 +783,8 @@ type Assignment struct {
Expr ExprNode
}
// Restore implements Recoverable interface.
func (n *Assignment) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *Assignment) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -825,8 +822,8 @@ type LoadDataStmt struct {
IgnoreLines uint64
}
// Restore implements Recoverable interface.
func (n *LoadDataStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *LoadDataStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -883,8 +880,8 @@ type InsertStmt struct {
Select ResultSetNode
}
// Restore implements Recoverable interface.
func (n *InsertStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *InsertStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -964,8 +961,8 @@ type DeleteStmt struct {
TableHints []*TableOptimizerHint
}
// Restore implements Recoverable interface.
func (n *DeleteStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DeleteStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1029,8 +1026,8 @@ type UpdateStmt struct {
TableHints []*TableOptimizerHint
}
// Restore implements Recoverable interface.
func (n *UpdateStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *UpdateStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1085,8 +1082,8 @@ type Limit struct {
Offset ExprNode
}
// Restore implements Recoverable interface.
func (n *Limit) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *Limit) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1170,8 +1167,8 @@ type ShowStmt struct {
Where ExprNode
}
// Restore implements Recoverable interface.
func (n *ShowStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ShowStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1235,8 +1232,8 @@ type WindowSpec struct {
Frame *FrameClause
}
// Restore implements Recoverable interface.
func (n *WindowSpec) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *WindowSpec) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1278,8 +1275,8 @@ type PartitionByClause struct {
Items []*ByItem
}
// Restore implements Recoverable interface.
func (n *PartitionByClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PartitionByClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1319,8 +1316,8 @@ type FrameClause struct {
Extent FrameExtent
}
// Restore implements Recoverable interface.
func (n *FrameClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *FrameClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1372,8 +1369,8 @@ type FrameBound struct {
Unit ExprNode
}
// Restore implements Recoverable interface.
func (n *FrameBound) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *FrameBound) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......
......@@ -79,9 +79,24 @@ type BetweenExpr struct {
Not bool
}
// Restore implements Recoverable interface.
func (n *BetweenExpr) Restore(sb *strings.Builder) error {
return errors.New("Not implemented")
// Restore implements Node interface.
func (n *BetweenExpr) Restore(ctx *RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore BetweenExpr.Expr")
}
if n.Not {
ctx.WriteKeyWord(" NOT BETWEEN ")
} else {
ctx.WriteKeyWord(" BETWEEN ")
}
if err := n.Left.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore BetweenExpr.Left")
}
ctx.WriteKeyWord(" AND ")
if err := n.Right.Restore(ctx); err != nil {
return errors.Annotate(err, "An error occurred while restore BetweenExpr.Right ")
}
return nil
}
// Format the ExprNode into a Writer.
......@@ -137,8 +152,8 @@ type BinaryOperationExpr struct {
R ExprNode
}
// Restore implements Recoverable interface.
func (n *BinaryOperationExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *BinaryOperationExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -183,8 +198,8 @@ type WhenClause struct {
Result ExprNode
}
// Restore implements Recoverable interface.
func (n *WhenClause) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *WhenClause) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -221,8 +236,8 @@ type CaseExpr struct {
ElseClause ExprNode
}
// Restore implements Recoverable interface.
func (n *CaseExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CaseExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -290,8 +305,8 @@ type SubqueryExpr struct {
Exists bool
}
// Restore implements Recoverable interface.
func (n *SubqueryExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *SubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -331,8 +346,8 @@ type CompareSubqueryExpr struct {
All bool
}
// Restore implements Recoverable interface.
func (n *CompareSubqueryExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CompareSubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -369,17 +384,17 @@ type ColumnName struct {
Name model.CIStr
}
// Restore implements Recoverable interface.
func (n *ColumnName) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ColumnName) Restore(ctx *RestoreCtx) error {
if n.Schema.O != "" {
WriteName(sb, n.Schema.O)
sb.WriteString(".")
ctx.WriteName(n.Schema.O)
ctx.WritePlain(".")
}
if n.Table.O != "" {
WriteName(sb, n.Table.O)
sb.WriteString(".")
ctx.WriteName(n.Table.O)
ctx.WritePlain(".")
}
WriteName(sb, n.Name.O)
ctx.WriteName(n.Name.O)
return nil
}
......@@ -431,10 +446,9 @@ type ColumnNameExpr struct {
Refer *ResultField
}
// Restore implements Recoverable interface.
func (n *ColumnNameExpr) Restore(sb *strings.Builder) error {
err := n.Name.Restore(sb)
if err != nil {
// Restore implements Node interface.
func (n *ColumnNameExpr) Restore(ctx *RestoreCtx) error {
if err := n.Name.Restore(ctx); err != nil {
return errors.Trace(err)
}
return nil
......@@ -468,8 +482,8 @@ type DefaultExpr struct {
Name *ColumnName
}
// Restore implements Recoverable interface.
func (n *DefaultExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DefaultExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -505,8 +519,8 @@ type ExistsSubqueryExpr struct {
Not bool
}
// Restore implements Recoverable interface.
func (n *ExistsSubqueryExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ExistsSubqueryExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -543,8 +557,8 @@ type PatternInExpr struct {
Sel ExprNode
}
// Restore implements Recoverable interface.
func (n *PatternInExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PatternInExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -603,9 +617,16 @@ type IsNullExpr struct {
Not bool
}
// Restore implements Recoverable interface.
func (n *IsNullExpr) Restore(sb *strings.Builder) error {
n.Format(sb)
// Restore implements Node interface.
func (n *IsNullExpr) Restore(ctx *RestoreCtx) error {
if err := n.Expr.Restore(ctx); err != nil {
return errors.Trace(err)
}
if n.Not {
ctx.WriteKeyWord(" IS NOT NULL")
} else {
ctx.WriteKeyWord(" IS NULL")
}
return nil
}
......@@ -645,8 +666,8 @@ type IsTruthExpr struct {
True int64
}
// Restore implements Recoverable interface.
func (n *IsTruthExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *IsTruthExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -696,8 +717,8 @@ type PatternLikeExpr struct {
PatTypes []byte
}
// Restore implements Recoverable interface.
func (n *PatternLikeExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PatternLikeExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -754,8 +775,8 @@ type ParenthesesExpr struct {
Expr ExprNode
}
// Restore implements Recoverable interface.
func (n *ParenthesesExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ParenthesesExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -796,8 +817,8 @@ type PositionExpr struct {
Refer *ResultField
}
// Restore implements Recoverable interface.
func (n *PositionExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PositionExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -839,8 +860,8 @@ type PatternRegexpExpr struct {
Sexpr *string
}
// Restore implements Recoverable interface.
func (n *PatternRegexpExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PatternRegexpExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -883,8 +904,8 @@ type RowExpr struct {
Values []ExprNode
}
// Restore implements Recoverable interface.
func (n *RowExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *RowExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -919,9 +940,14 @@ type UnaryOperationExpr struct {
V ExprNode
}
// Restore implements Recoverable interface.
func (n *UnaryOperationExpr) Restore(sb *strings.Builder) error {
n.Format(sb)
// Restore implements Node interface.
func (n *UnaryOperationExpr) Restore(ctx *RestoreCtx) error {
if err := n.Op.Restore(ctx.In); err != nil {
return errors.Trace(err)
}
if err := n.V.Restore(ctx); err != nil {
return errors.Trace(err)
}
return nil
}
......@@ -953,8 +979,8 @@ type ValuesExpr struct {
Column *ColumnNameExpr
}
// Restore implements Recoverable interface.
func (n *ValuesExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ValuesExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -995,8 +1021,8 @@ type VariableExpr struct {
Value ExprNode
}
// Restore implements Recoverable interface.
func (n *VariableExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *VariableExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -1029,8 +1055,8 @@ type MaxValueExpr struct {
exprNode
}
// Restore implements Recoverable interface.
func (n *MaxValueExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *MaxValueExpr) Restore(ctx *RestoreCtx) error {
panic("Not implemented")
}
......
......@@ -16,7 +16,6 @@ package ast
import (
"fmt"
"io"
"strings"
"github.com/pingcap/errors"
"github.com/pingcap/parser/model"
......@@ -329,8 +328,8 @@ type FuncCallExpr struct {
Args []ExprNode
}
// Restore implements Recoverable interface.
func (n *FuncCallExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *FuncCallExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -406,8 +405,8 @@ type FuncCastExpr struct {
FunctionType CastFunctionType
}
// Restore implements Recoverable interface.
func (n *FuncCastExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *FuncCastExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -519,8 +518,8 @@ type AggregateFuncExpr struct {
Distinct bool
}
// Restore implements Recoverable interface.
func (n *AggregateFuncExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *AggregateFuncExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -592,8 +591,8 @@ type WindowFuncExpr struct {
Spec WindowSpec
}
// Restore implements Recoverable interface.
func (n *WindowFuncExpr) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *WindowFuncExpr) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......
......@@ -98,8 +98,8 @@ type TraceStmt struct {
Format string
}
// Restore implements Recoverable interface.
func (n *TraceStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TraceStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -129,8 +129,8 @@ type ExplainStmt struct {
Analyze bool
}
// Restore implements Recoverable interface.
func (n *ExplainStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ExplainStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -160,8 +160,8 @@ type PrepareStmt struct {
SQLVar *VariableExpr
}
// Restore implements Recoverable interface.
func (n *PrepareStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PrepareStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -190,8 +190,8 @@ type DeallocateStmt struct {
Name string
}
// Restore implements Recoverable interface.
func (n *DeallocateStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DeallocateStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -223,8 +223,8 @@ type ExecuteStmt struct {
ExecID uint32
}
// Restore implements Recoverable interface.
func (n *ExecuteStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *ExecuteStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -251,8 +251,8 @@ type BeginStmt struct {
stmtNode
}
// Restore implements Recoverable interface.
func (n *BeginStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *BeginStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -274,8 +274,8 @@ type BinlogStmt struct {
Str string
}
// Restore implements Recoverable interface.
func (n *BinlogStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *BinlogStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -295,8 +295,8 @@ type CommitStmt struct {
stmtNode
}
// Restore implements Recoverable interface.
func (n *CommitStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CommitStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -316,8 +316,8 @@ type RollbackStmt struct {
stmtNode
}
// Restore implements Recoverable interface.
func (n *RollbackStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *RollbackStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -339,10 +339,10 @@ type UseStmt struct {
DBName string
}
// Restore implements Recoverable interface.
func (n *UseStmt) Restore(sb *strings.Builder) error {
sb.WriteString("USE ")
WriteName(sb, n.DBName)
// Restore implements Node interface.
func (n *UseStmt) Restore(ctx *RestoreCtx) error {
ctx.WriteKeyWord("USE ")
ctx.WriteName(n.DBName)
return nil
}
......@@ -377,8 +377,8 @@ type VariableAssignment struct {
ExtendValue ValueExpr
}
// Restore implements Recoverable interface.
func (n *VariableAssignment) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *VariableAssignment) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -418,8 +418,8 @@ type FlushStmt struct {
ReadLock bool
}
// Restore implements Recoverable interface.
func (n *FlushStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *FlushStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -453,8 +453,8 @@ type KillStmt struct {
TiDBExtension bool
}
// Restore implements Recoverable interface.
func (n *KillStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *KillStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -475,8 +475,8 @@ type SetStmt struct {
Variables []*VariableAssignment
}
// Restore implements Recoverable interface.
func (n *SetStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *SetStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -527,8 +527,8 @@ type SetPwdStmt struct {
Password string
}
// Restore implements Recoverable interface.
func (n *SetPwdStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *SetPwdStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -595,8 +595,8 @@ type CreateUserStmt struct {
Specs []*UserSpec
}
// Restore implements Recoverable interface.
func (n *CreateUserStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *CreateUserStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -631,8 +631,8 @@ type AlterUserStmt struct {
Specs []*UserSpec
}
// Restore implements Recoverable interface.
func (n *AlterUserStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *AlterUserStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -666,8 +666,8 @@ type DropUserStmt struct {
UserList []*auth.UserIdentity
}
// Restore implements Recoverable interface.
func (n *DropUserStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DropUserStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -688,8 +688,8 @@ type DoStmt struct {
Exprs []ExprNode
}
// Restore implements Recoverable interface.
func (n *DoStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DoStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -780,8 +780,8 @@ type AdminStmt struct {
ShowSlow *ShowSlow
}
// Restore implements Recoverable interface.
func (n *AdminStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *AdminStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -812,8 +812,8 @@ type PrivElem struct {
Cols []*ColumnName
}
// Restore implements Recoverable interface.
func (n *PrivElem) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *PrivElem) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -875,8 +875,8 @@ type RevokeStmt struct {
Users []*UserSpec
}
// Restore implements Recoverable interface.
func (n *RevokeStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *RevokeStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -908,8 +908,8 @@ type GrantStmt struct {
WithGrant bool
}
// Restore implements Recoverable interface.
func (n *GrantStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *GrantStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -978,8 +978,8 @@ type TableOptimizerHint struct {
MaxExecutionTime uint64
}
// Restore implements Recoverable interface.
func (n *TableOptimizerHint) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *TableOptimizerHint) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......
......@@ -14,8 +14,6 @@
package ast
import (
"strings"
"github.com/pingcap/errors"
"github.com/pingcap/parser/model"
)
......@@ -39,8 +37,8 @@ type AnalyzeTableStmt struct {
IndexFlag bool
}
// Restore implements Recoverable interface.
func (n *AnalyzeTableStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *AnalyzeTableStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -68,8 +66,8 @@ type DropStatsStmt struct {
Table *TableName
}
// Restore implements Recoverable interface.
func (n *DropStatsStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *DropStatsStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......@@ -95,8 +93,8 @@ type LoadStatsStmt struct {
Path string
}
// Restore implements Recoverable interface.
func (n *LoadStatsStmt) Restore(sb *strings.Builder) error {
// Restore implements Node interface.
func (n *LoadStatsStmt) Restore(ctx *RestoreCtx) error {
return errors.New("Not implemented")
}
......
......@@ -13,7 +13,11 @@
package ast
import "strings"
import (
"fmt"
"io"
"strings"
)
// IsReadOnly checks whether the input ast is readOnly.
func IsReadOnly(node Node) bool {
......@@ -62,14 +66,150 @@ func (checker *readOnlyChecker) Leave(in Node) (out Node, ok bool) {
return in, checker.readOnly
}
// WriteName append escaped `name` with back quote to `sb`.
func WriteName(sb *strings.Builder, name string) {
sb.WriteString("`")
sb.WriteString(EscapeName(name))
sb.WriteString("`")
//RestoreFlag mark the Restore format
type RestoreFlags uint64
// Mutually exclusive group of `RestoreFlags`:
// [RestoreStringSingleQuotes, RestoreStringDoubleQuotes]
// [RestoreKeyWordUppercase, RestoreKeyWordLowercase]
// [RestoreNameUppercase, RestoreNameLowercase]
// [RestoreNameDoubleQuotes, RestoreNameBackQuotes]
// The flag with the left position in each group has a higher priority.
const (
RestoreStringSingleQuotes RestoreFlags = 1 << iota
RestoreStringDoubleQuotes
RestoreStringEscapeBackslash
RestoreKeyWordUppercase
RestoreKeyWordLowercase
RestoreNameUppercase
RestoreNameLowercase
RestoreNameDoubleQuotes
RestoreNameBackQuotes
)
const (
DefaultRestoreFlags = RestoreStringSingleQuotes | RestoreKeyWordUppercase | RestoreNameBackQuotes
)
func (rf RestoreFlags) has(flag RestoreFlags) bool {
return rf&flag != 0
}
// HasStringSingleQuotesFlag returns a boolean indicating when `rf` has `RestoreStringSingleQuotes` flag.
func (rf RestoreFlags) HasStringSingleQuotesFlag() bool {
return rf.has(RestoreStringSingleQuotes)
}
// HasStringDoubleQuotesFlag returns a boolean indicating whether `rf` has `RestoreStringDoubleQuotes` flag.
func (rf RestoreFlags) HasStringDoubleQuotesFlag() bool {
return rf.has(RestoreStringDoubleQuotes)
}
// HasStringEscapeBackslashFlag returns a boolean indicating whether `rf` has `RestoreStringEscapeBackslash` flag.
func (rf RestoreFlags) HasStringEscapeBackslashFlag() bool {
return rf.has(RestoreStringEscapeBackslash)
}
// HasKeyWordUppercaseFlag returns a boolean indicating whether `rf` has `RestoreKeyWordUppercase` flag.
func (rf RestoreFlags) HasKeyWordUppercaseFlag() bool {
return rf.has(RestoreKeyWordUppercase)
}
// HasKeyWordLowercaseFlag returns a boolean indicating whether `rf` has `RestoreKeyWordLowercase` flag.
func (rf RestoreFlags) HasKeyWordLowercaseFlag() bool {
return rf.has(RestoreKeyWordLowercase)
}
// HasNameUppercaseFlag returns a boolean indicating whether `rf` has `RestoreNameUppercase` flag.
func (rf RestoreFlags) HasNameUppercaseFlag() bool {
return rf.has(RestoreNameUppercase)
}
// HasNameLowercaseFlag returns a boolean indicating whether `rf` has `RestoreNameLowercase` flag.
func (rf RestoreFlags) HasNameLowercaseFlag() bool {
return rf.has(RestoreNameLowercase)
}
// HasNameDoubleQuotesFlag returns a boolean indicating whether `rf` has `RestoreNameDoubleQuotes` flag.
func (rf RestoreFlags) HasNameDoubleQuotesFlag() bool {
return rf.has(RestoreNameDoubleQuotes)
}
// HasNameBackQuotesFlag returns a boolean indicating whether `rf` has `RestoreNameBackQuotes` flag.
func (rf RestoreFlags) HasNameBackQuotesFlag() bool {
return rf.has(RestoreNameBackQuotes)
}
// RestoreCtx is `Restore` context to hold flags and writer.
type RestoreCtx struct {
Flags RestoreFlags
In io.Writer
}
// NewRestoreCtx returns a new `RestoreCtx`.
func NewRestoreCtx(flags RestoreFlags, in io.Writer) *RestoreCtx {
return &RestoreCtx{flags, in}
}
// WriteKeyWord writes the `keyWord` into writer.
// `keyWord` will be converted format(uppercase and lowercase for now) according to `RestoreFlags`.
func (ctx *RestoreCtx) WriteKeyWord(keyWord string) {
switch {
case ctx.Flags.HasKeyWordUppercaseFlag():
keyWord = strings.ToUpper(keyWord)
case ctx.Flags.HasKeyWordLowercaseFlag():
keyWord = strings.ToLower(keyWord)
}
fmt.Fprint(ctx.In, keyWord)
}
// WriteString writes the string into writer
// `str` may be wrapped in quotes and escaped according to RestoreFlags.
func (ctx *RestoreCtx) WriteString(str string) {
if ctx.Flags.HasStringEscapeBackslashFlag() {
str = strings.Replace(str, `\`, `\\`, -1)
}
quotes := ""
switch {
case ctx.Flags.HasStringSingleQuotesFlag():
str = strings.Replace(str, `'`, `''`, -1)
quotes = `'`
case ctx.Flags.HasStringDoubleQuotesFlag():
str = strings.Replace(str, `"`, `""`, -1)
quotes = `"`
}
fmt.Fprint(ctx.In, quotes, str, quotes)
}
// WriteName writes the name into writer
// `name` maybe wrapped in quotes and escaped according to RestoreFlags.
func (ctx *RestoreCtx) WriteName(name string) {
switch {
case ctx.Flags.HasNameUppercaseFlag():
name = strings.ToUpper(name)
case ctx.Flags.HasNameLowercaseFlag():
name = strings.ToLower(name)
}
quotes := ""
switch {
case ctx.Flags.HasNameDoubleQuotesFlag():
name = strings.Replace(name, `"`, `""`, -1)
quotes = `"`
case ctx.Flags.HasNameBackQuotesFlag():
name = strings.Replace(name, "`", "``", -1)
quotes = "`"
}
fmt.Fprint(ctx.In, quotes, name, quotes)
}
// WritePlain writes the plain text into writer without any handling.
func (ctx *RestoreCtx) WritePlain(plainText string) {
fmt.Fprint(ctx.In, plainText)
}
// EscapeName escape the `name`
func EscapeName(name string) string {
return strings.Replace(name, "`", "``", -1)
// WritePlainf write the plain text into writer without any handling.
func (ctx *RestoreCtx) WritePlainf(format string, a ...interface{}) {
fmt.Fprintf(ctx.In, format, a...)
}
......@@ -7,11 +7,10 @@ require (
github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186
github.com/cznic/y v0.0.0-20170802143616-045f81c6662a
github.com/pingcap/check v0.0.0-20171206051426-1c287c953996
github.com/pingcap/check v0.0.0-20181213055612-5c2b07721bdb
github.com/pingcap/errors v0.11.0
github.com/pingcap/tidb v0.0.0-20181203021530-741adcee43e2
github.com/pingcap/tidb v0.0.0-20181217070741-096bb68e6bef
github.com/pingcap/tipb v0.0.0-20181012112600-11e33c750323
github.com/sirupsen/logrus v1.2.0
golang.org/x/net v0.0.0-20181029044818-c44066c5c816
golang.org/x/text v0.3.0
)
......@@ -250,6 +250,14 @@ func (t *TableInfo) GetAutoIncrementColInfo() *ColumnInfo {
return nil
}
func (t *TableInfo) IsAutoIncColUnsigned() bool {
col := t.GetAutoIncrementColInfo()
if col == nil {
return false
}
return mysql.HasUnsignedFlag(col.Flag)
}
// Cols returns the columns of the table in public state.
func (t *TableInfo) Cols() []*ColumnInfo {
publicColumns := make([]*ColumnInfo, len(t.Columns))
......
......@@ -16,6 +16,8 @@ package opcode
import (
"fmt"
"io"
"github.com/pingcap/errors"
)
// Op is opcode type.
......@@ -136,3 +138,12 @@ var opsLiteral = map[Op]string{
func (o Op) Format(w io.Writer) {
fmt.Fprintf(w, "%s", opsLiteral[o])
}
// Restore the Op into a Writer
func (o Op) Restore(w io.Writer) error {
if v, ok := opsLiteral[o]; ok {
fmt.Fprint(w, v)
return nil
}
return errors.Errorf("Invalid opcode type %d during restoring AST to SQL text", o)
}
......@@ -128,12 +128,24 @@ func DefaultParamTypeForValue(value interface{}, tp *FieldType) {
tp.Decimal = UnspecifiedLength
default:
DefaultTypeForValue(value, tp)
if hasVariantFieldLength(tp) {
tp.Flen = UnspecifiedLength
}
if tp.Tp == mysql.TypeUnspecified {
tp.Tp = mysql.TypeVarString
}
}
}
func hasVariantFieldLength(tp *FieldType) bool {
switch tp.Tp {
case mysql.TypeLonglong, mysql.TypeVarString, mysql.TypeDouble, mysql.TypeBlob,
mysql.TypeBit, mysql.TypeDuration, mysql.TypeNewDecimal, mysql.TypeEnum, mysql.TypeSet:
return true
}
return false
}
// DefaultTypeForValue returns the default FieldType for the value.
func DefaultTypeForValue(value interface{}, tp *FieldType) {
switch x := value.(type) {
......
......@@ -17,7 +17,6 @@ import (
"fmt"
"io"
"strconv"
"strings"
"github.com/pingcap/errors"
"github.com/pingcap/parser/ast"
......@@ -69,11 +68,45 @@ type ValueExpr struct {
projectionOffset int
}
// Restore implements Recoverable interface.
func (n *ValueExpr) Restore(sb *strings.Builder) error {
err := n.format(sb)
if err != nil {
return errors.Trace(err)
// Restore implements Node interface.
func (n *ValueExpr) Restore(ctx *ast.RestoreCtx) error {
switch n.Kind() {
case types.KindNull:
ctx.WriteKeyWord("NULL")
case types.KindInt64:
if n.Type.Flag&mysql.IsBooleanFlag != 0 {
if n.GetInt64() > 0 {
ctx.WriteKeyWord("TRUE")
} else {
ctx.WriteKeyWord("FALSE")
}
} else {
ctx.WritePlain(strconv.FormatInt(n.GetInt64(), 10))
}
case types.KindUint64:
ctx.WritePlain(strconv.FormatUint(n.GetUint64(), 10))
case types.KindFloat32:
ctx.WritePlain(strconv.FormatFloat(n.GetFloat64(), 'e', -1, 32))
case types.KindFloat64:
ctx.WritePlain(strconv.FormatFloat(n.GetFloat64(), 'e', -1, 64))
case types.KindString, types.KindBytes:
ctx.WriteString(n.GetString())
case types.KindMysqlDecimal:
ctx.WritePlain(n.GetMysqlDecimal().String())
case types.KindBinaryLiteral:
if n.Type.Flag&mysql.UnsignedFlag != 0 {
ctx.WritePlainf("x'%x'", n.GetBytes())
} else {
ctx.WritePlain(n.GetBinaryLiteral().ToBitLiteralString(true))
}
case types.KindMysqlDuration, types.KindMysqlEnum,
types.KindMysqlBit, types.KindMysqlSet, types.KindMysqlTime,
types.KindInterface, types.KindMinNotNull, types.KindMaxValue,
types.KindRaw, types.KindMysqlJSON:
// TODO implement Restore function
return errors.New("Not implemented")
default:
return errors.New("can't format to string")
}
return nil
}
......@@ -84,7 +117,7 @@ func (n *ValueExpr) GetDatumString() string {
}
// Format the ExprNode into a Writer.
func (n *ValueExpr) format(w io.Writer) error {
func (n *ValueExpr) Format(w io.Writer) {
var s string
switch n.Kind() {
case types.KindNull:
......@@ -116,18 +149,9 @@ func (n *ValueExpr) format(w io.Writer) error {
s = n.GetBinaryLiteral().ToBitLiteralString(true)
}
default:
return errors.New("can't format to string")
}
fmt.Fprint(w, s)
return nil
}
// Format the ExprNode into a Writer.
func (n *ValueExpr) Format(w io.Writer) {
err := n.format(w)
if err != nil {
panic("Can't format to string")
}
fmt.Fprint(w, s)
}
// newValueExpr creates a ValueExpr with value, and sets default field type.
......@@ -170,9 +194,9 @@ type ParamMarkerExpr struct {
Order int
}
// Restore implements Recoverable interface.
func (n *ParamMarkerExpr) Restore(sb *strings.Builder) error {
sb.WriteString("?")
// Restore implements Node interface.
func (n *ParamMarkerExpr) Restore(ctx *ast.RestoreCtx) error {
ctx.WritePlain("?")
return nil
}
......
......@@ -105,106 +105,106 @@
"revisionTime": "2018-10-24T15:10:47Z"
},
{
"checksumSHA1": "xbV0lm0Qw8rFC82Dttxbf5ypBjA=",
"checksumSHA1": "fjZ4hf54cBBlV260wsAMZJ5T3po=",
"path": "github.com/pingcap/parser",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "RosqMriA/39ZEtqGgNU+bOfRBVc=",
"checksumSHA1": "nRo2Z/Gyb1ziK+CKQi1OAOMa4hc=",
"path": "github.com/pingcap/parser/ast",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "skWGV4FNvD3vr+5olepaPPnylUw=",
"path": "github.com/pingcap/parser/auth",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "t4UHo966WzU9Z0IJkyGHRp0loOk=",
"path": "github.com/pingcap/parser/charset",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "SInoXbsRe0tnBwmatmtZYfSFbdk=",
"path": "github.com/pingcap/parser/format",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "reRV2qecd6NpB7tIW3JeK46K/sk=",
"checksumSHA1": "WZYTGDMnc1UfTdjdZoBbISsnpRY=",
"path": "github.com/pingcap/parser/model",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "QBa9yiMDQNl2cLLwqlRoNTpCPNg=",
"path": "github.com/pingcap/parser/mysql",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "oNBCSwJRykKuzIKgPCttatB9hAo=",
"checksumSHA1": "+O6CYIE0jT8pIDxWRP9FtKwFZjI=",
"path": "github.com/pingcap/parser/opcode",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "XvnUllvwMYd6HrMvMiKnn4cGN2M=",
"path": "github.com/pingcap/parser/terror",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "YoDiJ3sniNqxkP5X/BDkx6efteA=",
"path": "github.com/pingcap/parser/types",
"revision": "f20218bc290343c2752c4926c1bf4264343bbef4",
"revisionTime": "2018-12-12T04:21:31Z"
"revision": "b7f4816358997259f649a06fd126db3542b644c8",
"revisionTime": "2018-12-17T08:17:10Z"
},
{
"checksumSHA1": "fWqL/7jTYOiqDNmiUcQi3u45Hw0=",
"path": "github.com/pingcap/tidb/sessionctx/stmtctx",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "0CCq+3fAyaXs9XU+xWaRvbbtSOQ=",
"checksumSHA1": "kXyszfR2fQ6bHvuCCFlHRkt1mF0=",
"path": "github.com/pingcap/tidb/types",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "DWVD7+ygtT66IQ+cqXmMJ5OVqUk=",
"path": "github.com/pingcap/tidb/types/json",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "Zp5ME8OXNTmHnYTwJJUZlydN4/U=",
"checksumSHA1": "6vi/eCZXqNTa5eAUpxDZet4LPlY=",
"path": "github.com/pingcap/tidb/types/parser_driver",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "s709bhSrG2Ec35406mGtrySid4s=",
"path": "github.com/pingcap/tidb/util/execdetails",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "nUC7zVoAMNR2a+z2iGqHoN2AkFE=",
"path": "github.com/pingcap/tidb/util/hack",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "xSyepiuqsoaaeDch7cXeumvVHKM=",
"path": "github.com/pingcap/tidb/util/memory",
"revision": "4ccd7456fcdc5e62e68f49a0a542cbcf88e38343",
"revisionTime": "2018-12-13T09:52:39Z"
"revision": "ab88f0b1c3b6db829f3e553963673a9bf7752899",
"revisionTime": "2018-12-17T12:08:05Z"
},
{
"checksumSHA1": "SmYeIK/fIYXNu8IKxD6HOVQVTuU=",
......@@ -401,62 +401,62 @@
{
"checksumSHA1": "aKn1oKcY74N8TRLm3Ayt7Q4bbI4=",
"path": "vitess.io/vitess/go/bytes2",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "JVCEN4UGRmg3TofIBdzZMZ3G0Ww=",
"path": "vitess.io/vitess/go/hack",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "e1WJ7vCnVrlQQQlc6n/FewCDMso=",
"checksumSHA1": "F5pcGq+2W1FHEjgktTdKOE6W8mk=",
"path": "vitess.io/vitess/go/sqltypes",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "ntFIQYkBS51G6y+FEkjFW40+HOU=",
"path": "vitess.io/vitess/go/vt/log",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "tPQFPwbMdjuX0qjNl4Zl8zc37JQ=",
"path": "vitess.io/vitess/go/vt/proto/query",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "o0tR/c7lgr0pLkxk7CdvjiNDAKU=",
"path": "vitess.io/vitess/go/vt/proto/topodata",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "77UojBqi0yyeQvR70j7C3kcKclQ=",
"path": "vitess.io/vitess/go/vt/proto/vtgate",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "QpWGhoVDwM+8+sgYLI/YU+95iGU=",
"path": "vitess.io/vitess/go/vt/proto/vtrpc",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "lENrUY/YyxwYFHYN+21TBH92P3U=",
"path": "vitess.io/vitess/go/vt/sqlparser",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
},
{
"checksumSHA1": "oF4XzuOzwvj1iduX/lYqNSyY/HM=",
"checksumSHA1": "Jx+gOh/kiBDSZxEIWHyYn9brjdo=",
"path": "vitess.io/vitess/go/vt/vterrors",
"revision": "eb5a5e0e435db30856600b794d8cff235fdf24b7",
"revisionTime": "2018-12-13T22:28:01Z"
"revision": "935bf8ac1ad1e75bc8fd26a74fbfc906f15aa7d0",
"revisionTime": "2018-12-17T04:01:44Z"
}
],
"rootPath": "github.com/XiaoMi/soar"
......
......@@ -16,7 +16,9 @@ limitations under the License.
package sqltypes
import "reflect"
import (
"vitess.io/vitess/go/vt/vterrors"
)
// QueryResponse represents a query response for ExecuteBatch.
type QueryResponse struct {
......@@ -34,7 +36,7 @@ func QueryResponsesEqual(r1, r2 []QueryResponse) bool {
if !r.QueryResult.Equal(r2[i].QueryResult) {
return false
}
if !reflect.DeepEqual(r.QueryError, r2[i].QueryError) {
if !vterrors.Equals(r.QueryError, r2[i].QueryError) {
return false
}
}
......
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreedto in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package vterrors provides helpers for propagating internal errors
// through the Vitess system (including across RPC boundaries) in a
// structured way.
package vterrors
/*
Vitess uses canonical error codes for error reporting. This is based
on years of industry experience with error reporting. This idea is
that errors should be classified into a small set of errors (10 or so)
with very specific meaning. Each error has a code, and a message. When
errors are passed around (even through RPCs), the code is
propagated. To handle errors, only the code should be looked at (and
not string-matching on the error message).
Vitess defines the error codes in /proto/vtrpc.proto. Along with an
RPCError message that can be used to transmit errors through RPCs, in
the message payloads. These codes match the names and numbers defined
by gRPC.
Vitess also defines a standardized error implementation that allows
you to build an error with an associated canonical code.
While sending an error through gRPC, these codes are transmitted
using gRPC's error propagation mechanism and decoded back to
the original code on the other end.
*/
package vterrors
/* This file is copied from https://github.com/pkg/errors/blob/v0.8.0/stack.go */
import (
"fmt"
"io"
"path"
"runtime"
"strings"
)
// Frame represents a program counter inside a stack frame.
type Frame uintptr
// pc returns the program counter for this frame;
// multiple frames may have the same PC value.
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
// file returns the full path to the file that contains the
// function for this Frame's pc.
func (f Frame) file() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
file, _ := fn.FileLine(f.pc())
return file
}
// line returns the line number of source code of the
// function for this Frame's pc.
func (f Frame) line() int {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return 0
}
_, line := fn.FileLine(f.pc())
return line
}
// Format formats the frame according to the fmt.Formatter interface.
//
// %s source file
// %d source line
// %n function name
// %v equivalent to %s:%d
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+s path of source file relative to the compile time GOPATH
// %+v equivalent to %+s:%d
func (f Frame) Format(s fmt.State, verb rune) {
switch verb {
case 's':
switch {
case s.Flag('+'):
pc := f.pc()
fn := runtime.FuncForPC(pc)
if fn == nil {
io.WriteString(s, "unknown")
} else {
file, _ := fn.FileLine(pc)
fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
}
default:
io.WriteString(s, path.Base(f.file()))
}
case 'd':
fmt.Fprintf(s, "%d", f.line())
case 'n':
name := runtime.FuncForPC(f.pc()).Name()
io.WriteString(s, funcname(name))
case 'v':
f.Format(s, 's')
io.WriteString(s, ":")
f.Format(s, 'd')
}
}
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
type StackTrace []Frame
// Format format the stacktrace according to the fmt.Formatter interface.
//
// %s source file
// %d source line
// %n function name
// %v equivalent to %s:%d
//
// Format accepts flags that alter the printing of some verbs, as follows:
//
// %+s path of source file relative to the compile time GOPATH
// %+v equivalent to %+s:%d
func (st StackTrace) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case s.Flag('+'):
for _, f := range st {
fmt.Fprintf(s, "\n%+v", f)
}
case s.Flag('#'):
fmt.Fprintf(s, "%#v", []Frame(st))
default:
fmt.Fprintf(s, "%v", []Frame(st))
}
case 's':
fmt.Fprintf(s, "%s", []Frame(st))
}
}
// stack represents a stack of program counters.
type stack []uintptr
func (s *stack) Format(st fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case st.Flag('+'):
for _, pc := range *s {
f := Frame(pc)
fmt.Fprintf(st, "\n%+v", f)
}
}
}
}
func (s *stack) StackTrace() StackTrace {
f := make([]Frame, len(*s))
for i := 0; i < len(f); i++ {
f[i] = Frame((*s)[i])
}
return f
}
func callers() *stack {
const depth = 32
var pcs [depth]uintptr
n := runtime.Callers(3, pcs[:])
var st stack = pcs[0:n]
return &st
}
// funcname removes the path prefix component of a function's name reported by func.Name().
func funcname(name string) string {
i := strings.LastIndex(name, "/")
name = name[i+1:]
i = strings.Index(name, ".")
return name[i+1:]
}
func trimGOPATH(name, file string) string {
// Here we want to get the source file path relative to the compile time
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
// GOPATH at runtime, but we can infer the number of path segments in the
// GOPATH. We note that fn.Name() returns the function name qualified by
// the import path, which does not include the GOPATH. Thus we can trim
// segments from the beginning of the file path until the number of path
// separators remaining is one more than the number of path separators in
// the function name. For example, given:
//
// GOPATH /home/user
// file /home/user/src/pkg/sub/file.go
// fn.Name() pkg/sub.Type.Method
//
// We want to produce:
//
// pkg/sub/file.go
//
// From this we can easily see that fn.Name() has one less path separator
// than our desired output. We count separators from the end of the file
// path until it finds two more than in the function name and then move
// one character forward to preserve the initial path segment without a
// leading separator.
const sep = "/"
goal := strings.Count(name, sep) + 2
i := len(file)
for n := 0; n < goal; n++ {
i = strings.LastIndex(file[:i], sep)
if i == -1 {
// not enough separators found, set i so that the slice expression
// below leaves file unmodified
i = -len(sep)
break
}
}
// get back to 0 or trim the leading separator
file = file[i+len(sep):]
return file
}
/*
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreedto in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package vterrors provides simple error handling primitives for Vitess
//
// In all Vitess code, errors should be propagated using vterrors.Wrapf()
// and not fmt.Errorf().
//
// New errors should be created using vterrors.New
//
// Vitess uses canonical error codes for error reporting. This is based
// on years of industry experience with error reporting. This idea is
// that errors should be classified into a small set of errors (10 or so)
// with very specific meaning. Each error has a code, and a message. When
// errors are passed around (even through RPCs), the code is
// propagated. To handle errors, only the code should be looked at (and
// not string-matching on the error message).
//
// Error codes are defined in /proto/vtrpc.proto. Along with an
// RPCError message that can be used to transmit errors through RPCs, in
// the message payloads. These codes match the names and numbers defined
// by gRPC.
//
// A standardized error implementation that allows you to build an error
// with an associated canonical code is also defined.
// While sending an error through gRPC, these codes are transmitted
// using gRPC's error propagation mechanism and decoded back to
// the original code on the other end.
//
// Retrieving the cause of an error
//
// Using vterrors.Wrap constructs a stack of errors, adding context to the
// preceding error. Depending on the nature of the error it may be necessary
// to reverse the operation of errors.Wrap to retrieve the original error
// for inspection. Any error value which implements this interface
//
// type causer interface {
// Cause() error
// }
//
// can be inspected by vterrors.Cause and vterrors.RootCause.
//
// * vterrors.Cause will find the immediate cause if one is available, or nil
// if the error is not a `causer` or if no cause is available.
// * vterrors.RootCause will recursively retrieve
// the topmost error which does not implement causer, which is assumed to be
// the original cause. For example:
//
// switch err := errors.RootCause(err).(type) {
// case *MyError:
// // handle specifically
// default:
// // unknown error
// }
//
// causer interface is not exported by this package, but is considered a part
// of stable public API.
//
// Formatted printing of errors
//
// All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported
//
// %s print the error. If the error has a Cause it will be
// printed recursively
// %v see %s
// %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail.
//
// Most but not all of the code in this file was originally copied from
// https://github.com/pkg/errors/blob/v0.8.0/errors.go
package vterrors
import (
"fmt"
"golang.org/x/net/context"
"io"
vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
)
type vtError struct {
code vtrpcpb.Code
err string
}
// New creates a new error using the code and input string.
func New(code vtrpcpb.Code, in string) error {
if code == vtrpcpb.Code_OK {
panic("OK is an invalid error code; use INTERNAL instead")
}
return &vtError{
// New returns an error with the supplied message.
// New also records the stack trace at the point it was called.
func New(code vtrpcpb.Code, message string) error {
return &fundamental{
msg: message,
code: code,
err: in,
stack: callers(),
}
}
// Wrap wraps the given error, returning a new error with the given message as a prefix but with the same error code (if err was a vterror) and message of the passed error.
func Wrap(err error, message string) error {
return New(Code(err), fmt.Sprintf("%v: %v", message, err.Error()))
// NewWithoutCode returns an error when no applicable error code is available
// It will record the stack trace when creating the error
func NewWithoutCode(message string) error {
return &fundamental{
msg: message,
code: vtrpcpb.Code_UNKNOWN,
stack: callers(),
}
}
// Wrapf wraps the given error, returning a new error with the given format string as a prefix but with the same error code (if err was a vterror) and message of the passed error.
func Wrapf(err error, format string, args ...interface{}) error {
return Wrap(err, fmt.Sprintf(format, args...))
// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
func Errorf(code vtrpcpb.Code, format string, args ...interface{}) error {
return &fundamental{
msg: fmt.Sprintf(format, args...),
code: code,
stack: callers(),
}
}
// Errorf returns a new error built using Printf style arguments.
func Errorf(code vtrpcpb.Code, format string, args ...interface{}) error {
return New(code, fmt.Sprintf(format, args...))
// fundamental is an error that has a message and a stack, but no caller.
type fundamental struct {
msg string
code vtrpcpb.Code
*stack
}
func (e *vtError) Error() string {
return e.err
func (f *fundamental) Error() string { return f.msg }
func (f *fundamental) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
io.WriteString(s, "Code: "+f.code.String()+"\n")
io.WriteString(s, f.msg+"\n")
f.stack.Format(s, verb)
return
}
fallthrough
case 's':
io.WriteString(s, f.msg)
case 'q':
fmt.Fprintf(s, "%q", f.msg)
}
}
// Code returns the error code if it's a vtError.
// If err is nil, it returns ok. Otherwise, it returns unknown.
// If err is nil, it returns ok.
func Code(err error) vtrpcpb.Code {
if err == nil {
return vtrpcpb.Code_OK
}
if err, ok := err.(*vtError); ok {
if err, ok := err.(*fundamental); ok {
return err.code
}
cause := Cause(err)
if cause != err && cause != nil {
// If we did not find an error code at the outer level, let's find the cause and check it's code
return Code(cause)
}
// Handle some special cases.
switch err {
case context.Canceled:
......@@ -78,16 +158,111 @@ func Code(err error) vtrpcpb.Code {
return vtrpcpb.Code_UNKNOWN
}
// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
if err == nil {
return nil
}
return &wrapping{
cause: err,
msg: message,
stack: callers(),
}
}
// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is call, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &wrapping{
cause: err,
msg: fmt.Sprintf(format, args...),
stack: callers(),
}
}
type wrapping struct {
cause error
msg string
stack *stack
}
func (w *wrapping) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *wrapping) Cause() error { return w.cause }
func (w *wrapping) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v\n", w.Cause())
io.WriteString(s, w.msg)
w.stack.Format(s, verb)
return
}
fallthrough
case 's', 'q':
io.WriteString(s, w.Error())
}
}
// RootCause returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
// type causer interface {
// Cause() error
// }
//
// If the error does not implement Cause, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
func RootCause(err error) error {
for {
cause := Cause(err)
if cause == nil {
return err
}
err = cause
}
}
//
// Cause will return the immediate cause, if possible.
// An error value has a cause if it implements the following
// interface:
//
// type causer interface {
// Cause() error
// }
// If the error does not implement Cause, nil will be returned
func Cause(err error) error {
type causer interface {
Cause() error
}
causerObj, ok := err.(causer)
if !ok {
return nil
}
return causerObj.Cause()
}
// Equals returns true iff the error message and the code returned by Code()
// is equal.
// are equal.
func Equals(a, b error) bool {
if a == nil && b == nil {
// Both are nil.
return true
}
if a == nil && b != nil || a != nil && b == nil {
// One of the two is nil.
if a == nil || b == nil {
// One of the two is nil, since we know both are not nil.
return false
}
......@@ -97,5 +272,5 @@ func Equals(a, b error) bool {
// Print is meant to print the vtError object in test failures.
// For comparing two vterrors, use Equals() instead.
func Print(err error) string {
return fmt.Sprintf("%v: %v", Code(err), err.Error())
return fmt.Sprintf("%v: %v\n", Code(err), err.Error())
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册