delete command

This commit is contained in:
jackfoxy 2023-03-03 09:35:01 -08:00
parent 2b7b843224
commit 6905429cf8
4 changed files with 207 additions and 68 deletions

View File

@ -14,6 +14,7 @@
create-namespace:ast
create-table:ast
create-view:ast
delete:ast
drop-database:ast
drop-index:ast
drop-namespace:ast
@ -35,6 +36,8 @@
%create-namespace
%create-table
%create-view
%cte
%delete
%drop-database
%drop-index
%drop-namespace
@ -1155,6 +1158,25 @@
joined-objects [joined joined-objects]
raw-joined-objects +.raw-joined-objects
==
++ produce-delete
|= a=*
^- delete:ast
=/ ctes=(list cte-query:ast) ~
?> ?=(qualified-object:ast -.a)
?: =(%where +<.a)
(delete:ast %delete -.a ~ `(produce-predicate (predicate-list +>-.a)))
?: =(%end-command +<.a)
(delete:ast %delete -.a ~ ~)
=/ raw-ctes +<.a
|-
?~ raw-ctes
(delete:ast %delete -.a (flop ctes) `(produce-predicate (predicate-list +>->.a)))
?: ?&(=(%cte -<.raw-ctes) =(%as ->+<.raw-ctes))
%= $
raw-ctes +.raw-ctes
ctes [(cte-query:ast %cte ->+>.raw-ctes (produce-simple-query ->-.raw-ctes)) ctes]
==
~|('cannot produce delete from parsed: {<a>}' !!)
++ produce-select
|= a=*
^- select:ast
@ -1216,7 +1238,7 @@
==
?> ?=(qualified-column:ast -.a) $(columns [-.a columns], a +.a)
++ produce-simple-query
|= a=(list *)
|= a=*
^- simple-query:ast
=/ from=(unit from:ast) ~
=/ scalars=(list scalar-function:ast) ~
@ -1224,20 +1246,19 @@
=/ group-by=(list grouping-column:ast) ~
=/ having=(unit predicate:ast) ~
=/ select=(unit select:ast) ~
=/ order-by=(list ordering-column:ast) ~
|-
?~ a ~|("cannot parse simple-query {<a>}" !!)
?: =(i.a %query) $(a t.a)
?: =(i.a %end-command)
?: =(-.a %query) $(a +.a)
?: =(-.a %end-command)
(simple-query:ast %simple-query from [%scalars scalars] predicate [%group-by group-by] [%having having] (need select) order-by)
::?: =(i.a %scalars) $(a t.a, scalars +.i.a)
?: =(-<.a %scalars) $(a t.a, scalars ~)
?: =(-<.a %where) $(a t.a, predicate `(produce-predicate (predicate-list +.i.a)))
?: =(-<.a %select) $(a t.a, select `(produce-select +.i.a))
?: =(-<.a %group-by) $(a t.a, group-by (group-by-list ->.a))
?: =(-<.a %order-by) $(a t.a, order-by (order-by-list ->.a))
?: =(-<-.a %query-object) $(a t.a, from `(produce-from i.a))
?: =(-<.a %scalars) $(a +.a, scalars ~)
?: =(-<.a %where) $(a +.a, predicate `(produce-predicate (predicate-list ->.a)))
?: =(-<.a %select) $(a +.a, select `(produce-select ->.a))
?: =(-<.a %group-by) $(a +.a, group-by (group-by-list ->.a))
?: =(-<.a %order-by) $(a +.a, order-by (order-by-list ->.a))
?: =(-<-.a %query-object) $(a +.a, from `(produce-from -.a))
~|("cannot parse simple-query {<a>}" !!)
::
:: parse urQL command
@ -1392,6 +1413,29 @@
parse-query09
parse-query10
==
++ parse-cte ;~ plug
(cold %cte ;~(plug whitespace (jest '(')))
;~ pose
;~(pfix ;~(whitespace (jester 'from')) parse-query)
;~(pfix (jester 'from') parse-query)
parse-query
==
;~ pose
;~(pfix whitespace ;~(pfix (jest ')') ;~(pfix whitespace (jester 'as'))))
;~(pfix (jest ')') ;~(pfix whitespace (jester 'as')))
==
;~(pose ;~(sfix parse-alias whitespace) parse-alias)
==
++ parse-ctes
(more com parse-cte)
++ parse-delete ;~ plug
;~(pfix whitespace parse-qualified-3object)
;~ pose
;~(pfix whitespace ;~(plug ;~(pfix (jester 'with') parse-ctes) ;~(plug (cold %where ;~(pfix whitespace (jester 'where'))) parse-predicate) end-or-next-command))
;~(pfix whitespace ;~(plug (cold %where (jester 'where')) parse-predicate end-or-next-command))
end-or-next-command
==
==
++ parse-revoke ;~ plug
:: permission
;~(pfix whitespace ;~(pose (jester 'adminread') (jester 'readonly') (jester 'readwrite') (jester 'all')))
@ -1420,6 +1464,9 @@
(cold %create-table ;~(plug whitespace (jester 'create') whitespace (jester 'table')))
(cold %create-view ;~(plug whitespace (jester 'create') whitespace (jester 'view')))
(cold %create-index ;~(plug whitespace (jester 'create'))) :: must be last of creates
(cold %cte ;~(plug whitespace (jester 'with')))
(cold %delete ;~(plug whitespace (jester 'delete') whitespace (jester 'from')))
(cold %delete ;~(plug whitespace (jester 'delete')))
(cold %drop-database ;~(plug whitespace (jester 'drop') whitespace (jester 'database')))
(cold %drop-index ;~(plug whitespace (jester 'drop') whitespace (jester 'index')))
(cold %drop-namespace ;~(plug whitespace (jester 'drop') whitespace (jester 'namespace')))
@ -1626,6 +1673,34 @@
==
%create-view
!!
%cte
~| "Cannot parse ctes {<q.q.command-nail>}"
~| "command-nail: {<command-nail>}"
=/ ctes-nail (parse-ctes [[1 1] q.q.command-nail])
~| "ctes-nail: {<ctes-nail>}"
=/ parsed (wonk ctes-nail)
=/ next-cursor
(get-next-cursor [script-position +<.command-nail p.q.u.+3:q.+3:ctes-nail])
~| "parsed: {<parsed>}"
~| "remainder: {<q.q.u.+3:q.+3.ctes-nail>}"
:: %= $
:: script q.q.u.+3.q:ctes-nail
:: script-position next-cursor
:: commands
:: [`command-ast`(produce-simple-cte parsed) commands]
:: ==
!!
%delete
=/ delete-nail (parse-delete [[1 1] q.q.command-nail])
=/ parsed (wonk delete-nail)
=/ next-cursor
(get-next-cursor [script-position +<.command-nail p.q.u.+3:q.+3:delete-nail])
%= $
script q.q.u.+3.q:delete-nail
script-position next-cursor
commands
[`command-ast`(produce-delete parsed) commands]
==
%drop-database
=/ drop-database-nail (parse-drop-database [[1 1] q.q.command-nail])
=/ parsed (wonk drop-database-nail)
@ -1781,21 +1856,16 @@
==
~|("Cannot parse insert {<parsed>}" !!)
%query
~| "Cannot parse query {<q.q.command-nail>}"
~| "command-nail: {<command-nail>}"
=/ query-nail (parse-query [[1 1] q.q.command-nail])
~| "query-nail: {<query-nail>}"
=/ 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>}"
%= $
script q.q.u.+3.q:query-nail
script-position next-cursor
commands
[`command-ast`(produce-simple-query parsed) commands]
==
script q.q.u.+3.q:query-nail
script-position next-cursor
commands
[`command-ast`(produce-simple-query parsed) commands]
==
%revoke
=/ revoke-nail (parse-revoke [[1 1] q.q.command-nail])
=/ parsed (wonk revoke-nail)

View File

@ -222,7 +222,7 @@
%delete
table=qualified-object
(list cte-query)
predicate
(unit predicate)
==
+$ insert-values $%([%data (list (list datum))] [%query query])
+$ insert

View File

@ -1,60 +1,68 @@
/- ast
/+ parse, *test
::
:: we frequently break the rules of unit and regression tests here
:: by testing more than one thing per result, otherwise there would
:: just be too many tests
::
:: each arm tests one urql command
::
:: common things to test
:: 1) basic command works producing AST object
:: 2) multiple ASTs
:: 3) all keywords are case ambivalent
:: 4) all names follow rules for faces
:: 5) all qualifier combinations work
::
:: -test /=urql=/tests/lib/parse/hoon ~
|%
++ bar
[[%qualified-column [%qualified-object ~ 'UNKNOWN' 'COLUMN-OR-CTE' 'bar'] 'bar' ~] ~ ~]
::
:: delete
::
++ column-foo [%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='foo'] column='foo' alias=~]
++ column-bar [%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='bar'] column='bar' alias=~]
++ all-columns [%qualified-object ship=~ database='ALL' namespace='ALL' name='ALL']
++ from-foo
[~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] alias=~] joins=~]]
++ literal-10 [[%ud 10] ~ ~]
++ aggregates
~[[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='foo'] column='foo' alias=~] [%selected-aggregate [%aggregate function='count' source=[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='foo'] column='foo' alias=~]] alias=[~ 'CountFoo']] [%selected-aggregate [%aggregate function='count' source=[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='bar'] column='bar' alias=~]] alias=~] [%selected-aggregate [%aggregate function='sum' source=[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='bar'] column='bar' alias=~]] alias=~] [%selected-aggregate [%aggregate function='sum' source=[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='foobar'] column='foobar' alias=~]] alias=[~ 'foobar']]]
++ aggregate-count-foobar [%aggregate function='count' source=[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='foobar'] column='foobar' alias=~]]
++ col1
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col1'] column='col1' alias=~]
++ col2
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col2'] column='col2' alias=~]
++ col3
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col3'] column='col3' alias=~]
++ col4
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col4'] column='col4' alias=~]
++ delete-pred
`[%eq [column-foo ~ ~] [column-bar ~ ~]]
++ cte-t1
[%cte name='t1' [%simple-query ~ [%scalars ~] ~ [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[all-columns]] ~]]
++ cte-foobar
[%cte name='foobar' [%simple-query [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='foobar'] alias=~] joins=~]] [%scalars ~] `[%eq [col1 ~ ~] [[value-type=%ud value=2] ~ ~]] [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[col3 col4]] ~]]
++ cte-bar
[%cte name='bar' [%simple-query [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='bar'] alias=~] joins=~]] [%scalars ~] `[%eq [col1 ~ ~] [col2 ~ ~]] [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[col2]] ~]]
::
::
:: mixed aggregates
++ test-select-23
=/ select "select foo , COUNT(foo) as CountFoo, cOUNT( bar) ,sum(bar ) , sum( foobar ) as foobar "
:: delete from foo;delete foo
++ test-delete-01
=/ expected1 [[%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~ ~]]
=/ expected2 [[%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~ ~]]
%+ expect-eq
!> ~[[%simple-query ~ [%scalars ~] ~ [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=aggregates] ~]]
!> (parse:parse(current-database 'db1') select)
!> ~[expected1 expected2]
!> (parse:parse(current-database 'db1') "delete from foo;delete foo")
::
:: aggregate inequality
++ test-predicate-31
=/ select "from foo where count( foobar ) > 10 select * "
=/ pred=(tree predicate-component:ast) [%gt [aggregate-count-foobar ~ ~] literal-10]
:: delete with predicate
++ test-delete-02
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~ delete-pred]
%+ expect-eq
!> ~[[%simple-query from-foo [%scalars ~] `pred [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[all-columns]] ~]]
!> (parse:parse(current-database 'db1') select)
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo where foo=bar")
::
:: aggregate inequality, no whitespace
++ test-predicate-32
=/ select "from foo where count(foobar) > 10 select *"
=/ pred=(tree predicate-component:ast) [%gt [aggregate-count-foobar ~ ~] literal-10]
:: delete with one cte and predicate
++ test-delete-03
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~[cte-t1] delete-pred]
%+ expect-eq
!> ~[[%simple-query from-foo [%scalars ~] `pred [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[all-columns]] ~]]
!> (parse:parse(current-database 'db1') select)
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo with (select *) as t1 where foo=bar")
::
:: aggregate equality
++ test-predicate-33
=/ select "from foo where bar = count(foobar) select *"
=/ pred=(tree predicate-component:ast) [%eq bar [aggregate-count-foobar ~ ~]]
:: delete with two ctes and predicate
++ test-delete-04
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~[cte-t1 cte-foobar] delete-pred]
%+ expect-eq
!> ~[[%simple-query from-foo [%scalars ~] `pred [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[all-columns]] ~]]
!> (parse:parse(current-database 'db1') select)
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo with (select *) as t1, (from foobar where col1=2 select col3, col4) as foobar where foo=bar")
::
:: delete with three ctes and predicate
++ test-delete-05
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~[cte-t1 cte-foobar cte-bar] delete-pred]
%+ expect-eq
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo with (select *) as t1, (from foobar where col1=2 select col3, col4) as foobar, (from bar where col1=col2 select col2) as bar where foo=bar")
::
:: fail delete cte with no predicate
++ test-fail-delete-06
%- expect-fail
|. (parse:parse(current-database 'other-db') "delete from foo with (select *) as t1")
--

View File

@ -346,6 +346,67 @@
%- expect-fail
|. (parse:parse(current-database 'other-db') urql)
::
:: delete
::
++ col1
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col1'] column='col1' alias=~]
++ col2
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col2'] column='col2' alias=~]
++ col3
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col3'] column='col3' alias=~]
++ col4
[%qualified-column qualifier=[%qualified-object ship=~ database='UNKNOWN' namespace='COLUMN-OR-CTE' name='col4'] column='col4' alias=~]
++ delete-pred
`[%eq [column-foo ~ ~] [column-bar ~ ~]]
++ cte-t1
[%cte name='t1' [%simple-query ~ [%scalars ~] ~ [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[all-columns]] ~]]
++ cte-foobar
[%cte name='foobar' [%simple-query [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='foobar'] alias=~] joins=~]] [%scalars ~] `[%eq [col1 ~ ~] [[value-type=%ud value=2] ~ ~]] [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[col3 col4]] ~]]
++ cte-bar
[%cte name='bar' [%simple-query [~ [%from object=[%query-object object=[%qualified-object ship=~ database='db1' namespace='dbo' name='bar'] alias=~] joins=~]] [%scalars ~] `[%eq [col1 ~ ~] [col2 ~ ~]] [%group-by ~] [%having ~] [%select top=~ bottom=~ distinct=%.n columns=~[col2]] ~]]
:: delete from foo;delete foo
::
:: delete from foo;delete foo
++ test-delete-01
=/ expected1 [[%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~ ~]]
=/ expected2 [[%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~ ~]]
%+ expect-eq
!> ~[expected1 expected2]
!> (parse:parse(current-database 'db1') "delete from foo;delete foo")
::
:: delete with predicate
++ test-delete-02
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~ delete-pred]
%+ expect-eq
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo where foo=bar")
::
:: delete with one cte and predicate
++ test-delete-03
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~[cte-t1] delete-pred]
%+ expect-eq
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo with (select *) as t1 where foo=bar")
::
:: delete with two ctes and predicate
++ test-delete-04
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~[cte-t1 cte-foobar] delete-pred]
%+ expect-eq
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo with (select *) as t1, (from foobar where col1=2 select col3, col4) as foobar where foo=bar")
::
:: delete with three ctes and predicate
++ test-delete-05
=/ expected [%delete table=[%qualified-object ship=~ database='db1' namespace='dbo' name='foo'] ~[cte-t1 cte-foobar cte-bar] delete-pred]
%+ expect-eq
!> ~[expected]
!> (parse:parse(current-database 'db1') "delete from foo with (select *) as t1, (from foobar where col1=2 select col3, col4) as foobar, (from bar where col1=col2 select col2) as bar where foo=bar")
::
:: fail delete cte with no predicate
++ test-fail-delete-06
%- expect-fail
|. (parse:parse(current-database 'other-db') "delete from foo with (select *) as t1")
::
:: drop database
::
:: tests 1, 2, 3, 5, and extra whitespace characters, force db.name, name