beginnings of declarative code
[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
11our @EXPORT = qw(expr SELECT AS FROM BY JOIN ON LEFT);
12
13sub expr (&) {
14 _run_expr($_[0])->{expr};
15}
16
17sub _run_expr {
18 local $_ = Data::Query::ExprBuilder::Identifier->new({
19 expr => Identifier(),
20 });
21 $_[0]->();
22}
23
24sub _value {
25 ref($_[0]) ? $_[0]->{expr} : perl_scalar_value($_[0])
26}
27
28sub AS {
29 my $as = shift;
30 (bless(\$as, 'LIES::AS'), @_);
31}
32
33sub SELECT (&;@) {
34 my @select = map _value($_), _run_expr(shift);
35 my @final;
36 while (@select) {
37 my $e = shift @select;
38 push @final,
39 (ref($select[0]) eq 'LIES::AS'
40 ? Alias(${shift(@select)}, $e)
41 : $e
42 );
43 }
44
45 return Select(\@final, $_[0]);
46}
47
48sub BY (&;@) { @_ }
49
50sub FROM (&;@) {
51 my @from = _run_expr(shift);
52 my $from_dq = do {
53 if (@from == 2 and ref($from[1]) eq 'LIES::AS') {
54 Alias(${$from[1]}, _value($from[0]))
55 } elsif (@from == 1) {
56 _value($from[0]);
57 }
58 };
59 while ($_[0] and is_Join($_[0])) {
60 $from_dq = { %{+shift}, left => $from_dq };
61 }
62 return $from_dq;
63 die "Huh?"
64}
65
66sub LEFT {
67 my ($join, @rest) = @_;
68 die "LEFT used as modifier on non-join ${join}"
69 unless is_Join($join);
70 return +{ %$join, outer => 'LEFT' }, @rest;
71}
72
73sub JOIN (&;@) {
74 my $join = FROM(\&{+shift});
75 my $on = do {
76 if ($_[0]->$_isa('LIES::ON')) {
77 ${+shift}
78 } else {
79 undef
80 }
81 };
82 Join(undef, $join, $on), @_;
83}
84
85sub ON (&;@) {
86 my $on = _value(_run_expr(shift));
87 return bless(\$on, 'LIES::ON'), @_;
88}
89
90sub WHERE (&;@) {
91 my $w = shift;
92 return Where(_value(_run_expr($w))), @_;
93}
94
951;