nested where nodes
[dbsrgits/Data-Query.git] / lib / Data / Query / ExprDeclare.pm
CommitLineData
aad6ee1b 1package Data::Query::ExprDeclare;
2
3use strictures;
4use Data::Query::ExprBuilder::Identifier;
5use Data::Query::ExprHelpers;
6use Data::Query::Constants;
7use Safe::Isa;
8
9use base qw(Exporter);
10
9f0ad8f6 11our @EXPORT = qw(
d2773428 12 expr SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC LIMIT OFFSET
9f0ad8f6 13);
aad6ee1b 14
15sub expr (&) {
16 _run_expr($_[0])->{expr};
17}
18
19sub _run_expr {
20 local $_ = Data::Query::ExprBuilder::Identifier->new({
21 expr => Identifier(),
22 });
23 $_[0]->();
24}
25
26sub _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
36sub AS {
37 my $as = shift;
38 (bless(\$as, 'LIES::AS'), @_);
39}
40
41sub 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
d2773428 53 my $final = Select(\@final, shift);
54
55 if (is_Slice($_[0])) {
56 my ($limit, $offset) = @{+shift}{qw(limit offset)};
57 $final = Slice($offset, $limit, $final);
58 }
59
60 return $final;
aad6ee1b 61}
62
63sub BY (&;@) { @_ }
64
65sub FROM (&;@) {
66 my @from = _run_expr(shift);
67 my $from_dq = do {
68 if (@from == 2 and ref($from[1]) eq 'LIES::AS') {
69 Alias(${$from[1]}, _value($from[0]))
70 } elsif (@from == 1) {
71 _value($from[0]);
72 }
73 };
4e0c6139 74 while (is_Join($_[0])) {
aad6ee1b 75 $from_dq = { %{+shift}, left => $from_dq };
76 }
4e0c6139 77 if (is_Where($_[0])) {
9f0ad8f6 78 my $where = shift->{where};
79 if (is_Select($from_dq)) {
80 $from_dq = Select($from_dq->{select}, Where($where, $from_dq->{from}));
81 } else {
82 $from_dq = Where($where, $from_dq);
83 }
84 }
85 while (is_Order($_[0])) {
86 my $order = shift;
87 $from_dq = Order($order->{by}, $order->{reverse}, $from_dq);
4e0c6139 88 }
d2773428 89 return ($from_dq, @_);
aad6ee1b 90}
91
92sub LEFT {
93 my ($join, @rest) = @_;
94 die "LEFT used as modifier on non-join ${join}"
95 unless is_Join($join);
96 return +{ %$join, outer => 'LEFT' }, @rest;
97}
98
99sub JOIN (&;@) {
d2773428 100 my ($join) = FROM(\&{+shift});
aad6ee1b 101 my $on = do {
102 if ($_[0]->$_isa('LIES::ON')) {
103 ${+shift}
104 } else {
105 undef
106 }
107 };
108 Join(undef, $join, $on), @_;
109}
110
111sub ON (&;@) {
112 my $on = _value(_run_expr(shift));
113 return bless(\$on, 'LIES::ON'), @_;
114}
115
116sub WHERE (&;@) {
117 my $w = shift;
118 return Where(_value(_run_expr($w))), @_;
119}
120
9f0ad8f6 121sub DESC { bless({}, 'LIES::DESC'), @_ }
122
123sub ORDER {
124 my @order = map _value($_), _run_expr(shift);
125 my $reverse = do {
126 if ($_[0]->$_isa('LIES::DESC')) {
127 shift; 1;
128 } else {
129 0;
130 }
131 };
d2773428 132 return ((compose { Order($b, $reverse, $a) } @order, undef), @_);
133}
134
135sub LIMIT (&;@) {
136 my ($limit) = map _value($_), _run_expr(shift);
137 if (is_Slice($_[0])) {
138 my $slice = shift;
139 return +{ %{$slice}, limit => $limit }, @_;
140 }
141 return Slice(undef, $limit), @_;
142}
143
144sub OFFSET (&;@) {
145 my ($offset) = map _value($_), _run_expr(shift);
146 return Slice($offset, undef), @_;
9f0ad8f6 147}
148
aad6ee1b 1491;