add compose routine and refactor FetchFirst to functional style
[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
9fcc2256 8our @EXPORT = qw(perl_scalar_value perl_operator Literal Identifier compose);
12e6eab8 9
10sub perl_scalar_value {
11 +{
9c8fc055 12 type => DQ_VALUE,
13 subtype => { Perl => 'Scalar' },
7f462f86 14 value => $_[0],
15 $_[1] ? (value_meta => $_[1]) : ()
12e6eab8 16 }
17}
18
19sub perl_operator {
20 my ($op, @args) = @_;
21 +{
22 type => DQ_OPERATOR,
23 operator => { Perl => $op },
24 args => \@args
25 }
26}
27
6b45ffe4 28my %map = (
29 Join => [ qw(left right on outer) ],
30 Alias => [ qw(to from) ],
31 Operator => [ qw(operator args) ],
32 Select => [ qw(select from) ],
33 Where => [ qw(where from) ],
34 Order => [ qw(by reverse from) ],
35 Group => [ qw(by from) ],
36 Delete => [ qw(where target) ],
37 Update => [ qw(set where target) ],
38 Insert => [ qw(names values target returning) ],
39 Slice => [ qw(offset limit from) ],
40);
41
42sub Literal {
43 if (ref($_[0])) {
44 return +{
45 type => DQ_LITERAL,
46 parts => @{$_[0]},
47 };
48 }
49 return +{
50 type => DQ_LITERAL,
51 literal => $_[0],
52 ($_[1] ? (values => $_[1]) : ())
53 };
54}
55
56sub Identifier {
57 return +{
9c8fc055 58 type => DQ_IDENTIFIER,
6b45ffe4 59 elements => [ @_ ],
60 };
61}
62
63foreach my $name (values %Data::Query::Constants::CONST) {
64 no strict 'refs';
65 my $sub = "is_${name}";
66 *$sub = sub {
67 my $dq = $_[0]||$_;
68 $dq->{type} eq $name
69 };
70 push @EXPORT, $sub;
71 if ($map{$name}) {
72 my @map = @{$map{$name}};
73 *$name = sub {
74 my $dq = { type => $name };
75 foreach (0..$#_) {
76 $dq->{$map[$_]} = $_[$_] if defined $_[$_];
77 }
78 return $dq;
79 };
80 push @EXPORT, $name;
9c8fc055 81 }
82}
83
9fcc2256 84sub compose (&@) {
85 my $code = shift;
86 require Scalar::Util;
87 my $type = Scalar::Util::reftype($code);
88 unless($type and $type eq 'CODE') {
89 require Carp;
90 Carp::croak("Not a subroutine reference");
91 }
92 no strict 'refs';
93
94 return shift unless @_ > 1;
95
96 use vars qw($a $b);
97
98 my $caller = caller;
99 local(*{$caller."::a"}) = \my $a;
100 local(*{$caller."::b"}) = \my $b;
101
102 $a = pop;
103 foreach (reverse @_) {
104 $b = $_;
105 $a = &{$code}();
106 }
107
108 $a;
109}
110
111
12e6eab8 1121;