mirror of
https://github.com/jackfoxy/urQL.git
synced 2024-12-14 18:41:40 +03:00
more predicate tests, more clean-up
This commit is contained in:
parent
ae1d4382b2
commit
b49267d458
@ -1,2 +1,5 @@
|
||||
# urQL
|
||||
RDBMS for Urbit
|
||||
Scripting language grammar and parser for an Urbit RDBMS.
|
||||
|
||||
Pull Requests are appreciated, but you should start a discussion before you proceed. If green-lit then open an issue.
|
||||
|
||||
|
@ -50,7 +50,12 @@ There are no subqueries.
|
||||
JOINs and/or CTEs handle all such use cases and emphasize composability.
|
||||
CTEs can be referenced for certain use cases in predicates.
|
||||
|
||||
Reading and/or updating data on foreign ships is allowed provided the ship's pilot has granted permission. Cross database joins are allowed, but not cross ship joins.
|
||||
The result of a UNION set operation is as according to _union_ in set theory (no duplicate rows returned).
|
||||
Use COMBINE to include duplicates.
|
||||
Relational division is supported with a DIVIDED BY operator.
|
||||
|
||||
Reading and/or updating data on foreign ships is allowed provided the ship's pilot has granted permission.
|
||||
Cross database joins are allowed, but not cross ship joins.
|
||||
Views cannot be defined on foreign databases.
|
||||
|
||||
This document has placeholders for Stored Procedures and Triggers, which have yet to be defined. We anticipate these will be points for integration with hoon.
|
||||
|
@ -493,8 +493,6 @@
|
||||
parse-join-type
|
||||
parse-query-object
|
||||
;~(pfix whitespace ;~(pfix (jester 'on') parse-predicate))
|
||||
::;~(pfix whitespace ;~(pfix (jester 'on') ;~(less predicate-stop prn)))
|
||||
::(easy ~)
|
||||
==
|
||||
++ parse-object-and-joins ~+ ;~ plug
|
||||
parse-query-object
|
||||
@ -551,11 +549,12 @@
|
||||
(cold %lt (just '<'))
|
||||
(cold %and ;~(plug (jester 'and') whitespace))
|
||||
(cold %or ;~(plug (jester 'or') whitespace))
|
||||
:: to do %distinct %not-distinct:
|
||||
:: (cold %distinct ;~(plug (jester 'is') whitespace (jester 'distinct') whitespace (jester 'from')))
|
||||
:: (cold %not-distinct ;~(plug (jester 'is') whitespace (jester 'not') whitespace (jester 'distinct') whitespace (jester 'from')))
|
||||
:: ternary operator
|
||||
(cold %between ;~(plug (jester 'between') whitespace))
|
||||
:: nesting directors
|
||||
:: nesting
|
||||
(cold %pal pal)
|
||||
(cold %par par)
|
||||
==
|
||||
@ -646,9 +645,7 @@
|
||||
^- predicate:ast
|
||||
=/ working-tree=predicate:ast ~
|
||||
=/ tree-stack=(list predicate:ast) ~
|
||||
~| "produce-predicate parsed: {<parsed>}"
|
||||
|-
|
||||
~| "-.parsed: {<-.parsed>}"
|
||||
?: =((lent parsed) 0)
|
||||
|-
|
||||
?~ tree-stack
|
||||
@ -661,6 +658,7 @@
|
||||
==
|
||||
?- -.parsed
|
||||
%pal :: push working predicate onto the stack
|
||||
?~ working-tree $(parsed +.parsed)
|
||||
%= $
|
||||
tree-stack [working-tree tree-stack]
|
||||
working-tree ~
|
||||
@ -695,10 +693,6 @@
|
||||
?~ l.working-tree ~|("binary-operator, left tree empty" !!)
|
||||
?~ r.working-tree ~|("binary-operator, right tree empty" !!)
|
||||
~|("binary-operator can't get here {<working-tree>}" !!)
|
||||
:: %= $
|
||||
:: working-tree [-.parsed working-tree ~]
|
||||
:: parsed +.parsed
|
||||
:: ==
|
||||
ternary-operator:ast
|
||||
?~ working-tree !!
|
||||
?~ l.working-tree ~|("ternary-operator, left tree empty" !!)
|
||||
@ -720,13 +714,19 @@
|
||||
?~ working-tree ~|("operator {<-.parsed>} can only follow equality or inequality operator" !!)
|
||||
?~ r.working-tree
|
||||
?: ?&(?=(binary-operator:ast n.working-tree) ?!(=(%in n.working-tree)))
|
||||
?> ?=(qualified-column:ast +<.parsed) :: to do: this must resolve to a CTE
|
||||
%= $
|
||||
working-tree [-.working-tree +<.working-tree [-.parsed [+<.parsed ~ ~] ~]]
|
||||
parsed +>.parsed
|
||||
==
|
||||
~|("operator {<-.parsed>} can only follow equality or inequality operator" !!)
|
||||
~|("all-any-operator can't get here" !!)
|
||||
?: ?=(value-literal-list:ast +<.parsed)
|
||||
%= $
|
||||
working-tree [-.working-tree +<.working-tree [-.parsed [+<.parsed ~ ~] ~]]
|
||||
parsed +>.parsed
|
||||
==
|
||||
?: ?=(qualified-column:ast +<.parsed) :: to do: this must resolve to a CTE or list
|
||||
%= $
|
||||
working-tree [-.working-tree +<.working-tree [-.parsed [+<.parsed ~ ~] ~]]
|
||||
parsed +>.parsed
|
||||
==
|
||||
~|("all-any-operator {<-.parsed>} must target CTE or literal list {<+<.parsed>}" !!)
|
||||
~|("all-any-operator {<-.parsed>} can only follow equality or inequality operator" !!)
|
||||
~|("all-any-operator {<-.parsed>} can't get here, working-tree {<working-tree>}" !!)
|
||||
qualified-column:ast
|
||||
?~ working-tree
|
||||
?: ?=(binary-operator:ast +<.parsed)
|
||||
@ -752,7 +752,7 @@
|
||||
working-tree [%not (produce-predicate ~[-.parsed %in +>+<.parsed]) ~]
|
||||
parsed +>+>.parsed
|
||||
==
|
||||
!!
|
||||
~|("unary-operator {<+<.parsed>} can't get here after qualified-column, working-tree {<working-tree>}" !!)
|
||||
?: =(%between +<.parsed)
|
||||
?: =(%and +>+<.parsed)
|
||||
%= $
|
||||
@ -807,7 +807,7 @@
|
||||
working-tree [%not (produce-predicate ~[-.parsed %in +>+<.parsed]) ~]
|
||||
parsed +>+>.parsed
|
||||
==
|
||||
!!
|
||||
~|("unary-operator {<+<.parsed>} can't get here after value-literal, working-tree {<working-tree>}" !!)
|
||||
?: =(%between +<.parsed)
|
||||
?: =(%and +>+<.parsed)
|
||||
%= $
|
||||
@ -820,7 +820,7 @@
|
||||
[%between (produce-predicate ~[-.parsed %gte +>-.parsed]) (produce-predicate ~[-.parsed %lte +>+<.parsed])]
|
||||
parsed +>+>.parsed
|
||||
==
|
||||
!!
|
||||
~|("value-literal can't get here after {<+<.parsed>} , working-tree {<working-tree>}" !!)
|
||||
?~ l.working-tree
|
||||
%= $
|
||||
working-tree [-.working-tree [-.parsed ~ ~] ~]
|
||||
@ -1076,10 +1076,8 @@
|
||||
(from:ast %from query-object (flop joined-objects))
|
||||
~|("cross join must be only join in query" !!) :: to do, not sure this is required, investigate later
|
||||
(from:ast %from query-object (flop joined-objects))
|
||||
|
||||
?> ?=(join-type:ast -<.raw-joined-objects)
|
||||
?> ?=(query-object:ast ->-.raw-joined-objects)
|
||||
|
||||
?: ?=(%cross-join -<.raw-joined-objects)
|
||||
%= $
|
||||
joined-objects
|
||||
@ -1502,13 +1500,13 @@
|
||||
script-position next-cursor
|
||||
commands [`command-ast`(drop-database:ast %drop-database parsed %.n) commands]
|
||||
==
|
||||
~| "Cannot parse drop-database {<parsed>}"
|
||||
?: ?=([@ @] parsed) :: force name
|
||||
%= $
|
||||
script q.q.u.+3.q:drop-database-nail
|
||||
script-position next-cursor
|
||||
commands [`command-ast`(drop-database:ast %drop-database +.parsed %.y) commands]
|
||||
==
|
||||
::~|("Cannot parse drop-database {<parsed>}" !!)
|
||||
!!
|
||||
%drop-index
|
||||
=/ drop-index-nail (parse-drop-index [[1 1] q.q.command-nail])
|
||||
@ -1543,13 +1541,13 @@
|
||||
script-position next-cursor
|
||||
commands [`command-ast`(drop-namespace:ast %drop-namespace -.parsed +.parsed %.n) commands]
|
||||
==
|
||||
~| "Cannot parse drop-namespace {<parsed>}"
|
||||
?: ?=([* [@ @]] parsed) :: force db.name
|
||||
%= $
|
||||
script q.q.u.+3.q:drop-namespace-nail
|
||||
script-position next-cursor
|
||||
commands [`command-ast`(drop-namespace:ast %drop-namespace +<.parsed +>.parsed %.y) commands]
|
||||
==
|
||||
::~|("Cannot parse drop-namespace {<parsed>}" !!)
|
||||
!!
|
||||
%drop-table
|
||||
=/ drop-table-nail (drop-table-or-view [[1 1] q.q.command-nail])
|
||||
@ -1652,8 +1650,8 @@
|
||||
=/ parsed (wonk query-nail)
|
||||
=/ next-cursor
|
||||
(get-next-cursor [script-position +<.command-nail p.q.u.+3:q.+3:query-nail])
|
||||
~| "parsed: {<parsed>}"
|
||||
~| "remainder: {<q.q.u.+3:q.+3.query-nail>}"
|
||||
:: ~| "parsed: {<parsed>}"
|
||||
:: ~| "remainder: {<q.q.u.+3:q.+3.query-nail>}"
|
||||
%= $
|
||||
script q.q.u.+3.q:query-nail
|
||||
script-position next-cursor
|
||||
@ -1661,7 +1659,6 @@
|
||||
[`command-ast`(produce-simple-query parsed) commands]
|
||||
==
|
||||
%revoke
|
||||
|
||||
=/ revoke-nail (parse-revoke [[1 1] q.q.command-nail])
|
||||
=/ parsed (wonk revoke-nail)
|
||||
=/ next-cursor
|
||||
|
@ -24,16 +24,16 @@
|
||||
|
||||
++ foobar [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN-OR-CTE' 'foobar'] 'foobar' ~] ~ ~]
|
||||
|
||||
++ a1-adoption-email [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A1'] 'adoption-email' 0] 0 0]
|
||||
++ a2-adoption-email [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A2'] 'adoption-email' 0] 0 0]
|
||||
++ a1-adoption-email [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A1'] 'adoption-email' ~] ~ ~]
|
||||
++ a2-adoption-email [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A2'] 'adoption-email' ~] ~ ~]
|
||||
|
||||
++ a1-adoption-date [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A1'] 'adoption-date' 0] 0 0]
|
||||
++ a2-adoption-date [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A2'] 'adoption-date' 0] 0 0]
|
||||
++ a1-adoption-date [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A1'] 'adoption-date' ~] ~ ~]
|
||||
++ a2-adoption-date [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A2'] 'adoption-date' ~] ~ ~]
|
||||
|
||||
++ a1-name [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A1'] 'name' 0] 0 0]
|
||||
++ a2-name [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A2'] 'name' 0] 0 0]
|
||||
++ a1-species [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A1'] 'species' 0] 0 0]
|
||||
++ a2-species [[%qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN' 'A2'] 'species' 0] 0 0]
|
||||
++ a1-name [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A1'] 'name' ~] ~ ~]
|
||||
++ a2-name [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A2'] 'name' ~] ~ ~]
|
||||
++ a1-species [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A1'] 'species' ~] ~ ~]
|
||||
++ a2-species [[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN' 'A2'] 'species' ~] ~ ~]
|
||||
|
||||
++ value-literal-list [[%value-literal-list %ud '3;2;1'] ~ ~]
|
||||
++ aggregate-count-foo [%aggregate %count %qualified-column [%qualified-object 0 'UNKNOWN' 'COLUMN-OR-CTE' %foo] %foo 0]
|
||||
@ -341,70 +341,84 @@
|
||||
:: !> ~[expected]
|
||||
:: !> (parse:parse(current-database 'db1') query)
|
||||
|
||||
++ test-predicate-27
|
||||
:: =/ predicate "foobar >=foo And foobar<=bar ".
|
||||
:: " and T1.foo2 = ~zod ".
|
||||
:: " or ".
|
||||
:: " foobar>=foo ".
|
||||
:: " AND T1.foo2=~zod ".
|
||||
:: " OR ".
|
||||
:: " foo = 1 ".
|
||||
:: " AND T1.foo3 < any (1,2,3)"
|
||||
:: expected/actual match
|
||||
::++ test-predicate-27
|
||||
:: =/ query "FROM adoptions AS T1 JOIN adoptions AS T2 ON T1.foo = T2.bar ".
|
||||
:: " WHERE foobar >=foo And foobar<=bar ".
|
||||
:: " and T1.foo2 = ~zod ".
|
||||
:: " or ".
|
||||
:: " foobar>=foo ".
|
||||
:: " AND T1.foo2=~zod ".
|
||||
:: " OR ".
|
||||
:: " foo = 1 ".
|
||||
:: " AND T1.foo3 < any (1,2,3) ".
|
||||
:: " SELECT *"
|
||||
:: =/ joinpred=(tree predicate-component:ast) [%eq t1-foo t2-bar]
|
||||
:: =/ pred=(tree predicate-component:ast) and-and-or-and-or-and
|
||||
:: =/ expected=simple-query:ast
|
||||
:: [%simple-query [~ [%priori [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T1']] joins=~[[%joined-object join=%join object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T2']] predicate=`joinpred]]]] ~ `pred]] [%select top=~ bottom=~ distinct=%.n columns=~[%all]] ~]
|
||||
:: %+ expect-eq
|
||||
:: !> and-and-or-and-or-and
|
||||
:: !> (wonk (parse-predicate:parse [[1 1] predicate]))
|
||||
=/ query "FROM adoptions AS T1 JOIN adoptions AS T2 ON T1.foo = T2.bar ".
|
||||
" WHERE foobar >=foo And foobar<=bar ".
|
||||
" and T1.foo2 = ~zod ".
|
||||
" or ".
|
||||
" foobar>=foo ".
|
||||
" AND T1.foo2=~zod ".
|
||||
" OR ".
|
||||
" foo = 1 ".
|
||||
" AND T1.foo3 < any (1,2,3) ".
|
||||
" SELECT *"
|
||||
=/ joinpred=(tree predicate-component:ast) [%eq t1-foo t2-bar]
|
||||
=/ pred=(tree predicate-component:ast) and-and-or-and-or-and
|
||||
=/ expected=simple-query:ast
|
||||
[%simple-query [~ [%priori [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T1']] joins=~[[%joined-object join=%join object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T2']] predicate=`joinpred]]]] ~ `pred]] [%select top=~ bottom=~ distinct=%.n columns=~[%all]] ~]
|
||||
%+ expect-eq
|
||||
!> ~[expected]
|
||||
!> (parse:parse(current-database 'db1') query)
|
||||
|
||||
:: !> ~[expected]
|
||||
:: !> (parse:parse(current-database 'db1') query)
|
||||
|
||||
::
|
||||
:: simple nesting
|
||||
:: expected/actual match
|
||||
::++ test-predicate-28
|
||||
:: =/ predicate "(foobar > foo OR foobar < bar) ".
|
||||
:: " AND T1.foo>foo2 ".
|
||||
:: " AND T2.bar IN (1,2,3) ".
|
||||
:: " AND (T1.foo3< any (1,2,3) OR T1.foo2=~zod AND foo=1 ) "
|
||||
:: =/ query "FROM adoptions AS T1 JOIN adoptions AS T2 ON T1.foo = T2.bar ".
|
||||
:: " WHERE (foobar > foo OR foobar < bar) ".
|
||||
:: " AND T1.foo>foo2 ".
|
||||
:: " AND T2.bar IN (1,2,3) ".
|
||||
:: " AND (T1.foo3< any (1,2,3) OR T1.foo2=~zod AND foo=1 ) ".
|
||||
:: " SELECT *"
|
||||
:: =/ joinpred=(tree predicate-component:ast) [%eq t1-foo t2-bar]
|
||||
:: =/ pred=(tree predicate-component:ast) king-and
|
||||
:: =/ expected=simple-query:ast
|
||||
:: [%simple-query [~ [%priori [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T1']] joins=~[[%joined-object join=%join object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T2']] predicate=`joinpred]]]] ~ `pred]] [%select top=~ bottom=~ distinct=%.n columns=~[%all]] ~]
|
||||
:: %+ expect-eq
|
||||
:: !> king-and
|
||||
:: !> (wonk (parse-predicate:parse [[1 1] predicate]))
|
||||
:: !> ~[expected]
|
||||
:: !> (parse:parse(current-database 'db1') query)
|
||||
|
||||
::
|
||||
:: nesting
|
||||
:: expected/actual match
|
||||
::++ test-predicate-29
|
||||
:: =/ predicate "foobar > foo AND foobar < bar ".
|
||||
:: " AND ( T1.foo>foo2 AND T2.bar IN (1,2,3) ".
|
||||
:: " OR (T1.foo3< any (1,2,3) AND T1.foo2=~zod AND foo=1 ) ".
|
||||
:: " OR (foo3=foo4 AND foo5=foo6) ".
|
||||
:: " OR foo4=foo5 ".
|
||||
:: " ) ".
|
||||
:: " AND foo6=foo7"
|
||||
:: =/ query "FROM adoptions AS T1 JOIN adoptions AS T2 ON T1.foo = T2.bar ".
|
||||
:: " WHERE foobar > foo AND foobar < bar ".
|
||||
:: " AND ( T1.foo>foo2 AND T2.bar IN (1,2,3) ".
|
||||
:: " OR (T1.foo3< any (1,2,3) AND T1.foo2=~zod AND foo=1 ) ".
|
||||
:: " OR (foo3=foo4 AND foo5=foo6) ".
|
||||
:: " OR foo4=foo5 ".
|
||||
:: " ) ".
|
||||
:: " AND foo6=foo7".
|
||||
:: " SELECT *"
|
||||
:: =/ joinpred=(tree predicate-component:ast) [%eq t1-foo t2-bar]
|
||||
:: =/ pred=(tree predicate-component:ast) a-a-l-a-o-l-a-a-r-o-r-a-l-o-r-a
|
||||
:: =/ expected=simple-query:ast
|
||||
:: [%simple-query [~ [%priori [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T1']] joins=~[[%joined-object join=%join object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T2']] predicate=`joinpred]]]] ~ `pred]] [%select top=~ bottom=~ distinct=%.n columns=~[%all]] ~]
|
||||
:: %+ expect-eq
|
||||
:: !> a-a-l-a-o-l-a-a-r-o-r-a-l-o-r-a
|
||||
:: !> (wonk (parse-predicate:parse [[1 1] predicate]))
|
||||
:: !> ~[expected]
|
||||
:: !> (parse:parse(current-database 'db1') query)
|
||||
|
||||
|
||||
::
|
||||
:: simple nesting, superfluous () around entire predicate
|
||||
:: expected/actual match
|
||||
::++ test-predicate-30
|
||||
:: =/ predicate "((foobar > foo OR foobar < bar) ".
|
||||
:: " AND T1.foo>foo2 ".
|
||||
:: " AND T2.bar IN (1,2,3) ".
|
||||
:: " AND (T1.foo3< any (1,2,3) OR T1.foo2=~zod AND foo=1 )) "
|
||||
:: =/ query "FROM adoptions AS T1 JOIN adoptions AS T2 ON T1.foo = T2.bar ".
|
||||
:: " WHERE ((foobar > foo OR foobar < bar) ".
|
||||
:: " AND T1.foo>foo2 ".
|
||||
:: " AND T2.bar IN (1,2,3) ".
|
||||
:: " AND (T1.foo3< any (1,2,3) OR T1.foo2=~zod AND foo=1 )) ".
|
||||
:: " SELECT *"
|
||||
:: =/ joinpred=(tree predicate-component:ast) [%eq t1-foo t2-bar]
|
||||
:: =/ pred=(tree predicate-component:ast) king-and
|
||||
:: =/ expected=simple-query:ast
|
||||
:: [%simple-query [~ [%priori [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T1']] joins=~[[%joined-object join=%join object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T2']] predicate=`joinpred]]]] ~ `pred]] [%select top=~ bottom=~ distinct=%.n columns=~[%all]] ~]
|
||||
:: %+ expect-eq
|
||||
:: !> king-and
|
||||
:: !> (wonk (parse-predicate:parse [[1 1] predicate]))
|
||||
:: !> ~[expected]
|
||||
:: !> (parse:parse(current-database 'db1') query)
|
||||
|
||||
::
|
||||
:: aggregate inequality
|
||||
::++ test-predicate-31
|
||||
@ -428,18 +442,25 @@
|
||||
:: !> (wonk (parse-predicate:parse [[1 1] predicate]))
|
||||
::
|
||||
:: complext predicate, bug test
|
||||
:: expected/actual match
|
||||
::++ test-predicate-34
|
||||
:: =/ predicate " A1.adoption-email = A2.adoption-email ".
|
||||
:: " AND A1.adoption-date = A2.adoption-date ".
|
||||
:: " AND foo = bar ".
|
||||
:: " AND ((A1.name = A2.name AND A1.species > A2.species) ".
|
||||
:: " OR ".
|
||||
:: " (A1.name > A2.name AND A1.species = A2.species) ".
|
||||
:: " OR ".
|
||||
:: " (A1.name > A2.name AND A1.species > A2.species) ".
|
||||
:: " ) "
|
||||
:: =/ query "FROM adoptions AS T1 JOIN adoptions AS T2 ON T1.foo = T2.bar ".
|
||||
:: " WHERE A1.adoption-email = A2.adoption-email ".
|
||||
:: " AND A1.adoption-date = A2.adoption-date ".
|
||||
:: " AND foo = bar ".
|
||||
:: " AND ((A1.name = A2.name AND A1.species > A2.species) ".
|
||||
:: " OR ".
|
||||
:: " (A1.name > A2.name AND A1.species = A2.species) ".
|
||||
:: " OR ".
|
||||
:: " (A1.name > A2.name AND A1.species > A2.species) ".
|
||||
:: " ) ".
|
||||
:: " SELECT *"
|
||||
:: =/ joinpred=(tree predicate-component:ast) [%eq t1-foo t2-bar]
|
||||
:: =/ pred=(tree predicate-component:ast)
|
||||
:: [%and [%and [%and [%eq a1-adoption-email a2-adoption-email] [%eq a1-adoption-date a2-adoption-date]] [%eq foo bar]] [%or [%or [%and [%eq a1-name a2-name] [%gt a1-species a2-species]] [%and [%gt a1-name a2-name] [%eq a1-species a2-species]]] [%and [%gt a1-name a2-name] [%gt a1-species a2-species]]]]
|
||||
:: =/ expected=simple-query:ast
|
||||
:: [%simple-query [~ [%priori [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T1']] joins=~[[%joined-object join=%join object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='adoptions'] alias=[~ 'T2']] predicate=`joinpred]]]] ~ `pred]] [%select top=~ bottom=~ distinct=%.n columns=~[%all]] ~]
|
||||
:: %+ expect-eq
|
||||
:: !> [%and [%and [%and [%eq a1-adoption-email a2-adoption-email] [%eq a1-adoption-date a2-adoption-date]] [%eq foo bar]] [%or [%or [%and [%eq a1-name a2-name] [%gt a1-species a2-species]] [%and [%gt a1-name a2-name] [%eq a1-species a2-species]]] [%and [%gt a1-name a2-name] [%gt a1-species a2-species]]]]
|
||||
:: !> (wonk (parse-predicate:parse [[1 1] predicate]))
|
||||
|
||||
:: !> ~[expected]
|
||||
:: !> (parse:parse(current-database 'db1') query)
|
||||
--
|
Loading…
Reference in New Issue
Block a user