_site/cover/pgsqlp_select.COVER.html

1 %% Copyright (c) 2023 Peter Morgan <peter.james.morgan@gmail.com>
2 %%
3 %% Licensed under the Apache License, Version 2.0 (the "License");
4 %% you may not use this file except in compliance with the License.
5 %% You may obtain a copy of the License at
6 %%
7 %% http://www.apache.org/licenses/LICENSE-2.0
8 %%
9 %% Unless required by applicable law or agreed to in writing, software
10 %% distributed under the License is distributed on an "AS IS" BASIS,
11 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 %% See the License for the specific language governing permissions and
13 %% limitations under the License.
14
15
16 -module(pgsqlp_select).
17
18
19 -feature(maybe_expr, enable).
20
21
22 -export([expression/0]).
23 -import(pgsqlp, [t/1]).
24 -import(pgsqlp, [to_atom/1]).
25 -import(scran_branch, [alt/1]).
26 -import(scran_character_complete, [multispace0/0]).
27 -import(scran_character_complete, [multispace1/0]).
28 -import(scran_character_complete, [re/1]).
29 -import(scran_character_complete, [re_no_case/1]).
30 -import(scran_character_complete, [tag/1]).
31 -import(scran_character_complete, [tag_no_case/1]).
32 -import(scran_combinator, [is_not/1]).
33 -import(scran_combinator, [map_parser/2]).
34 -import(scran_combinator, [opt/1]).
35 -import(scran_multi, [separated_list1/2]).
36 -import(scran_result, [kv/2]).
37 -import(scran_sequence, [delimited/3]).
38 -import(scran_sequence, [preceded/2]).
39 -import(scran_sequence, [sequence/1]).
40 -include_lib("kernel/include/logger.hrl").
41
42
43 %% SELECT pg_catalog.set_config('search_path', '', false);
44 expression() ->
45 18 fun
46 (Input) ->
47 24 (sequence(
48 [kv(action, to_atom(tag_no_case("SELECT"))),
49 opt(t(preceded(multispace1(),
50 alt([tag_no_case("DISTINCT"),
51 tag_no_case("ALL")])))),
52 opt(kv(output,
53 preceded(
54 multispace1(),
55 separated_list1(
56 sequence([multispace0(), tag(","), multispace0()]),
57 pgsqlp_scalar:expression())))),
58
59 opt(preceded(multispace1(), from())),
60 opt(preceded(multispace1(), where())),
61
62 opt(preceded(multispace1(), order_by()))]))(Input)
63 end.
64
65 preceded_by(First, Second) ->
66 3 fun
67 (Input) ->
68 3 (preceded(First, preceded(multispace1(), Second)))(Input)
69 end.
70
71 order_by() ->
72 24 fun
73 (Input) ->
74 3 (kv(?FUNCTION_NAME,
75 preceded_by(
76 tag_no_case("ORDER BY"),
77 pgsqlp_scalar:expression())))(Input)
78 end.
79
80 where() ->
81 24 fun
82 (Input) ->
83 13 (kv(?FUNCTION_NAME,
84 preceded(
85 tag_no_case("WHERE"),
86 preceded(
87 multispace1(),
88 pgsqlp_scalar:expression()))))(Input)
89 end.
90
91 from() ->
92 24 fun
93 (Input) ->
94 13 (kv(?FUNCTION_NAME,
95 preceded(
96 tag_no_case("FROM"),
97 preceded(
98 multispace1(),
99 separated_list1(
100 sequence([multispace0(),
101 tag(","),
102 multispace0()]),
103 from_item())))))(Input)
104 end.
105
106
107 from_item() ->
108 34 fun
109 (Input) ->
110 21 (kv(?FUNCTION_NAME,
111 alt([sequence(
112 [table_name(),
113 opt(
114 sequence(
115 [preceded(
116 multispace1(),
117 join_type()),
118 preceded(
119 multispace1(),
120 from_item()),
121 preceded(
122 multispace1(),
123 on())]))]),
124
125 sequence(
126 [opt(t(tag_no_case("LATERAL"))),
127 preceded(
128 multispace0(),
129 sequence(
130 [pgsqlp_scalar:function_call(),
131 opt(table_alias())]))])])))(Input)
132 end.
133
134 on() ->
135 21 fun
136 (Input) ->
137 5 (preceded(
138 tag_no_case("ON"),
139 preceded(
140 multispace1(),
141 delimited(
142 tag("("),
143 pgsqlp_scalar:expression(),
144 tag(")")))))(Input)
145 end.
146
147
148 join_type() ->
149 21 fun
150 (Input) ->
151 17 (kv(?FUNCTION_NAME,
152 alt([re_no_case("(INNER )?JOIN"),
153 re_no_case("LEFT (OUTER )?JOIN"),
154 re_no_case("RIGHT (OUTER )?JOIN"),
155 re_no_case("FULL (OUTER )?JOIN")])))(Input)
156 end.
157
158
159 table_name() ->
160 21 fun
161 (Input) ->
162 21 (sequence(
163 [kv(?FUNCTION_NAME,
164 separated_list1(
165 tag("."),
166 name())),
167 opt(table_alias())]))(Input)
168 end.
169
170
171 table_alias() ->
172 42 fun
173 (Input) ->
174 21 (kv(?FUNCTION_NAME,
175 preceded(
176 sequence(
177 [multispace1(),
178 opt(sequence(
179 [tag_no_case("AS"),
180 multispace1()]))]),
181 name())))(Input)
182 end.
183
184
185 name() ->
186 42 fun
187 (Input) ->
188 58 (map_parser(
189 re("[a-z_]+"),
190 is_not(pgsqlp:reserved())))(Input)
191 end.
Line Hits Source