X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FData%2FQuery%2FExprHelpers.pm;h=6020be6c3e74a7cd8cfaa6809e57a03d6afb6cc3;hb=5a0586236846b07ec90b3ea1e28f8a6f7c0fa8bf;hp=1ba349e84d7c4b78bf90388c2bfc7bc4ee8d4cbd;hpb=12e6eab8ff2e8bab91319d401dd2e984a5e781e5;p=dbsrgits%2FData-Query.git diff --git a/lib/Data/Query/ExprHelpers.pm b/lib/Data/Query/ExprHelpers.pm index 1ba349e..6020be6 100644 --- a/lib/Data/Query/ExprHelpers.pm +++ b/lib/Data/Query/ExprHelpers.pm @@ -1,17 +1,18 @@ package Data::Query::ExprHelpers; use strictures 1; -use Data::Query::Constants qw(DQ_VALUE DQ_OPERATOR); +use Data::Query::Constants; use base qw(Exporter); -our @EXPORT_OK = qw(perl_scalar_value perl_operator); +our @EXPORT = qw(perl_scalar_value perl_operator Literal Identifier compose); sub perl_scalar_value { +{ - type => DQ_VALUE, - subtype => { Perl => 'Scalar' }, - value => $_[0] + type => DQ_VALUE, + subtype => { Perl => 'Scalar' }, + value => $_[0], + $_[1] ? (value_meta => $_[1]) : () } } @@ -24,4 +25,95 @@ sub perl_operator { } } +my %map = ( + Join => [ qw(left right on outer) ], + Alias => [ qw(to from) ], + Operator => [ qw(operator args) ], + Select => [ qw(select from) ], + Where => [ qw(where from) ], + Order => [ qw(by reverse from) ], + Group => [ qw(by from) ], + Delete => [ qw(where target) ], + Update => [ qw(set where target) ], + Insert => [ qw(names values target returning) ], + Slice => [ qw(offset limit from) ], +); + +sub Literal { + my $subtype = shift; + if (ref($_[0])) { + return +{ + type => DQ_LITERAL, + subtype => $subtype, + parts => $_[0], + }; + } + return +{ + type => DQ_LITERAL, + subtype => $subtype, + literal => $_[0], + ($_[1] ? (values => $_[1]) : ()) + }; +} + +sub Identifier { + return +{ + type => DQ_IDENTIFIER, + elements => [ @_ ], + }; +} + +foreach my $name (values %Data::Query::Constants::CONST) { + no strict 'refs'; + my $sub = "is_${name}"; + *$sub = sub { + my $dq = $_[0]||$_; + $dq->{type} and $dq->{type} eq $name + }; + push @EXPORT, $sub; + if ($map{$name}) { + my @map = @{$map{$name}}; + *$name = sub { + my $dq = { type => $name }; + foreach (0..$#_) { + $dq->{$map[$_]} = $_[$_] if defined $_[$_]; + } + return $dq; + }; + push @EXPORT, $name; + } +} + +sub is_Having { is_Where($_[0]) and is_Group($_[0]->{from}) } + +push @EXPORT, 'is_Having'; + +sub compose (&@) { + my $code = shift; + require Scalar::Util; + my $type = Scalar::Util::reftype($code); + unless($type and $type eq 'CODE') { + require Carp; + Carp::croak("Not a subroutine reference"); + } + no strict 'refs'; + + return shift unless @_ > 1; + + use vars qw($a $b); + + my $caller = caller; + local(*{$caller."::a"}) = \my $a; + local(*{$caller."::b"}) = \my $b; + + $a = pop; + foreach (reverse @_) { + $b = $_; + $a = &{$code}(); + } + + $a; +} + + 1;