From: Matt S Trout Date: Mon, 15 Apr 2019 20:21:59 +0000 (+0000) Subject: basic with support X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=scpubgit%2FQ-Branch.git;a=commitdiff_plain;h=1ba47f38ffd3b99b3ae3be9520edafd560bfb026;hp=d175037fcf14677c8969f3ab389d00eba99d306c basic with support --- diff --git a/lib/SQL/Abstract/ExtraClauses.pm b/lib/SQL/Abstract/ExtraClauses.pm index af7dc52..e29aea3 100644 --- a/lib/SQL/Abstract/ExtraClauses.pm +++ b/lib/SQL/Abstract/ExtraClauses.pm @@ -21,7 +21,7 @@ sub register_defaults { } } die "Huh?" unless @before_setop; - $self->clauses_of(select => @clauses); + $self->clauses_of(select => 'with', @clauses); $self->clause_expanders( 'select.group_by', sub { $_[0]->_expand_maybe_list_expr($_[1], -ident) @@ -115,6 +115,52 @@ sub register_defaults { })); }); } + $self->clause_expander('select.with' => my $with_expander = sub { + my ($self, $with) = @_; + if (ref($with) eq 'HASH') { + return +{ + %$with, + queries => [ map $self->expand_expr($_), @{$with->{queries}} ] + } + } + my @with = @$with; + my @exp; + while (my ($name, $query) = splice @with, 0, 2) { + my @n = map $self->expand_expr($_, -ident), + ref($name) eq 'ARRAY' ? @$name : $name; + push @exp, [ + \@n, + $self->expand_expr($query) + ]; + } + return +{ queries => \@exp }; + }); + $self->clause_expander('select.with_recursive' => sub { + my ($self, $with) = @_; + my $exp = $self->$with_expander($with); + return +{ + %$exp, + type => 'recursive' + }; + }); + $self->clause_renderer('select.with' => sub { + my ($self, $with) = @_; + my $q_part = [ $self->join_clauses(', ', + map { + my ($alias, $query) = @$_; + [ $self->join_clauses(' ', + [ $self->_render_alias($alias) ], + [ $self->format_keyword('as') ], + [ $self->render_aqt($query) ], + ) ] + } @{$with->{queries}} + ) ]; + return $self->join_clauses('', + [ $self->format_keyword(join '_', 'with', ($with->{type}||'')).' (' ], + $q_part, + [ ')' ], + ); + }); return $self; } @@ -208,23 +254,29 @@ sub _expand_op_as { sub _render_as { my ($self, $args) = @_; - my ($thing, $as, @cols) = @$args; + my ($thing, @alias) = @$args; return $self->join_clauses( ' ', [ $self->render_aqt($thing) ], [ $self->format_keyword('as') ], - (@cols - ? [ $self->join_clauses('', - [ $self->render_aqt($as) ], - [ '(' ], - [ $self->join_clauses( - ', ', - map [ $self->render_aqt($_) ], @cols - ) ], - [ ')' ], - ) ] - : [ $self->render_aqt($as) ] - ), + [ $self->_render_alias(\@alias) ], + ); +} + +sub _render_alias { + my ($self, $args) = @_; + my ($as, @cols) = @$args; + return (@cols + ? $self->join_clauses('', + [ $self->render_aqt($as) ], + [ '(' ], + [ $self->join_clauses( + ', ', + map [ $self->render_aqt($_) ], @cols + ) ], + [ ')' ], + ) + : $self->render_aqt($as) ); } diff --git a/xt/clauses.t b/xt/clauses.t index 66b971e..df6f2bf 100644 --- a/xt/clauses.t +++ b/xt/clauses.t @@ -186,4 +186,15 @@ is_same_sql( q{(SELECT * FROM foo) EXCEPT (SELECT * FROM foo_exclusions)}, ); +$sql = $sqlac->select({ + with => [ foo => { -select => { select => \1 } } ], + select => '*', + from => 'foo' +}); + +is_same_sql( + $sql, + q{WITH (foo AS (SELECT 1)) SELECT * FROM foo}, +); + done_testing;