X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FAbstract%2FReference.pm;h=fd29f339d98e63b9261ae239c27e466893eac2e9;hb=ef42b9a699e2dc37e13870b0f7f5db38cd907c71;hp=771d222eaa473cf5e3647d7b323267348b5b78db;hpb=662bd62324f98cd0bc4a70bbb01d17629f7ec44b;p=scpubgit%2FQ-Branch.git diff --git a/lib/SQL/Abstract/Reference.pm b/lib/SQL/Abstract/Reference.pm index 771d222..fd29f33 100644 --- a/lib/SQL/Abstract/Reference.pm +++ b/lib/SQL/Abstract/Reference.pm @@ -912,4 +912,215 @@ Expands to a bind node with the currently applicable column name if known: foo = ? [ 3 ] +=head1 Query Types + +=head2 select + +A select node accepts select, from, where and order_by clauses. + +The select clause is expanded as a list expression with a -ident default: + + # expr + { -select => { _ => [ 'foo', 'bar', { -count => 'baz' } ] } } + + # aqt + { -select => { select => { -op => [ + ',', { -ident => [ 'foo' ] }, { -ident => [ 'bar' ] }, + { -func => [ 'count', { -ident => [ 'baz' ] } ] }, + ] } } } + + # query + SELECT foo, bar, COUNT(baz) + [] + +The from clause is expanded as a list expression with a -ident default: + + # expr + { -select => { + from => [ 'schema1.table1', { -ident => [ 'schema2', 'table2' ] } ] + } } + + # aqt + { -select => { from => { -from_list => [ + { -ident => [ 'schema1', 'table1' ] }, + { -ident => [ 'schema2', 'table2' ] }, + ] } } } + + # query + FROM schema1.table1, schema2.table2 + [] + +The where clause is expanded as a plain expression: + + # expr + { -select => { where => { foo => 3 } } } + + # aqt + { -select => { where => { + -op => [ '=', { -ident => [ 'foo' ] }, { -bind => [ 'foo', 3 ] } ] + } } } + + # query + WHERE foo = ? + [ 3 ] + +The order_by clause expands as a list expression at top level, but a hashref +element may be either an expr or a hashpair with key -asc or -desc to indicate +an order by direction: + + # expr + { -select => + { order_by => [ 'foo', { -desc => 'bar' }, { -max => 'baz' } ] } + } + + # aqt + { -select => { order_by => { -op => [ + ',', { -ident => [ 'foo' ] }, { + -op => [ ',', { -op => [ 'desc', { -ident => [ 'bar' ] } ] } ] + }, { -func => [ 'max', { -ident => [ 'baz' ] } ] }, + ] } } } + + # query + ORDER BY foo, bar DESC, MAX(baz) + [] + +=head2 + +An insert node accepts an into/target clause, a fields clause, a values/from +clause, and a returning clause. + +The target clause is expanded with an ident default. + +The fields clause is expanded as a list expression if an arrayref, and +otherwise passed through. + +The from clause may either be an expr, a literal, an arrayref of column +values, or a hashref mapping colum names to values. + +The returning clause is expanded as a list expr with an ident default. + + # expr + { -insert => { + into => 'foo', + returning => 'id', + values => { bar => 'yay', baz => 'argh' }, + } } + + # aqt + { -insert => { + fields => + { -row => [ { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ] }, + from => { -values => [ { -row => [ + { -bind => [ 'bar', 'yay' ] }, + { -bind => [ 'baz', 'argh' ] }, + ] } ] }, + returning => { -op => [ ',', { -ident => [ 'id' ] } ] }, + target => { -op => [ ',', { -ident => [ 'foo' ] } ] }, + } } + + # query + INSERT INTO foo (bar, baz) VALUES (?, ?) RETURNING id + [ 'yay', 'argh' ] + + # expr + { -insert => { + fields => [ 'bar', 'baz' ], + from => { -select => { _ => [ 'bar', 'baz' ], from => 'other' } }, + into => 'foo', + } } + + # aqt + { -insert => { + fields => { -row => [ { -op => + [ ',', { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ] + } ] }, + from => { -select => { + from => { -from_list => [ { -ident => [ 'other' ] } ] }, + select => { -op => + [ ',', { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ] + }, + } }, + target => { -op => [ ',', { -ident => [ 'foo' ] } ] }, + } } + + # query + INSERT INTO foo (bar, baz) SELECT bar, baz FROM other + [] + +=head2 update + +An update node accepts update/target (either may be used at expansion time), +set, where, and returning clauses. + +The target clause is expanded with an ident default. + +The set clause (if not already a list expr) is expanded as a hashref where +the keys are identifiers to be set and the values are exprs/values. + +The where clauses is expanded as a normal expr. + +The returning clause is expanded as a list expr with an ident default. + + # expr + { -update => { + _ => 'foo', + returning => [ 'id', 'baz' ], + set => { bar => 3, baz => { baz => { '+' => 1 } } }, + where => { -not => { -ident => 'quux' } }, + } } + + # aqt + { -update => { + returning => + { + -op => [ ',', { -ident => [ 'id' ] }, { -ident => [ 'baz' ] } ] + }, + set => { -op => [ + ',', { -op => + [ '=', { -ident => [ 'bar' ] }, { -bind => [ 'bar', 3 ] } ] + }, { -op => [ + '=', { -ident => [ 'baz' ] }, { -op => [ + '+', { -ident => [ 'baz' ] }, + { -bind => [ 'baz', 1 ] }, + ] }, + ] }, + ] }, + target => { -from_list => [ { -ident => [ 'foo' ] } ] }, + where => { -op => [ 'not', { -ident => [ 'quux' ] } ] }, + } } + + # query + UPDATE foo SET bar = ?, baz = baz + ? WHERE (NOT quux) RETURNING id, baz + [ 3, 1 ] + +=head2 delete + +delete accepts from/target, where, and returning clauses. + +The target clause is expanded with an ident default. + +The where clauses is expanded as a normal expr. + +The returning clause is expanded as a list expr with an ident default. + + # expr + { -delete => { + from => 'foo', + returning => 'id', + where => { bar => { '<' => 10 } }, + } } + + # aqt + { -delete => { + returning => { -op => [ ',', { -ident => [ 'id' ] } ] }, + target => { -op => [ ',', { -ident => [ 'foo' ] } ] }, + where => { -op => + [ '<', { -ident => [ 'bar' ] }, { -bind => [ 'bar', 10 ] } ] + }, + } } + + # query + DELETE FROM foo WHERE bar < ? RETURNING id + [ 10 ] + =cut