add slice_subquery method for DBIC introspection
[dbsrgits/Data-Query.git] / lib / Data / Query / ExprHelpers.pm
CommitLineData
12e6eab8 1package Data::Query::ExprHelpers;
2
3use strictures 1;
6b45ffe4 4use Data::Query::Constants;
12e6eab8 5
6use base qw(Exporter);
7
bb5b7a0d 8our @EXPORT = qw(
9 perl_scalar_value perl_operator Literal Identifier compose intersperse
10);
11
12sub intersperse { my $i = shift; my @i = map +($_, $i), @_; pop @i; @i }
12e6eab8 13
14sub perl_scalar_value {
15 +{
9c8fc055 16 type => DQ_VALUE,
17 subtype => { Perl => 'Scalar' },
7f462f86 18 value => $_[0],
19 $_[1] ? (value_meta => $_[1]) : ()
12e6eab8 20 }
21}
22
23sub perl_operator {
24 my ($op, @args) = @_;
25 +{
26 type => DQ_OPERATOR,
27 operator => { Perl => $op },
28 args => \@args
29 }
30}
31
6b45ffe4 32my %map = (
33 Join => [ qw(left right on outer) ],
34 Alias => [ qw(to from) ],
35 Operator => [ qw(operator args) ],
36 Select => [ qw(select from) ],
37 Where => [ qw(where from) ],
e3335558 38 Order => [ qw(by reverse nulls from) ],
6b45ffe4 39 Group => [ qw(by from) ],
40 Delete => [ qw(where target) ],
41 Update => [ qw(set where target) ],
42 Insert => [ qw(names values target returning) ],
43 Slice => [ qw(offset limit from) ],
44);
45
46sub Literal {
af2d4155 47 my $subtype = shift;
6b45ffe4 48 if (ref($_[0])) {
49 return +{
50 type => DQ_LITERAL,
af2d4155 51 subtype => $subtype,
cc5ec83c 52 parts => $_[0],
6b45ffe4 53 };
54 }
55 return +{
56 type => DQ_LITERAL,
af2d4155 57 subtype => $subtype,
6b45ffe4 58 literal => $_[0],
59 ($_[1] ? (values => $_[1]) : ())
60 };
61}
62
63sub Identifier {
64 return +{
9c8fc055 65 type => DQ_IDENTIFIER,
6b45ffe4 66 elements => [ @_ ],
67 };
68}
69
70foreach my $name (values %Data::Query::Constants::CONST) {
71 no strict 'refs';
72 my $sub = "is_${name}";
73 *$sub = sub {
74 my $dq = $_[0]||$_;
5a058623 75 $dq->{type} and $dq->{type} eq $name
6b45ffe4 76 };
77 push @EXPORT, $sub;
abb46fd0 78 if (my @map = @{$map{$name}||[]}) {
6b45ffe4 79 *$name = sub {
80 my $dq = { type => $name };
abb46fd0 81 foreach (0..$#map) {
6b45ffe4 82 $dq->{$map[$_]} = $_[$_] if defined $_[$_];
83 }
abb46fd0 84
85 if (my $optional = $_[$#map+1]) {
86 unless(ref $optional eq 'HASH') {
87 require Carp;
88 Carp::croak("Not a hashreference");
89 }
90 @{$dq}{keys %$optional} = values %$optional;
91 }
92
6b45ffe4 93 return $dq;
94 };
95 push @EXPORT, $name;
9c8fc055 96 }
97}
98
5a058623 99sub is_Having { is_Where($_[0]) and is_Group($_[0]->{from}) }
100
101push @EXPORT, 'is_Having';
102
9fcc2256 103sub compose (&@) {
104 my $code = shift;
105 require Scalar::Util;
106 my $type = Scalar::Util::reftype($code);
107 unless($type and $type eq 'CODE') {
108 require Carp;
109 Carp::croak("Not a subroutine reference");
110 }
111 no strict 'refs';
112
113 return shift unless @_ > 1;
114
115 use vars qw($a $b);
116
117 my $caller = caller;
118 local(*{$caller."::a"}) = \my $a;
119 local(*{$caller."::b"}) = \my $b;
120
121 $a = pop;
122 foreach (reverse @_) {
123 $b = $_;
124 $a = &{$code}();
125 }
126
127 $a;
128}
129
130
12e6eab8 1311;