snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
221
server/pkg/ql/parser_nodes.go
Normal file
221
server/pkg/ql/parser_nodes.go
Normal file
@@ -0,0 +1,221 @@
|
||||
package ql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SelectStatement represents a SQL SELECT statement.
|
||||
type (
|
||||
parserNode interface {
|
||||
fmt.Stringer
|
||||
|
||||
Validate() error
|
||||
ToAST() *ASTNode
|
||||
}
|
||||
|
||||
parserNodeSet []parserNode // Stream of comma delimited nodes
|
||||
parserNodes []parserNode // Stream of space delimited nodes
|
||||
|
||||
lNull struct{}
|
||||
lBoolean struct{ value bool }
|
||||
|
||||
lString struct {
|
||||
value string
|
||||
args []interface{}
|
||||
}
|
||||
|
||||
lNumber struct {
|
||||
value string
|
||||
}
|
||||
|
||||
operator struct {
|
||||
kind string
|
||||
}
|
||||
|
||||
Ident struct {
|
||||
Value string
|
||||
args []interface{}
|
||||
}
|
||||
|
||||
keyword struct {
|
||||
keyword string
|
||||
}
|
||||
|
||||
interval struct {
|
||||
value string
|
||||
unit string
|
||||
}
|
||||
|
||||
function struct {
|
||||
name string
|
||||
arguments parserNodeSet
|
||||
}
|
||||
|
||||
opDef struct {
|
||||
name string
|
||||
weight int
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
ops = map[string]opDef{
|
||||
// generic comparison
|
||||
`=`: {name: `eq`, weight: 40},
|
||||
`==`: {name: `eq`, weight: 40},
|
||||
`===`: {name: `eq`, weight: 40},
|
||||
`!=`: {name: `ne`, weight: 40},
|
||||
`!==`: {name: `ne`, weight: 40},
|
||||
`<>`: {name: `ne`, weight: 40},
|
||||
`<`: {name: `lt`, weight: 30},
|
||||
`<=`: {name: `le`, weight: 30},
|
||||
`>`: {name: `gt`, weight: 30},
|
||||
`>=`: {name: `ge`, weight: 30},
|
||||
`IS`: {name: `is`, weight: 40},
|
||||
`IS NOT`: {name: `nis`, weight: 40},
|
||||
`IN`: {name: `in`, weight: 40},
|
||||
`NOT IN`: {name: `nin`, weight: 40},
|
||||
|
||||
// conjunction
|
||||
`AND`: {name: `and`, weight: 50},
|
||||
`&&`: {name: `and`, weight: 50},
|
||||
`OR`: {name: `or`, weight: 60},
|
||||
`||`: {name: `or`, weight: 60},
|
||||
`XOR`: {name: `xor`, weight: 60},
|
||||
|
||||
// math
|
||||
`+`: {name: `add`, weight: 20},
|
||||
`-`: {name: `sub`, weight: 20},
|
||||
`*`: {name: `mult`, weight: 10},
|
||||
`/`: {name: `div`, weight: 10},
|
||||
|
||||
// modifiers
|
||||
`!`: {name: `not`, weight: 0},
|
||||
|
||||
// str comp.
|
||||
`LIKE`: {name: `like`, weight: 40},
|
||||
`NOT LIKE`: {name: `nlike`, weight: 40},
|
||||
|
||||
// range comp.
|
||||
`BETWEEN`: {name: `between`, weight: 40},
|
||||
`NOT BETWEEN`: {name: `nbetween`, weight: 40},
|
||||
}
|
||||
)
|
||||
|
||||
func isUnary(s string) bool {
|
||||
return s == "!" || s == "not"
|
||||
}
|
||||
|
||||
func isOperator(s string) bool {
|
||||
return s == "and" || s == "or" || s == "xor"
|
||||
}
|
||||
|
||||
func getOp(op string) *opDef {
|
||||
o, ok := ops[strings.ToUpper(op)]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return &o
|
||||
}
|
||||
|
||||
func (n lNull) Validate() (err error) { return }
|
||||
func (n lNull) String() string { return "NULL" }
|
||||
|
||||
func (n lBoolean) Validate() (err error) { return }
|
||||
func (n lBoolean) String() string {
|
||||
if n.value {
|
||||
return "TRUE"
|
||||
} else {
|
||||
return "FALSE"
|
||||
}
|
||||
}
|
||||
|
||||
func (n lString) Validate() (err error) { return }
|
||||
func (n lString) String() string { return fmt.Sprintf("%q", n.value) }
|
||||
|
||||
func (n lNumber) Validate() (err error) { return }
|
||||
func (n lNumber) String() string { return n.value }
|
||||
|
||||
func (n operator) Validate() (err error) {
|
||||
if getOp(n.kind) == nil {
|
||||
return fmt.Errorf("unknown operator '%s'", n.kind)
|
||||
}
|
||||
return
|
||||
}
|
||||
func (n operator) String() string { return n.kind }
|
||||
|
||||
func (n keyword) Validate() (err error) { return }
|
||||
func (n keyword) String() string { return n.keyword }
|
||||
|
||||
func (n interval) Validate() (err error) { return }
|
||||
func (n interval) String() string { return fmt.Sprintf("INTERVAL %s %s", n.value, n.unit) }
|
||||
|
||||
func (n function) Validate() (err error) { return }
|
||||
func (n function) String() string { return fmt.Sprintf("%s(%s)", n.name, n.arguments) }
|
||||
|
||||
func (n Ident) Validate() (err error) { return }
|
||||
func (n Ident) String() string { return n.Value }
|
||||
|
||||
func (nn parserNodes) Validate() (err error) {
|
||||
if err = validate(nn); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
l := len(nn)
|
||||
if l == 0 {
|
||||
return fmt.Errorf("empty set")
|
||||
}
|
||||
|
||||
if op, ok := nn[0].(operator); ok && !isUnary(op.kind) {
|
||||
return fmt.Errorf("malformed expression, unexpected operator '%s' at first node", op)
|
||||
}
|
||||
|
||||
if l > 1 {
|
||||
if op, ok := nn[l-1].(operator); ok {
|
||||
return fmt.Errorf("malformed expression, unexpected operator '%s' at last node", op)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (nn parserNodes) String() (out string) {
|
||||
for i, n := range nn {
|
||||
if i > 0 {
|
||||
out = out + " "
|
||||
}
|
||||
|
||||
out = out + n.String()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (nn parserNodeSet) Validate() (err error) {
|
||||
return validate(nn)
|
||||
}
|
||||
|
||||
func (nn parserNodeSet) String() (out string) {
|
||||
for i, n := range nn {
|
||||
if i > 0 {
|
||||
out = out + ", "
|
||||
}
|
||||
out = out + n.String()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func validate(nn []parserNode) (err error) {
|
||||
if len(nn) == 0 {
|
||||
return fmt.Errorf("empty node set")
|
||||
}
|
||||
|
||||
for _, n := range nn {
|
||||
if err = n.Validate(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user