Commit | Line | Data |
aad6ee1b |
1 | package Data::Query::ExprDeclare; |
2 | |
3 | use strictures; |
4 | use Data::Query::ExprBuilder::Identifier; |
5 | use Data::Query::ExprHelpers; |
6 | use Data::Query::Constants; |
7 | use Safe::Isa; |
8 | |
9 | use base qw(Exporter); |
10 | |
9f0ad8f6 |
11 | our @EXPORT = qw( |
12 | expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC |
13 | ); |
aad6ee1b |
14 | |
15 | sub expr (&) { |
16 | _run_expr($_[0])->{expr}; |
17 | } |
18 | |
19 | sub _run_expr { |
20 | local $_ = Data::Query::ExprBuilder::Identifier->new({ |
21 | expr => Identifier(), |
22 | }); |
23 | $_[0]->(); |
24 | } |
25 | |
26 | sub _value { |
4e0c6139 |
27 | if ($_[0]->$_isa('Data::Query::ExprBuilder')) { |
28 | $_[0]->{expr}; |
29 | } elsif (ref($_[0])) { |
30 | $_[0] |
31 | } else { |
32 | perl_scalar_value($_[0]); |
33 | } |
aad6ee1b |
34 | } |
35 | |
36 | sub AS { |
37 | my $as = shift; |
38 | (bless(\$as, 'LIES::AS'), @_); |
39 | } |
40 | |
41 | sub SELECT (&;@) { |
42 | my @select = map _value($_), _run_expr(shift); |
43 | my @final; |
44 | while (@select) { |
45 | my $e = shift @select; |
46 | push @final, |
47 | (ref($select[0]) eq 'LIES::AS' |
48 | ? Alias(${shift(@select)}, $e) |
49 | : $e |
50 | ); |
51 | } |
52 | |
53 | return Select(\@final, $_[0]); |
54 | } |
55 | |
56 | sub BY (&;@) { @_ } |
57 | |
58 | sub FROM (&;@) { |
59 | my @from = _run_expr(shift); |
60 | my $from_dq = do { |
61 | if (@from == 2 and ref($from[1]) eq 'LIES::AS') { |
62 | Alias(${$from[1]}, _value($from[0])) |
63 | } elsif (@from == 1) { |
64 | _value($from[0]); |
65 | } |
66 | }; |
4e0c6139 |
67 | while (is_Join($_[0])) { |
aad6ee1b |
68 | $from_dq = { %{+shift}, left => $from_dq }; |
69 | } |
4e0c6139 |
70 | if (is_Where($_[0])) { |
9f0ad8f6 |
71 | my $where = shift->{where}; |
72 | if (is_Select($from_dq)) { |
73 | $from_dq = Select($from_dq->{select}, Where($where, $from_dq->{from})); |
74 | } else { |
75 | $from_dq = Where($where, $from_dq); |
76 | } |
77 | } |
78 | while (is_Order($_[0])) { |
79 | my $order = shift; |
80 | $from_dq = Order($order->{by}, $order->{reverse}, $from_dq); |
4e0c6139 |
81 | } |
aad6ee1b |
82 | return $from_dq; |
aad6ee1b |
83 | } |
84 | |
85 | sub LEFT { |
86 | my ($join, @rest) = @_; |
87 | die "LEFT used as modifier on non-join ${join}" |
88 | unless is_Join($join); |
89 | return +{ %$join, outer => 'LEFT' }, @rest; |
90 | } |
91 | |
92 | sub JOIN (&;@) { |
93 | my $join = FROM(\&{+shift}); |
94 | my $on = do { |
95 | if ($_[0]->$_isa('LIES::ON')) { |
96 | ${+shift} |
97 | } else { |
98 | undef |
99 | } |
100 | }; |
101 | Join(undef, $join, $on), @_; |
102 | } |
103 | |
104 | sub ON (&;@) { |
105 | my $on = _value(_run_expr(shift)); |
106 | return bless(\$on, 'LIES::ON'), @_; |
107 | } |
108 | |
109 | sub WHERE (&;@) { |
110 | my $w = shift; |
111 | return Where(_value(_run_expr($w))), @_; |
112 | } |
113 | |
9f0ad8f6 |
114 | sub DESC { bless({}, 'LIES::DESC'), @_ } |
115 | |
116 | sub ORDER { |
117 | my @order = map _value($_), _run_expr(shift); |
118 | my $reverse = do { |
119 | if ($_[0]->$_isa('LIES::DESC')) { |
120 | shift; 1; |
121 | } else { |
122 | 0; |
123 | } |
124 | }; |
125 | return compose { Order($b, $reverse, $a) } @order, undef; |
126 | } |
127 | |
aad6ee1b |
128 | 1; |