%{ // Copyright (c) 2014 The ql Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Initial yacc source generated by ebnf2y[1] // at 2013-10-04 23:10:47.861401015 +0200 CEST // // $ ebnf2y -o ql.y -oe ql.ebnf -start StatementList -pkg ql -p _ // // [1]: http://modernc.org/ebnf2y package ql import ( "fmt" "modernc.org/mathutil" ) %} %union { line int col int item interface{} list []interface{} } %token /*yy:token "1.%d" */ floatLit "floating-point literal" /*yy:token "%c" */ identifier "identifier" /*yy:token "%di" */ imaginaryLit "imaginary literal" /*yy:token "%d" */ intLit "integer literal" /*yy:token "$%d" */ qlParam "QL parameter" /*yy:token "\"%c\"" */ stringLit "string literal" add "ADD" alter "ALTER" and "AND" andand "&&" andnot "&^" as "AS" asc "ASC" begin "BEGIN" between "BETWEEN" bigIntType "bigint" bigRatType "bigrat" blobType "blob" boolType "bool" by "BY" byteType "byte" column "COLUMN" commit "COMMIT" complex128Type "complex128" complex64Type "complex64" create "CREATE" defaultKwd "DEFAULT" deleteKwd "DELETE" desc "DESC" distinct "DISTINCT" drop "DROP" durationType "duration" eq "==" exists "EXISTS" explain "EXPLAIN" falseKwd "false" floatType "float" float32Type "float32" float64Type "float64" from "FROM" full "FULL" ge ">=" group "GROUP" ifKwd "IF" in "IN" index "INDEX" insert "INSERT" intType "int" int16Type "int16" int32Type "int32" int64Type "int64" int8Type "int8" into "INTO" is "IS" join "JOIN" le "<=" left "LEFT" like "LIKE" limit "LIMIT" lsh "<<" neq "!=" not "NOT" null "NULL" offset "OFFSET" on "ON" or "OR" order "ORDER" oror "||" outer "OUTER" right "RIGHT" rollback "ROLLBACK" rsh ">>" runeType "rune" selectKwd "SELECT" set "SET" stringType "string" tableKwd "TABLE" timeType "time" transaction "TRANSACTION" trueKwd "true" truncate "TRUNCATE" uintType "uint" uint16Type "uint16" uint32Type "uint32" uint64Type "uint64" uint8Type "uint8", unique "UNIQUE" update "UPDATE" values "VALUES" where "WHERE" parseExpression "parse expression prefix" %type AlterTableStmt "ALTER TABLE statement" Assignment "assignment" AssignmentList "assignment list" AssignmentList1 "assignment list optional trailing comma" BeginTransactionStmt "BEGIN TRANSACTION statement" Call "function call" Call1 "function call optional argument list" ColumnDef "table column definition" ColumnName "column name" ColumnNameList "column name list" ColumnNameList1 "column name list with optional trailing comma" CommaOpt "optional comma" CommitStmt "COMMIT statement" Constraint "column value constraint" ConstraintOpt "optional column value constraint" Conversion "conversion" CreateIndexStmt "CREATE INDEX statement" CreateIndexIfNotExists "CREATE INDEX statement optional IF NOT EXISTS cluse" CreateIndexStmtUnique "CREATE INDEX optional UNIQUE clause" CreateTableStmt "CREATE TABLE statement" CreateTableStmt1 "CREATE TABLE statement colum definition list" Default "DEFAULT clause" DefaultOpt "optional DEFAULT clause" DeleteFromStmt "DELETE FROM statement" DropIndexStmt "DROP INDEX statement" DropIndexIfExists "DROP INDEX statement optional IF EXISTS clause" DropTableStmt "DROP TABLE statement" EmptyStmt "empty statement" ExplainStmt "EXPLAIN statement" Expression "expression" ExpressionList "expression list" ExpressionList1 "expression list expression" Factor "expression factor" Factor1 "binary expression factor" Field "field expression" Field1 "field expression optional AS clause" FieldList "field expression list" GroupByClause "GROUP BY clause" Index "string index" InsertIntoStmt "INSERT INTO statement" InsertIntoStmt0 "INSERT INTO statement optional if not exists clause" InsertIntoStmt1 "INSERT INTO statement optional column list clause" InsertIntoStmt2 "INSERT INTO statement optional values list" JoinClause "SELECT statement JOIN clause" JoinClauseOpt "SELECT statement optional JOIN clause" JoinType "join type" Literal "literal value" logAnd "logical and operator" logOr "logical or operator" Operand "operand" OrderBy "ORDER BY clause" OrderBy1 "ORDER BY clause optional collation specification" OuterOpt "optional OUTER clause" QualifiedIdent "qualified identifier" PrimaryExpression "primary expression" PrimaryFactor "primary expression factor" PrimaryTerm "primary expression term" RecordSet "record set" RecordSet1 "record set name or parenthesized SELECTECT statement" RecordSet2 "record set optional AS clause" RollbackStmt "ROLLBACK statement" SelectStmt "SELECT statement" SelectStmtDistinct "SELECT statement optional DISTINCT clause" SelectStmtFieldList "SELECT statement field list" SelectStmtGroup "SELECT statement optional GROUP BY clause" SelectStmtLimit "SELECT statement optional LIMIT clause" SelectStmtOffset "SELECT statement optional OFFSET clause" SelectStmtOrder "SELECT statement optional ORDER BY clause" SelectStmtWhere "SELECT statement optional WHERE clause" Slice "string slice" Statement "statement" StatementList "statement list" TableName "table name" Term "expression term" TruncateTableStmt "TRANSACTION TABLE statement" Type "type" UnaryExpr "unary expression" UpdateStmt "UPDATE statement" UpdateStmt1 "UPDATE statement optional WHERE clause" WhereClause "WHERE clause" %type RecordSetList SelectStmtFrom "SELECT statement optional FROM clause" %start Start %% Start: StatementList | parseExpression Expression { yylex.(*lexer).expr = expr($2) } AlterTableStmt: "ALTER" "TABLE" TableName "ADD" ColumnDef { $$ = &alterTableAddStmt{tableName: $3.(string), c: $5.(*col)} } | "ALTER" "TABLE" TableName "DROP" "COLUMN" ColumnName { $$ = &alterTableDropColumnStmt{tableName: $3.(string), colName: $6.(string)} } Assignment: ColumnName '=' Expression { $$ = assignment{colName: $1.(string), expr: expr($3)} } AssignmentList: Assignment AssignmentList1 CommaOpt { $$ = append([]assignment{$1.(assignment)}, $2.([]assignment)...) } AssignmentList1: /* EMPTY */ { $$ = []assignment{} } | AssignmentList1 ',' Assignment { $$ = append($1.([]assignment), $3.(assignment)) } BeginTransactionStmt: "BEGIN" "TRANSACTION" { $$ = beginTransactionStmt{} } Call: '(' Call1 ')' { $$ = $2 } | '(' '*' ')' { $$ = '*' } Call1: /* EMPTY */ { $$ = []expression{} } | ExpressionList ColumnDef: ColumnName Type ConstraintOpt DefaultOpt { x := &col{name: $1.(string), typ: $2.(int), constraint: $3.(*constraint)} if $4 != nil { x.dflt = expr($4) } $$ = x } ColumnName: identifier ColumnNameList: ColumnName ColumnNameList1 CommaOpt { $$ = append([]string{$1.(string)}, $2.([]string)...) } ColumnNameList1: /* EMPTY */ { $$ = []string{} } | ColumnNameList1 ',' ColumnName { $$ = append($1.([]string), $3.(string)) } CommitStmt: "COMMIT" { $$ = commitStmt{} } Constraint: "NOT" "NULL" { $$ = &constraint{} } | Expression { $$ = &constraint{expr($1)} } ConstraintOpt: { $$ = (*constraint)(nil) } | Constraint Conversion: Type '(' Expression ')' { $$ = &conversion{typ: $1.(int), val: expr($3)} } CreateIndexStmt: "CREATE" CreateIndexStmtUnique "INDEX" CreateIndexIfNotExists identifier "ON" identifier '(' ExpressionList ')' { indexName, tableName, exprList := $5.(string), $7.(string), $9.([]expression) simpleIndex := len(exprList) == 1 var columnName string if simpleIndex { expr := exprList[0] switch x := expr.(type) { case *ident: columnName = x.s case *call: if x.f == "id" && len(x.arg) == 0 { columnName = "id()" break } simpleIndex = false default: simpleIndex = false } } if !simpleIndex { columnName = "" } $$ = &createIndexStmt{unique: $2.(bool), ifNotExists: $4.(bool), indexName: indexName, tableName: tableName, colName: columnName, exprList: exprList} if indexName == tableName || indexName == columnName { yylex.(*lexer).err("index name collision: %s", indexName) return 1 } if yylex.(*lexer).root { break } if isSystemName[indexName] || isSystemName[tableName] { yylex.(*lexer).err("name is used for system tables: %s", indexName) return 1 } } CreateIndexIfNotExists: { $$ = false } | "IF" "NOT" "EXISTS" { $$ = true } CreateIndexStmtUnique: { $$ = false } | "UNIQUE" { $$ = true } CreateTableStmt: "CREATE" "TABLE" TableName '(' ColumnDef CreateTableStmt1 CommaOpt ')' { nm := $3.(string) $$ = &createTableStmt{tableName: nm, cols: append([]*col{$5.(*col)}, $6.([]*col)...)} if yylex.(*lexer).root { break } if isSystemName[nm] { yylex.(*lexer).err("name is used for system tables: %s", nm) return 1 } } | "CREATE" "TABLE" "IF" "NOT" "EXISTS" TableName '(' ColumnDef CreateTableStmt1 CommaOpt ')' { nm := $6.(string) $$ = &createTableStmt{ifNotExists: true, tableName: nm, cols: append([]*col{$8.(*col)}, $9.([]*col)...)} if yylex.(*lexer).root { break } if isSystemName[nm] { yylex.(*lexer).err("name is used for system tables: %s", nm) return 1 } } CreateTableStmt1: /* EMPTY */ { $$ = []*col{} } | CreateTableStmt1 ',' ColumnDef { $$ = append($1.([]*col), $3.(*col)) } Default: "DEFAULT" Expression { $$ = $2 } DefaultOpt: { $$ = nil } | Default DeleteFromStmt: "DELETE" "FROM" TableName { $$ = &truncateTableStmt{$3.(string)} if yylex.(*lexer).root { break } if isSystemName[$3.(string)] { yylex.(*lexer).err("name is used for system tables: %s", $3.(string)) return 1 } } | "DELETE" "FROM" TableName WhereClause { $$ = &deleteStmt{tableName: $3.(string), where: $4.(*whereRset).expr} if yylex.(*lexer).root { break } if isSystemName[$3.(string)] { yylex.(*lexer).err("name is used for system tables: %s", $3.(string)) return 1 } } DropIndexStmt: "DROP" "INDEX" DropIndexIfExists identifier { $$ = &dropIndexStmt{ifExists: $3.(bool), indexName: $4.(string)} } DropIndexIfExists: { $$ = false } | "IF" "EXISTS" { $$ = true } DropTableStmt: "DROP" "TABLE" TableName { nm := $3.(string) $$ = &dropTableStmt{tableName: nm} if yylex.(*lexer).root { break } if isSystemName[nm] { yylex.(*lexer).err("name is used for system tables: %s", nm) return 1 } } | "DROP" "TABLE" "IF" "EXISTS" TableName { nm := $5.(string) $$ = &dropTableStmt{ifExists: true, tableName: nm} if yylex.(*lexer).root { break } if isSystemName[nm] { yylex.(*lexer).err("name is used for system tables: %s", nm) return 1 } } EmptyStmt: /* EMPTY */ { $$ = nil } ExplainStmt: "EXPLAIN" Statement { $$ = &explainStmt{$2.(stmt)} } Expression: Term | Expression logOr Term { var err error if $$, err = newBinaryOperation(oror, $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } logOr: "||" { } | "OR" { } Eq: "==" | '=' ExpressionList: Expression ExpressionList1 CommaOpt { $$ = append([]expression{expr($1)}, $2.([]expression)...) } ExpressionList1: /* EMPTY */ { $$ = []expression(nil) } | ExpressionList1 ',' Expression { $$ = append($1.([]expression), expr($3)) } Factor: Factor1 | Factor1 "IN" '(' ExpressionList ')' { $$ = &pIn{expr: $1.(expression), list: $4.([]expression)} } | Factor1 "NOT" "IN" '(' ExpressionList ')' { $$ = &pIn{expr: $1.(expression), not: true, list: $5.([]expression)} } | Factor1 "IN" '(' SelectStmt semiOpt ')' { $$ = &pIn{expr: $1.(expression), sel: $4.(*selectStmt)} } | Factor1 "NOT" "IN" '(' SelectStmt semiOpt ')' { $$ = &pIn{expr: $1.(expression), not: true, sel: $5.(*selectStmt)} } | Factor1 "BETWEEN" PrimaryFactor "AND" PrimaryFactor { var err error if $$, err = newBetween($1, $3, $5, false); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 "NOT" "BETWEEN" PrimaryFactor "AND" PrimaryFactor { var err error if $$, err = newBetween($1, $4, $6, true); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 "IS" "NULL" { $$ = &isNull{expr: $1.(expression)} } | Factor1 "IS" "NOT" "NULL" { $$ = &isNull{expr: $1.(expression), not: true} } Factor1: PrimaryFactor | Factor1 ">=" PrimaryFactor { var err error if $$, err = newBinaryOperation(ge, $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 '>' PrimaryFactor { var err error if $$, err = newBinaryOperation('>', $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 "<=" PrimaryFactor { var err error if $$, err = newBinaryOperation(le, $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 '<' PrimaryFactor { var err error if $$, err = newBinaryOperation('<', $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 "!=" PrimaryFactor { var err error if $$, err = newBinaryOperation(neq, $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 Eq PrimaryFactor { var err error if $$, err = newBinaryOperation(eq, $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | Factor1 "LIKE" PrimaryFactor { $$ = &pLike{expr: $1.(expression), pattern: $3.(expression)} } Field: Expression Field1 { expr, name := expr($1), $2.(string) if name == "" { s, ok := expr.(*ident) if ok { name = s.s } } $$ = &fld{expr: expr, name: name} } Field1: /* EMPTY */ { $$ = "" } | "AS" identifier { $$ = $2 } FieldList: Field { $$ = []*fld{$1.(*fld)} } | FieldList ',' Field { l, f := $1.([]*fld), $3.(*fld) if f.name != "" { if f := findFld(l, f.name); f != nil { yylex.(*lexer).err("duplicate field name %q", f.name) return 1 } } $$ = append($1.([]*fld), $3.(*fld)) } GroupByClause: "GROUP" "BY" ColumnNameList { $$ = &groupByRset{colNames: $3.([]string)} } Index: '[' Expression ']' { $$ = $2 } InsertIntoStmt: "INSERT" "INTO" TableName InsertIntoStmt0 InsertIntoStmt1 "VALUES" '(' ExpressionList ')' InsertIntoStmt2 CommaOpt { $$ = &insertIntoStmt{tableName: $3.(string), ifNotExists: $4.(bool), colNames: $5.([]string), lists: append([][]expression{$8.([]expression)}, $10.([][]expression)...)} if yylex.(*lexer).root { break } if isSystemName[$3.(string)] { yylex.(*lexer).err("name is used for system tables: %s", $3.(string)) return 1 } } | "INSERT" "INTO" TableName InsertIntoStmt0 InsertIntoStmt1 SelectStmt { $$ = &insertIntoStmt{tableName: $3.(string), ifNotExists: $4.(bool), colNames: $5.([]string), sel: $6.(*selectStmt)} } InsertIntoStmt0: { $$ = false } | "IF" "NOT" "EXISTS" { $$ = true } InsertIntoStmt1: /* EMPTY */ { $$ = []string{} } | '(' ColumnNameList ')' { $$ = $2 } InsertIntoStmt2: /* EMPTY */ { $$ = [][]expression{} } | InsertIntoStmt2 ',' '(' ExpressionList ')' { $$ = append($1.([][]expression), $4.([]expression)) } Literal: "false" | "NULL" | "true" | floatLit | imaginaryLit | intLit | stringLit Operand: Literal { $$ = value{$1} } | qlParam { n := $1.(int) $$ = parameter{n} l := yylex.(*lexer) l.params = mathutil.Max(l.params, n) if n == 0 { l.err("parameter number must be non zero") return 1 } } | QualifiedIdent { $$ = &ident{$1.(string)} } | '(' Expression ')' { $$ = &pexpr{expr: expr($2)} } OrderBy: "ORDER" "BY" ExpressionList OrderBy1 { $$ = &orderByRset{by: $3.([]expression), asc: $4.(bool)} } OrderBy1: /* EMPTY */ { $$ = true // ASC by default } | "ASC" { $$ = true } | "DESC" { $$ = false } PrimaryExpression: Operand | Conversion | PrimaryExpression Index { var err error if $$, err = newIndex($1.(expression), expr($2)); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryExpression Slice { var err error s := $2.([2]*expression) if $$, err = newSlice($1.(expression), s[0], s[1]); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryExpression Call { x := yylex.(*lexer) f, ok := $1.(*ident) if !ok { x.err("expected identifier or qualified identifier") return 1 } if r, ok := $2.(rune); ok { if f.isQualified() || f.s != "count" || r != '*' { x.err(fmt.Sprintf("invalid expression %s(%c)", f, r)) return 1 } $2 = []expression(nil) } var err error var agg bool if $$, agg, err = newCall(f.s, $2.([]expression)); err != nil { x.err("%v", err) return 1 } if n := len(x.agg); n > 0 { x.agg[n-1] = x.agg[n-1] || agg } } PrimaryFactor: PrimaryTerm | PrimaryFactor '^' PrimaryTerm { var err error if $$, err = newBinaryOperation('^', $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryFactor '|' PrimaryTerm { var err error if $$, err = newBinaryOperation('|', $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryFactor '-' PrimaryTerm { var err error if $$, err = newBinaryOperation('-', $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryFactor '+' PrimaryTerm { var err error $$, err = newBinaryOperation('+', $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } PrimaryTerm: UnaryExpr | PrimaryTerm "&^" UnaryExpr { var err error $$, err = newBinaryOperation(andnot, $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryTerm '&' UnaryExpr { var err error $$, err = newBinaryOperation('&', $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryTerm "<<" UnaryExpr { var err error $$, err = newBinaryOperation(lsh, $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryTerm ">>" UnaryExpr { var err error $$, err = newBinaryOperation(rsh, $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryTerm '%' UnaryExpr { var err error $$, err = newBinaryOperation('%', $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryTerm '/' UnaryExpr { var err error $$, err = newBinaryOperation('/', $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | PrimaryTerm '*' UnaryExpr { var err error $$, err = newBinaryOperation('*', $1, $3) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } QualifiedIdent: identifier | identifier '.' identifier { $$ = fmt.Sprintf("%s.%s", $1.(string), $3.(string)) } RecordSet: RecordSet1 RecordSet2 { $$ = []interface{}{$1, $2} } RecordSet1: identifier | '(' SelectStmt semiOpt ')' { $$ = $2 } semiOpt: /* EMPTY */ | ';' RecordSet2: /* EMPTY */ { $$ = "" } | "AS" identifier { $$ = $2 } RecordSetList: RecordSet { $$ = []interface{}{$1} } | RecordSetList ',' RecordSet { $$ = append($1, $3) } RollbackStmt: "ROLLBACK" { $$ = rollbackStmt{} } JoinType: "LEFT" { $$ = leftJoin } | "RIGHT" { $$ = rightJoin } | "FULL" { $$ = fullJoin } OuterOpt: { $$ = nil } | "OUTER" JoinClause: JoinType OuterOpt "JOIN" RecordSet "ON" Expression { $$ = []interface{}{$1, $4, $6} } JoinClauseOpt: { $$ = nil } | JoinClause SelectStmt: "SELECT" SelectStmtDistinct SelectStmtFieldList SelectStmtFrom JoinClauseOpt SelectStmtWhere SelectStmtGroup SelectStmtOrder SelectStmtLimit SelectStmtOffset { x := yylex.(*lexer) n := len(x.agg) join := &joinRset{sources: $4} if o := $5; o != nil { o := o.([]interface{}) join.typ = o[0].(int) join.sources = append(join.sources, o[1].([]interface{})) join.on = o[2].(expression) } $$ = &selectStmt{ distinct: $2.(bool), flds: $3.([]*fld), from: join, hasAggregates: x.agg[n-1], where: $6.(*whereRset), group: $7.(*groupByRset), order: $8.(*orderByRset), limit: $9.(*limitRset), offset: $10.(*offsetRset), } x.agg = x.agg[:n-1] } SelectStmtFrom: { $$ = nil } | "FROM" RecordSetList CommaOpt { $$ = $2 } SelectStmtLimit: { $$ = (*limitRset)(nil) } | "LIMIT" Expression { $$ = &limitRset{expr: expr($2)} } SelectStmtOffset: { $$ = (*offsetRset)(nil) } | "OFFSET" Expression { $$ = &offsetRset{expr: expr($2)} } SelectStmtDistinct: /* EMPTY */ { $$ = false } | "DISTINCT" { $$ = true } SelectStmtFieldList: '*' { $$ = []*fld{} } | FieldList { $$ = $1 } | FieldList ',' { $$ = $1 } SelectStmtWhere: /* EMPTY */ { $$ = (*whereRset)(nil) } | WhereClause SelectStmtGroup: /* EMPTY */ { $$ = (*groupByRset)(nil) } | GroupByClause SelectStmtOrder: /* EMPTY */ { $$ = (*orderByRset)(nil) } | OrderBy Slice: '[' ':' ']' { $$ = [2]*expression{nil, nil} } | '[' ':' Expression ']' { hi := expr($3) $$ = [2]*expression{nil, &hi} } | '[' Expression ':' ']' { lo := expr($2) $$ = [2]*expression{&lo, nil} } | '[' Expression ':' Expression ']' { lo := expr($2) hi := expr($4) $$ = [2]*expression{&lo, &hi} } Statement: EmptyStmt | AlterTableStmt | BeginTransactionStmt | CommitStmt | CreateIndexStmt | CreateTableStmt | DeleteFromStmt | DropIndexStmt | DropTableStmt | ExplainStmt | InsertIntoStmt | RollbackStmt | SelectStmt | TruncateTableStmt | UpdateStmt StatementList: Statement { if $1 != nil { yylex.(*lexer).list = []stmt{$1.(stmt)} } } | StatementList ';' Statement { if $3 != nil { yylex.(*lexer).list = append(yylex.(*lexer).list, $3.(stmt)) } } TableName: identifier Term: Factor | Term logAnd Factor { var err error if $$, err = newBinaryOperation(andand, $1, $3); err != nil { yylex.(*lexer).err("%v", err) return 1 } } logAnd: "&&" { } | "AND" { } TruncateTableStmt: "TRUNCATE" "TABLE" TableName { $$ = &truncateTableStmt{tableName: $3.(string)} } Type: "bigint" | "bigrat" | "blob" | "bool" | "byte" | "complex128" | "complex64" | "duration" | "float" | "float32" | "float64" | "int" | "int16" | "int32" | "int64" | "int8" | "rune" | "string" | "time" | "uint" | "uint16" | "uint32" | "uint64" | "uint8" UpdateStmt: "UPDATE" TableName SetOpt AssignmentList UpdateStmt1 { var expr expression if w := $5; w != nil { expr = w.(*whereRset).expr } $$ = &updateStmt{tableName: $2.(string), list: $4.([]assignment), where: expr} if yylex.(*lexer).root { break } if isSystemName[$2.(string)] { yylex.(*lexer).err("name is used for system tables: %s", $2.(string)) return 1 } } UpdateStmt1: /* EMPTY */ { $$ = nil } | WhereClause UnaryExpr: PrimaryExpression | '^' PrimaryExpression { var err error $$, err = newUnaryOperation('^', $2) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | '!' PrimaryExpression { var err error $$, err = newUnaryOperation('!', $2) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | '-' PrimaryExpression { var err error $$, err = newUnaryOperation('-', $2) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } | '+' PrimaryExpression { var err error $$, err = newUnaryOperation('+', $2) if err != nil { yylex.(*lexer).err("%v", err) return 1 } } WhereClause: "WHERE" Expression { $$ = &whereRset{expr: expr($2)} } | "WHERE" "EXISTS" '(' SelectStmt ')' { $$ = &whereRset{exists: true, sel:($4.(*selectStmt))} } | "WHERE" "NOT" "EXISTS" '(' SelectStmt ')' { $$ = &whereRset{sel:($5.(*selectStmt))} } SetOpt: { } | "SET" { } CommaOpt: { } | ',' { } %% func expr(v interface{}) expression { e := v.(expression) for { x, ok := e.(*pexpr) if !ok { return e } e = x.expr } }