featurebase/sql3/parser/ast.go
Seebs c66d392c87 uncomment old LIMIT tests, make them pass
We forward-ported a handful of tests from the previous parser
which relied on LIMIT clauses, but then we didn't support that.
Now that we do, we uncomment most of these tests, and actually
give them the correct data structures to compare with.

We leave two tests commented out. One was using `limit 10, 5` to
express a limit plus offset, and the other is using `not fld = 1`
as a WHERE clause, but we don't support unary-not to negate
other expressions.

In the process, we discover that converting a SELECT with a
LIMIT clause back to a string has a missing space, and fix that.
2023-04-06 11:49:11 -05:00

4857 lines
119 KiB
Go

// 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 (*CopyStatement) node() {}
func (*CommitStatement) node() {}
func (*CreateDatabaseStatement) node() {}
func (*CreateIndexStatement) node() {}
func (*CreateTableStatement) node() {}
func (*CreateFunctionStatement) node() {}
func (*CreateModelStatement) 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 (*DropModelStatement) 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 (*PredictStatement) node() {}
func (*SetLiteralExpr) node() {}
func (*ParenSource) node() {}
func (*PrimaryKeyConstraint) node() {}
func (*QualifiedRef) node() {}
func (*QualifiedTableName) node() {}
func (*Range) node() {}
func (*ReturnStatement) 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 (*CopyStatement) 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 (*CreateModelStatement) stmt() {}
func (*CreateViewStatement) stmt() {}
func (*DeleteStatement) stmt() {}
func (*DropDatabaseStatement) stmt() {}
func (*DropIndexStatement) stmt() {}
func (*DropTableStatement) stmt() {}
func (*DropFunctionStatement) stmt() {}
func (*DropViewStatement) stmt() {}
func (*DropModelStatement) stmt() {}
func (*PredictStatement) stmt() {}
func (*ExplainStatement) stmt() {}
func (*InsertStatement) stmt() {}
func (*ReleaseStatement) stmt() {}
func (*ReturnStatement) 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 *DropModelStatement:
return stmt.Clone()
case *ExplainStatement:
return stmt.Clone()
case *InsertStatement:
return stmt.Clone()
case *BulkInsertStatement:
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()
case *SysVariable:
return expr.Clone()
case *DateLit:
return expr.Clone()
case *SetLiteralExpr:
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
}
// 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())
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 system 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 svar.String()
}
func (svar *SysVariable) String() string {
return svar.Token.String()
}
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 DropModelStatement struct {
Drop Pos // position of DROP keyword
Model Pos // position of MODEL 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 *DropModelStatement) Clone() *DropModelStatement {
if s == nil {
return nil
}
other := *s
other.Name = s.Name.Clone()
return &other
}
// String returns the string representation of the statement.
func (s *DropModelStatement) String() string {
var buf bytes.Buffer
buf.WriteString("DROP MODEL")
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 FunctionOptionDefinition struct {
Name *Ident // option name
OptionExpr Expr // option expression
}
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
ReturnType *Type // return def
With Pos // position of WITH keyword
Options []*FunctionOptionDefinition // options
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.ReturnType.String())
if s.With.IsValid() {
buf.WriteString(" WITH ")
if len(s.Options) > 0 {
buf.WriteString(" (")
for idx, p := range s.Options {
if idx > 0 {
buf.WriteString(", ")
}
fmt.Fprintf(&buf, "%s %s", p.Name.Name, p.OptionExpr.String())
}
buf.WriteString(")")
}
}
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 ReturnStatement struct {
Return Pos // position of RETURN keyword
ReturnExpr Expr // what we are returning
}
// Clone returns a deep copy of s.
func (s *ReturnStatement) Clone() *ReturnStatement {
if s == nil {
return nil
}
other := *s
other.ReturnExpr = CloneExpr(s.ReturnExpr)
return &other
}
func (s *ReturnStatement) String() string {
var buf bytes.Buffer
buf.WriteString("RETURN")
fmt.Fprintf(&buf, " %s", s.ReturnExpr.String())
return buf.String()
}
type ModelOptionDefinition struct {
Name *Ident // option name
OptionExpr Expr // option expression
}
type CreateModelStatement struct {
Create Pos // position of CREATE keyword
Model Pos // position of MODEL 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 // model name
With Pos // position of WITH keyword
Options []*ModelOptionDefinition // options
As Pos // position of AS keyword
ModelQuery *SelectStatement // model query
}
// Clone returns a deep copy of s.
func (s *CreateModelStatement) Clone() *CreateModelStatement {
if s == nil {
return nil
}
other := *s
other.Name = s.Name.Clone()
other.ModelQuery = s.ModelQuery.Clone()
return &other
}
// String returns the string representation of the statement.
func (s *CreateModelStatement) String() string {
var buf bytes.Buffer
buf.WriteString("CREATE MODEL")
if s.IfNotExists.IsValid() {
buf.WriteString(" IF NOT EXISTS")
}
fmt.Fprintf(&buf, " %s", s.Name.String())
if len(s.Options) > 0 {
buf.WriteString(" (")
for idx, p := range s.Options {
if idx > 0 {
buf.WriteString(", ")
}
fmt.Fprintf(&buf, "%s %s", p.Name.Name, p.OptionExpr.String())
}
buf.WriteString(")")
}
buf.WriteString(" AS ")
buf.WriteString(s.ModelQuery.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.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())
}
if s.AllowMissingValues != nil {
buf.WriteString(" ALLOW_MISSING_VALUES ")
}
return buf.String()
}
func (s *BulkInsertStatement) Clone() *BulkInsertStatement {
if s == nil {
return nil
}
other := *s
other.Table = s.Table.Clone()
other.Columns = cloneIdents(s.Columns)
other.TransformList = cloneExprs(s.TransformList)
other.DataSource = CloneExpr(s.DataSource)
other.BatchSize = CloneExpr(s.BatchSize)
other.RowsLimit = CloneExpr(s.RowsLimit)
other.Format = CloneExpr(s.Format)
other.Input = CloneExpr(s.Input)
other.HeaderRow = CloneExpr(s.HeaderRow)
other.AllowMissingValues = CloneExpr(s.AllowMissingValues)
other.MapList = cloneBulkInsertMap(s.MapList)
return &other
}
func cloneBulkInsertMap(s []*BulkInsertMapDefinition) []*BulkInsertMapDefinition {
other := make([]*BulkInsertMapDefinition, len(s))
for i := range s {
other[i] = s[i].Clone()
}
return other
}
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 CopyStatement struct {
Copy Pos // position of COPY keyword
Source Source // source table
To Pos // position of TO keyword
TargetName *Ident // target table name
Where Pos // position of WHERE keyword
WhereExpr Expr // where clause expression
With Pos // position of WITH keyword
Url Expr // url for target server
ApiKey Expr // apikey for target server
}
func (c *CopyStatement) Clone() *CopyStatement {
if c == nil {
return nil
}
other := *c
other.Source = CloneSource(c.Source)
other.TargetName = c.TargetName.Clone()
other.WhereExpr = CloneExpr(c.WhereExpr)
other.Url = CloneExpr(c.Url)
other.ApiKey = CloneExpr(c.ApiKey)
return &other
}
func (c *CopyStatement) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "COPY %s to %s", c.Source.String(), c.TargetName.String())
if c.WhereExpr != nil {
fmt.Fprintf(&buf, " WHERE %s", c.WhereExpr.String())
}
if c.With.IsValid() {
fmt.Fprintf(&buf, " WITH")
if c.Url != nil {
fmt.Fprintf(&buf, " URL %s", c.Url.String())
}
if c.ApiKey != nil {
fmt.Fprintf(&buf, " APIKEY %s", c.Url.String())
}
}
return buf.String()
}
type PredictStatement struct {
Predict Pos // position of PREDICT keyword
Using Pos // position of USING keyword
ModelName *Ident // model name
InputQuery *SelectStatement // input query
}
func (c *PredictStatement) Clone() *PredictStatement {
if c == nil {
return nil
}
other := *c
other.ModelName = c.ModelName.Clone()
other.InputQuery = c.InputQuery.Clone()
return &other
}
func (c *PredictStatement) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "PREDICT USING %s", c.ModelName.String())
fmt.Fprintf(&buf, " %s", c.InputQuery.String())
return buf.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
Limit Pos // position of LIMIT keyword
LimitExpr Expr // LIMIT expr
}
// 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.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)
other.LimitExpr = CloneExpr(s.LimitExpr)
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(" ")
}
buf.WriteString("SELECT ")
if s.Distinct.IsValid() {
buf.WriteString("DISTINCT ")
}
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())
}
}
if s.Limit.IsValid() {
fmt.Fprintf(&buf, " LIMIT %s", s.LimitExpr.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)
other.Operator = c.Operator.Clone()
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()
}