X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FAbstract%2FExtraClauses.pm;h=39e6f51103ae9f65c019ef42e4d702b336e120a9;hb=e67751dd9effc7f5066e264c1d6149613a7efa42;hp=cb64a5e395ba17764a0fca49cef10a9b69b55649;hpb=e90782e3e5e44cc2d65fe4ebdc14c1712152682f;p=scpubgit%2FQ-Branch.git diff --git a/lib/SQL/Abstract/ExtraClauses.pm b/lib/SQL/Abstract/ExtraClauses.pm index cb64a5e..39e6f51 100644 --- a/lib/SQL/Abstract/ExtraClauses.pm +++ b/lib/SQL/Abstract/ExtraClauses.pm @@ -17,9 +17,27 @@ sub cb { }; } +sub register { + my ($self, @pairs) = @_; + my $sqla = $self->sqla; + while (my ($method, $cases) = splice(@pairs, 0, 2)) { + my @cases = @$cases; + while (my ($name, $case) = splice(@cases, 0, 2)) { + $sqla->$method($name, $self->cb($case)); + } + } + return $self; +} + sub apply_to { my ($self, $sqla) = @_; $self = $self->new unless ref($self); + local $self->{sqla} = $sqla; + $self->register_extensions($sqla); +} + +sub register_extensions { + my ($self, $sqla) = @_; my @clauses = $sqla->clauses_of('select'); my @before_setop; CLAUSE: foreach my $idx (0..$#clauses) { @@ -31,20 +49,25 @@ sub apply_to { } die "Huh?" unless @before_setop; $sqla->clauses_of(select => 'with', @clauses); - $sqla->clause_expanders( - 'select.group_by', $self->cb(sub { - $_[0]->expand_maybe_list_expr($_[2], -ident) - }), - 'select.having', $self->cb(sub { $_[0]->expand_expr($_[2]) }), + $self->register( + clause_expanders => [ + 'select.group_by' + => sub { $_[0]->expand_maybe_list_expr($_[2], -ident) }, + 'select.having' + => sub { $_[0]->expand_expr($_[2]) }, + ], + (map +( + "${_}er" => [ + do { + my $x = $_; + (map +($_ => "_${x}_${_}"), qw(join from_list alias)) + } + ] + ), qw(expand render)), + binop_expander => [ as => '_expand_op_as' ], + renderer => [ as => '_render_as' ], + expander => [ cast => '_expand_cast' ], ); - foreach my $thing (qw(join from_list)) { - $sqla->expander($thing => $self->cb("_expand_${thing}")) - ->renderer($thing => $self->cb("_render_${thing}")) - } - $sqla->binop_expander(as => $self->cb('_expand_op_as')); - $sqla->renderer(as => $self->cb('_render_as')); - $sqla->expander(alias => $self->cb('_expand_alias')); - $sqla->renderer(alias => $self->cb('_render_alias')); $sqla->clauses_of(update => sub { my ($self, @clauses) = @_; @@ -105,8 +128,6 @@ sub apply_to { $sqla->clause_renderer("${stmt}.with" => $w_rdr); } - $sqla->expander(cast => $self->cb('_expand_cast')); - $sqla->clause_expanders( "select.from", $self->cb('_expand_from_list'), "update.target", $self->cb('_expand_update_clause_target'), @@ -337,3 +358,101 @@ sub _expand_clause_setop { } 1; + +__END__ + +=head1 NAME + +SQL::Abstract::ExtraClauses - new/experimental additions to L + +=head1 SYNOPSIS + + my $sqla = SQL::Abstract->new; + SQL::Abstract::ExtraClauses->apply_to($sqla); + +=head1 METHODS + +=head2 apply_to + +Applies the plugin to an L object. + +=head2 cb + +For plugin authors, creates a callback to call a method on the plugin. + +=head2 sqla + +Available only during plugin callback executions, contains the currently +active L object. + +=head1 NODE TYPES + +=head2 alias + +Represents a table alias. Expands name and column names with ident as default. + + # expr + { -alias => [ 't', 'x', 'y', 'z' ] } + + # aqt + { -alias => [ + { -ident => [ 't' ] }, { -ident => [ 'x' ] }, + { -ident => [ 'y' ] }, { -ident => [ 'z' ] }, + ] } + + # query + t(x, y, z) + [] + +=head2 as + +Represents an sql AS. LHS is expanded with ident as default, RHS is treated +as a list of arguments for the alias node. + + # expr + { foo => { -as => 'bar' } } + + # aqt + { -as => + [ + { -ident => [ 'foo' ] }, + { -alias => [ { -ident => [ 'bar' ] } ] }, + ] + } + + # query + foo AS bar + [] + + # expr + { -as => [ { -select => { _ => 'blah' } }, 't', 'blah' ] } + + # aqt + { -as => [ + { -select => + { select => { -op => [ ',', { -ident => [ 'blah' ] } ] } } + }, + { -alias => [ { -ident => [ 't' ] }, { -ident => [ 'blah' ] } ] }, + ] } + + # query + (SELECT blah) AS t(blah) + [] + +=head2 cast + + # expr + { -cast => [ { -ident => 'birthday' }, 'date' ] } + + # aqt + { -func => [ + 'cast', { + -as => [ { -ident => [ 'birthday' ] }, { -ident => [ 'date' ] } ] + }, + ] } + + # query + CAST(birthday AS date) + [] + +=cut