// Copyright 2021 Molecula Corp. All rights reserved. package parser import ( "bytes" "fmt" "strings" "time" ) type Node interface { node() fmt.Stringer } func (*AlterDatabaseStatement) node() {} func (*AlterTableStatement) node() {} func (*AlterViewStatement) node() {} func (*AnalyzeStatement) node() {} func (*Assignment) node() {} func (*ShowDatabasesStatement) node() {} func (*ShowTablesStatement) node() {} func (*ShowColumnsStatement) node() {} func (*ShowCreateTableStatement) node() {} func (*BeginStatement) node() {} func (*BinaryExpr) node() {} func (*BoolLit) node() {} func (*BulkInsertMapDefinition) node() {} func (*BulkInsertStatement) node() {} func (*CacheTypeConstraint) node() {} func (*Call) node() {} func (*CaseBlock) node() {} func (*CaseExpr) node() {} func (*CastExpr) node() {} func (*CheckConstraint) node() {} func (*ColumnDefinition) node() {} func (*CommitStatement) node() {} func (*CreateDatabaseStatement) node() {} func (*CreateIndexStatement) node() {} func (*CreateTableStatement) node() {} func (*CreateFunctionStatement) node() {} func (*CreateViewStatement) node() {} func (*DateLit) node() {} func (*DefaultConstraint) node() {} func (*DeleteStatement) node() {} func (*DropDatabaseStatement) node() {} func (*DropIndexStatement) node() {} func (*DropTableStatement) node() {} func (*DropFunctionStatement) node() {} func (*DropViewStatement) node() {} func (*Exists) node() {} func (*ExplainStatement) node() {} func (*ExprList) node() {} func (*FilterClause) node() {} func (*FloatLit) node() {} func (*ForeignKeyArg) node() {} func (*ForeignKeyConstraint) node() {} func (*FrameSpec) node() {} func (*Ident) node() {} func (*Variable) node() {} func (*SysVariable) node() {} func (*IndexedColumn) node() {} func (*InsertStatement) node() {} func (*JoinClause) node() {} func (*JoinOperator) node() {} func (*KeyPartitionsOption) node() {} func (*MinConstraint) node() {} func (*MaxConstraint) node() {} func (*NotNullConstraint) node() {} func (*NullLit) node() {} func (*IntegerLit) node() {} func (*OnConstraint) node() {} func (*OrderingTerm) node() {} func (*OverClause) node() {} func (*ParenExpr) node() {} func (*SetLiteralExpr) node() {} func (*ParenSource) node() {} func (*PrimaryKeyConstraint) node() {} func (*QualifiedRef) node() {} func (*QualifiedTableName) node() {} func (*Range) node() {} func (*ReleaseStatement) node() {} func (*ResultColumn) node() {} func (*RollbackStatement) node() {} func (*SavepointStatement) node() {} func (*SelectStatement) node() {} func (*StringLit) node() {} func (*TableValuedFunction) node() {} func (*TimeUnitConstraint) node() {} func (*TimeQuantumConstraint) node() {} func (*TupleLiteralExpr) node() {} func (*Type) node() {} func (*UnaryExpr) node() {} func (*UniqueConstraint) node() {} func (*UnitsOption) node() {} func (*UpdateStatement) node() {} func (*UpsertClause) node() {} func (*UsingConstraint) node() {} func (*Window) node() {} func (*WindowDefinition) node() {} func (*WithClause) node() {} func (*CommentOption) node() {} type Statement interface { Node stmt() } func (*AlterDatabaseStatement) stmt() {} func (*AlterTableStatement) stmt() {} func (*AlterViewStatement) stmt() {} func (*AnalyzeStatement) stmt() {} func (*BeginStatement) stmt() {} func (*BulkInsertStatement) stmt() {} func (*ShowDatabasesStatement) stmt() {} func (*ShowTablesStatement) stmt() {} func (*ShowColumnsStatement) stmt() {} func (*ShowCreateTableStatement) stmt() {} func (*CommitStatement) stmt() {} func (*CreateDatabaseStatement) stmt() {} func (*CreateIndexStatement) stmt() {} func (*CreateTableStatement) stmt() {} func (*CreateFunctionStatement) stmt() {} func (*CreateViewStatement) stmt() {} func (*DeleteStatement) stmt() {} func (*DropDatabaseStatement) stmt() {} func (*DropIndexStatement) stmt() {} func (*DropTableStatement) stmt() {} func (*DropFunctionStatement) stmt() {} func (*DropViewStatement) stmt() {} func (*ExplainStatement) stmt() {} func (*InsertStatement) stmt() {} func (*ReleaseStatement) stmt() {} func (*RollbackStatement) stmt() {} func (*SavepointStatement) stmt() {} func (*SelectStatement) stmt() {} func (*UpdateStatement) stmt() {} // CloneStatement returns a deep copy stmt. func CloneStatement(stmt Statement) Statement { if stmt == nil { return nil } switch stmt := stmt.(type) { case *AlterDatabaseStatement: return stmt.Clone() case *AlterTableStatement: return stmt.Clone() case *AlterViewStatement: return stmt.Clone() case *AnalyzeStatement: return stmt.Clone() case *BeginStatement: return stmt.Clone() case *CommitStatement: return stmt.Clone() case *CreateDatabaseStatement: return stmt.Clone() case *CreateIndexStatement: return stmt.Clone() case *CreateTableStatement: return stmt.Clone() case *CreateFunctionStatement: return stmt.Clone() case *CreateViewStatement: return stmt.Clone() case *DeleteStatement: return stmt.Clone() case *DropDatabaseStatement: return stmt.Clone() case *DropIndexStatement: return stmt.Clone() case *DropTableStatement: return stmt.Clone() case *DropFunctionStatement: return stmt.Clone() case *DropViewStatement: return stmt.Clone() case *ExplainStatement: return stmt.Clone() case *InsertStatement: return stmt.Clone() case *ReleaseStatement: return stmt.Clone() case *RollbackStatement: return stmt.Clone() case *SavepointStatement: return stmt.Clone() case *SelectStatement: return stmt.Clone() case *UpdateStatement: return stmt.Clone() case *ShowTablesStatement: return stmt.Clone() case *ShowColumnsStatement: return stmt.Clone() case *ShowCreateTableStatement: return stmt.Clone() case *ShowDatabasesStatement: return stmt.Clone() default: panic(fmt.Sprintf("invalid statement type: %T", stmt)) } } func cloneStatements(a []Statement) []Statement { if a == nil { return nil } other := make([]Statement, len(a)) for i := range a { other[i] = CloneStatement(a[i]) } return other } // StatementSource returns the root statement for a statement. func StatementSource(stmt Statement) Source { switch stmt := stmt.(type) { case *SelectStatement: return stmt.Source case *UpdateStatement: return stmt.Table case *DeleteStatement: return stmt.Source default: return nil } } type Expr interface { Node expr() IsLiteral() bool DataType() ExprDataType Pos() Pos } func (*BinaryExpr) expr() {} func (*BoolLit) expr() {} func (*Call) expr() {} func (*CaseExpr) expr() {} func (*CaseBlock) expr() {} func (*CastExpr) expr() {} func (*DateLit) expr() {} func (*Exists) expr() {} func (*ExprList) expr() {} func (*Ident) expr() {} func (*Variable) expr() {} func (*SysVariable) expr() {} func (*NullLit) expr() {} func (*IntegerLit) expr() {} func (*FloatLit) expr() {} func (*ParenExpr) expr() {} func (*SetLiteralExpr) expr() {} func (*TupleLiteralExpr) expr() {} func (*QualifiedRef) expr() {} func (*Range) expr() {} func (*StringLit) expr() {} func (*UnaryExpr) expr() {} func (*SelectStatement) expr() {} // CloneExpr returns a deep copy expr. func CloneExpr(expr Expr) Expr { if expr == nil { return nil } switch expr := expr.(type) { case *BinaryExpr: return expr.Clone() case *BoolLit: return expr.Clone() case *Call: return expr.Clone() case *CaseExpr: return expr.Clone() case *CastExpr: return expr.Clone() case *Exists: return expr.Clone() case *ExprList: return expr.Clone() case *Ident: return expr.Clone() case *NullLit: return expr.Clone() case *FloatLit: return expr.Clone() case *IntegerLit: return expr.Clone() case *ParenExpr: return expr.Clone() case *QualifiedRef: return expr.Clone() case *Range: return expr.Clone() case *StringLit: return expr.Clone() case *TupleLiteralExpr: return expr.Clone() case *UnaryExpr: return expr.Clone() case *Variable: return expr.Clone() default: panic(fmt.Sprintf("invalid expr type: %T", expr)) } } func cloneExprs(a []Expr) []Expr { if a == nil { return nil } other := make([]Expr, len(a)) for i := range a { other[i] = CloneExpr(a[i]) } return other } // ExprString returns the string representation of expr. // Returns a blank string if expr is nil. func ExprString(expr Expr) string { if expr == nil { return "" } return expr.String() } // SplitExprTree splits apart expr so it is a list of all AND joined expressions. // For example, the expression "A AND B AND (C OR (D AND E))" would be split into // a list of "A", "B", "C OR (D AND E)". func SplitExprTree(expr Expr) []Expr { if expr == nil { return nil } var a []Expr splitExprTree(expr, &a) return a } func splitExprTree(expr Expr, a *[]Expr) { switch expr := expr.(type) { case *BinaryExpr: if expr.Op != AND { *a = append(*a, expr) return } splitExprTree(expr.X, a) splitExprTree(expr.Y, a) case *ParenExpr: splitExprTree(expr.X, a) default: *a = append(*a, expr) } } // SourceOutputColumn is an identifier that is either a possible output column // for a Source or a referenced output column for a Source. These are computed during // the analysis phase type SourceOutputColumn struct { TableName string ColumnName string ColumnIndex int Datatype ExprDataType } // Source represents a data source for a select statement. // A select statement has one source, but they can be one of a table ref, a join, // another select statement or any of the above parenthesiszed. For join operators, the Source // can form a graph, with the join terms being themselves a Source. type Source interface { Node source() SourceFromAlias(alias string) Source // get the possible output columns from the source PossibleOutputColumns() []*SourceOutputColumn // find output columns by name OutputColumnNamed(name string) (*SourceOutputColumn, error) OutputColumnQualifierNamed(qualifier string, name string) (*SourceOutputColumn, error) } func (*JoinClause) source() {} func (*ParenSource) source() {} func (*QualifiedTableName) source() {} func (*TableValuedFunction) source() {} func (*SelectStatement) source() {} // CloneSource returns a deep copy src. func CloneSource(src Source) Source { if src == nil { return nil } switch src := src.(type) { case *JoinClause: return src.Clone() case *ParenSource: return src.Clone() case *QualifiedTableName: return src.Clone() case *SelectStatement: return src.Clone() default: panic(fmt.Sprintf("invalid source type: %T", src)) } } // SourceList returns a list of sources starting from a source. func SourceList(src Source) []Source { var a []Source ForEachSource(src, func(s Source) bool { a = append(a, s) return true }) return a } // ForEachSource calls fn for every source within the current scope. // Stops iteration if fn returns false. func ForEachSource(src Source, fn func(Source) bool) { forEachSource(src, fn) } func forEachSource(src Source, fn func(Source) bool) bool { if !fn(src) { return false } switch src := src.(type) { case *JoinClause: if !forEachSource(src.X, fn) { return false } else if !forEachSource(src.Y, fn) { return false } case *SelectStatement: if !forEachSource(src.Source, fn) { return false } } return true } // JoinConstraint represents either an ON or USING join constraint. type JoinConstraint interface { Node joinConstraint() } func (*OnConstraint) joinConstraint() {} func (*UsingConstraint) joinConstraint() {} // CloneJoinConstraint returns a deep copy cons. func CloneJoinConstraint(cons JoinConstraint) JoinConstraint { if cons == nil { return nil } switch cons := cons.(type) { case *OnConstraint: return cons.Clone() case *UsingConstraint: return cons.Clone() default: panic(fmt.Sprintf("invalid join constraint type: %T", cons)) } } type ExplainStatement struct { Explain Pos // position of EXPLAIN Query Pos // position of QUERY (optional) QueryPlan Pos // position of PLAN after QUERY (optional) Stmt Statement // target statement } // Clone returns a deep copy of s. func (s *ExplainStatement) Clone() *ExplainStatement { if s == nil { return nil } other := *s other.Stmt = CloneStatement(s.Stmt) return &other } // String returns the string representation of the statement. func (s *ExplainStatement) String() string { var buf bytes.Buffer buf.WriteString("EXPLAIN") if s.QueryPlan.IsValid() { buf.WriteString(" QUERY PLAN") } fmt.Fprintf(&buf, " %s", s.Stmt.String()) return buf.String() } type ShowDatabasesStatement struct { Show Pos // position of SHOW Databases Pos // position of DATABASES } // String returns the string representation of the statement. func (s *ShowDatabasesStatement) String() string { return "SHOW DATABASES" } // String returns the string representation of the statement. func (s *ShowDatabasesStatement) Clone() *ShowDatabasesStatement { o := *s return &o } type ShowTablesStatement struct { Show Pos // position of SHOW Tables Pos // position of TABLES } // String returns the string representation of the statement. func (s *ShowTablesStatement) String() string { return "SHOW TABLES" } func (s *ShowTablesStatement) Clone() *ShowTablesStatement { other := *s return &other } type ShowColumnsStatement struct { Show Pos // position of SHOW Columns Pos // position of COLUMNS From Pos // position of FROM TableName *Ident // name of table } // String returns the string representation of the statement. func (s *ShowColumnsStatement) String() string { var buf bytes.Buffer buf.WriteString("SHOW COLUMNS ") if s.TableName != nil { buf.WriteString("FROM") fmt.Fprintf(&buf, " %s", s.TableName.String()) } return buf.String() } func (s *ShowColumnsStatement) Clone() *ShowColumnsStatement { other := *s return &other } type ShowCreateTableStatement struct { Show Pos // position of SHOW Create Pos // position of CREATE Table Pos // position of CREATE TableName *Ident // name of table } // String returns the string representation of the statement. func (s *ShowCreateTableStatement) String() string { var buf bytes.Buffer buf.WriteString("SHOW CREATE TABLE") if s.TableName != nil { fmt.Fprintf(&buf, " %s", s.TableName.String()) } return buf.String() } func (s *ShowCreateTableStatement) Clone() *ShowCreateTableStatement { other := *s other.TableName = s.TableName.Clone() return &other } type BeginStatement struct { Begin Pos // position of BEGIN Deferred Pos // position of DEFERRED keyword Immediate Pos // position of IMMEDIATE keyword Exclusive Pos // position of EXCLUSIVE keyword Transaction Pos // position of TRANSACTION keyword (optional) } // Clone returns a deep copy of s. func (s *BeginStatement) Clone() *BeginStatement { if s == nil { return nil } other := *s return &other } // String returns the string representation of the statement. func (s *BeginStatement) String() string { var buf bytes.Buffer buf.WriteString("BEGIN") if s.Deferred.IsValid() { buf.WriteString(" DEFERRED") } else if s.Immediate.IsValid() { buf.WriteString(" IMMEDIATE") } else if s.Exclusive.IsValid() { buf.WriteString(" EXCLUSIVE") } if s.Transaction.IsValid() { buf.WriteString(" TRANSACTION") } return buf.String() } type CommitStatement struct { Commit Pos // position of COMMIT keyword End Pos // position of END keyword Transaction Pos // position of TRANSACTION keyword (optional) } // Clone returns a deep copy of s. func (s *CommitStatement) Clone() *CommitStatement { if s == nil { return nil } other := *s return &other } // String returns the string representation of the statement. func (s *CommitStatement) String() string { var buf bytes.Buffer if s.End.IsValid() { buf.WriteString("END") } else { buf.WriteString("COMMIT") } if s.Transaction.IsValid() { buf.WriteString(" TRANSACTION") } return buf.String() } type RollbackStatement struct { Rollback Pos // position of ROLLBACK keyword Transaction Pos // position of TRANSACTION keyword (optional) To Pos // position of TO keyword (optional) Savepoint Pos // position of SAVEPOINT keyword (optional) SavepointName *Ident // name of savepoint } // Clone returns a deep copy of s. func (s *RollbackStatement) Clone() *RollbackStatement { if s == nil { return s } other := *s other.SavepointName = s.SavepointName.Clone() return &other } // String returns the string representation of the statement. func (s *RollbackStatement) String() string { var buf bytes.Buffer buf.WriteString("ROLLBACK") if s.Transaction.IsValid() { buf.WriteString(" TRANSACTION") } if s.SavepointName != nil { buf.WriteString(" TO") if s.Savepoint.IsValid() { buf.WriteString(" SAVEPOINT") } fmt.Fprintf(&buf, " %s", s.SavepointName.String()) } return buf.String() } type SavepointStatement struct { Savepoint Pos // position of SAVEPOINT keyword Name *Ident // name of savepoint } // Clone returns a deep copy of s. func (s *SavepointStatement) Clone() *SavepointStatement { if s == nil { return s } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *SavepointStatement) String() string { return fmt.Sprintf("SAVEPOINT %s", s.Name.String()) } type ReleaseStatement struct { Release Pos // position of RELEASE keyword Savepoint Pos // position of SAVEPOINT keyword (optional) Name *Ident // name of savepoint } // Clone returns a deep copy of s. func (s *ReleaseStatement) Clone() *ReleaseStatement { if s == nil { return s } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *ReleaseStatement) String() string { var buf bytes.Buffer buf.WriteString("RELEASE") if s.Savepoint.IsValid() { buf.WriteString(" SAVEPOINT") } fmt.Fprintf(&buf, " %s", s.Name.String()) return buf.String() } type CreateDatabaseStatement struct { Create Pos // position of CREATE keyword Database Pos // position of DATABASE keyword If Pos // position of IF keyword (optional) IfNot Pos // position of NOT keyword (optional) IfNotExists Pos // position of EXISTS keyword (optional) Name *Ident // database name With Pos // position of WITH keyword Options []DatabaseOption // database options } // Clone returns a deep copy of s. func (s *CreateDatabaseStatement) Clone() *CreateDatabaseStatement { if s == nil { return s } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *CreateDatabaseStatement) String() string { var buf bytes.Buffer buf.WriteString("CREATE DATABASE") if s.IfNotExists.IsValid() { buf.WriteString(" IF NOT EXISTS") } buf.WriteString(" ") buf.WriteString(s.Name.String()) if s.With.IsValid() { buf.WriteString(" WITH") for _, opt := range s.Options { buf.WriteString(" ") buf.WriteString(opt.String()) } } return buf.String() } type CreateTableStatement struct { Create Pos // position of CREATE keyword Table Pos // position of TABLE keyword If Pos // position of IF keyword (optional) IfNot Pos // position of NOT keyword (optional) IfNotExists Pos // position of EXISTS keyword (optional) Name *Ident // table name Lparen Pos // position of left paren of column list Columns []*ColumnDefinition // column definitions Constraints []Constraint // table constraints Rparen Pos // position of right paren of column list As Pos // position of AS keyword (optional) Select *SelectStatement // select stmt to build from Options []TableOption // table options } // Clone returns a deep copy of s. func (s *CreateTableStatement) Clone() *CreateTableStatement { if s == nil { return s } other := *s other.Name = s.Name.Clone() other.Columns = cloneColumnDefinitions(s.Columns) other.Constraints = cloneConstraints(s.Constraints) other.Options = cloneTableOptions(s.Options) other.Select = s.Select.Clone() return &other } // String returns the string representation of the statement. func (s *CreateTableStatement) String() string { var buf bytes.Buffer buf.WriteString("CREATE TABLE") if s.IfNotExists.IsValid() { buf.WriteString(" IF NOT EXISTS") } buf.WriteString(" ") buf.WriteString(s.Name.String()) if s.Select != nil { buf.WriteString(" ") if s.As.IsValid() { buf.WriteString("AS ") } buf.WriteString(s.Select.String()) } else { buf.WriteString(" (") for i := range s.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(s.Columns[i].String()) } for i := range s.Constraints { buf.WriteString(", ") buf.WriteString(s.Constraints[i].String()) } buf.WriteString(")") } for i := range s.Options { buf.WriteString(" ") buf.WriteString(s.Options[i].String()) } return buf.String() } type ColumnDefinition struct { Name *Ident // column name Type *Type // data type Constraints []Constraint // column constraints } // Clone returns a deep copy of d. func (d *ColumnDefinition) Clone() *ColumnDefinition { if d == nil { return d } other := *d other.Name = d.Name.Clone() other.Type = d.Type.Clone() other.Constraints = cloneConstraints(d.Constraints) return &other } func cloneColumnDefinitions(a []*ColumnDefinition) []*ColumnDefinition { if a == nil { return nil } other := make([]*ColumnDefinition, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the statement. func (c *ColumnDefinition) String() string { var buf bytes.Buffer buf.WriteString(c.Name.String()) buf.WriteString(" ") buf.WriteString(c.Type.String()) for i := range c.Constraints { buf.WriteString(" ") buf.WriteString(c.Constraints[i].String()) } return buf.String() } type DatabaseOption interface { Node dbOption() } func (*UnitsOption) dbOption() {} func (*CommentOption) dbOption() {} type UnitsOption struct { Units Pos // position of UNITS keyword Expr Expr // expression } func (o *UnitsOption) String() string { var buf bytes.Buffer buf.WriteString("UNITS ") buf.WriteString(o.Expr.String()) return buf.String() } type TableOption interface { Node option() } func cloneTableOptions(a []TableOption) []TableOption { if a == nil { return nil } other := make([]TableOption, len(a)) for i := range a { other[i] = CloneTableOption(a[i]) } return other } func CloneTableOption(opt TableOption) TableOption { if opt == nil { return nil } switch cons := opt.(type) { case *KeyPartitionsOption: return cons.Clone() case *CommentOption: return cons.Clone() default: panic(fmt.Sprintf("invalid table option type: %T", cons)) } } func (*KeyPartitionsOption) option() {} func (*CommentOption) option() {} type KeyPartitionsOption struct { KeyPartitions Pos // position of KEYPARTITIONS keyword Expr Expr // expression } func (o *KeyPartitionsOption) String() string { var buf bytes.Buffer buf.WriteString("KEYPARTITIONS ") buf.WriteString(o.Expr.String()) return buf.String() } func (o *KeyPartitionsOption) Clone() *KeyPartitionsOption { other := *o other.Expr = CloneExpr(o.Expr) return &other } type CommentOption struct { Comment Pos // position of COMMENT keyword Expr Expr // expression } func (o *CommentOption) String() string { var buf bytes.Buffer buf.WriteString("COMMENT ") buf.WriteString(o.Expr.String()) return buf.String() } func (o *CommentOption) Clone() *CommentOption { other := *o other.Expr = CloneExpr(o.Expr) return &other } type Constraint interface { Node constraint() } func (*PrimaryKeyConstraint) constraint() {} func (*NotNullConstraint) constraint() {} func (*UniqueConstraint) constraint() {} func (*CheckConstraint) constraint() {} func (*DefaultConstraint) constraint() {} func (*ForeignKeyConstraint) constraint() {} func (*MinConstraint) constraint() {} func (*MaxConstraint) constraint() {} func (*CacheTypeConstraint) constraint() {} func (*TimeUnitConstraint) constraint() {} func (*TimeQuantumConstraint) constraint() {} // CloneConstraint returns a deep copy cons. func CloneConstraint(cons Constraint) Constraint { if cons == nil { return nil } switch cons := cons.(type) { case *PrimaryKeyConstraint: return cons.Clone() case *NotNullConstraint: return cons.Clone() case *UniqueConstraint: return cons.Clone() case *CheckConstraint: return cons.Clone() case *DefaultConstraint: return cons.Clone() case *ForeignKeyConstraint: return cons.Clone() case *MaxConstraint: return cons.Clone() case *MinConstraint: return cons.Clone() case *CacheTypeConstraint: return cons.Clone() case *TimeUnitConstraint: return cons.Clone() case *TimeQuantumConstraint: return cons.Clone() default: panic(fmt.Sprintf("invalid constraint type: %T", cons)) } } func cloneConstraints(a []Constraint) []Constraint { if a == nil { return nil } other := make([]Constraint, len(a)) for i := range a { other[i] = CloneConstraint(a[i]) } return other } type PrimaryKeyConstraint struct { Constraint Pos // position of CONSTRAINT keyword Name *Ident // constraint name Primary Pos // position of PRIMARY keyword Key Pos // position of KEY keyword Lparen Pos // position of left paren (table only) Columns []*Ident // indexed columns (table only) Rparen Pos // position of right paren (table only) Autoincrement Pos // position of AUTOINCREMENT keyword (column only) } // Clone returns a deep copy of c. func (c *PrimaryKeyConstraint) Clone() *PrimaryKeyConstraint { if c == nil { return c } other := *c other.Name = c.Name.Clone() other.Columns = cloneIdents(c.Columns) return &other } // String returns the string representation of the constraint. func (c *PrimaryKeyConstraint) String() string { var buf bytes.Buffer if c.Name != nil { buf.WriteString("CONSTRAINT ") buf.WriteString(c.Name.String()) buf.WriteString(" ") } buf.WriteString("PRIMARY KEY") if len(c.Columns) > 0 { buf.WriteString(" (") for i := range c.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(c.Columns[i].String()) } buf.WriteString(")") } if c.Autoincrement.IsValid() { buf.WriteString(" AUTOINCREMENT") } return buf.String() } type NotNullConstraint struct { Constraint Pos // position of CONSTRAINT keyword Name *Ident // constraint name Not Pos // position of NOT keyword Null Pos // position of NULL keyword } // Clone returns a deep copy of c. func (c *NotNullConstraint) Clone() *NotNullConstraint { if c == nil { return c } other := *c other.Name = c.Name.Clone() return &other } // String returns the string representation of the constraint. func (c *NotNullConstraint) String() string { var buf bytes.Buffer if c.Name != nil { buf.WriteString("CONSTRAINT ") buf.WriteString(c.Name.String()) buf.WriteString(" ") } buf.WriteString("NOT NULL") return buf.String() } type UniqueConstraint struct { Constraint Pos // position of CONSTRAINT keyword Name *Ident // constraint name Unique Pos // position of UNIQUE keyword Lparen Pos // position of left paren (table only) Columns []*Ident // indexed columns (table only) Rparen Pos // position of right paren (table only) } // Clone returns a deep copy of c. func (c *UniqueConstraint) Clone() *UniqueConstraint { if c == nil { return c } other := *c other.Name = c.Name.Clone() other.Columns = cloneIdents(c.Columns) return &other } // String returns the string representation of the constraint. func (c *UniqueConstraint) String() string { var buf bytes.Buffer if c.Name != nil { buf.WriteString("CONSTRAINT ") buf.WriteString(c.Name.String()) buf.WriteString(" ") } buf.WriteString("UNIQUE") if len(c.Columns) > 0 { buf.WriteString(" (") for i := range c.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(c.Columns[i].String()) } buf.WriteString(")") } return buf.String() } type MinConstraint struct { Min Pos // position of MIN keyword Expr Expr // min expression } // Clone returns a deep copy of c. func (c *MinConstraint) Clone() *MinConstraint { if c == nil { return c } other := *c other.Expr = CloneExpr(c.Expr) return &other } // String returns the string representation of the constraint. func (c *MinConstraint) String() string { var buf bytes.Buffer buf.WriteString("MIN ") buf.WriteString(c.Expr.String()) return buf.String() } type MaxConstraint struct { Max Pos // position of MAX keyword Expr Expr // check expression } // Clone returns a deep copy of c. func (c *MaxConstraint) Clone() *MaxConstraint { if c == nil { return c } other := *c other.Expr = CloneExpr(c.Expr) return &other } // String returns the string representation of the constraint. func (c *MaxConstraint) String() string { var buf bytes.Buffer buf.WriteString("MAX ") buf.WriteString(c.Expr.String()) return buf.String() } type CacheTypeConstraint struct { CacheType Pos // position of CACHETYPE keyword CacheTypeValue string Size Pos // position of SIZE keyword SizeExpr Expr // check expression } // Clone returns a deep copy of c. func (c *CacheTypeConstraint) Clone() *CacheTypeConstraint { if c == nil { return c } other := *c other.SizeExpr = CloneExpr(c.SizeExpr) return &other } // String returns the string representation of the constraint. func (c *CacheTypeConstraint) String() string { var buf bytes.Buffer buf.WriteString("CACHETYPE ") buf.WriteString(c.CacheTypeValue) if c.Size.IsValid() { buf.WriteString(" SIZE ") buf.WriteString(c.SizeExpr.String()) } return buf.String() } type TimeUnitConstraint struct { TimeUnit Pos // position of TIMEUNIT keyword Expr Expr // expression Epoch Pos // position of TIMEUNIT keyword EpochExpr Expr // expression } // Clone returns a deep copy of c. func (c *TimeUnitConstraint) Clone() *TimeUnitConstraint { if c == nil { return c } other := *c other.Expr = CloneExpr(c.Expr) return &other } // String returns the string representation of the constraint. func (c *TimeUnitConstraint) String() string { var buf bytes.Buffer buf.WriteString("TIMEUNIT ") buf.WriteString(c.Expr.String()) if c.Epoch.IsValid() { buf.WriteString(" EPOCH ") buf.WriteString(c.EpochExpr.String()) } return buf.String() } type TimeQuantumConstraint struct { TimeQuantum Pos // position of TIMEQUANTUM keyword Expr Expr // expression Ttl Pos TtlExpr Expr } // Clone returns a deep copy of c. func (c *TimeQuantumConstraint) Clone() *TimeQuantumConstraint { if c == nil { return c } other := *c other.Expr = CloneExpr(c.Expr) other.TtlExpr = CloneExpr(c.TtlExpr) return &other } // String returns the string representation of the constraint. func (c *TimeQuantumConstraint) String() string { var buf bytes.Buffer buf.WriteString("TIMEQUANTUM ") buf.WriteString(c.Expr.String()) return buf.String() } type CheckConstraint struct { Constraint Pos // position of CONSTRAINT keyword Name *Ident // constraint name Check Pos // position of UNIQUE keyword Lparen Pos // position of left paren Expr Expr // check expression Rparen Pos // position of right paren } // Clone returns a deep copy of c. func (c *CheckConstraint) Clone() *CheckConstraint { if c == nil { return c } other := *c other.Name = c.Name.Clone() other.Expr = CloneExpr(c.Expr) return &other } // String returns the string representation of the constraint. func (c *CheckConstraint) String() string { var buf bytes.Buffer if c.Name != nil { buf.WriteString("CONSTRAINT ") buf.WriteString(c.Name.String()) buf.WriteString(" ") } buf.WriteString("CHECK (") buf.WriteString(c.Expr.String()) buf.WriteString(")") return buf.String() } type DefaultConstraint struct { Constraint Pos // position of CONSTRAINT keyword Name *Ident // constraint name Default Pos // position of DEFAULT keyword Lparen Pos // position of left paren Expr Expr // default expression Rparen Pos // position of right paren } // Clone returns a deep copy of c. func (c *DefaultConstraint) Clone() *DefaultConstraint { if c == nil { return c } other := *c other.Name = c.Name.Clone() other.Expr = CloneExpr(c.Expr) return &other } // String returns the string representation of the constraint. func (c *DefaultConstraint) String() string { var buf bytes.Buffer if c.Name != nil { buf.WriteString("CONSTRAINT ") buf.WriteString(c.Name.String()) buf.WriteString(" ") } buf.WriteString("DEFAULT ") if c.Lparen.IsValid() { buf.WriteString("(") buf.WriteString(c.Expr.String()) buf.WriteString(")") } else { buf.WriteString(c.Expr.String()) } return buf.String() } type ForeignKeyConstraint struct { Constraint Pos // position of CONSTRAINT keyword Name *Ident // constraint name Foreign Pos // position of FOREIGN keyword (table only) ForeignKey Pos // position of KEY keyword after FOREIGN (table only) Lparen Pos // position of left paren (table only) Columns []*Ident // indexed columns (table only) Rparen Pos // position of right paren (table only) References Pos // position of REFERENCES keyword ForeignTable *Ident // foreign table name ForeignLparen Pos // position of left paren ForeignColumns []*Ident // column list ForeignRparen Pos // position of right paren Args []*ForeignKeyArg // arguments Deferrable Pos // position of DEFERRABLE keyword Not Pos // position of NOT keyword NotDeferrable Pos // position of DEFERRABLE keyword after NOT Initially Pos // position of INITIALLY keyword InitiallyDeferred Pos // position of DEFERRED keyword after INITIALLY InitiallyImmediate Pos // position of IMMEDIATE keyword after INITIALLY } // Clone returns a deep copy of c. func (c *ForeignKeyConstraint) Clone() *ForeignKeyConstraint { if c == nil { return c } other := *c other.Name = c.Name.Clone() other.Columns = cloneIdents(c.Columns) other.ForeignTable = c.ForeignTable.Clone() other.ForeignColumns = cloneIdents(c.ForeignColumns) other.Args = cloneForeignKeyArgs(c.Args) return &other } // String returns the string representation of the constraint. func (c *ForeignKeyConstraint) String() string { var buf bytes.Buffer if c.Name != nil { buf.WriteString("CONSTRAINT ") buf.WriteString(c.Name.String()) buf.WriteString(" ") } if len(c.Columns) > 0 { buf.WriteString("FOREIGN KEY (") for i := range c.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(c.Columns[i].String()) } buf.WriteString(") ") } buf.WriteString("REFERENCES ") buf.WriteString(c.ForeignTable.String()) if len(c.ForeignColumns) > 0 { buf.WriteString(" (") for i := range c.ForeignColumns { if i != 0 { buf.WriteString(", ") } buf.WriteString(c.ForeignColumns[i].String()) } buf.WriteString(")") } for i := range c.Args { buf.WriteString(" ") buf.WriteString(c.Args[i].String()) } if c.Deferrable.IsValid() || c.NotDeferrable.IsValid() { if c.Deferrable.IsValid() { buf.WriteString(" DEFERRABLE") } else { buf.WriteString(" NOT DEFERRABLE") } if c.InitiallyDeferred.IsValid() { buf.WriteString(" INITIALLY DEFERRED") } else if c.InitiallyImmediate.IsValid() { buf.WriteString(" INITIALLY IMMEDIATE") } } return buf.String() } type ForeignKeyArg struct { On Pos // position of ON keyword OnUpdate Pos // position of the UPDATE keyword OnDelete Pos // position of the DELETE keyword Set Pos // position of the SET keyword SetNull Pos // position of the NULL keyword after SET SetDefault Pos // position of the DEFAULT keyword after SET Cascade Pos // position of the CASCADE keyword Restrict Pos // position of the RESTRICT keyword No Pos // position of the NO keyword NoAction Pos // position of the ACTION keyword after NO } // Clone returns a deep copy of arg. func (arg *ForeignKeyArg) Clone() *ForeignKeyArg { if arg == nil { return nil } other := *arg return &other } func cloneForeignKeyArgs(a []*ForeignKeyArg) []*ForeignKeyArg { if a == nil { return nil } other := make([]*ForeignKeyArg, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the argument. func (c *ForeignKeyArg) String() string { var buf bytes.Buffer buf.WriteString("ON") if c.OnUpdate.IsValid() { buf.WriteString(" UPDATE") } else { buf.WriteString(" DELETE") } if c.SetNull.IsValid() { buf.WriteString(" SET NULL") } else if c.SetDefault.IsValid() { buf.WriteString(" SET DEFAULT") } else if c.Cascade.IsValid() { buf.WriteString(" CASCADE") } else if c.Restrict.IsValid() { buf.WriteString(" RESTRICT") } else if c.NoAction.IsValid() { buf.WriteString(" NO ACTION") } return buf.String() } type AnalyzeStatement struct { Analyze Pos // position of ANALYZE keyword Name *Ident // table name } // Clone returns a deep copy of s. func (s *AnalyzeStatement) Clone() *AnalyzeStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *AnalyzeStatement) String() string { return fmt.Sprintf("ANALYZE %s", s.Name.String()) } type AlterDatabaseStatement struct { Alter Pos // position of ALTER keyword Database Pos // position of DATABASE keyword Name *Ident // database name With Pos // position of WITH keyword Option DatabaseOption } // Clone returns a deep copy of s. func (s *AlterDatabaseStatement) Clone() *AlterDatabaseStatement { if s == nil { return nil } other := *s other.Name = other.Name.Clone() return &other } // String returns the string representation of the statement. func (s *AlterDatabaseStatement) String() string { var buf bytes.Buffer buf.WriteString("ALTER DATABASE ") buf.WriteString(s.Name.String()) if s.Option != nil { buf.WriteString(" WITH ") buf.WriteString(s.Option.String()) } return buf.String() } type AlterTableStatement struct { Alter Pos // position of ALTER keyword Table Pos // position of TABLE keyword Name *Ident // table name Rename Pos // position of RENAME keyword //RenameTo Pos // position of TO keyword after RENAME //NewName *Ident // new table name RenameColumn Pos // position of COLUMN keyword after RENAME OldColumnName *Ident // old column name To Pos // position of TO keyword NewColumnName *Ident // new column name Add Pos // position of ADD keyword AddColumn Pos // position of COLUMN keyword after ADD ColumnDef *ColumnDefinition // new column definition Drop Pos // position of ADD keyword DropColumn Pos // position of COLUMN keyword after ADD DropColumnName *Ident // drop column name } // Clone returns a deep copy of s. func (s *AlterTableStatement) Clone() *AlterTableStatement { if s == nil { return nil } other := *s other.Name = other.Name.Clone() //other.NewName = s.NewName.Clone() other.OldColumnName = s.OldColumnName.Clone() other.NewColumnName = s.NewColumnName.Clone() other.ColumnDef = s.ColumnDef.Clone() other.DropColumnName = s.DropColumnName.Clone() return &other } // String returns the string representation of the statement. func (s *AlterTableStatement) String() string { var buf bytes.Buffer buf.WriteString("ALTER TABLE ") buf.WriteString(s.Name.String()) if s.OldColumnName != nil { buf.WriteString(" RENAME ") if s.RenameColumn.IsValid() { buf.WriteString("COLUMN ") } buf.WriteString(s.OldColumnName.String()) buf.WriteString(" TO ") buf.WriteString(s.NewColumnName.String()) } else if s.DropColumnName != nil { buf.WriteString(" DROP ") if s.DropColumn.IsValid() { buf.WriteString("COLUMN ") } buf.WriteString(s.DropColumnName.String()) } else if s.ColumnDef != nil { buf.WriteString(" ADD ") if s.AddColumn.IsValid() { buf.WriteString("COLUMN ") } buf.WriteString(s.ColumnDef.String()) } return buf.String() } type Ident struct { NamePos Pos // identifier position Name string // identifier name Quoted bool // true if double quoted } func (expr *Ident) IsLiteral() bool { return false } func (expr *Ident) DataType() ExprDataType { return NewDataTypeVoid() } func (expr *Ident) Pos() Pos { return expr.NamePos } // Clone returns a deep copy of i. func (i *Ident) Clone() *Ident { if i == nil { return nil } other := *i return &other } func cloneIdents(a []*Ident) []*Ident { if a == nil { return nil } other := make([]*Ident, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the expression. func (i *Ident) String() string { if i.Quoted { return `"` + strings.Replace(i.Name, `"`, `""`, -1) + `"` } return i.Name } // IdentName returns the name of ident. Returns a blank string if ident is nil. func IdentName(ident *Ident) string { if ident == nil { return "" } return ident.Name } // SysVariable represents built-in system variables that can be referenced in the sql for current date, current time and other potential pre-determinable values. // In SQL these system provided data elements are referenced using keywords such as CURRENT_DATE & CURRENT_TIMESTAMP, etc. type SysVariable struct { NamePos Pos // variable position in sql Token Token // parser token mapped to the variable's name/keyword } func (*SysVariable) IsLiteral() bool { return false } func (svar *SysVariable) Pos() Pos { return svar.NamePos } func (svar *SysVariable) Clone() *SysVariable { if svar == nil { return nil } other := *svar return &other } func (svar *SysVariable) Name() string { return tokens[svar.Token] } func (svar *SysVariable) String() string { return svar.Name() } func (svar *SysVariable) DataType() ExprDataType { switch svar.Token { case CURRENT_DATE, CURRENT_TIMESTAMP: return NewDataTypeTimestamp() } return nil } type Variable struct { NamePos Pos // variable position Name string // variable name VariableIndex int VarDataType ExprDataType } func (expr *Variable) IsLiteral() bool { return false } func (expr *Variable) DataType() ExprDataType { return expr.VarDataType } func (expr *Variable) Pos() Pos { return expr.NamePos } // Clone returns a deep copy of i. func (i *Variable) Clone() *Variable { if i == nil { return nil } other := *i return &other } // String returns the string representation of the expression. func (i *Variable) String() string { return i.Name } func (i *Variable) VarName() string { return i.Name[1:] } type Type struct { Name *Ident // type name Lparen Pos // position of left paren (optional) Precision *IntegerLit // precision (optional) Scale *IntegerLit // scale (optional) Rparen Pos // position of right paren (optional) } // Clone returns a deep copy of t. func (t *Type) Clone() *Type { if t == nil { return nil } other := *t other.Name = t.Name.Clone() other.Precision = t.Precision.Clone() other.Scale = t.Scale.Clone() return &other } // String returns the string representation of the type. func (t *Type) String() string { if t.Precision != nil && t.Scale != nil { return fmt.Sprintf("%s(%s,%s)", t.Name.Name, t.Precision.String(), t.Scale.String()) } else if t.Precision != nil { return fmt.Sprintf("%s(%s)", t.Name.Name, t.Precision.String()) } else if t.Scale != nil { // I'm not sure how you're supposed to tell this from the t.Precision case. return fmt.Sprintf("%s(%s)", t.Name.Name, t.Scale.String()) } return t.Name.Name } type StringLit struct { ValuePos Pos // literal position Value string // literal value (without quotes) IsBlob bool // are we a blob? } func (expr *StringLit) IsLiteral() bool { return true } func (expr *StringLit) DataType() ExprDataType { return NewDataTypeString() } func (expr *StringLit) Pos() Pos { return expr.ValuePos } func (expr *StringLit) ConvertToTimestamp() *DateLit { //try to coerce to a date if tm, err := time.ParseInLocation(time.RFC3339Nano, expr.Value, time.UTC); err == nil { return &DateLit{ValuePos: expr.ValuePos, Value: tm} } else if tm, err := time.ParseInLocation(time.RFC3339, expr.Value, time.UTC); err == nil { return &DateLit{ValuePos: expr.ValuePos, Value: tm} } else if tm, err := time.ParseInLocation("2006-01-02", expr.Value, time.UTC); err == nil { return &DateLit{ValuePos: expr.ValuePos, Value: tm} } else { return nil } } // Clone returns a deep copy of lit. func (lit *StringLit) Clone() *StringLit { if lit == nil { return nil } other := *lit return &other } // String returns the string representation of the expression. func (lit *StringLit) String() string { if lit.IsBlob { return `x'` + strings.Replace(lit.Value, `'`, `''`, -1) + `'` } else { return `'` + strings.Replace(lit.Value, `'`, `''`, -1) + `'` } } type IntegerLit struct { ValuePos Pos // literal position Value string // literal value } func (expr *IntegerLit) IsLiteral() bool { return true } func (expr *IntegerLit) DataType() ExprDataType { return NewDataTypeInt() } func (expr *IntegerLit) Pos() Pos { return expr.ValuePos } // Clone returns a deep copy of lit. func (lit *IntegerLit) Clone() *IntegerLit { if lit == nil { return nil } other := *lit return &other } // String returns the string representation of the expression. func (lit *IntegerLit) String() string { return lit.Value } type FloatLit struct { ValuePos Pos // literal position Value string // literal value } func (expr *FloatLit) IsLiteral() bool { return true } func (expr *FloatLit) DataType() ExprDataType { //how many decimal places do we have on the right of the point? scale := NumDecimalPlaces(expr.Value) return NewDataTypeDecimal(int64(scale)) } func (expr *FloatLit) Pos() Pos { return expr.ValuePos } // Clone returns a deep copy of lit. func (lit *FloatLit) Clone() *FloatLit { if lit == nil { return nil } other := *lit return &other } // String returns the string representation of the expression. func (lit *FloatLit) String() string { return lit.Value } type NullLit struct { ValuePos Pos } func (expr *NullLit) IsLiteral() bool { return true } func (expr *NullLit) DataType() ExprDataType { return NewDataTypeVoid() } func (expr *NullLit) Pos() Pos { return expr.ValuePos } // Clone returns a deep copy of lit. func (lit *NullLit) Clone() *NullLit { if lit == nil { return nil } other := *lit return &other } // String returns the string representation of the expression. func (lit *NullLit) String() string { return "NULL" } type BoolLit struct { ValuePos Pos // literal position Value bool // literal value } func (expr *BoolLit) IsLiteral() bool { return true } func (expr *BoolLit) DataType() ExprDataType { return NewDataTypeBool() } func (expr *BoolLit) Pos() Pos { return expr.ValuePos } // Clone returns a deep copy of lit. func (lit *BoolLit) Clone() *BoolLit { if lit == nil { return nil } other := *lit return &other } // String returns the string representation of the expression. func (lit *BoolLit) String() string { if lit.Value { return "TRUE" } return "FALSE" } type DateLit struct { ValuePos Pos // literal position Value time.Time // literal value } func (expr *DateLit) IsLiteral() bool { return true } func (expr *DateLit) DataType() ExprDataType { return NewDataTypeTimestamp() } func (expr *DateLit) Pos() Pos { return expr.ValuePos } // Clone returns a deep copy of lit. func (lit *DateLit) Clone() *DateLit { if lit == nil { return nil } other := *lit return &other } // String returns the string representation of the Datetime value. func (lit *DateLit) String() string { return "'" + lit.Value.Format(time.RFC3339) + "'" } type UnaryExpr struct { OpPos Pos // operation position Op Token // operation X Expr // target expression ResultDataType ExprDataType } func (expr *UnaryExpr) IsLiteral() bool { return expr.X.IsLiteral() } func (expr *UnaryExpr) DataType() ExprDataType { return expr.ResultDataType } func (expr *UnaryExpr) Pos() Pos { return expr.OpPos } // Clone returns a deep copy of expr. func (expr *UnaryExpr) Clone() *UnaryExpr { if expr == nil { return nil } other := *expr other.X = CloneExpr(expr.X) return &other } // String returns the string representation of the expression. func (expr *UnaryExpr) String() string { switch expr.Op { case PLUS: return "+" + expr.X.String() case MINUS: return "-" + expr.X.String() case BITNOT: return "!" + expr.X.String() default: panic(fmt.Sprintf("sql.UnaryExpr.String(): invalid op %s", expr.Op)) } } type BinaryExpr struct { X Expr // lhs OpPos Pos // position of Op Op Token // operator Y Expr // rhs ResultDataType ExprDataType } func (expr *BinaryExpr) IsLiteral() bool { return expr.X.IsLiteral() && expr.Y.IsLiteral() } func (expr *BinaryExpr) DataType() ExprDataType { return expr.ResultDataType } func (expr *BinaryExpr) Pos() Pos { return expr.X.Pos() } // Clone returns a deep copy of expr. func (expr *BinaryExpr) Clone() *BinaryExpr { if expr == nil { return nil } other := *expr other.X = CloneExpr(expr.X) other.Y = CloneExpr(expr.Y) return &other } // String returns the string representation of the expression. func (expr *BinaryExpr) String() string { switch expr.Op { case PLUS: return expr.X.String() + " + " + expr.Y.String() case MINUS: return expr.X.String() + " - " + expr.Y.String() case STAR: return expr.X.String() + " * " + expr.Y.String() case SLASH: return expr.X.String() + " / " + expr.Y.String() case REM: return expr.X.String() + " % " + expr.Y.String() case CONCAT: return expr.X.String() + " || " + expr.Y.String() case BETWEEN: return expr.X.String() + " BETWEEN " + expr.Y.String() case NOTBETWEEN: return expr.X.String() + " NOT BETWEEN " + expr.Y.String() case LSHIFT: return expr.X.String() + " << " + expr.Y.String() case RSHIFT: return expr.X.String() + " >> " + expr.Y.String() case BITAND: return expr.X.String() + " & " + expr.Y.String() case BITOR: return expr.X.String() + " | " + expr.Y.String() case LT: return expr.X.String() + " < " + expr.Y.String() case LE: return expr.X.String() + " <= " + expr.Y.String() case GT: return expr.X.String() + " > " + expr.Y.String() case GE: return expr.X.String() + " >= " + expr.Y.String() case EQ: return expr.X.String() + " = " + expr.Y.String() case NE: return expr.X.String() + " != " + expr.Y.String() case IS: return expr.X.String() + " IS " + expr.Y.String() case ISNOT: return expr.X.String() + " IS NOT " + expr.Y.String() case IN: return expr.X.String() + " IN " + expr.Y.String() case NOTIN: return expr.X.String() + " NOT IN " + expr.Y.String() case LIKE: return expr.X.String() + " LIKE " + expr.Y.String() case NOTLIKE: return expr.X.String() + " NOT LIKE " + expr.Y.String() case GLOB: return expr.X.String() + " GLOB " + expr.Y.String() case NOTGLOB: return expr.X.String() + " NOT GLOB " + expr.Y.String() case MATCH: return expr.X.String() + " MATCH " + expr.Y.String() case NOTMATCH: return expr.X.String() + " NOT MATCH " + expr.Y.String() case REGEXP: return expr.X.String() + " REGEXP " + expr.Y.String() case NOTREGEXP: return expr.X.String() + " NOT REGEXP " + expr.Y.String() case AND: return expr.X.String() + " AND " + expr.Y.String() case OR: return expr.X.String() + " OR " + expr.Y.String() default: panic(fmt.Sprintf("sql.BinaryExpr.String(): invalid op %s", expr.Op)) } } type CastExpr struct { Cast Pos // position of CAST keyword Lparen Pos // position of left paren X Expr // target expression As Pos // position of AS keyword Type *Type // cast type Rparen Pos // position of right paren ResultDataType ExprDataType } func (expr *CastExpr) IsLiteral() bool { return expr.X.IsLiteral() } func (expr *CastExpr) DataType() ExprDataType { return expr.ResultDataType } func (expr *CastExpr) Pos() Pos { return expr.Cast } // Clone returns a deep copy of expr. func (expr *CastExpr) Clone() *CastExpr { if expr == nil { return nil } other := *expr other.X = CloneExpr(expr.X) other.Type = expr.Type.Clone() return &other } // String returns the string representation of the expression. func (expr *CastExpr) String() string { return fmt.Sprintf("CAST (%s AS %s)", expr.X.String(), expr.Type.String()) } type CaseExpr struct { Case Pos // position of CASE keyword Operand Expr // optional condition after the CASE keyword Blocks []*CaseBlock // list of WHEN/THEN pairs Else Pos // position of ELSE keyword ElseExpr Expr // expression used by default case End Pos // position of END keyword ResultDataType ExprDataType } func (expr *CaseExpr) IsLiteral() bool { return false } func (expr *CaseExpr) DataType() ExprDataType { return expr.ResultDataType } func (expr *CaseExpr) Pos() Pos { return expr.Case } // Clone returns a deep copy of expr. func (expr *CaseExpr) Clone() *CaseExpr { if expr == nil { return nil } other := *expr other.Operand = CloneExpr(expr.Operand) other.Blocks = cloneCaseBlocks(expr.Blocks) other.ElseExpr = CloneExpr(expr.ElseExpr) return &other } // String returns the string representation of the expression. func (expr *CaseExpr) String() string { var buf bytes.Buffer buf.WriteString("CASE") if expr.Operand != nil { buf.WriteString(" ") buf.WriteString(expr.Operand.String()) } for _, blk := range expr.Blocks { buf.WriteString(" ") buf.WriteString(blk.String()) } if expr.ElseExpr != nil { buf.WriteString(" ELSE ") buf.WriteString(expr.ElseExpr.String()) } buf.WriteString(" END") return buf.String() } type CaseBlock struct { When Pos // position of WHEN keyword Condition Expr // block condition Then Pos // position of THEN keyword Body Expr // result expression } func (expr *CaseBlock) IsLiteral() bool { return false } func (expr *CaseBlock) DataType() ExprDataType { return expr.Body.DataType() } func (expr *CaseBlock) Pos() Pos { return expr.When } // Clone returns a deep copy of blk. func (blk *CaseBlock) Clone() *CaseBlock { if blk == nil { return nil } other := *blk other.Condition = CloneExpr(blk.Condition) other.Body = CloneExpr(blk.Body) return &other } func cloneCaseBlocks(a []*CaseBlock) []*CaseBlock { if a == nil { return nil } other := make([]*CaseBlock, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the block. func (b *CaseBlock) String() string { return fmt.Sprintf("WHEN %s THEN %s", b.Condition.String(), b.Body.String()) } type Exists struct { Not Pos // position of optional NOT keyword Exists Pos // position of EXISTS keyword Lparen Pos // position of left paren Select *SelectStatement // select statement Rparen Pos // position of right paren } func (expr *Exists) IsLiteral() bool { return false } func (expr *Exists) DataType() ExprDataType { return NewDataTypeBool() } func (expr *Exists) Pos() Pos { if expr.Not.IsValid() { return expr.Not } return expr.Exists } // Clone returns a deep copy of expr. func (expr *Exists) Clone() *Exists { if expr == nil { return nil } other := *expr other.Select = expr.Select.Clone() return &other } // String returns the string representation of the expression. func (expr *Exists) String() string { if expr.Not.IsValid() { return fmt.Sprintf("NOT EXISTS (%s)", expr.Select.String()) } return fmt.Sprintf("EXISTS (%s)", expr.Select.String()) } type ExprList struct { Lparen Pos // position of left paren Exprs []Expr // list of expressions Rparen Pos // position of right paren } func (expr *ExprList) IsLiteral() bool { for _, e := range expr.Exprs { if !e.IsLiteral() { return false } } return true } func (expr *ExprList) DataType() ExprDataType { return NewDataTypeVoid() } func (expr *ExprList) Pos() Pos { return expr.Lparen } // Clone returns a deep copy of l. func (l *ExprList) Clone() *ExprList { if l == nil { return nil } other := *l other.Exprs = cloneExprs(l.Exprs) return &other } func cloneExprLists(a []*ExprList) []*ExprList { if a == nil { return nil } other := make([]*ExprList, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the expression. func (l *ExprList) String() string { var buf bytes.Buffer buf.WriteString("(") for i, expr := range l.Exprs { if i != 0 { buf.WriteString(", ") } buf.WriteString(expr.String()) } buf.WriteString(")") return buf.String() } type Range struct { X Expr // lhs expression And Pos // position of AND keyword Y Expr // rhs expression ResultDataType ExprDataType } func (expr *Range) IsLiteral() bool { return false } func (expr *Range) DataType() ExprDataType { return expr.ResultDataType } func (expr *Range) Pos() Pos { return expr.X.Pos() } // Clone returns a deep copy of r. func (r *Range) Clone() *Range { if r == nil { return nil } other := *r other.X = CloneExpr(r.X) other.Y = CloneExpr(r.Y) return &other } // String returns the string representation of the expression. func (r *Range) String() string { return fmt.Sprintf("%s AND %s", r.X.String(), r.Y.String()) } type QualifiedRef struct { Table *Ident // table name Dot Pos // position of dot Star Pos // position of * (result column only) Column *Ident // column name ColumnIndex int // Set by the planner; not at parse-time RefDataType ExprDataType } func (expr *QualifiedRef) IsLiteral() bool { return false } func (expr *QualifiedRef) DataType() ExprDataType { return expr.RefDataType } func (expr *QualifiedRef) Pos() Pos { return expr.Table.Pos() } // Clone returns a deep copy of r. func (r *QualifiedRef) Clone() *QualifiedRef { if r == nil { return nil } other := *r other.Table = r.Table.Clone() other.Column = r.Column.Clone() return &other } // String returns the string representation of the expression. func (r *QualifiedRef) String() string { if r.Star.IsValid() { return fmt.Sprintf("%s.*", r.Table.String()) } return fmt.Sprintf("%s.%s", r.Table.String(), r.Column.String()) } type Call struct { Name *Ident // function name Lparen Pos // position of left paren Star Pos // position of * Distinct Pos // position of DISTINCT keyword Args []Expr // argument list Rparen Pos // position of right paren Filter *FilterClause // filter clause Over *OverClause // over clause ResultDataType ExprDataType } func (expr *Call) IsLiteral() bool { return false } func (expr *Call) DataType() ExprDataType { return expr.ResultDataType } func (expr *Call) Pos() Pos { return expr.Name.Pos() } // Clone returns a deep copy of c. func (c *Call) Clone() *Call { if c == nil { return nil } other := *c other.Name = c.Name.Clone() other.Args = cloneExprs(c.Args) other.Filter = c.Filter.Clone() other.Over = c.Over.Clone() return &other } // String returns the string representation of the expression. func (c *Call) String() string { var buf bytes.Buffer buf.WriteString(c.Name.Name) buf.WriteString("(") if c.Star.IsValid() { buf.WriteString("*") } else { if c.Distinct.IsValid() { buf.WriteString("DISTINCT") if len(c.Args) != 0 { buf.WriteString(" ") } } for i, arg := range c.Args { if i != 0 { buf.WriteString(", ") } buf.WriteString(arg.String()) } } buf.WriteString(")") if c.Filter != nil { buf.WriteString(" ") buf.WriteString(c.Filter.String()) } if c.Over != nil { buf.WriteString(" ") buf.WriteString(c.Over.String()) } return buf.String() } type FilterClause struct { Filter Pos // position of FILTER keyword Lparen Pos // position of left paren Where Pos // position of WHERE keyword X Expr // filter expression Rparen Pos // position of right paren } // Clone returns a deep copy of c. func (c *FilterClause) Clone() *FilterClause { if c == nil { return nil } other := *c other.X = CloneExpr(c.X) return &other } // String returns the string representation of the clause. func (c *FilterClause) String() string { return fmt.Sprintf("FILTER (WHERE %s)", c.X.String()) } type OverClause struct { Over Pos // position of OVER keyword Name *Ident // window name Definition *WindowDefinition // window definition } // Clone returns a deep copy of c. func (c *OverClause) Clone() *OverClause { if c == nil { return nil } other := *c other.Name = c.Name.Clone() other.Definition = c.Definition.Clone() return &other } // String returns the string representation of the clause. func (c *OverClause) String() string { if c.Name != nil { return fmt.Sprintf("OVER %s", c.Name.String()) } return fmt.Sprintf("OVER %s", c.Definition.String()) } type OrderingTerm struct { X Expr // ordering expression Asc Pos // position of ASC keyword Desc Pos // position of DESC keyword Nulls Pos // position of NULLS keyword NullsFirst Pos // position of FIRST keyword NullsLast Pos // position of LAST keyword } // Clone returns a deep copy of t. func (t *OrderingTerm) Clone() *OrderingTerm { if t == nil { return nil } other := *t other.X = CloneExpr(t.X) return &other } func cloneOrderingTerms(a []*OrderingTerm) []*OrderingTerm { if a == nil { return nil } other := make([]*OrderingTerm, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the term. func (t *OrderingTerm) String() string { var buf bytes.Buffer buf.WriteString(t.X.String()) if t.Asc.IsValid() { buf.WriteString(" ASC") } else if t.Desc.IsValid() { buf.WriteString(" DESC") } if t.NullsFirst.IsValid() { buf.WriteString(" NULLS FIRST") } else if t.NullsLast.IsValid() { buf.WriteString(" NULLS LAST") } return buf.String() } type FrameSpec struct { Range Pos // position of RANGE keyword Rows Pos // position of ROWS keyword Groups Pos // position of GROUPS keyword Between Pos // position of BETWEEN keyword X Expr // lhs expression UnboundedX Pos // position of lhs UNBOUNDED keyword PrecedingX Pos // position of lhs PRECEDING keyword CurrentX Pos // position of lhs CURRENT keyword CurrentRowX Pos // position of lhs ROW keyword FollowingX Pos // position of lhs FOLLOWING keyword And Pos // position of AND keyword Y Expr // lhs expression UnboundedY Pos // position of rhs UNBOUNDED keyword FollowingY Pos // position of rhs FOLLOWING keyword CurrentY Pos // position of rhs CURRENT keyword CurrentRowY Pos // position of rhs ROW keyword PrecedingY Pos // position of rhs PRECEDING keyword Exclude Pos // position of EXCLUDE keyword ExcludeNo Pos // position of NO keyword after EXCLUDE ExcludeNoOthers Pos // position of OTHERS keyword after EXCLUDE NO ExcludeCurrent Pos // position of CURRENT keyword after EXCLUDE ExcludeCurrentRow Pos // position of ROW keyword after EXCLUDE CURRENT ExcludeGroup Pos // position of GROUP keyword after EXCLUDE ExcludeTies Pos // position of TIES keyword after EXCLUDE } // Clone returns a deep copy of s. func (s *FrameSpec) Clone() *FrameSpec { if s == nil { return nil } other := *s other.X = CloneExpr(s.X) other.Y = CloneExpr(s.Y) return &other } // String returns the string representation of the frame spec. func (s *FrameSpec) String() string { var buf bytes.Buffer if s.Range.IsValid() { buf.WriteString("RANGE") } else if s.Rows.IsValid() { buf.WriteString("ROWS") } else if s.Groups.IsValid() { buf.WriteString("GROUPS") } if s.Between.IsValid() { buf.WriteString(" BETWEEN") if s.UnboundedX.IsValid() && s.PrecedingX.IsValid() { buf.WriteString(" UNBOUNDED PRECEDING") } else if s.X != nil && s.PrecedingX.IsValid() { fmt.Fprintf(&buf, " %s PRECEDING", s.X.String()) } else if s.CurrentRowX.IsValid() { buf.WriteString(" CURRENT ROW") } else if s.X != nil && s.FollowingX.IsValid() { fmt.Fprintf(&buf, " %s FOLLOWING", s.X.String()) } buf.WriteString(" AND") if s.Y != nil && s.PrecedingY.IsValid() { fmt.Fprintf(&buf, " %s PRECEDING", s.Y.String()) } else if s.CurrentRowY.IsValid() { buf.WriteString(" CURRENT ROW") } else if s.Y != nil && s.FollowingY.IsValid() { fmt.Fprintf(&buf, " %s FOLLOWING", s.Y.String()) } else if s.UnboundedY.IsValid() && s.FollowingY.IsValid() { buf.WriteString(" UNBOUNDED FOLLOWING") } } else { if s.UnboundedX.IsValid() && s.PrecedingX.IsValid() { buf.WriteString(" UNBOUNDED PRECEDING") } else if s.X != nil && s.PrecedingX.IsValid() { fmt.Fprintf(&buf, " %s PRECEDING", s.X.String()) } else if s.CurrentRowX.IsValid() { buf.WriteString(" CURRENT ROW") } } if s.ExcludeNoOthers.IsValid() { buf.WriteString(" EXCLUDE NO OTHERS") } else if s.ExcludeCurrentRow.IsValid() { buf.WriteString(" EXCLUDE CURRENT ROW") } else if s.ExcludeGroup.IsValid() { buf.WriteString(" EXCLUDE GROUP") } else if s.ExcludeTies.IsValid() { buf.WriteString(" EXCLUDE TIES") } return buf.String() } type ColumnArg interface { Node columnArg() } type DropDatabaseStatement struct { Drop Pos // position of DROP keyword Database Pos // position of DATABASE keyword If Pos // position of IF keyword IfExists Pos // position of EXISTS keyword after IF Name *Ident // database name } // Clone returns a deep copy of s. func (s *DropDatabaseStatement) Clone() *DropDatabaseStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *DropDatabaseStatement) String() string { var buf bytes.Buffer buf.WriteString("DROP DATABASE") if s.IfExists.IsValid() { buf.WriteString(" IF EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) return buf.String() } type DropTableStatement struct { Drop Pos // position of DROP keyword Table Pos // position of TABLE keyword If Pos // position of IF keyword IfExists Pos // position of EXISTS keyword after IF Name *Ident // table name } // Clone returns a deep copy of s. func (s *DropTableStatement) Clone() *DropTableStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *DropTableStatement) String() string { var buf bytes.Buffer buf.WriteString("DROP TABLE") if s.IfExists.IsValid() { buf.WriteString(" IF EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) return buf.String() } type CreateViewStatement struct { Create Pos // position of CREATE keyword View Pos // position of VIEW keyword If Pos // position of IF keyword IfNot Pos // position of NOT keyword after IF IfNotExists Pos // position of EXISTS keyword after IF NOT Name *Ident // view name // TODO(pok) - we'll do this later - see note in parseCompileView() // Lparen Pos // position of column list left paren // Columns []*Ident // column list // Rparen Pos // position of column list right paren As Pos // position of AS keyword Select *SelectStatement // source statement } // Clone returns a deep copy of s. func (s *CreateViewStatement) Clone() *CreateViewStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() // other.Columns = cloneIdents(s.Columns) other.Select = s.Select.Clone() return &other } // String returns the string representation of the statement. func (s *CreateViewStatement) String() string { var buf bytes.Buffer buf.WriteString("CREATE VIEW") if s.IfNotExists.IsValid() { buf.WriteString(" IF NOT EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) // if len(s.Columns) > 0 { // buf.WriteString(" (") // for i, col := range s.Columns { // if i != 0 { // buf.WriteString(", ") // } // buf.WriteString(col.String()) // } // buf.WriteString(")") // } fmt.Fprintf(&buf, " AS %s", s.Select.String()) return buf.String() } type AlterViewStatement struct { Alter Pos // position of CREATE keyword View Pos // position of VIEW keyword Name *Ident // view name // TODO(pok) - we'll do this later - see note in parseCompileView() // Lparen Pos // position of column list left paren // Columns []*Ident // column list // Rparen Pos // position of column list right paren As Pos // position of AS keyword Select *SelectStatement // source statement } // Clone returns a deep copy of s. func (s *AlterViewStatement) Clone() *AlterViewStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() // other.Columns = cloneIdents(s.Columns) other.Select = s.Select.Clone() return &other } // String returns the string representation of the statement. func (s *AlterViewStatement) String() string { var buf bytes.Buffer buf.WriteString("ALTER VIEW") fmt.Fprintf(&buf, " %s", s.Name.String()) // if len(s.Columns) > 0 { // buf.WriteString(" (") // for i, col := range s.Columns { // if i != 0 { // buf.WriteString(", ") // } // buf.WriteString(col.String()) // } // buf.WriteString(")") // } fmt.Fprintf(&buf, " AS %s", s.Select.String()) return buf.String() } type DropViewStatement struct { Drop Pos // position of DROP keyword View Pos // position of VIEW keyword If Pos // position of IF keyword IfExists Pos // position of EXISTS keyword after IF Name *Ident // view name } // Clone returns a deep copy of s. func (s *DropViewStatement) Clone() *DropViewStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *DropViewStatement) String() string { var buf bytes.Buffer buf.WriteString("DROP VIEW") if s.IfExists.IsValid() { buf.WriteString(" IF EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) return buf.String() } type CreateIndexStatement struct { Create Pos // position of CREATE keyword Unique Pos // position of optional UNIQUE keyword Index Pos // position of INDEX keyword If Pos // position of IF keyword IfNot Pos // position of NOT keyword after IF IfNotExists Pos // position of EXISTS keyword after IF NOT Name *Ident // index name On Pos // position of ON keyword Table *Ident // index name Lparen Pos // position of column list left paren Columns []*IndexedColumn // column list Rparen Pos // position of column list right paren Where Pos // position of WHERE keyword WhereExpr Expr // conditional expression } // Clone returns a deep copy of s. func (s *CreateIndexStatement) Clone() *CreateIndexStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() other.Table = s.Table.Clone() other.Columns = cloneIndexedColumns(s.Columns) other.WhereExpr = CloneExpr(s.WhereExpr) return &other } // String returns the string representation of the statement. func (s *CreateIndexStatement) String() string { var buf bytes.Buffer buf.WriteString("CREATE") if s.Unique.IsValid() { buf.WriteString(" UNIQUE") } buf.WriteString(" INDEX") if s.IfNotExists.IsValid() { buf.WriteString(" IF NOT EXISTS") } fmt.Fprintf(&buf, " %s ON %s ", s.Name.String(), s.Table.String()) buf.WriteString("(") for i, col := range s.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") if s.WhereExpr != nil { fmt.Fprintf(&buf, " WHERE %s", s.WhereExpr.String()) } return buf.String() } type DropIndexStatement struct { Drop Pos // position of DROP keyword Index Pos // position of INDEX keyword If Pos // position of IF keyword IfExists Pos // position of EXISTS keyword after IF Name *Ident // index name } // Clone returns a deep copy of s. func (s *DropIndexStatement) Clone() *DropIndexStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() return &other } // String returns the string representation of the statement. func (s *DropIndexStatement) String() string { var buf bytes.Buffer buf.WriteString("DROP INDEX") if s.IfExists.IsValid() { buf.WriteString(" IF EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) return buf.String() } type ParameterDefinition struct { Name *Variable // parameter name Type *Type // data type } type CreateFunctionStatement struct { Create Pos // position of CREATE keyword Function Pos // position of FUNCTION keyword If Pos // position of IF keyword IfNot Pos // position of NOT keyword after IF IfNotExists Pos // position of EXISTS keyword after IF NOT Name *Ident // index name Lparen Pos // position of parameter LParen Parameters []*ParameterDefinition // parameters Rparen Pos // position of parameter RParen Returns Pos // position of RETURNS keyword ReturnDef *ParameterDefinition // return def As Pos // position of AS keyword Begin Pos // position of BEGIN keyword Body []Statement // function body End Pos // position of END keyword } // Clone returns a deep copy of s. func (s *CreateFunctionStatement) Clone() *CreateFunctionStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() other.Body = cloneStatements(s.Body) return &other } // String returns the string representation of the statement. func (s *CreateFunctionStatement) String() string { var buf bytes.Buffer buf.WriteString("CREATE FUNCTION") if s.IfNotExists.IsValid() { buf.WriteString(" IF NOT EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) if len(s.Parameters) > 0 { buf.WriteString(" (") for idx, p := range s.Parameters { if idx > 0 { buf.WriteString(", ") } fmt.Fprintf(&buf, "%s %s", p.Name.Name, p.Type.Name) } buf.WriteString(")") } buf.WriteString(" RETURNS ") fmt.Fprintf(&buf, "%s %s", s.ReturnDef.Name, s.ReturnDef.Type.Name) buf.WriteString(" AS BEGIN") for i := range s.Body { fmt.Fprintf(&buf, " %s;", s.Body[i].String()) } buf.WriteString(" END") return buf.String() } type DropFunctionStatement struct { Drop Pos // position of DROP keyword Function Pos // position of FUNCTION keyword If Pos // position of IF keyword IfExists Pos // position of EXISTS keyword after IF Name *Ident // trigger name } // Clone returns a deep copy of s. func (s *DropFunctionStatement) Clone() *DropFunctionStatement { if s == nil { return nil } other := *s other.Name = s.Name.Clone() return &other } func (s *DropFunctionStatement) String() string { var buf bytes.Buffer buf.WriteString("DROP FUNCTION") if s.IfExists.IsValid() { buf.WriteString(" IF EXISTS") } fmt.Fprintf(&buf, " %s", s.Name.String()) return buf.String() } type BulkInsertMapDefinition struct { Name *Ident // map name Type *Type // data type MapExpr Expr } // Clone returns a deep copy of d. func (d *BulkInsertMapDefinition) Clone() *BulkInsertMapDefinition { if d == nil { return d } other := *d other.Name = d.Name.Clone() other.Type = d.Type.Clone() //other.MapExpr = d.MapExpr.Clone() return &other } // String returns the string representation of the statement. func (c *BulkInsertMapDefinition) String() string { var buf bytes.Buffer buf.WriteString(c.MapExpr.String()) buf.WriteString(" ") buf.WriteString(c.Name.String()) buf.WriteString(" ") buf.WriteString(c.Type.String()) return buf.String() } type BulkInsertStatement struct { Bulk Pos // position of BULK keyword Insert Pos // position of INSERT keyword Replace Pos // position of REPLACE keyword Into Pos // position of INTO keyword Table *Ident // table name ColumnsLparen Pos // position of column list left paren Columns []*Ident // optional column list ColumnsRparen Pos // position of column list right paren Map Pos // position of MAP keyword MapLparen Pos // position of column list left paren MapList []*BulkInsertMapDefinition // source to column map MapRparen Pos // position of column list right paren Transform Pos // position of MAP keyword TransformLparen Pos // position of column list left paren TransformList []Expr // source to column map TransformRparen Pos // position of column list right paren From Pos // position of FROM keyword DataSource Expr // data source With Pos // position of WITH keyword BatchSize Expr RowsLimit Expr Format Expr Input Expr HeaderRow Expr // has header row (that needs to be skipped) AllowMissingValues Expr // allows missing values } func (s *BulkInsertStatement) String() string { var buf bytes.Buffer buf.WriteString("BULK ") if s.Replace.IsValid() { buf.WriteString("REPLACE") } else { buf.WriteString("INSERT") } buf.WriteString(" INTO ") fmt.Fprintf(&buf, " %s", s.Table.String()) if s.Columns != nil { buf.WriteString("(") for i, col := range s.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") } buf.WriteString(" MAP ") buf.WriteString("(") for i, m := range s.MapList { if i != 0 { buf.WriteString(", ") } buf.WriteString(m.String()) } buf.WriteString(")") if s.TransformList != nil { buf.WriteString(" TRANSFORM ") buf.WriteString("(") for i, t := range s.TransformList { if i != 0 { buf.WriteString(", ") } buf.WriteString(t.String()) } buf.WriteString(")") } buf.WriteString(" FROM ") fmt.Fprintf(&buf, " %s", s.DataSource.String()) buf.WriteString(" WITH ") if s.Format != nil { buf.WriteString("FORMAT ") buf.WriteString(s.Format.String()) } if s.Input != nil { buf.WriteString("INPUT ") buf.WriteString(s.Input.String()) } if s.HeaderRow != nil { buf.WriteString("HEADER_ROW ") } if s.BatchSize != nil { buf.WriteString("BATCHSIZE ") buf.WriteString(s.BatchSize.String()) } if s.RowsLimit != nil { buf.WriteString("ROWSLIMIT ") buf.WriteString(s.RowsLimit.String()) } return buf.String() } type InsertStatement struct { //WithClause *WithClause // clause containing CTEs Insert Pos // position of INSERT keyword Replace Pos // position of REPLACE keyword InsertOr Pos // position of OR keyword after INSERT InsertOrReplace Pos // position of REPLACE keyword after INSERT OR // InsertOrRollback Pos // position of ROLLBACK keyword after INSERT OR // InsertOrAbort Pos // position of ABORT keyword after INSERT OR // InsertOrFail Pos // position of FAIL keyword after INSERT OR // InsertOrIgnore Pos // position of IGNORE keyword after INSERT OR Into Pos // position of INTO keyword Table *Ident // table name As Pos // position of AS keyword Alias *Ident // optional alias ColumnsLparen Pos // position of column list left paren Columns []*Ident // optional column list ColumnsRparen Pos // position of column list right paren Values Pos // position of VALUES keyword TupleList []*ExprList // multiple tuples // Select *SelectStatement // SELECT statement // Default Pos // position of DEFAULT keyword // DefaultValues Pos // position of VALUES keyword after DEFAULT // UpsertClause *UpsertClause // optional upsert clause } // Clone returns a deep copy of s. func (s *InsertStatement) Clone() *InsertStatement { if s == nil { return nil } other := *s //other.WithClause = s.WithClause.Clone() other.Table = s.Table.Clone() other.Alias = s.Alias.Clone() other.Columns = cloneIdents(s.Columns) other.TupleList = cloneExprLists(s.TupleList) //other.Select = s.Select.Clone() //other.UpsertClause = s.UpsertClause.Clone() return &other } func (s *InsertStatement) String() string { var buf bytes.Buffer //if s.WithClause != nil { // buf.WriteString(s.WithClause.String()) // buf.WriteString(" ") //} if s.Replace.IsValid() { buf.WriteString("REPLACE") } else { buf.WriteString("INSERT") } /*if s.InsertOrReplace.IsValid() { buf.WriteString(" OR REPLACE") //} else if s.InsertOrRollback.IsValid() { // buf.WriteString(" OR ROLLBACK") //} else if s.InsertOrAbort.IsValid() { // buf.WriteString(" OR ABORT") //} else if s.InsertOrFail.IsValid() { // buf.WriteString(" OR FAIL") //} else if s.InsertOrIgnore.IsValid() { // buf.WriteString(" OR IGNORE") //} }*/ fmt.Fprintf(&buf, " INTO %s ", s.Table.String()) if s.Alias != nil { fmt.Fprintf(&buf, "AS %s ", s.Alias.String()) } if len(s.Columns) != 0 { buf.WriteString("(") for i, col := range s.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") } //if s.DefaultValues.IsValid() { // buf.WriteString(" DEFAULT VALUES") //} else if s.Select != nil { // fmt.Fprintf(&buf, " %s", s.Select.String()) //} else { buf.WriteString(" VALUES") for i, tuple := range s.TupleList { if i != 0 { buf.WriteString(",") } buf.WriteString(" (") for j, expr := range tuple.Exprs { if j != 0 { buf.WriteString(", ") } buf.WriteString(expr.String()) } buf.WriteString(")") } //} //if s.UpsertClause != nil { // fmt.Fprintf(&buf, " %s", s.UpsertClause.String()) //} return buf.String() } type UpsertClause struct { On Pos // position of ON keyword OnConflict Pos // position of CONFLICT keyword after ON Lparen Pos // position of column list left paren Columns []*IndexedColumn // optional indexed column list Rparen Pos // position of column list right paren Where Pos // position of WHERE keyword WhereExpr Expr // optional conditional expression Do Pos // position of DO keyword DoNothing Pos // position of NOTHING keyword after DO DoUpdate Pos // position of UPDATE keyword after DO DoUpdateSet Pos // position of SET keyword after DO UPDATE Assignments []*Assignment // list of column assignments UpdateWhere Pos // position of WHERE keyword for DO UPDATE SET UpdateWhereExpr Expr // optional conditional expression for DO UPDATE SET } // Clone returns a deep copy of c. func (c *UpsertClause) Clone() *UpsertClause { if c == nil { return nil } other := *c other.Columns = cloneIndexedColumns(c.Columns) other.WhereExpr = CloneExpr(c.WhereExpr) other.Assignments = cloneAssignments(c.Assignments) other.UpdateWhereExpr = CloneExpr(c.UpdateWhereExpr) return &other } // String returns the string representation of the clause. func (c *UpsertClause) String() string { var buf bytes.Buffer buf.WriteString("ON CONFLICT") if len(c.Columns) != 0 { buf.WriteString(" (") for i, col := range c.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") if c.WhereExpr != nil { fmt.Fprintf(&buf, " WHERE %s", c.WhereExpr.String()) } } buf.WriteString(" DO") if c.DoNothing.IsValid() { buf.WriteString(" NOTHING") } else { buf.WriteString(" UPDATE SET ") for i := range c.Assignments { if i != 0 { buf.WriteString(", ") } buf.WriteString(c.Assignments[i].String()) } if c.UpdateWhereExpr != nil { fmt.Fprintf(&buf, " WHERE %s", c.UpdateWhereExpr.String()) } } return buf.String() } type UpdateStatement struct { WithClause *WithClause // clause containing CTEs Update Pos // position of UPDATE keyword UpdateOr Pos // position of OR keyword after UPDATE UpdateOrReplace Pos // position of REPLACE keyword after UPDATE OR UpdateOrRollback Pos // position of ROLLBACK keyword after UPDATE OR UpdateOrAbort Pos // position of ABORT keyword after UPDATE OR UpdateOrFail Pos // position of FAIL keyword after UPDATE OR UpdateOrIgnore Pos // position of IGNORE keyword after UPDATE OR Table *QualifiedTableName // table name Set Pos // position of SET keyword Assignments []*Assignment // list of column assignments Where Pos // position of WHERE keyword WhereExpr Expr // conditional expression } // Clone returns a deep copy of s. func (s *UpdateStatement) Clone() *UpdateStatement { if s == nil { return nil } other := *s other.WithClause = s.WithClause.Clone() other.Table = s.Table.Clone() other.Assignments = cloneAssignments(s.Assignments) other.WhereExpr = CloneExpr(s.WhereExpr) return &other } // String returns the string representation of the clause. func (s *UpdateStatement) String() string { var buf bytes.Buffer if s.WithClause != nil { buf.WriteString(s.WithClause.String()) buf.WriteString(" ") } buf.WriteString("UPDATE") if s.UpdateOrRollback.IsValid() { buf.WriteString(" OR ROLLBACK") } else if s.UpdateOrAbort.IsValid() { buf.WriteString(" OR ABORT") } else if s.UpdateOrReplace.IsValid() { buf.WriteString(" OR REPLACE") } else if s.UpdateOrFail.IsValid() { buf.WriteString(" OR FAIL") } else if s.UpdateOrIgnore.IsValid() { buf.WriteString(" OR IGNORE") } fmt.Fprintf(&buf, " %s ", s.Table.String()) buf.WriteString("SET ") for i := range s.Assignments { if i != 0 { buf.WriteString(", ") } buf.WriteString(s.Assignments[i].String()) } if s.WhereExpr != nil { fmt.Fprintf(&buf, " WHERE %s", s.WhereExpr.String()) } return buf.String() } type DeleteStatement struct { // WithClause *WithClause // clause containing CTEs Delete Pos // position of UPDATE keyword From Pos // position of FROM keyword TableName *QualifiedTableName // the name of the table we are deleting from Source Source // source for the delete Where Pos // position of WHERE keyword WhereExpr Expr // conditional expression } // Clone returns a deep copy of s. func (s *DeleteStatement) Clone() *DeleteStatement { if s == nil { return nil } other := *s //other.WithClause = s.WithClause.Clone() other.Source = CloneSource(s.Source) other.WhereExpr = CloneExpr(s.WhereExpr) return &other } // String returns the string representation of the clause. func (s *DeleteStatement) String() string { var buf bytes.Buffer fmt.Fprintf(&buf, "DELETE FROM %s", s.TableName.String()) if s.WhereExpr != nil { fmt.Fprintf(&buf, " WHERE %s", s.WhereExpr.String()) } return buf.String() } // Assignment is used within the UPDATE statement & upsert clause. // It is similiar to an expression except that it must be an equality. type Assignment struct { Lparen Pos // position of column list left paren Columns []*Ident // column list Rparen Pos // position of column list right paren Eq Pos // position of = Expr Expr // assigned expression } // Clone returns a deep copy of a. func (a *Assignment) Clone() *Assignment { if a == nil { return nil } other := *a other.Columns = cloneIdents(a.Columns) other.Expr = CloneExpr(a.Expr) return &other } func cloneAssignments(a []*Assignment) []*Assignment { if a == nil { return nil } other := make([]*Assignment, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the clause. func (a *Assignment) String() string { var buf bytes.Buffer if len(a.Columns) == 1 { buf.WriteString(a.Columns[0].String()) } else if len(a.Columns) > 1 { buf.WriteString("(") for i, col := range a.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") } fmt.Fprintf(&buf, " = %s", a.Expr.String()) return buf.String() } type IndexedColumn struct { X Expr // column expression Asc Pos // position of optional ASC keyword Desc Pos // position of optional DESC keyword } // Clone returns a deep copy of c. func (c *IndexedColumn) Clone() *IndexedColumn { if c == nil { return nil } other := *c other.X = CloneExpr(c.X) return &other } func cloneIndexedColumns(a []*IndexedColumn) []*IndexedColumn { if a == nil { return nil } other := make([]*IndexedColumn, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the column. func (c *IndexedColumn) String() string { if c.Asc.IsValid() { return fmt.Sprintf("%s ASC", c.X.String()) } else if c.Desc.IsValid() { return fmt.Sprintf("%s DESC", c.X.String()) } return c.X.String() } type SelectStatement struct { WithClause *WithClause // clause containing CTEs // Values Pos // position of VALUES keyword // ValueLists []*ExprList // lists of lists of values Select Pos // position of SELECT keyword Distinct Pos // position of DISTINCT keyword // All Pos // position of ALL keyword Columns []*ResultColumn // list of result columns in the SELECT clause Top Pos // position of TOP keyword TopN Pos // position of TOPN keyword TopExpr Expr // TOP expr From Pos // position of FROM keyword Source Source // chain of tables & subqueries in FROM clause Where Pos // position of WHERE keyword WhereExpr Expr // condition for WHERE clause Group Pos // position of GROUP keyword GroupBy Pos // position of BY keyword after GROUP GroupByExprs []Expr // group by expression list Having Pos // position of HAVING keyword HavingExpr Expr // HAVING expression Window Pos // position of WINDOW keyword Windows []*Window // window list Union Pos // position of UNION keyword UnionAll Pos // position of ALL keyword after UNION Intersect Pos // position of INTERSECT keyword Except Pos // position of EXCEPT keyword Compound *SelectStatement // compounded SELECT statement Order Pos // position of ORDER keyword OrderBy Pos // position of BY keyword after ORDER OrderingTerms []*OrderingTerm // terms of ORDER BY clause } // Clone returns a deep copy of s. func (s *SelectStatement) Clone() *SelectStatement { if s == nil { return nil } other := *s other.WithClause = s.WithClause.Clone() //other.ValueLists = cloneExprLists(s.ValueLists) other.TopExpr = CloneExpr(s.TopExpr) other.Columns = cloneResultColumns(s.Columns) other.Source = CloneSource(s.Source) other.WhereExpr = CloneExpr(s.WhereExpr) other.GroupByExprs = cloneExprs(s.GroupByExprs) other.HavingExpr = CloneExpr(s.HavingExpr) other.Windows = cloneWindows(s.Windows) other.Compound = s.Compound.Clone() other.OrderingTerms = cloneOrderingTerms(s.OrderingTerms) return &other } func (expr *SelectStatement) IsLiteral() bool { return false } // HasWildcard returns true any result column contains a wildcard (STAR). func (s *SelectStatement) HasWildcard() bool { for _, col := range s.Columns { // Unqualified wildcard. if col.Star.IsValid() { return true } // Table-qualified wildcard. if ref, ok := col.Expr.(*QualifiedRef); ok && ref.Star.IsValid() { return true } } return false } func (s *SelectStatement) DataType() ExprDataType { return nil } func (s *SelectStatement) Pos() Pos { return s.Select } // String returns the string representation of the statement. func (s *SelectStatement) String() string { var buf bytes.Buffer if s.WithClause != nil { buf.WriteString(s.WithClause.String()) buf.WriteString(" ") } /*if len(s.ValueLists) > 0 { buf.WriteString("VALUES ") for i, exprs := range s.ValueLists { if i != 0 { buf.WriteString(", ") } buf.WriteString("(") for j, expr := range exprs.Exprs { if j != 0 { buf.WriteString(", ") } buf.WriteString(expr.String()) } buf.WriteString(")") } } else {*/ buf.WriteString("SELECT ") if s.Distinct.IsValid() { buf.WriteString("DISTINCT ") } //else if s.All.IsValid() { // buf.WriteString("ALL ") //} if s.Top.IsValid() { fmt.Fprintf(&buf, "TOP(%s) ", s.TopExpr.String()) } if s.TopN.IsValid() { fmt.Fprintf(&buf, "TOPN(%s) ", s.TopExpr.String()) } for i, col := range s.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } if s.Source != nil { fmt.Fprintf(&buf, " FROM %s", s.Source.String()) } if s.WhereExpr != nil { fmt.Fprintf(&buf, " WHERE %s", s.WhereExpr.String()) } if len(s.GroupByExprs) != 0 { buf.WriteString(" GROUP BY ") for i, expr := range s.GroupByExprs { if i != 0 { buf.WriteString(", ") } buf.WriteString(expr.String()) } if s.HavingExpr != nil { fmt.Fprintf(&buf, " HAVING %s", s.HavingExpr.String()) } } if len(s.Windows) != 0 { buf.WriteString(" WINDOW ") for i, window := range s.Windows { if i != 0 { buf.WriteString(", ") } buf.WriteString(window.String()) } } // } // Write compound operator. if s.Compound != nil { switch { case s.Union.IsValid(): buf.WriteString(" UNION") if s.UnionAll.IsValid() { buf.WriteString(" ALL") } case s.Intersect.IsValid(): buf.WriteString(" INTERSECT") case s.Except.IsValid(): buf.WriteString(" EXCEPT") } fmt.Fprintf(&buf, " %s", s.Compound.String()) } // Write ORDER BY. if len(s.OrderingTerms) != 0 { buf.WriteString(" ORDER BY ") for i, term := range s.OrderingTerms { if i != 0 { buf.WriteString(", ") } buf.WriteString(term.String()) } } return buf.String() } func (c *SelectStatement) SourceFromAlias(alias string) Source { return nil } func (c *SelectStatement) PossibleOutputColumns() []*SourceOutputColumn { result := make([]*SourceOutputColumn, 0) // populate the output columns from the columns in the select list for idx, col := range c.Columns { soc := &SourceOutputColumn{ TableName: "", ColumnName: col.Name(), ColumnIndex: idx, Datatype: col.Expr.DataType(), } result = append(result, soc) } return result } func (c *SelectStatement) OutputColumnNamed(name string) (*SourceOutputColumn, error) { ocs := c.PossibleOutputColumns() for _, oc := range ocs { if strings.EqualFold(oc.ColumnName, name) { return oc, nil } } return nil, nil } func (c *SelectStatement) OutputColumnQualifierNamed(qualifier string, name string) (*SourceOutputColumn, error) { return nil, nil } type ResultColumn struct { Star Pos // position of * Expr Expr // column expression (may be "tbl.*") As Pos // position of AS keyword Alias *Ident // alias name } // Name returns the column name. Uses the alias, if specified. // Otherwise returns a generated name. func (c *ResultColumn) Name() string { if c.Alias != nil { return IdentName(c.Alias) } switch expr := c.Expr.(type) { case *Ident: return IdentName(expr) case *QualifiedRef: return IdentName(expr.Column) default: return "" } } func (expr *ResultColumn) IsLiteral() bool { return false } // Clone returns a deep copy of c. func (c *ResultColumn) Clone() *ResultColumn { if c == nil { return nil } other := *c other.Expr = CloneExpr(c.Expr) other.Alias = c.Alias.Clone() return &other } func cloneResultColumns(a []*ResultColumn) []*ResultColumn { if a == nil { return nil } other := make([]*ResultColumn, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the column. func (c *ResultColumn) String() string { if c.Star.IsValid() { return "*" } else if c.Alias != nil { if c.As.IsValid() { return fmt.Sprintf("%s AS %s", c.Expr.String(), c.Alias.String()) } else { return fmt.Sprintf("%s %s", c.Expr.String(), c.Alias.String()) } } return c.Expr.String() } type QualifiedTableName struct { Name *Ident // table name As Pos // position of AS keyword Alias *Ident // optional table alias Indexed Pos // position of INDEXED keyword IndexedBy Pos // position of BY keyword after INDEXED Not Pos // position of NOT keyword before INDEXED NotIndexed Pos // position of NOT keyword before INDEXED Index *Ident // name of index OutputColumns []*SourceOutputColumn // output columns - populated during analysis } // TableName returns the name used to identify n. // Returns the alias, if one is specified. Otherwise returns the name. func (n *QualifiedTableName) TableName() string { if s := IdentName(n.Alias); s != "" { return s } return IdentName(n.Name) } func (n *QualifiedTableName) MatchesTablenameOrAlias(match string) bool { return strings.EqualFold(IdentName(n.Alias), match) || strings.EqualFold(IdentName(n.Name), match) } // Clone returns a deep copy of n. func (n *QualifiedTableName) Clone() *QualifiedTableName { if n == nil { return nil } other := *n other.Name = n.Name.Clone() other.Alias = n.Alias.Clone() other.Index = n.Index.Clone() return &other } // String returns the string representation of the table name. func (n *QualifiedTableName) String() string { var buf bytes.Buffer buf.WriteString(n.Name.String()) if n.Alias != nil { if n.As.IsValid() { buf.WriteString(" AS") } fmt.Fprintf(&buf, " %s", n.Alias.String()) } if n.Index != nil { fmt.Fprintf(&buf, " INDEXED BY %s", n.Index.String()) } else if n.NotIndexed.IsValid() { buf.WriteString(" NOT INDEXED") } return buf.String() } func (c *QualifiedTableName) SourceFromAlias(alias string) Source { if strings.EqualFold(IdentName(c.Alias), alias) { return c } if strings.EqualFold(IdentName(c.Name), alias) { return c } return nil } func (c *QualifiedTableName) PossibleOutputColumns() []*SourceOutputColumn { return c.OutputColumns } func (c *QualifiedTableName) OutputColumnNamed(name string) (*SourceOutputColumn, error) { for _, oc := range c.OutputColumns { if strings.EqualFold(oc.ColumnName, name) { return oc, nil } } return nil, nil } func (c *QualifiedTableName) OutputColumnQualifierNamed(qualifier string, name string) (*SourceOutputColumn, error) { if strings.EqualFold(IdentName(c.Alias), qualifier) || strings.EqualFold(IdentName(c.Name), qualifier) { return c.OutputColumnNamed(name) } return nil, nil } type TableValuedFunction struct { Name *Ident // table name As Pos // position of AS keyword Alias *Ident // optional table alias Call *Call // call OutputColumns []*SourceOutputColumn // output columns - populated during analysis } // TableName returns the name used to identify n. // Returns the alias, if one is specified. Otherwise returns the name. func (n *TableValuedFunction) TableName() string { if s := IdentName(n.Alias); s != "" { return s } return IdentName(n.Name) } func (n *TableValuedFunction) MatchesTablenameOrAlias(match string) bool { return strings.EqualFold(IdentName(n.Alias), match) || strings.EqualFold(IdentName(n.Name), match) } // Clone returns a deep copy of n. func (n *TableValuedFunction) Clone() *TableValuedFunction { if n == nil { return nil } other := *n other.Name = n.Name.Clone() other.Alias = n.Alias.Clone() return &other } // String returns the string representation of the table name. func (n *TableValuedFunction) String() string { var buf bytes.Buffer buf.WriteString(n.Name.String()) if n.Alias != nil { if n.As.IsValid() { buf.WriteString(" AS") } fmt.Fprintf(&buf, " %s", n.Alias.String()) } return buf.String() } func (c *TableValuedFunction) SourceFromAlias(alias string) Source { if strings.EqualFold(IdentName(c.Alias), alias) { return c } if strings.EqualFold(IdentName(c.Name), alias) { return c } return nil } func (c *TableValuedFunction) PossibleOutputColumns() []*SourceOutputColumn { return c.OutputColumns } func (c *TableValuedFunction) OutputColumnNamed(name string) (*SourceOutputColumn, error) { for _, oc := range c.OutputColumns { if strings.EqualFold(oc.ColumnName, name) { return oc, nil } } return nil, nil } func (c *TableValuedFunction) OutputColumnQualifierNamed(qualifier string, name string) (*SourceOutputColumn, error) { if strings.EqualFold(IdentName(c.Alias), qualifier) || strings.EqualFold(IdentName(c.Name), qualifier) { return c.OutputColumnNamed(name) } return nil, nil } type ParenSource struct { Lparen Pos // position of left paren X Source // nested source Rparen Pos // position of right paren As Pos // position of AS keyword (select source only) Alias *Ident // optional table alias (select source only) } // Clone returns a deep copy of s. func (s *ParenSource) Clone() *ParenSource { if s == nil { return nil } other := *s other.X = CloneSource(s.X) other.Alias = s.Alias.Clone() return &other } // String returns the string representation of the source. func (s *ParenSource) String() string { if s.Alias != nil { return fmt.Sprintf("(%s) AS %s", s.X.String(), s.Alias.String()) } return fmt.Sprintf("(%s)", s.X.String()) } func (c *ParenSource) SourceFromAlias(alias string) Source { if strings.EqualFold(IdentName(c.Alias), alias) { return c } return c.X.SourceFromAlias(alias) } func (c *ParenSource) PossibleOutputColumns() []*SourceOutputColumn { aliasName := IdentName(c.Alias) poc := c.X.PossibleOutputColumns() for _, pc := range poc { pc.TableName = aliasName } return poc } func (c *ParenSource) OutputColumnNamed(name string) (*SourceOutputColumn, error) { return c.X.OutputColumnNamed(name) } func (c *ParenSource) OutputColumnQualifierNamed(qualifier string, name string) (*SourceOutputColumn, error) { if strings.EqualFold(IdentName(c.Alias), qualifier) { return c.OutputColumnNamed(name) } return nil, nil } type JoinClause struct { X Source // lhs source Operator *JoinOperator // join operator Y Source // rhs source Constraint JoinConstraint // join constraint } // Clone returns a deep copy of c. func (c *JoinClause) Clone() *JoinClause { if c == nil { return nil } other := *c other.X = CloneSource(c.X) other.Y = CloneSource(c.Y) other.Constraint = CloneJoinConstraint(c.Constraint) return &other } // String returns the string representation of the clause. func (c *JoinClause) String() string { var buf bytes.Buffer fmt.Fprintf(&buf, "%s%s%s", c.X.String(), c.Operator.String(), c.Y.String()) if c.Constraint != nil { fmt.Fprintf(&buf, " %s", c.Constraint.String()) } return buf.String() } func (c *JoinClause) PossibleOutputColumns() []*SourceOutputColumn { poc := make([]*SourceOutputColumn, 0) poc = append(poc, c.X.PossibleOutputColumns()...) poc = append(poc, c.Y.PossibleOutputColumns()...) return poc } func (c *JoinClause) OutputColumnNamed(name string) (*SourceOutputColumn, error) { if col, err := c.X.OutputColumnNamed(name); err != nil { return nil, err } else if col != nil { return col, nil } if col, err := c.Y.OutputColumnNamed(name); err != nil { return nil, err } else if col != nil { return col, nil } return nil, nil } func (c *JoinClause) OutputColumnQualifierNamed(qualifier string, name string) (*SourceOutputColumn, error) { if col, err := c.X.OutputColumnQualifierNamed(qualifier, name); err != nil { return nil, err } else if col != nil { return col, nil } if col, err := c.Y.OutputColumnQualifierNamed(qualifier, name); err != nil { return nil, err } else if col != nil { return col, nil } return nil, nil } func (c *JoinClause) SourceFromAlias(alias string) Source { if src := c.X.SourceFromAlias(alias); src != nil { return src } if src := c.Y.SourceFromAlias(alias); src != nil { return src } return nil } type JoinOperator struct { Comma Pos // position of comma Left Pos // position of LEFT keyword Right Pos // position of RIGHT keyword Full Pos // position of FULL keyword Outer Pos // position of OUTER keyword Inner Pos // position of INNER keyword // Cross Pos // position of CROSS keyword // TODO(pok) - add cross back when we do it Join Pos // position of JOIN keyword } // Clone returns a deep copy of op. func (op *JoinOperator) Clone() *JoinOperator { if op == nil { return nil } other := *op return &other } // String returns the string representation of the operator. func (op *JoinOperator) String() string { if op.Comma.IsValid() { return ", " } var buf bytes.Buffer if op.Left.IsValid() { buf.WriteString(" LEFT") if op.Outer.IsValid() { buf.WriteString(" OUTER") } } else if op.Inner.IsValid() { buf.WriteString(" INNER") // } else if op.Cross.IsValid() { // buf.WriteString(" CROSS") } buf.WriteString(" JOIN ") return buf.String() } type OnConstraint struct { On Pos // position of ON keyword X Expr // constraint expression } // Clone returns a deep copy of c. func (c *OnConstraint) Clone() *OnConstraint { if c == nil { return nil } other := *c other.X = CloneExpr(c.X) return &other } // String returns the string representation of the constraint. func (c *OnConstraint) String() string { return "ON " + c.X.String() } type UsingConstraint struct { Using Pos // position of USING keyword Lparen Pos // position of left paren Columns []*Ident // column list Rparen Pos // position of right paren } // Clone returns a deep copy of c. func (c *UsingConstraint) Clone() *UsingConstraint { if c == nil { return nil } other := *c other.Columns = cloneIdents(c.Columns) return &other } // String returns the string representation of the constraint. func (c *UsingConstraint) String() string { var buf bytes.Buffer buf.WriteString("USING (") for i, col := range c.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") return buf.String() } type WithClause struct { With Pos // position of WITH keyword Recursive Pos // position of RECURSIVE keyword CTEs []*CTE // common table expressions } // Clone returns a deep copy of c. func (c *WithClause) Clone() *WithClause { if c == nil { return nil } other := *c other.CTEs = cloneCTEs(c.CTEs) return &other } // String returns the string representation of the clause. func (c *WithClause) String() string { var buf bytes.Buffer buf.WriteString("WITH ") if c.Recursive.IsValid() { buf.WriteString("RECURSIVE ") } for i, cte := range c.CTEs { if i != 0 { buf.WriteString(", ") } buf.WriteString(cte.String()) } return buf.String() } // CTE represents an AST node for a common table expression. type CTE struct { TableName *Ident // table name ColumnsLparen Pos // position of column list left paren Columns []*Ident // optional column list ColumnsRparen Pos // position of column list right paren As Pos // position of AS keyword SelectLparen Pos // position of select left paren Select *SelectStatement // select statement SelectRparen Pos // position of select right paren } // Clone returns a deep copy of cte. func (cte *CTE) Clone() *CTE { if cte == nil { return nil } other := *cte other.TableName = cte.TableName.Clone() other.Columns = cloneIdents(cte.Columns) other.Select = cte.Select.Clone() return &other } func cloneCTEs(a []*CTE) []*CTE { if a == nil { return nil } other := make([]*CTE, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the CTE. func (cte *CTE) String() string { var buf bytes.Buffer fmt.Fprintf(&buf, "%s", cte.TableName.String()) if len(cte.Columns) != 0 { buf.WriteString(" (") for i, col := range cte.Columns { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString(")") } if cte.As.IsValid() { buf.WriteString(" AS") } fmt.Fprintf(&buf, " (%s)", cte.Select.String()) return buf.String() } type ParenExpr struct { Lparen Pos // position of left paren X Expr // parenthesized expression Rparen Pos // position of right paren } func (expr *ParenExpr) IsLiteral() bool { return expr.X.IsLiteral() } func (expr *ParenExpr) DataType() ExprDataType { return expr.X.DataType() } func (expr *ParenExpr) Pos() Pos { return expr.Lparen } // Clone returns a deep copy of expr. func (expr *ParenExpr) Clone() *ParenExpr { if expr == nil { return nil } other := *expr other.X = CloneExpr(expr.X) return &other } // String returns the string representation of the expression. func (expr *ParenExpr) String() string { return fmt.Sprintf("(%s)", expr.X.String()) } type SetLiteralExpr struct { Lbracket Pos // position of left bracket Members []Expr // bracketed expression Rbracket Pos // position of right bracket ResultDataType ExprDataType } func (expr *SetLiteralExpr) IsLiteral() bool { return true } func (expr *SetLiteralExpr) DataType() ExprDataType { return expr.ResultDataType } func (expr *SetLiteralExpr) Pos() Pos { return expr.Lbracket } // Clone returns a deep copy of expr. func (expr *SetLiteralExpr) Clone() *SetLiteralExpr { if expr == nil { return nil } other := *expr other.Members = cloneExprs(expr.Members) return &other } // String returns the string representation of the expression. func (expr *SetLiteralExpr) String() string { var buf bytes.Buffer if len(expr.Members) != 0 { buf.WriteString("[") for i, col := range expr.Members { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString("]") } return buf.String() } type TupleLiteralExpr struct { Lbrace Pos // position of left brace Members []Expr // bracketed expression Rbrace Pos // position of right brace ResultDataType ExprDataType } func (expr *TupleLiteralExpr) IsLiteral() bool { return true } func (expr *TupleLiteralExpr) DataType() ExprDataType { return expr.ResultDataType } func (expr *TupleLiteralExpr) Pos() Pos { return expr.Lbrace } // Clone returns a deep copy of expr. func (expr *TupleLiteralExpr) Clone() *TupleLiteralExpr { if expr == nil { return nil } other := *expr other.Members = cloneExprs(expr.Members) return &other } // String returns the string representation of the expression. func (expr *TupleLiteralExpr) String() string { var buf bytes.Buffer if len(expr.Members) != 0 { buf.WriteString("{") for i, col := range expr.Members { if i != 0 { buf.WriteString(", ") } buf.WriteString(col.String()) } buf.WriteString("}") } return buf.String() } type Window struct { Name *Ident // name of window As Pos // position of AS keyword Definition *WindowDefinition // window definition } // Clone returns a deep copy of w. func (w *Window) Clone() *Window { if w == nil { return nil } other := *w other.Name = w.Name.Clone() other.Definition = w.Definition.Clone() return &other } func cloneWindows(a []*Window) []*Window { if a == nil { return nil } other := make([]*Window, len(a)) for i := range a { other[i] = a[i].Clone() } return other } // String returns the string representation of the window. func (w *Window) String() string { return fmt.Sprintf("%s AS %s", w.Name.String(), w.Definition.String()) } type WindowDefinition struct { Lparen Pos // position of left paren Base *Ident // base window name Partition Pos // position of PARTITION keyword PartitionBy Pos // position of BY keyword (after PARTITION) Partitions []Expr // partition expressions Order Pos // position of ORDER keyword OrderBy Pos // position of BY keyword (after ORDER) OrderingTerms []*OrderingTerm // ordering terms Frame *FrameSpec // frame Rparen Pos // position of right paren } // Clone returns a deep copy of d. func (d *WindowDefinition) Clone() *WindowDefinition { if d == nil { return nil } other := *d other.Base = d.Base.Clone() other.Partitions = cloneExprs(d.Partitions) other.OrderingTerms = cloneOrderingTerms(d.OrderingTerms) other.Frame = d.Frame.Clone() return &other } // String returns the string representation of the window definition. func (d *WindowDefinition) String() string { var buf bytes.Buffer buf.WriteString("(") if d.Base != nil { buf.WriteString(d.Base.String()) } if len(d.Partitions) != 0 { if buf.Len() > 1 { buf.WriteString(" ") } buf.WriteString("PARTITION BY ") for i, p := range d.Partitions { if i != 0 { buf.WriteString(", ") } buf.WriteString(p.String()) } } if len(d.OrderingTerms) != 0 { if buf.Len() > 1 { buf.WriteString(" ") } buf.WriteString("ORDER BY ") for i, term := range d.OrderingTerms { if i != 0 { buf.WriteString(", ") } buf.WriteString(term.String()) } } if d.Frame != nil { if buf.Len() > 1 { buf.WriteString(" ") } buf.WriteString(d.Frame.String()) } buf.WriteString(")") return buf.String() }