make keyword-like subs optional exports from ExprDeclare
[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
0875b420 11our @EXPORT = qw(expr);
12
13our @EXPORT_OK = qw(
14 SELECT AS FROM BY JOIN ON LEFT WHERE ORDER GROUP DESC LIMIT OFFSET NULLS FIRST LAST
9f0ad8f6 15);
aad6ee1b 16
17sub expr (&) {
0875b420 18 _run_expr($_[0]);
aad6ee1b 19}
20
21sub _run_expr {
22 local $_ = Data::Query::ExprBuilder::Identifier->new({
23 expr => Identifier(),
24 });
25 $_[0]->();
26}
27
28sub _value {
4e0c6139 29 if ($_[0]->$_isa('Data::Query::ExprBuilder')) {
30 $_[0]->{expr};
31 } elsif (ref($_[0])) {
32 $_[0]
33 } else {
34 perl_scalar_value($_[0]);
35 }
aad6ee1b 36}
37
38sub AS {
39 my $as = shift;
40 (bless(\$as, 'LIES::AS'), @_);
41}
42
43sub SELECT (&;@) {
44 my @select = map _value($_), _run_expr(shift);
45 my @final;
46 while (@select) {
47 my $e = shift @select;
48 push @final,
49 (ref($select[0]) eq 'LIES::AS'
50 ? Alias(${shift(@select)}, $e)
51 : $e
52 );
53 }
54
d2773428 55 my $final = Select(\@final, shift);
56
57 if (is_Slice($_[0])) {
58 my ($limit, $offset) = @{+shift}{qw(limit offset)};
59 $final = Slice($offset, $limit, $final);
60 }
61
62 return $final;
aad6ee1b 63}
64
65sub BY (&;@) { @_ }
66
67sub FROM (&;@) {
68 my @from = _run_expr(shift);
69 my $from_dq = do {
70 if (@from == 2 and ref($from[1]) eq 'LIES::AS') {
71 Alias(${$from[1]}, _value($from[0]))
72 } elsif (@from == 1) {
73 _value($from[0]);
74 }
75 };
4e0c6139 76 while (is_Join($_[0])) {
aad6ee1b 77 $from_dq = { %{+shift}, left => $from_dq };
78 }
4e0c6139 79 if (is_Where($_[0])) {
9f0ad8f6 80 my $where = shift->{where};
81 if (is_Select($from_dq)) {
82 $from_dq = Select($from_dq->{select}, Where($where, $from_dq->{from}));
83 } else {
84 $from_dq = Where($where, $from_dq);
85 }
86 }
87 while (is_Order($_[0])) {
88 my $order = shift;
e3335558 89 $from_dq = Order($order->{by}, $order->{reverse}, $order->{nulls}, $from_dq);
4e0c6139 90 }
d2773428 91 return ($from_dq, @_);
aad6ee1b 92}
93
94sub LEFT {
95 my ($join, @rest) = @_;
96 die "LEFT used as modifier on non-join ${join}"
97 unless is_Join($join);
98 return +{ %$join, outer => 'LEFT' }, @rest;
99}
100
101sub JOIN (&;@) {
d2773428 102 my ($join) = FROM(\&{+shift});
aad6ee1b 103 my $on = do {
104 if ($_[0]->$_isa('LIES::ON')) {
105 ${+shift}
106 } else {
107 undef
108 }
109 };
110 Join(undef, $join, $on), @_;
111}
112
113sub ON (&;@) {
114 my $on = _value(_run_expr(shift));
115 return bless(\$on, 'LIES::ON'), @_;
116}
117
118sub WHERE (&;@) {
119 my $w = shift;
120 return Where(_value(_run_expr($w))), @_;
121}
122
9f0ad8f6 123sub DESC { bless({}, 'LIES::DESC'), @_ }
e3335558 124sub NULLS { bless(\shift, 'LIES::NULLS'), @_ }
125sub FIRST { 1, @_ }
126sub LAST { -1, @_ }
9f0ad8f6 127
128sub ORDER {
129 my @order = map _value($_), _run_expr(shift);
130 my $reverse = do {
131 if ($_[0]->$_isa('LIES::DESC')) {
132 shift; 1;
133 } else {
134 0;
135 }
136 };
e3335558 137 my $nulls = $_[0]->$_isa('LIES::NULLS') ? ${+shift} : undef;
138
139 return ((compose { Order($b, $reverse, $nulls, $a) } @order, undef), @_);
d2773428 140}
141
142sub LIMIT (&;@) {
143 my ($limit) = map _value($_), _run_expr(shift);
144 if (is_Slice($_[0])) {
145 my $slice = shift;
146 return +{ %{$slice}, limit => $limit }, @_;
147 }
148 return Slice(undef, $limit), @_;
149}
150
151sub OFFSET (&;@) {
152 my ($offset) = map _value($_), _run_expr(shift);
153 return Slice($offset, undef), @_;
9f0ad8f6 154}
155
aad6ee1b 1561;