151d73b954
MODIFY SQL statements have now been merged with UPDATE SQL statements, as the functionality was similar, but the code was duplicated. The DIFF SQL command has been added to the UPDATE query, so that records can be updated with DIFFs.
506 lines
14 KiB
Go
506 lines
14 KiB
Go
// Copyright © 2016 Abcum Ltd
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package sql
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// --------------------------------------------------
|
|
// Queries
|
|
// --------------------------------------------------
|
|
|
|
// Query represents a multi statement SQL query
|
|
type Query struct {
|
|
Statements Statements
|
|
}
|
|
|
|
// Statement represents a single SQL AST
|
|
type Statement interface{}
|
|
|
|
// Statements represents multiple SQL ASTs
|
|
type Statements []Statement
|
|
|
|
// --------------------------------------------------
|
|
// Trans
|
|
// --------------------------------------------------
|
|
|
|
// UseStatement represents a SQL BEGIN TRANSACTION statement.
|
|
type BeginStatement struct{}
|
|
|
|
// UseStatement represents a SQL CANCEL TRANSACTION statement.
|
|
type CancelStatement struct{}
|
|
|
|
// UseStatement represents a SQL COMMIT TRANSACTION statement.
|
|
type CommitStatement struct{}
|
|
|
|
// ReturnStatement represents a SQL RETURN statement.
|
|
type ReturnStatement struct {
|
|
What []Expr
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Use
|
|
// --------------------------------------------------
|
|
|
|
// UseStatement represents a SQL USE statement.
|
|
type UseStatement struct {
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Info
|
|
// --------------------------------------------------
|
|
|
|
// InfoStatement represents an SQL INFO statement.
|
|
type InfoStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// LET
|
|
// --------------------------------------------------
|
|
|
|
// LetStatement represents a SQL LET statement.
|
|
type LetStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"-" codec:"-"`
|
|
Expr Expr `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Normal
|
|
// --------------------------------------------------
|
|
|
|
// LiveStatement represents a SQL LIVE statement.
|
|
type LiveStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Expr []*Field `cork:"expr" codec:"expr"`
|
|
What []Expr `cork:"what" codec:"what"`
|
|
Cond []Expr `cork:"cond" codec:"cond"`
|
|
Echo Token `cork:"echo" codec:"echo"`
|
|
}
|
|
|
|
// SelectStatement represents a SQL SELECT statement.
|
|
type SelectStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Expr []*Field `cork:"expr" codec:"expr"`
|
|
What []Expr `cork:"what" codec:"what"`
|
|
Cond []Expr `cork:"cond" codec:"cond"`
|
|
Group []*Group `cork:"group" codec:"group"`
|
|
Order []*Order `cork:"order" codec:"order"`
|
|
Limit Expr `cork:"limit" codec:"limit"`
|
|
Start Expr `cork:"start" codec:"start"`
|
|
Version Expr `cork:"version" codec:"version"`
|
|
Echo Token `cork:"echo" codec:"echo"`
|
|
}
|
|
|
|
// CreateStatement represents a SQL CREATE statement.
|
|
type CreateStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What []Expr `cork:"what" codec:"what"`
|
|
Data []Expr `cork:"data" codec:"data"`
|
|
Echo Token `cork:"echo" codec:"echo"`
|
|
}
|
|
|
|
// UpdateStatement represents a SQL UPDATE statement.
|
|
type UpdateStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What []Expr `cork:"what" codec:"what"`
|
|
Data []Expr `cork:"data" codec:"data"`
|
|
Cond []Expr `cork:"cond" codec:"cond"`
|
|
Echo Token `cork:"echo" codec:"echo"`
|
|
}
|
|
|
|
// DeleteStatement represents a SQL DELETE statement.
|
|
type DeleteStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Hard bool `cork:"hard" codec:"hard"`
|
|
What []Expr `cork:"what" codec:"what"`
|
|
Cond []Expr `cork:"cond" codec:"cond"`
|
|
Echo Token `cork:"echo" codec:"echo"`
|
|
}
|
|
|
|
// RelateStatement represents a SQL RELATE statement.
|
|
type RelateStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Type []Expr `cork:"type" codec:"type"`
|
|
From []Expr `cork:"from" codec:"from"`
|
|
To []Expr `cork:"to" codec:"to"`
|
|
Data []Expr `cork:"data" codec:"data"`
|
|
Echo Token `cork:"echo" codec:"echo"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Scope
|
|
// --------------------------------------------------
|
|
|
|
// DefineScopeStatement represents an SQL DEFINE SCOPE statement.
|
|
type DefineScopeStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"name" codec:"name"`
|
|
Time time.Duration `cork:"time" codec:"time"`
|
|
Opts interface{} `cork:"opts" codec:"opts"`
|
|
}
|
|
|
|
// RemoveScopeStatement represents an SQL REMOVE SCOPE statement.
|
|
type RemoveScopeStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"name" codec:"name"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Table
|
|
// --------------------------------------------------
|
|
|
|
// DefineTableStatement represents an SQL DEFINE TABLE statement.
|
|
type DefineTableStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What []string `cork:"-" codec:"-"`
|
|
Full bool `cork:"full" codec:"full"`
|
|
}
|
|
|
|
// RemoveTableStatement represents an SQL REMOVE TABLE statement.
|
|
type RemoveTableStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What []string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Rules
|
|
// --------------------------------------------------
|
|
|
|
// DefineRulesStatement represents an SQL DEFINE RULES statement.
|
|
type DefineRulesStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What []string `cork:"-" codec:"-"`
|
|
When []string `cork:"-" codec:"-"`
|
|
Rule string `cork:"rule" codec:"rule"`
|
|
Cond []Expr `cork:"cond" codec:"cond"`
|
|
}
|
|
|
|
// RemoveRulesStatement represents an SQL REMOVE RULES statement.
|
|
type RemoveRulesStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
What []string `cork:"-" codec:"-"`
|
|
When []string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Field
|
|
// --------------------------------------------------
|
|
|
|
// DefineFieldStatement represents an SQL DEFINE FIELD statement.
|
|
type DefineFieldStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"name" codec:"name"`
|
|
What []string `cork:"-" codec:"-"`
|
|
Type string `cork:"type" codec:"type"`
|
|
Enum []interface{} `cork:"enum" codec:"enum"`
|
|
Code string `cork:"code" codec:"code"`
|
|
Min float64 `cork:"min" codec:"min"`
|
|
Max float64 `cork:"max" codec:"max"`
|
|
Match string `cork:"match" codec:"match"`
|
|
Default interface{} `cork:"default" codec:"default"`
|
|
Notnull bool `cork:"notnull" codec:"notnull"`
|
|
Readonly bool `cork:"readonly" codec:"readonly"`
|
|
Mandatory bool `cork:"mandatory" codec:"mandatory"`
|
|
Validate bool `cork:"validate" codec:"validate"`
|
|
}
|
|
|
|
// RemoveFieldStatement represents an SQL REMOVE FIELD statement.
|
|
type RemoveFieldStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"-" codec:"-"`
|
|
What []string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Index
|
|
// --------------------------------------------------
|
|
|
|
// DefineIndexStatement represents an SQL DEFINE INDEX statement.
|
|
type DefineIndexStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"name" codec:"name"`
|
|
What []string `cork:"-" codec:"-"`
|
|
Cols []string `cork:"cols" codec:"cols"`
|
|
Uniq bool `cork:"uniq" codec:"uniq"`
|
|
}
|
|
|
|
// RemoveIndexStatement represents an SQL REMOVE INDEX statement.
|
|
type RemoveIndexStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"-" codec:"-"`
|
|
What []string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// View
|
|
// --------------------------------------------------
|
|
|
|
// DefineViewStatement represents an SQL DEFINE VIEW statement.
|
|
type DefineViewStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"name" codec:"name"`
|
|
Expr []*Field `cork:"expr" codec:"expr"`
|
|
What []Expr `cork:"what" codec:"what"`
|
|
Cond []Expr `cork:"cond" codec:"cond"`
|
|
Group []*Group `cork:"group" codec:"group"`
|
|
}
|
|
|
|
// RemoveViewStatement represents an SQL REMOVE VIEW statement.
|
|
type RemoveViewStatement struct {
|
|
KV string `cork:"-" codec:"-"`
|
|
NS string `cork:"-" codec:"-"`
|
|
DB string `cork:"-" codec:"-"`
|
|
Name string `cork:"-" codec:"-"`
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Literals
|
|
// --------------------------------------------------
|
|
|
|
// Expr represents a sql expression
|
|
type Expr interface{}
|
|
|
|
// All represents a wildcard expression.
|
|
type All struct{}
|
|
|
|
// Asc represents the ASC expression.
|
|
type Asc struct{}
|
|
|
|
func (this Asc) MarshalText() (data []byte, err error) {
|
|
return []byte("~ASC~"), err
|
|
}
|
|
|
|
// Desc represents the DESC expression.
|
|
type Desc struct{}
|
|
|
|
func (this Desc) MarshalText() (data []byte, err error) {
|
|
return []byte("~DESC~"), err
|
|
}
|
|
|
|
// Null represents a null expression.
|
|
type Null struct{}
|
|
|
|
func (this Null) MarshalText() (data []byte, err error) {
|
|
return []byte("~NULL~"), err
|
|
}
|
|
|
|
// Void represents an expression which is not set.
|
|
type Void struct{}
|
|
|
|
func (this Void) MarshalText() (data []byte, err error) {
|
|
return []byte("~VOID~"), err
|
|
}
|
|
|
|
// Empty represents an expression which is null or "".
|
|
type Empty struct{}
|
|
|
|
func (this Empty) MarshalText() (data []byte, err error) {
|
|
return []byte("~EMPTY~"), err
|
|
}
|
|
|
|
// Field represents a SELECT AS clause.
|
|
type Field struct {
|
|
Expr Expr
|
|
Alias string
|
|
}
|
|
|
|
// Group represents a GROUP BY clause.
|
|
type Group struct {
|
|
Expr Expr
|
|
}
|
|
|
|
// Order represents a ORDER BY clause.
|
|
type Order struct {
|
|
Expr Expr
|
|
Dir Expr
|
|
}
|
|
|
|
// ClosedExpression represents a parenthesized expression.
|
|
type ClosedExpression struct {
|
|
Expr Expr
|
|
}
|
|
|
|
// BinaryExpression represents a binary expression tree,
|
|
type BinaryExpression struct {
|
|
LHS Expr
|
|
Op Token
|
|
RHS Expr
|
|
}
|
|
|
|
// DiffExpression represents a JSON DIFF PATCH
|
|
type DiffExpression struct {
|
|
JSON interface{}
|
|
}
|
|
|
|
// MergeExpression represents JSON to MERGE
|
|
type MergeExpression struct {
|
|
JSON interface{}
|
|
}
|
|
|
|
// ContentExpression represents JSON to REPLACE
|
|
type ContentExpression struct {
|
|
JSON interface{}
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Parts
|
|
// --------------------------------------------------
|
|
|
|
// Ident comment
|
|
type Ident struct {
|
|
ID string
|
|
}
|
|
|
|
func (this Ident) String() string {
|
|
return this.ID
|
|
}
|
|
|
|
func (this Ident) MarshalText() (data []byte, err error) {
|
|
return []byte("ID:" + this.ID), err
|
|
}
|
|
|
|
func NewIdent(ID string) *Ident {
|
|
return &Ident{ID}
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Parts
|
|
// --------------------------------------------------
|
|
|
|
// Param comment
|
|
type Param struct {
|
|
ID string
|
|
}
|
|
|
|
func (this Param) String() string {
|
|
return this.ID
|
|
}
|
|
|
|
func (this Param) MarshalText() (data []byte, err error) {
|
|
return []byte("ID:" + this.ID), err
|
|
}
|
|
|
|
func NewParam(ID string) *Param {
|
|
return &Param{ID}
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Parts
|
|
// --------------------------------------------------
|
|
|
|
// Table comment
|
|
type Table struct {
|
|
TB string
|
|
}
|
|
|
|
func (this Table) String() string {
|
|
return this.TB
|
|
}
|
|
|
|
func (this Table) MarshalText() (data []byte, err error) {
|
|
return []byte("TB:" + this.TB), err
|
|
}
|
|
|
|
func NewTable(TB string) *Table {
|
|
return &Table{TB}
|
|
}
|
|
|
|
// --------------------------------------------------
|
|
// Parts
|
|
// --------------------------------------------------
|
|
|
|
// Thing comment
|
|
type Thing struct {
|
|
TB interface{}
|
|
ID interface{}
|
|
}
|
|
|
|
func (this Thing) Bytes() []byte {
|
|
return []byte(this.String())
|
|
}
|
|
|
|
func (this Thing) String() string {
|
|
return fmt.Sprintf("@%s:%v", this.TB, this.ID)
|
|
}
|
|
|
|
func (this Thing) MarshalText() (data []byte, err error) {
|
|
return []byte(this.String()), err
|
|
}
|
|
|
|
func NewThing(TB interface{}, ID interface{}) *Thing {
|
|
if str, ok := ID.(string); ok {
|
|
if cnv, err := strconv.ParseFloat(str, 64); err == nil {
|
|
if cnv == float64(int64(cnv)) {
|
|
return &Thing{TB: TB, ID: int64(cnv)}
|
|
}
|
|
return &Thing{TB: TB, ID: cnv}
|
|
} else if cnv, err := time.Parse(RFCDate, str); err == nil {
|
|
return &Thing{TB: TB, ID: cnv.UTC()}
|
|
} else if cnv, err := time.Parse(RFCTime, str); err == nil {
|
|
return &Thing{TB: TB, ID: cnv.UTC()}
|
|
} else if cnv, err := time.Parse(RFCNorm, str); err == nil {
|
|
return &Thing{TB: TB, ID: cnv.UTC()}
|
|
} else if cnv, err := time.Parse(RFCText, str); err == nil {
|
|
return &Thing{TB: TB, ID: cnv.UTC()}
|
|
}
|
|
}
|
|
return &Thing{TB: TB, ID: ID}
|
|
}
|