mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-09-10 07:01:01 +00:00
Add variable support to PQL
This commit is contained in:
parent
8816583cd3
commit
3989b363ce
4 changed files with 1462 additions and 1295 deletions
55
pql/ast.go
55
pql/ast.go
|
|
@ -19,6 +19,22 @@ type Query struct {
|
|||
conditional []string
|
||||
}
|
||||
|
||||
// ExpandVars recursively replaces variables in the query with their values.
|
||||
func (q *Query) ExpandVars(vars map[string]interface{}) (*Query, error) {
|
||||
other := *q
|
||||
other.Calls = make([]*Call, 0, len(q.Calls))
|
||||
|
||||
for _, c := range q.Calls {
|
||||
newCalls, err := c.ExpandVars(vars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
other.Calls = append(other.Calls, newCalls...)
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (q *Query) startCall(name string) {
|
||||
// Coerce every name into a canonical form if we know of one.
|
||||
if canon, ok := canonicalCaps[strings.ToLower(name)]; ok {
|
||||
|
|
@ -896,6 +912,28 @@ func (c *Call) ArgString(key string) string {
|
|||
return s
|
||||
}
|
||||
|
||||
// ExpandVars recursively replaces variables in the call with their values.
|
||||
func (c *Call) ExpandVars(vars map[string]interface{}) ([]*Call, error) {
|
||||
other := *c
|
||||
other.Args = CopyArgs(c.Args)
|
||||
other.Children = make([]*Call, 0, len(c.Children))
|
||||
|
||||
// TODO: Replace field variables.
|
||||
|
||||
// Recursively expand variables in children.
|
||||
for _, child := range c.Children {
|
||||
newChildren, err := child.ExpandVars(vars)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
other.Children = append(other.Children, newChildren...)
|
||||
}
|
||||
|
||||
// TODO: Return multiple calls for list.
|
||||
|
||||
return []*Call{&other}, nil
|
||||
}
|
||||
|
||||
// Condition represents an operation & value.
|
||||
// When used in an argument map it represents a binary expression.
|
||||
type Condition struct {
|
||||
|
|
@ -1034,6 +1072,21 @@ func (cond *Condition) StringSliceValue() ([]string, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
// Variable represents a placeholder variable in a query.
|
||||
type Variable struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
// NewVariable returns a new instance of Variable.
|
||||
func NewVariable(name string) *Variable {
|
||||
return &Variable{Name: name}
|
||||
}
|
||||
|
||||
// String returns the string representation of v.
|
||||
func (v *Variable) String() string {
|
||||
return "$" + v.Name
|
||||
}
|
||||
|
||||
func formatValue(v interface{}) string {
|
||||
switch v := v.(type) {
|
||||
case nil:
|
||||
|
|
@ -1048,6 +1101,8 @@ func formatValue(v interface{}) string {
|
|||
return fmt.Sprintf("\"%s\"", v.Format(time.RFC3339Nano))
|
||||
case *Condition:
|
||||
return v.String()
|
||||
case *Variable:
|
||||
return v.String()
|
||||
default:
|
||||
return fmt.Sprintf("%v", v)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ items <- item (comma items)?
|
|||
item <- 'null' &(comma / close) { p.addVal(nil) }
|
||||
/ 'true' &(comma / close) { p.addVal(true) }
|
||||
/ 'false' &(comma / close) { p.addVal(false) }
|
||||
/ '$' < variable > { p.addVal(NewVariable(text)) }
|
||||
/ timefmt { p.addVal(text) }
|
||||
/ timestampfmt { p.addTimestampVal(text) }
|
||||
/ < decimal > { p.addNumVal(text) }
|
||||
|
|
@ -54,6 +55,8 @@ item <- 'null' &(comma / close) { p.addVal(nil) }
|
|||
doublequotedstring <- ( '\\"' / '\\\\' / '\\n' / '\\t' / [^"\\] )*
|
||||
singlequotedstring <- ( '\\\'' / '\\\\' / '\\n' / '\\t' / [^'\\] )*
|
||||
|
||||
variable <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )*
|
||||
|
||||
fieldExpr <- ( [[A-Z]] / '_' ) ( [[A-Z]] / [0-9] / '_' / '-' )*
|
||||
field <- <fieldExpr / reserved> { p.addField(text) }
|
||||
reserved <- '_row' / '_col' / '_start' / '_end' / '_timestamp' / '_field'
|
||||
|
|
|
|||
2690
pql/pql.peg.go
2690
pql/pql.peg.go
File diff suppressed because it is too large
Load diff
|
|
@ -752,6 +752,15 @@ func TestPQLDeepEquality(t *testing.T) {
|
|||
{Name: "Rows"},
|
||||
},
|
||||
}},
|
||||
{
|
||||
name: "Variable",
|
||||
call: "Row(f=$my_VAR123)",
|
||||
exp: &Call{
|
||||
Name: "Row",
|
||||
Args: map[string]interface{}{
|
||||
"f": &Variable{Name: "my_VAR123"},
|
||||
},
|
||||
}},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue