arel_toolkit 0.4.3 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/coverage.yml +48 -0
- data/.github/workflows/test.yml +68 -0
- data/.gitignore +3 -1
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/.tool-versions +1 -0
- data/Appraisals +4 -0
- data/CHANGELOG.md +49 -3
- data/Gemfile.lock +134 -84
- data/README.md +20 -3
- data/arel_toolkit.gemspec +3 -5
- data/bin/console +2 -1
- data/bin/setup +23 -2
- data/docker-compose.yml +11 -0
- data/gemfiles/active_record_6.gemfile +3 -3
- data/gemfiles/active_record_6.gemfile.lock +9 -7
- data/gemfiles/active_record_6_1.gemfile +7 -0
- data/gemfiles/active_record_6_1.gemfile.lock +263 -0
- data/gemfiles/arel_gems.gemfile.lock +9 -7
- data/gemfiles/default.gemfile.lock +9 -7
- data/lib/arel/enhance/context_enhancer/arel_table.rb +20 -0
- data/lib/arel/enhance/node.rb +20 -12
- data/lib/arel/enhance/visitor.rb +1 -1
- data/lib/arel/enhance.rb +2 -2
- data/lib/arel/extensions/conflict.rb +3 -3
- data/lib/arel/extensions/delete_statement.rb +19 -14
- data/lib/arel/extensions/infer.rb +2 -2
- data/lib/arel/extensions/insert_statement.rb +3 -3
- data/lib/arel/extensions/overlaps.rb +7 -1
- data/lib/arel/extensions/table.rb +7 -2
- data/lib/arel/extensions/transaction.rb +9 -9
- data/lib/arel/extensions/tree_manager.rb +0 -5
- data/lib/arel/extensions/update_statement.rb +8 -22
- data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +37 -5
- data/lib/arel/sql_to_arel/pg_query_visitor.rb +430 -521
- data/lib/arel/transformer/prefix_schema_name.rb +5 -3
- data/lib/arel/transformer.rb +0 -1
- data/lib/arel_toolkit/version.rb +1 -1
- metadata +15 -12
- data/.github/workflows/develop.yml +0 -90
- data/.github/workflows/master.yml +0 -67
- data/lib/arel/transformer/remove_active_record_info.rb +0 -40
@@ -2,8 +2,6 @@
|
|
2
2
|
# rubocop:disable Naming/MethodName
|
3
3
|
# rubocop:disable Metrics/CyclomaticComplexity
|
4
4
|
# rubocop:disable Metrics/AbcSize
|
5
|
-
# rubocop:disable Naming/UncommunicativeMethodParamName
|
6
|
-
# rubocop:disable Metrics/ParameterLists
|
7
5
|
|
8
6
|
require 'pg_query'
|
9
7
|
require_relative './pg_query_visitor/frame_options'
|
@@ -25,7 +23,7 @@ module Arel
|
|
25
23
|
@binds = binds
|
26
24
|
@sql = sql
|
27
25
|
|
28
|
-
Result.new visit(object, :top)
|
26
|
+
Result.new visit(object.stmts, :top)
|
29
27
|
rescue ::PgQuery::ParseError => e
|
30
28
|
new_error = ::PgQuery::ParseError.new(e.message, __FILE__, __LINE__, -1)
|
31
29
|
raise new_error, e.message, e.backtrace
|
@@ -37,58 +35,55 @@ module Arel
|
|
37
35
|
|
38
36
|
private
|
39
37
|
|
40
|
-
def visit_A_ArrayExpr(
|
41
|
-
Arel::Nodes::Array.new visit(elements)
|
38
|
+
def visit_A_ArrayExpr(attribute)
|
39
|
+
Arel::Nodes::Array.new visit(attribute.elements)
|
42
40
|
end
|
43
41
|
|
44
|
-
def visit_A_Const(
|
45
|
-
visit(val, :const)
|
42
|
+
def visit_A_Const(attribute)
|
43
|
+
visit(attribute.val, :const)
|
46
44
|
end
|
47
45
|
|
48
|
-
def visit_A_Expr(
|
49
|
-
case kind
|
50
|
-
when
|
51
|
-
left = visit(lexpr) if lexpr
|
52
|
-
right = visit(rexpr) if rexpr
|
53
|
-
operator = visit(name[0], :operator)
|
46
|
+
def visit_A_Expr(attribute)
|
47
|
+
case attribute.kind
|
48
|
+
when :AEXPR_OP
|
49
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
50
|
+
right = visit(attribute.rexpr) if attribute.rexpr
|
51
|
+
operator = visit(attribute.name[0], :operator)
|
54
52
|
generate_operator(left, right, operator)
|
55
53
|
|
56
|
-
when
|
57
|
-
left = visit(lexpr)
|
58
|
-
right = visit(rexpr)
|
54
|
+
when :AEXPR_OP_ANY
|
55
|
+
left = visit(attribute.lexpr)
|
56
|
+
right = visit(attribute.rexpr)
|
59
57
|
right = Arel::Nodes::Any.new right
|
60
|
-
operator = visit(name[0], :operator)
|
58
|
+
operator = visit(attribute.name[0], :operator)
|
61
59
|
generate_operator(left, right, operator)
|
62
60
|
|
63
|
-
when
|
64
|
-
left = visit(lexpr)
|
65
|
-
right = visit(rexpr)
|
61
|
+
when :AEXPR_OP_ALL
|
62
|
+
left = visit(attribute.lexpr)
|
63
|
+
right = visit(attribute.rexpr)
|
66
64
|
right = Arel::Nodes::All.new right
|
67
|
-
operator = visit(name[0], :operator)
|
65
|
+
operator = visit(attribute.name[0], :operator)
|
68
66
|
generate_operator(left, right, operator)
|
69
67
|
|
70
|
-
when
|
71
|
-
left = visit(lexpr)
|
72
|
-
right = visit(rexpr)
|
68
|
+
when :AEXPR_DISTINCT
|
69
|
+
left = visit(attribute.lexpr)
|
70
|
+
right = visit(attribute.rexpr)
|
73
71
|
Arel::Nodes::DistinctFrom.new(left, right)
|
74
72
|
|
75
|
-
when
|
76
|
-
left = visit(lexpr)
|
77
|
-
right = visit(rexpr)
|
73
|
+
when :AEXPR_NOT_DISTINCT
|
74
|
+
left = visit(attribute.lexpr)
|
75
|
+
right = visit(attribute.rexpr)
|
78
76
|
Arel::Nodes::NotDistinctFrom.new(left, right)
|
79
77
|
|
80
|
-
when
|
81
|
-
left = visit(lexpr)
|
82
|
-
right = visit(rexpr)
|
78
|
+
when :AEXPR_NULLIF
|
79
|
+
left = visit(attribute.lexpr)
|
80
|
+
right = visit(attribute.rexpr)
|
83
81
|
Arel::Nodes::NullIf.new(left, right)
|
84
82
|
|
85
|
-
when
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
left = visit(lexpr)
|
90
|
-
right = visit(rexpr)
|
91
|
-
operator = visit(name[0], :operator)
|
83
|
+
when :AEXPR_IN
|
84
|
+
left = visit(attribute.lexpr)
|
85
|
+
right = visit(attribute.rexpr)
|
86
|
+
operator = visit(attribute.name[0], :operator)
|
92
87
|
|
93
88
|
if operator == '<>'
|
94
89
|
Arel::Nodes::NotIn.new(left, right)
|
@@ -96,28 +91,9 @@ module Arel
|
|
96
91
|
Arel::Nodes::In.new(left, right)
|
97
92
|
end
|
98
93
|
|
99
|
-
when
|
100
|
-
left = visit(lexpr) if lexpr
|
101
|
-
right = visit(rexpr)
|
102
|
-
escape = nil
|
103
|
-
|
104
|
-
if right.is_a?(Array)
|
105
|
-
boom "Don't know how to handle length `#{right.length}`" if right.length != 2
|
106
|
-
|
107
|
-
right, escape = right
|
108
|
-
end
|
109
|
-
|
110
|
-
operator = visit(name[0], :operator)
|
111
|
-
|
112
|
-
if operator == '~~'
|
113
|
-
Arel::Nodes::Matches.new(left, right, escape, true)
|
114
|
-
else
|
115
|
-
Arel::Nodes::DoesNotMatch.new(left, right, escape, true)
|
116
|
-
end
|
117
|
-
|
118
|
-
when PgQuery::AEXPR_ILIKE
|
119
|
-
left = visit(lexpr) if lexpr
|
120
|
-
right = visit(rexpr)
|
94
|
+
when :AEXPR_LIKE, :AEXPR_ILIKE
|
95
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
96
|
+
right = visit(attribute.rexpr)
|
121
97
|
escape = nil
|
122
98
|
|
123
99
|
if right.is_a?(Array)
|
@@ -126,27 +102,21 @@ module Arel
|
|
126
102
|
right, escape = right
|
127
103
|
end
|
128
104
|
|
129
|
-
operator = visit(name[0], :operator)
|
105
|
+
operator = visit(attribute.name[0], :operator)
|
130
106
|
|
131
|
-
if
|
132
|
-
Arel::Nodes::Matches.new(left, right, escape,
|
107
|
+
if %w[~~ ~~*].include?(operator)
|
108
|
+
Arel::Nodes::Matches.new(left, right, escape, attribute.kind == :AEXPR_LIKE)
|
133
109
|
else
|
134
|
-
Arel::Nodes::DoesNotMatch.new(left, right, escape,
|
110
|
+
Arel::Nodes::DoesNotMatch.new(left, right, escape, attribute.kind == :AEXPR_LIKE)
|
135
111
|
end
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
right = visit(rexpr)
|
112
|
+
when :AEXPR_SIMILAR
|
113
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
114
|
+
right = visit(attribute.rexpr)
|
140
115
|
escape = nil
|
141
116
|
|
142
|
-
if right.is_a?(Array)
|
143
|
-
boom "Don't know how to handle length `#{right.length}`" if right.length != 2
|
144
|
-
|
145
|
-
right, escape = right
|
146
|
-
end
|
117
|
+
right, escape = right if right.is_a?(Array)
|
147
118
|
|
148
|
-
|
149
|
-
operator = visit(name[0], :operator)
|
119
|
+
operator = visit(attribute.name[0], :operator)
|
150
120
|
|
151
121
|
if operator == '~'
|
152
122
|
Arel::Nodes::Similar.new(left, right, escape)
|
@@ -154,67 +124,69 @@ module Arel
|
|
154
124
|
Arel::Nodes::NotSimilar.new(left, right, escape)
|
155
125
|
end
|
156
126
|
|
157
|
-
when
|
158
|
-
left = visit(lexpr) if lexpr
|
159
|
-
right = visit(rexpr)
|
127
|
+
when :AEXPR_BETWEEN
|
128
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
129
|
+
right = visit(attribute.rexpr)
|
160
130
|
Arel::Nodes::Between.new left, Arel::Nodes::And.new(right)
|
161
131
|
|
162
|
-
when
|
163
|
-
left = visit(lexpr) if lexpr
|
164
|
-
right = visit(rexpr)
|
132
|
+
when :AEXPR_NOT_BETWEEN
|
133
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
134
|
+
right = visit(attribute.rexpr)
|
165
135
|
Arel::Nodes::NotBetween.new left, Arel::Nodes::And.new(right)
|
166
136
|
|
167
|
-
when
|
168
|
-
left = visit(lexpr) if lexpr
|
169
|
-
right = visit(rexpr)
|
137
|
+
when :AEXPR_BETWEEN_SYM
|
138
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
139
|
+
right = visit(attribute.rexpr)
|
170
140
|
Arel::Nodes::BetweenSymmetric.new left, Arel::Nodes::And.new(right)
|
171
141
|
|
172
|
-
when
|
173
|
-
left = visit(lexpr) if lexpr
|
174
|
-
right = visit(rexpr)
|
142
|
+
when :AEXPR_NOT_BETWEEN_SYM
|
143
|
+
left = visit(attribute.lexpr) if attribute.lexpr
|
144
|
+
right = visit(attribute.rexpr)
|
175
145
|
Arel::Nodes::NotBetweenSymmetric.new left, Arel::Nodes::And.new(right)
|
176
146
|
|
177
|
-
when PgQuery::AEXPR_PAREN
|
178
|
-
boom 'https://github.com/mvgijssel/arel_toolkit/issues/35'
|
179
|
-
|
180
147
|
else
|
181
|
-
boom "Unknown Expr type `#{kind}`"
|
148
|
+
boom "Unknown Expr type `#{attribute.kind}`"
|
182
149
|
end
|
183
150
|
end
|
184
151
|
|
185
|
-
def visit_A_Indices(
|
186
|
-
visit uidx, context
|
152
|
+
def visit_A_Indices(attribute, context)
|
153
|
+
visit attribute.uidx, context
|
187
154
|
end
|
188
155
|
|
189
|
-
def visit_A_Indirection(
|
190
|
-
Arel::Nodes::Indirection.new(visit(arg), visit(indirection, :operator))
|
156
|
+
def visit_A_Indirection(attribute)
|
157
|
+
Arel::Nodes::Indirection.new(visit(attribute.arg), visit(attribute.indirection, :operator))
|
191
158
|
end
|
192
159
|
|
193
|
-
def visit_A_Star
|
160
|
+
def visit_A_Star(_attribute)
|
194
161
|
Arel.star
|
195
162
|
end
|
196
163
|
|
197
|
-
def visit_Alias(
|
198
|
-
|
164
|
+
def visit_Alias(attribute)
|
165
|
+
aliasname = if attribute.respond_to?(:aliasname)
|
166
|
+
attribute.aliasname
|
167
|
+
elsif attribute.is_a?(Hash)
|
168
|
+
attribute[:aliasname]
|
169
|
+
end
|
170
|
+
|
171
|
+
return if aliasname.nil?
|
172
|
+
|
173
|
+
Arel.sql visit_String(aliasname, nil)
|
199
174
|
end
|
200
175
|
|
201
|
-
def visit_BitString(
|
202
|
-
Arel::Nodes::BitString.new(str)
|
176
|
+
def visit_BitString(attribute)
|
177
|
+
Arel::Nodes::BitString.new(attribute.str)
|
203
178
|
end
|
204
179
|
|
205
|
-
def visit_BoolExpr(context = false
|
206
|
-
args = visit(args, context || true)
|
180
|
+
def visit_BoolExpr(attribute, context = false)
|
181
|
+
args = visit(attribute.args, context || true)
|
207
182
|
|
208
|
-
result = case boolop
|
209
|
-
when
|
183
|
+
result = case attribute.boolop
|
184
|
+
when :AND_EXPR
|
210
185
|
Arel::Nodes::And.new(args)
|
211
|
-
|
212
|
-
when PgQuery::BOOL_EXPR_OR
|
186
|
+
when :OR_EXPR
|
213
187
|
generate_boolean_expression(args, Arel::Nodes::Or)
|
214
|
-
|
215
|
-
when PgQuery::BOOL_EXPR_NOT
|
188
|
+
when :NOT_EXPR
|
216
189
|
Arel::Nodes::Not.new(args)
|
217
|
-
|
218
190
|
else
|
219
191
|
boom "? Boolop -> #{boolop}"
|
220
192
|
end
|
@@ -226,62 +198,56 @@ module Arel
|
|
226
198
|
end
|
227
199
|
end
|
228
200
|
|
229
|
-
def visit_BooleanTest(
|
230
|
-
arg = visit(arg)
|
201
|
+
def visit_BooleanTest(attribute)
|
202
|
+
arg = visit(attribute.arg)
|
231
203
|
|
232
|
-
case booltesttype
|
233
|
-
when
|
204
|
+
case attribute.booltesttype
|
205
|
+
when :IS_TRUE
|
234
206
|
Arel::Nodes::Equality.new(arg, Arel::Nodes::True.new)
|
235
|
-
|
236
|
-
when PgQuery::BOOLEAN_TEST_NOT_TRUE
|
207
|
+
when :IS_NOT_TRUE
|
237
208
|
Arel::Nodes::NotEqual.new(arg, Arel::Nodes::True.new)
|
238
|
-
|
239
|
-
when PgQuery::BOOLEAN_TEST_FALSE
|
209
|
+
when :IS_FALSE
|
240
210
|
Arel::Nodes::Equality.new(arg, Arel::Nodes::False.new)
|
241
|
-
|
242
|
-
when PgQuery::BOOLEAN_TEST_NOT_FALSE
|
211
|
+
when :IS_NOT_FALSE
|
243
212
|
Arel::Nodes::NotEqual.new(arg, Arel::Nodes::False.new)
|
244
|
-
|
245
|
-
when PgQuery::BOOLEAN_TEST_UNKNOWN
|
213
|
+
when :IS_UNKNOWN
|
246
214
|
Arel::Nodes::Equality.new(arg, Arel::Nodes::Unknown.new)
|
247
|
-
|
248
|
-
when PgQuery::BOOLEAN_TEST_NOT_UNKNOWN
|
215
|
+
when :IS_NOT_UNKNOWN
|
249
216
|
Arel::Nodes::NotEqual.new(arg, Arel::Nodes::Unknown.new)
|
250
|
-
|
251
217
|
else
|
252
218
|
boom '?'
|
253
219
|
end
|
254
220
|
end
|
255
221
|
|
256
|
-
def visit_CaseExpr(
|
222
|
+
def visit_CaseExpr(attribute)
|
257
223
|
Arel::Nodes::Case.new.tap do |kees|
|
258
|
-
kees.case = visit(arg) if arg
|
224
|
+
kees.case = visit(attribute.arg) if attribute.arg
|
259
225
|
|
260
|
-
kees.conditions = visit args
|
226
|
+
kees.conditions = visit attribute.args
|
261
227
|
|
262
|
-
if defresult
|
263
|
-
default_result = visit(defresult, :sql)
|
228
|
+
if attribute.defresult
|
229
|
+
default_result = visit(attribute.defresult, :sql)
|
264
230
|
|
265
231
|
kees.default = Arel::Nodes::Else.new default_result
|
266
232
|
end
|
267
233
|
end
|
268
234
|
end
|
269
235
|
|
270
|
-
def visit_CaseWhen(
|
271
|
-
expr = visit(expr)
|
272
|
-
result = visit(result)
|
236
|
+
def visit_CaseWhen(attribute)
|
237
|
+
expr = visit(attribute.expr)
|
238
|
+
result = visit(attribute.result)
|
273
239
|
|
274
240
|
Arel::Nodes::When.new(expr, result)
|
275
241
|
end
|
276
242
|
|
277
|
-
def visit_CoalesceExpr(
|
278
|
-
args = visit(args)
|
243
|
+
def visit_CoalesceExpr(attribute)
|
244
|
+
args = visit(attribute.args)
|
279
245
|
|
280
246
|
Arel::Nodes::Coalesce.new args
|
281
247
|
end
|
282
248
|
|
283
|
-
def visit_ColumnRef(
|
284
|
-
fields = fields.reverse
|
249
|
+
def visit_ColumnRef(attribute)
|
250
|
+
fields = attribute.fields.reverse
|
285
251
|
column = visit(fields[0], :operator)
|
286
252
|
table = visit(fields[1], :operator) if fields[1]
|
287
253
|
schema_name = visit(fields[2], :operator) if fields[2]
|
@@ -297,130 +263,101 @@ module Arel
|
|
297
263
|
Arel::Nodes::UnqualifiedColumn.new Arel::Attribute.new(nil, column)
|
298
264
|
end
|
299
265
|
|
300
|
-
def visit_CommonTableExpr(
|
301
|
-
cte_table = Arel::Table.new(ctename)
|
302
|
-
cte_definition = visit(ctequery)
|
266
|
+
def visit_CommonTableExpr(attribute)
|
267
|
+
cte_table = Arel::Table.new(attribute.ctename)
|
268
|
+
cte_definition = visit(attribute.ctequery)
|
303
269
|
Arel::Nodes::As.new(cte_table, Arel::Nodes::Grouping.new(cte_definition))
|
304
270
|
end
|
305
271
|
|
306
|
-
def visit_CurrentOfExpr(
|
307
|
-
Arel::Nodes::CurrentOfExpression.new(cursor_name)
|
272
|
+
def visit_CurrentOfExpr(attribute)
|
273
|
+
Arel::Nodes::CurrentOfExpression.new(attribute.cursor_name)
|
274
|
+
end
|
275
|
+
|
276
|
+
def visit_DeallocateStmt(attribute)
|
277
|
+
Arel::Nodes::Dealocate.new attribute.name.presence
|
308
278
|
end
|
309
279
|
|
310
|
-
def visit_DefElem(
|
311
|
-
case defname
|
280
|
+
def visit_DefElem(attribute)
|
281
|
+
case attribute.defname
|
312
282
|
when 'savepoint_name'
|
313
|
-
visit(arg)
|
283
|
+
visit(attribute.arg)
|
314
284
|
else
|
315
|
-
boom "Unknown defname `#{defname}` with defaction `#{defaction}`"
|
285
|
+
boom "Unknown defname `#{attribute.defname}` with defaction `#{attribute.defaction}`"
|
316
286
|
end
|
317
287
|
end
|
318
288
|
|
319
|
-
def visit_DeleteStmt(
|
320
|
-
relation
|
321
|
-
using_clause: nil,
|
322
|
-
where_clause: nil,
|
323
|
-
returning_list: [],
|
324
|
-
with_clause: nil
|
325
|
-
)
|
326
|
-
relation = visit(relation)
|
289
|
+
def visit_DeleteStmt(attribute)
|
290
|
+
relation = visit(attribute.relation)
|
327
291
|
|
328
292
|
delete_manager = Arel::DeleteManager.new
|
329
293
|
delete_statement = delete_manager.ast
|
330
294
|
delete_statement.relation = relation
|
331
|
-
delete_statement.using = visit(using_clause) if using_clause
|
332
|
-
delete_statement.wheres = where_clause ? [visit(where_clause)] : []
|
333
|
-
delete_statement.with = visit(with_clause) if with_clause
|
334
|
-
delete_statement.returning = visit(returning_list, :select)
|
295
|
+
delete_statement.using = visit(attribute.using_clause) if attribute.using_clause
|
296
|
+
delete_statement.wheres = attribute.where_clause ? [visit(attribute.where_clause)] : []
|
297
|
+
delete_statement.with = visit(attribute.with_clause) if attribute.with_clause
|
298
|
+
delete_statement.returning = visit(attribute.returning_list, :select)
|
335
299
|
delete_manager
|
336
300
|
end
|
337
301
|
|
338
|
-
def visit_Float(
|
339
|
-
Arel::Nodes::SqlLiteral.new str
|
302
|
+
def visit_Float(attribute)
|
303
|
+
Arel::Nodes::SqlLiteral.new attribute.str
|
340
304
|
end
|
341
305
|
|
342
306
|
# https://github.com/postgres/postgres/blob/REL_10_1/src/include/nodes/parsenodes.h
|
343
|
-
def visit_FuncCall(
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
agg_filter: nil,
|
348
|
-
agg_within_group: nil,
|
349
|
-
agg_star: nil,
|
350
|
-
agg_distinct: nil,
|
351
|
-
func_variadic: nil,
|
352
|
-
over: nil
|
353
|
-
)
|
354
|
-
args = if args
|
355
|
-
visit args
|
356
|
-
elsif agg_star
|
307
|
+
def visit_FuncCall(attribute)
|
308
|
+
args = if attribute.args.present?
|
309
|
+
visit attribute.args
|
310
|
+
elsif attribute.agg_star
|
357
311
|
[Arel.star]
|
358
312
|
else
|
359
313
|
[]
|
360
314
|
end
|
361
315
|
|
362
|
-
function_names = visit(funcname, :operator)
|
316
|
+
function_names = visit(attribute.funcname, :operator)
|
363
317
|
|
364
318
|
func = case function_names
|
365
319
|
when ['sum']
|
366
320
|
Arel::Nodes::Sum.new args
|
367
|
-
|
368
321
|
when ['count']
|
369
322
|
Arel::Nodes::Count.new args
|
370
|
-
|
371
323
|
when ['max']
|
372
324
|
Arel::Nodes::Max.new args
|
373
|
-
|
374
325
|
when ['min']
|
375
326
|
Arel::Nodes::Min.new args
|
376
|
-
|
377
327
|
when ['avg']
|
378
328
|
Arel::Nodes::Avg.new args
|
379
|
-
|
380
329
|
when [PG_CATALOG, 'like_escape']
|
381
330
|
args
|
382
|
-
|
383
|
-
when [PG_CATALOG, 'similar_escape']
|
331
|
+
when [PG_CATALOG, 'similar_to_escape']
|
384
332
|
args
|
385
|
-
|
386
333
|
when [PG_CATALOG, 'date_part']
|
387
334
|
field, expression = args
|
388
335
|
[Arel::Nodes::ExtractFrom.new(expression, field)]
|
389
|
-
|
390
336
|
when [PG_CATALOG, 'timezone']
|
391
337
|
timezone, expression = args
|
392
|
-
|
393
338
|
[Arel::Nodes::AtTimeZone.new(maybe_add_grouping(expression), timezone)]
|
394
|
-
|
395
339
|
# https://www.postgresql.org/docs/10/functions-string.html
|
396
340
|
when [PG_CATALOG, 'position']
|
397
341
|
string, substring = args
|
398
342
|
[Arel::Nodes::Position.new(substring, string)]
|
399
|
-
|
400
343
|
when [PG_CATALOG, 'overlay']
|
401
344
|
string, substring, start, length = args
|
402
345
|
[Arel::Nodes::Overlay.new(string, substring, start, length)]
|
403
|
-
|
404
346
|
when [PG_CATALOG, 'ltrim']
|
405
347
|
string, substring = args
|
406
348
|
[Arel::Nodes::Trim.new('leading', substring, string)]
|
407
|
-
|
408
349
|
when [PG_CATALOG, 'rtrim']
|
409
350
|
string, substring = args
|
410
351
|
[Arel::Nodes::Trim.new('trailing', substring, string)]
|
411
|
-
|
412
352
|
when [PG_CATALOG, 'btrim']
|
413
353
|
string, substring = args
|
414
354
|
[Arel::Nodes::Trim.new('both', substring, string)]
|
415
|
-
|
416
355
|
when [PG_CATALOG, 'substring']
|
417
356
|
string, pattern, escape = args
|
418
357
|
[Arel::Nodes::Substring.new(string, pattern, escape)]
|
419
|
-
|
420
358
|
when [PG_CATALOG, 'overlaps']
|
421
359
|
start1, end1, start2, end2 = args
|
422
360
|
[Arel::Nodes::Overlaps.new(start1, end1, start2, end2)]
|
423
|
-
|
424
361
|
else
|
425
362
|
case function_names.length
|
426
363
|
when 2
|
@@ -434,99 +371,99 @@ module Arel
|
|
434
371
|
end
|
435
372
|
end
|
436
373
|
|
437
|
-
func.distinct =
|
438
|
-
func.orders = (agg_order ? visit(agg_order) : []) unless
|
439
|
-
|
440
|
-
func.
|
441
|
-
|
374
|
+
func.distinct = attribute.agg_distinct unless func.is_a?(::Array)
|
375
|
+
func.orders = (attribute.agg_order ? visit(attribute.agg_order) : []) unless
|
376
|
+
func.is_a?(::Array)
|
377
|
+
func.filter = (attribute.agg_filter ? visit(attribute.agg_filter) : nil) unless
|
378
|
+
func.is_a?(::Array)
|
379
|
+
func.within_group = attribute.agg_within_group unless func.is_a?(::Array)
|
380
|
+
func.variardic = attribute.func_variadic unless func.is_a?(::Array)
|
442
381
|
|
443
|
-
if over
|
444
|
-
Arel::Nodes::Over.new(func, visit(over))
|
382
|
+
if attribute.over
|
383
|
+
Arel::Nodes::Over.new(func, visit(attribute.over))
|
445
384
|
else
|
446
385
|
func
|
447
386
|
end
|
448
387
|
end
|
449
388
|
|
450
|
-
def visit_InferClause(
|
451
|
-
left = Arel.sql(conname) if conname
|
452
|
-
right = visit(index_elems) if index_elems
|
389
|
+
def visit_InferClause(attribute)
|
390
|
+
left = Arel.sql(attribute.conname) if attribute.conname
|
391
|
+
right = visit(attribute.index_elems) if attribute.index_elems.present?
|
453
392
|
Arel::Nodes::Infer.new left, right
|
454
393
|
end
|
455
394
|
|
456
|
-
def visit_IndexElem(
|
457
|
-
boom "Unknown ordering `#{ordering}`" unless ordering
|
458
|
-
boom "Unknown nulls ordering `#{
|
395
|
+
def visit_IndexElem(attribute)
|
396
|
+
boom "Unknown ordering `#{attribute.ordering}`" unless attribute.ordering == :SORTBY_DEFAULT
|
397
|
+
boom "Unknown nulls ordering `#{attribute.nulls_ordering}`" unless
|
398
|
+
attribute.nulls_ordering == :SORTBY_NULLS_DEFAULT
|
459
399
|
|
460
|
-
Arel.sql visit_String(
|
400
|
+
Arel.sql visit_String(attribute.name)
|
461
401
|
end
|
462
402
|
|
463
|
-
def visit_InsertStmt(
|
464
|
-
relation
|
465
|
-
cols:
|
466
|
-
select_stmt: nil,
|
467
|
-
on_conflict_clause: nil,
|
468
|
-
with_clause: nil,
|
469
|
-
returning_list: [],
|
470
|
-
override:
|
471
|
-
)
|
472
|
-
relation = visit(relation)
|
473
|
-
cols = visit(cols, :insert).map do |col|
|
403
|
+
def visit_InsertStmt(attribute)
|
404
|
+
relation = visit(attribute.relation)
|
405
|
+
cols = visit(attribute.cols, :insert).map do |col|
|
474
406
|
Arel::Attribute.new(relation, col)
|
475
407
|
end
|
476
|
-
select_stmt = visit(select_stmt) if select_stmt
|
477
408
|
|
478
409
|
insert_manager = Arel::InsertManager.new
|
479
410
|
insert_statement = insert_manager.ast
|
480
411
|
insert_statement.relation = relation
|
481
412
|
insert_statement.columns = cols
|
482
|
-
insert_statement.override = override
|
483
|
-
insert_statement.with = visit(with_clause) if with_clause
|
484
|
-
|
485
|
-
if select_stmt
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
413
|
+
insert_statement.override = attribute.override
|
414
|
+
insert_statement.with = visit(attribute.with_clause) if attribute.with_clause
|
415
|
+
|
416
|
+
insert_statement.values = if attribute.select_stmt.present?
|
417
|
+
select_stmt = visit(attribute.select_stmt)
|
418
|
+
insert_statement.values = select_stmt.values_lists if
|
419
|
+
select_stmt.present?
|
420
|
+
else
|
421
|
+
insert_statement.values = Arel::Nodes::DefaultValues.new
|
422
|
+
end
|
423
|
+
|
424
|
+
insert_statement.returning = visit(attribute.returning_list, :select)
|
425
|
+
insert_statement.conflict = visit(attribute.on_conflict_clause) if
|
426
|
+
attribute.on_conflict_clause
|
493
427
|
insert_manager
|
494
428
|
end
|
495
429
|
|
496
|
-
def visit_Integer(
|
497
|
-
ival
|
430
|
+
def visit_Integer(attribute)
|
431
|
+
attribute.ival
|
498
432
|
end
|
499
433
|
|
500
|
-
def visit_IntoClause(
|
501
|
-
raise "Unknown on_commit `#{on_commit}`" unless
|
434
|
+
def visit_IntoClause(attribute)
|
435
|
+
raise "Unknown on_commit `#{attribute.on_commit}`" unless
|
436
|
+
attribute.on_commit == :ONCOMMIT_NOOP
|
502
437
|
|
503
|
-
Arel::Nodes::Into.new(visit(rel))
|
438
|
+
Arel::Nodes::Into.new(visit(attribute.rel))
|
504
439
|
end
|
505
440
|
|
506
|
-
def visit_JoinExpr(
|
507
|
-
join_class = case jointype
|
508
|
-
when
|
509
|
-
if is_natural
|
441
|
+
def visit_JoinExpr(attribute)
|
442
|
+
join_class = case attribute.jointype
|
443
|
+
when :JOIN_INNER
|
444
|
+
if attribute.is_natural
|
510
445
|
Arel::Nodes::NaturalJoin
|
511
|
-
elsif quals.nil?
|
446
|
+
elsif attribute.quals.nil?
|
512
447
|
Arel::Nodes::CrossJoin
|
513
448
|
else
|
514
449
|
Arel::Nodes::InnerJoin
|
515
450
|
end
|
516
|
-
when
|
451
|
+
when :JOIN_LEFT
|
517
452
|
Arel::Nodes::OuterJoin
|
518
|
-
when
|
453
|
+
when :JOIN_FULL
|
519
454
|
Arel::Nodes::FullOuterJoin
|
520
|
-
when
|
455
|
+
when :JOIN_RIGHT
|
521
456
|
Arel::Nodes::RightOuterJoin
|
522
457
|
end
|
523
458
|
|
524
|
-
larg = visit(larg)
|
525
|
-
rarg = visit(rarg)
|
526
|
-
|
527
|
-
quals = Arel::Nodes::On.new visit(quals) if quals
|
459
|
+
larg = visit(attribute.larg)
|
460
|
+
rarg = visit(attribute.rarg)
|
528
461
|
|
529
|
-
join =
|
462
|
+
join = if attribute.quals
|
463
|
+
join_class.new(rarg, Arel::Nodes::On.new(visit(attribute.quals)))
|
464
|
+
else
|
465
|
+
join_class.new(rarg, nil)
|
466
|
+
end
|
530
467
|
|
531
468
|
if larg.is_a?(Array)
|
532
469
|
larg.concat([join])
|
@@ -535,128 +472,136 @@ module Arel
|
|
535
472
|
end
|
536
473
|
end
|
537
474
|
|
538
|
-
def visit_LockingClause(
|
475
|
+
def visit_LockingClause(attribute)
|
539
476
|
strength_clause = {
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
}.fetch(strength)
|
477
|
+
LCS_FORKEYSHARE: 'FOR KEY SHARE',
|
478
|
+
LCS_FORSHARE: 'FOR SHARE',
|
479
|
+
LCS_FORNOKEYUPDATE: 'FOR NO KEY UPDATE',
|
480
|
+
LCS_FORUPDATE: 'FOR UPDATE',
|
481
|
+
}.fetch(attribute.strength)
|
545
482
|
wait_policy_clause = {
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
}.fetch(wait_policy)
|
483
|
+
LockWaitBlock: '',
|
484
|
+
LockWaitSkip: ' SKIP LOCKED',
|
485
|
+
LockWaitError: ' NOWAIT',
|
486
|
+
}.fetch(attribute.wait_policy)
|
550
487
|
|
551
488
|
Arel::Nodes::Lock.new Arel.sql("#{strength_clause}#{wait_policy_clause}")
|
552
489
|
end
|
553
490
|
|
554
|
-
def visit_MinMaxExpr(
|
555
|
-
case op
|
556
|
-
when
|
557
|
-
Arel::Nodes::Greatest.new visit(args)
|
558
|
-
when
|
559
|
-
Arel::Nodes::Least.new visit(args)
|
491
|
+
def visit_MinMaxExpr(attribute)
|
492
|
+
case attribute.op
|
493
|
+
when :IS_GREATEST
|
494
|
+
Arel::Nodes::Greatest.new visit(attribute.args)
|
495
|
+
when :IS_LEAST
|
496
|
+
Arel::Nodes::Least.new visit(attribute.args)
|
560
497
|
else
|
561
|
-
boom "Unknown Op -> #{op}"
|
498
|
+
boom "Unknown Op -> #{attribute.op}"
|
562
499
|
end
|
563
500
|
end
|
564
501
|
|
565
|
-
def visit_NamedArgExpr(
|
566
|
-
arg = visit(arg)
|
567
|
-
boom '' unless argnumber == -1
|
502
|
+
def visit_NamedArgExpr(attribute)
|
503
|
+
arg = visit(attribute.arg)
|
504
|
+
boom '' unless attribute.argnumber == -1
|
505
|
+
|
506
|
+
Arel::Nodes::NamedArgument.new(attribute.name, arg)
|
507
|
+
end
|
508
|
+
|
509
|
+
def visit_Node(attribute, context = nil)
|
510
|
+
return attribute.list.items.map { |item| visit_Node(item, context) } if
|
511
|
+
attribute.node == :list
|
568
512
|
|
569
|
-
|
513
|
+
visit(attribute[attribute.node.to_s], context)
|
570
514
|
end
|
571
515
|
|
572
|
-
def visit_Null(
|
516
|
+
def visit_Null(_attribute)
|
573
517
|
Arel.sql 'NULL'
|
574
518
|
end
|
575
519
|
|
576
|
-
def visit_NullTest(
|
577
|
-
arg = visit(arg)
|
520
|
+
def visit_NullTest(attribute)
|
521
|
+
arg = visit(attribute.arg)
|
578
522
|
|
579
|
-
case nulltesttype
|
580
|
-
when
|
523
|
+
case attribute.nulltesttype
|
524
|
+
when :IS_NULL
|
581
525
|
Arel::Nodes::Equality.new(arg, nil)
|
582
|
-
when
|
526
|
+
when :IS_NOT_NULL
|
583
527
|
Arel::Nodes::NotEqual.new(arg, nil)
|
584
528
|
end
|
585
529
|
end
|
586
530
|
|
587
|
-
def visit_OnConflictClause(
|
531
|
+
def visit_OnConflictClause(attribute)
|
588
532
|
conflict = Arel::Nodes::Conflict.new
|
589
|
-
conflict.action = action
|
590
|
-
conflict.infer = visit(infer) if infer
|
591
|
-
conflict.values = target_list ? visit(target_list, :update) : []
|
592
|
-
conflict.wheres = where_clause ? [visit(where_clause)] : []
|
533
|
+
conflict.action = attribute.action
|
534
|
+
conflict.infer = visit(attribute.infer) if attribute.infer
|
535
|
+
conflict.values = attribute.target_list ? visit(attribute.target_list, :update) : []
|
536
|
+
conflict.wheres = attribute.where_clause ? [visit(attribute.where_clause)] : []
|
593
537
|
conflict
|
594
538
|
end
|
595
539
|
|
596
|
-
def visit_ParamRef(
|
597
|
-
value = (binds[number - 1] unless binds.empty?)
|
540
|
+
def visit_ParamRef(attribute)
|
541
|
+
value = (binds[attribute.number - 1] unless binds.empty?)
|
598
542
|
|
599
543
|
Arel::Nodes::BindParam.new(value)
|
600
544
|
end
|
601
545
|
|
602
|
-
def
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
546
|
+
def visit_PrepareStmt(attribute)
|
547
|
+
Arel::Nodes::Prepare.new(
|
548
|
+
attribute.name,
|
549
|
+
attribute.argtypes.present? && visit(attribute.argtypes),
|
550
|
+
visit(attribute.query),
|
551
|
+
)
|
552
|
+
end
|
553
|
+
|
554
|
+
def visit_RangeFunction(attribute)
|
555
|
+
functions = attribute.functions.map do |function_array|
|
556
|
+
function, _empty_node = function_array.list.items
|
612
557
|
|
613
558
|
visit(function)
|
614
559
|
end
|
615
560
|
|
616
|
-
node = Arel::Nodes::RangeFunction.new functions, is_rowsfrom: is_rowsfrom
|
617
|
-
node = lateral ? Arel::Nodes::Lateral.new(node) : node
|
618
|
-
node = ordinality ? Arel::Nodes::WithOrdinality.new(node) : node
|
619
|
-
|
561
|
+
node = Arel::Nodes::RangeFunction.new functions, is_rowsfrom: attribute.is_rowsfrom
|
562
|
+
node = attribute.lateral ? Arel::Nodes::Lateral.new(node) : node
|
563
|
+
node = attribute.ordinality ? Arel::Nodes::WithOrdinality.new(node) : node
|
564
|
+
attribute.alias.nil? ? node : Arel::Nodes::As.new(node, visit(attribute.alias))
|
620
565
|
end
|
621
566
|
|
622
|
-
def visit_RangeSubselect(
|
623
|
-
aliaz = visit(
|
624
|
-
subquery = visit(subquery)
|
567
|
+
def visit_RangeSubselect(attribute)
|
568
|
+
aliaz = visit(attribute.alias)
|
569
|
+
subquery = visit(attribute.subquery)
|
625
570
|
node = Arel::Nodes::As.new(Arel::Nodes::Grouping.new(subquery), aliaz)
|
626
|
-
lateral ? Arel::Nodes::Lateral.new(node) : node
|
571
|
+
attribute.lateral ? Arel::Nodes::Lateral.new(node) : node
|
627
572
|
end
|
628
573
|
|
629
|
-
def visit_RangeVar(
|
574
|
+
def visit_RangeVar(attribute)
|
630
575
|
Arel::Table.new(
|
631
|
-
relname,
|
632
|
-
as: (visit(
|
633
|
-
only: !inh,
|
634
|
-
relpersistence: relpersistence,
|
635
|
-
schema_name: schemaname,
|
576
|
+
attribute.relname,
|
577
|
+
as: (visit(attribute.alias) if attribute.alias),
|
578
|
+
only: !attribute.inh,
|
579
|
+
relpersistence: attribute.relpersistence,
|
580
|
+
schema_name: attribute.schemaname.blank? ? nil : attribute.schemaname,
|
636
581
|
)
|
637
582
|
end
|
638
583
|
|
639
|
-
def visit_RawStmt(
|
640
|
-
visit(
|
584
|
+
def visit_RawStmt(attribute, context)
|
585
|
+
visit(attribute.stmt, context)
|
641
586
|
end
|
642
587
|
|
643
|
-
def visit_ResTarget(
|
588
|
+
def visit_ResTarget(attribute, context)
|
644
589
|
case context
|
645
590
|
when :select
|
646
|
-
val = visit(val)
|
591
|
+
val = visit(attribute.val)
|
647
592
|
|
648
|
-
if name
|
649
|
-
aliaz = visit_Alias(aliasname: name)
|
650
|
-
Arel::Nodes::As.new(val, aliaz)
|
651
|
-
else
|
593
|
+
if attribute.name.blank?
|
652
594
|
val
|
595
|
+
else
|
596
|
+
aliaz = visit_Alias(aliasname: attribute.name)
|
597
|
+
Arel::Nodes::As.new(val, aliaz)
|
653
598
|
end
|
654
599
|
when :insert
|
655
|
-
name
|
600
|
+
attribute.name
|
656
601
|
when :update
|
657
602
|
relation = nil
|
658
|
-
column = Arel::Attribute.new(relation, name)
|
659
|
-
value = visit(val)
|
603
|
+
column = Arel::Attribute.new(relation, attribute.name)
|
604
|
+
value = visit(attribute.val)
|
660
605
|
|
661
606
|
Nodes::Assignment.new(Nodes::UnqualifiedColumn.new(column), value)
|
662
607
|
else
|
@@ -664,36 +609,16 @@ module Arel
|
|
664
609
|
end
|
665
610
|
end
|
666
611
|
|
667
|
-
def visit_RowExpr(
|
668
|
-
Arel::Nodes::Row.new(visit(args), row_format)
|
669
|
-
end
|
670
|
-
|
671
|
-
def visit_SelectStmt(
|
672
|
-
context = nil,
|
673
|
-
from_clause: nil,
|
674
|
-
limit_count: nil,
|
675
|
-
target_list: nil,
|
676
|
-
sort_clause: nil,
|
677
|
-
where_clause: nil,
|
678
|
-
limit_offset: nil,
|
679
|
-
distinct_clause: nil,
|
680
|
-
group_clause: nil,
|
681
|
-
having_clause: nil,
|
682
|
-
with_clause: nil,
|
683
|
-
locking_clause: nil,
|
684
|
-
op:,
|
685
|
-
window_clause: nil,
|
686
|
-
values_lists: nil,
|
687
|
-
into_clause: nil,
|
688
|
-
all: nil,
|
689
|
-
larg: nil,
|
690
|
-
rarg: nil
|
691
|
-
)
|
612
|
+
def visit_RowExpr(attribute)
|
613
|
+
Arel::Nodes::Row.new(visit(attribute.args), attribute.row_format)
|
614
|
+
end
|
615
|
+
|
616
|
+
def visit_SelectStmt(attribute, context = nil)
|
692
617
|
select_manager = Arel::SelectManager.new
|
693
618
|
select_core = select_manager.ast.cores.last
|
694
619
|
select_statement = select_manager.ast
|
695
620
|
|
696
|
-
froms, join_sources = generate_sources(from_clause)
|
621
|
+
froms, join_sources = generate_sources(attribute.from_clause)
|
697
622
|
if froms
|
698
623
|
froms = froms.first if froms.length == 1
|
699
624
|
select_core.froms = froms
|
@@ -702,10 +627,10 @@ module Arel
|
|
702
627
|
select_core.from = froms if froms
|
703
628
|
select_core.source.right = join_sources
|
704
629
|
|
705
|
-
select_core.projections = visit(target_list, :select) if target_list
|
630
|
+
select_core.projections = visit(attribute.target_list, :select) if attribute.target_list
|
706
631
|
|
707
|
-
if where_clause
|
708
|
-
where_clause = visit(where_clause)
|
632
|
+
if attribute.where_clause
|
633
|
+
where_clause = visit(attribute.where_clause, :select)
|
709
634
|
where_clause = if where_clause.is_a?(Arel::Nodes::And)
|
710
635
|
where_clause
|
711
636
|
else
|
@@ -715,29 +640,42 @@ module Arel
|
|
715
640
|
select_core.wheres = [where_clause]
|
716
641
|
end
|
717
642
|
|
718
|
-
select_core.groups = visit(group_clause) if group_clause
|
719
|
-
select_core.havings = [visit(having_clause)] if having_clause
|
720
|
-
select_core.windows = visit(window_clause) if window_clause
|
721
|
-
select_core.into = visit(into_clause) if into_clause
|
722
|
-
select_core.top = ::Arel::Nodes::Top.new visit(limit_count) if
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
|
727
|
-
|
728
|
-
|
643
|
+
select_core.groups = visit(attribute.group_clause) if attribute.group_clause
|
644
|
+
select_core.havings = [visit(attribute.having_clause)] if attribute.having_clause
|
645
|
+
select_core.windows = visit(attribute.window_clause) if attribute.window_clause
|
646
|
+
select_core.into = visit(attribute.into_clause) if attribute.into_clause
|
647
|
+
select_core.top = ::Arel::Nodes::Top.new visit(attribute.limit_count) if
|
648
|
+
attribute.limit_count
|
649
|
+
|
650
|
+
if attribute.distinct_clause == []
|
651
|
+
select_core.set_quantifier = nil
|
652
|
+
elsif attribute.distinct_clause.is_a?(Google::Protobuf::RepeatedField)
|
653
|
+
select_core.set_quantifier = if attribute.distinct_clause.size == 1 &&
|
654
|
+
attribute.distinct_clause.first.to_h.compact.length.zero?
|
655
|
+
Arel::Nodes::Distinct.new
|
656
|
+
else
|
657
|
+
Arel::Nodes::DistinctOn.new(
|
658
|
+
visit(attribute.distinct_clause),
|
659
|
+
)
|
660
|
+
end
|
661
|
+
elsif attribute.distinct_clause.nil?
|
729
662
|
select_core.set_quantifier = nil
|
730
663
|
else
|
731
|
-
boom "Unknown distinct clause `#{distinct_clause}`"
|
664
|
+
boom "Unknown distinct clause `#{attribute.distinct_clause}`"
|
732
665
|
end
|
733
666
|
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
667
|
+
if attribute.limit_count
|
668
|
+
select_statement.limit = ::Arel::Nodes::Limit.new visit(attribute.limit_count)
|
669
|
+
end
|
670
|
+
if attribute.limit_offset
|
671
|
+
select_statement.offset = ::Arel::Nodes::Offset.new visit(attribute.limit_offset)
|
672
|
+
end
|
673
|
+
select_statement.orders = visit(attribute.sort_clause.to_a)
|
674
|
+
select_statement.with = visit(attribute.with_clause) if attribute.with_clause
|
675
|
+
select_statement.lock = visit(attribute.locking_clause) if attribute.locking_clause.present?
|
676
|
+
|
677
|
+
if attribute.values_lists.present?
|
678
|
+
values_lists = visit(attribute.values_lists).map do |values_list|
|
741
679
|
values_list.map do |value|
|
742
680
|
case value
|
743
681
|
when String
|
@@ -758,30 +696,30 @@ module Arel
|
|
758
696
|
select_statement.values_lists = Arel::Nodes::ValuesList.new(values_lists)
|
759
697
|
end
|
760
698
|
|
761
|
-
union = case op
|
762
|
-
when
|
699
|
+
union = case attribute.op
|
700
|
+
when :SET_OPERATION_UNDEFINED, :SETOP_NONE
|
763
701
|
nil
|
764
|
-
when
|
765
|
-
if all
|
766
|
-
Arel::Nodes::UnionAll.new(visit(larg), visit(rarg))
|
702
|
+
when :SETOP_UNION
|
703
|
+
if attribute.all
|
704
|
+
Arel::Nodes::UnionAll.new(visit(attribute.larg), visit(attribute.rarg))
|
767
705
|
else
|
768
|
-
Arel::Nodes::Union.new(visit(larg), visit(rarg))
|
706
|
+
Arel::Nodes::Union.new(visit(attribute.larg), visit(attribute.rarg))
|
769
707
|
end
|
770
|
-
when
|
771
|
-
if all
|
772
|
-
Arel::Nodes::IntersectAll.new(visit(larg), visit(rarg))
|
708
|
+
when :SETOP_INTERSECT
|
709
|
+
if attribute.all
|
710
|
+
Arel::Nodes::IntersectAll.new(visit(attribute.larg), visit(attribute.rarg))
|
773
711
|
else
|
774
|
-
Arel::Nodes::Intersect.new(visit(larg), visit(rarg))
|
712
|
+
Arel::Nodes::Intersect.new(visit(attribute.larg), visit(attribute.rarg))
|
775
713
|
end
|
776
|
-
when
|
777
|
-
if all
|
778
|
-
Arel::Nodes::ExceptAll.new(visit(larg), visit(rarg))
|
714
|
+
when :SETOP_EXCEPT
|
715
|
+
if attribute.all
|
716
|
+
Arel::Nodes::ExceptAll.new(visit(attribute.larg), visit(attribute.rarg))
|
779
717
|
else
|
780
|
-
Arel::Nodes::Except.new(visit(larg), visit(rarg))
|
718
|
+
Arel::Nodes::Except.new(visit(attribute.larg), visit(attribute.rarg))
|
781
719
|
end
|
782
720
|
else
|
783
721
|
# https://www.postgresql.org/docs/10/queries-union.html
|
784
|
-
boom "Unknown combining queries op `#{op}`"
|
722
|
+
boom "Unknown combining queries op `#{attribute.op}`"
|
785
723
|
end
|
786
724
|
|
787
725
|
unless union.nil?
|
@@ -800,88 +738,96 @@ module Arel
|
|
800
738
|
Arel::Nodes::SetToDefault.new
|
801
739
|
end
|
802
740
|
|
803
|
-
def visit_SortBy(
|
804
|
-
result = visit(node)
|
805
|
-
case sortby_dir
|
806
|
-
when
|
807
|
-
Arel::Nodes::Ascending.new(
|
808
|
-
|
809
|
-
|
741
|
+
def visit_SortBy(attribute)
|
742
|
+
result = visit(attribute.node)
|
743
|
+
case attribute.sortby_dir
|
744
|
+
when :SORTBY_ASC
|
745
|
+
Arel::Nodes::Ascending.new(
|
746
|
+
result,
|
747
|
+
PgQuery::SortByNulls.descriptor.to_h[attribute.sortby_nulls] - 1,
|
748
|
+
)
|
749
|
+
when :SORTBY_DESC
|
750
|
+
Arel::Nodes::Descending.new(
|
751
|
+
result,
|
752
|
+
PgQuery::SortByNulls.descriptor.to_h[attribute.sortby_nulls] - 1,
|
753
|
+
)
|
810
754
|
else
|
811
755
|
result
|
812
756
|
end
|
813
757
|
end
|
814
758
|
|
815
|
-
def visit_SQLValueFunction(
|
816
|
-
|
817
|
-
-> { Arel::Nodes::CurrentDate.new },
|
818
|
-
-> { Arel::Nodes::CurrentTime.new },
|
819
|
-
-> { Arel::Nodes::CurrentTime.new(precision: typmod) },
|
820
|
-
-> { Arel::Nodes::CurrentTimestamp.new },
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
-> { Arel::Nodes::
|
825
|
-
-> { Arel::Nodes::
|
826
|
-
-> { Arel::Nodes::
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
-> { Arel::Nodes::
|
831
|
-
-> { Arel::Nodes::
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
759
|
+
def visit_SQLValueFunction(attribute)
|
760
|
+
{
|
761
|
+
SVFOP_CURRENT_DATE: -> { Arel::Nodes::CurrentDate.new },
|
762
|
+
SVFOP_CURRENT_TIME: -> { Arel::Nodes::CurrentTime.new },
|
763
|
+
SVFOP_CURRENT_TIME_N: -> { Arel::Nodes::CurrentTime.new(precision: attribute.typmod) },
|
764
|
+
SVFOP_CURRENT_TIMESTAMP: -> { Arel::Nodes::CurrentTimestamp.new },
|
765
|
+
SVFOP_CURRENT_TIMESTAMP_N: lambda {
|
766
|
+
Arel::Nodes::CurrentTimestamp.new(precision: attribute.typmod)
|
767
|
+
},
|
768
|
+
SVFOP_LOCALTIME: -> { Arel::Nodes::LocalTime.new },
|
769
|
+
SVFOP_LOCALTIME_N: -> { Arel::Nodes::LocalTime.new(precision: attribute.typmod) },
|
770
|
+
SVFOP_LOCALTIMESTAMP: -> { Arel::Nodes::LocalTimestamp.new },
|
771
|
+
SVFOP_LOCALTIMESTAMP_N: lambda {
|
772
|
+
Arel::Nodes::LocalTimestamp.new(precision: attribute.typmod)
|
773
|
+
},
|
774
|
+
SVFOP_CURRENT_ROLE: -> { Arel::Nodes::CurrentRole.new },
|
775
|
+
SVFOP_CURRENT_USER: -> { Arel::Nodes::CurrentUser.new },
|
776
|
+
SVFOP_USER: -> { Arel::Nodes::User.new },
|
777
|
+
SVFOP_SESSION_USER: -> { Arel::Nodes::SessionUser.new },
|
778
|
+
SVFOP_CURRENT_CATALOG: -> { Arel::Nodes::CurrentCatalog.new },
|
779
|
+
SVFOP_CURRENT_SCHEMA: -> { Arel::Nodes::CurrentSchema.new },
|
780
|
+
}[attribute.op].call
|
781
|
+
end
|
782
|
+
|
783
|
+
def visit_String(attribute, context = nil)
|
836
784
|
case context
|
837
785
|
when :operator
|
838
|
-
str
|
786
|
+
attribute.str
|
839
787
|
when :const
|
840
|
-
Arel::Nodes.build_quoted str
|
788
|
+
Arel::Nodes.build_quoted attribute.str
|
841
789
|
else
|
842
|
-
"\"#{
|
790
|
+
"\"#{attribute}\""
|
843
791
|
end
|
844
792
|
end
|
845
793
|
|
846
|
-
def visit_SubLink(
|
847
|
-
subselect = visit(subselect)
|
848
|
-
testexpr = visit(testexpr) if testexpr
|
849
|
-
operator = if oper_name
|
850
|
-
operator = visit(oper_name, :operator)
|
851
|
-
if operator.length > 1
|
852
|
-
boom 'https://github.com/mvgijssel/arel_toolkit/issues/39'
|
853
|
-
end
|
794
|
+
def visit_SubLink(attribute)
|
795
|
+
subselect = visit(attribute.subselect)
|
796
|
+
testexpr = visit(attribute.testexpr) if attribute.testexpr
|
797
|
+
operator = if attribute.oper_name
|
798
|
+
operator = visit(attribute.oper_name, :operator)
|
799
|
+
boom 'Unable to handle operator length > 1' if operator.length > 1
|
854
800
|
|
855
801
|
operator.first
|
856
802
|
end
|
857
803
|
|
858
|
-
generate_sublink(sub_link_type, subselect, testexpr, operator)
|
804
|
+
generate_sublink(attribute.sub_link_type, subselect, testexpr, operator)
|
859
805
|
end
|
860
806
|
|
861
|
-
def visit_TransactionStmt(
|
807
|
+
def visit_TransactionStmt(attribute)
|
862
808
|
Arel::Nodes::Transaction.new(
|
863
|
-
kind,
|
864
|
-
(
|
809
|
+
PgQuery::TransactionStmtKind.descriptor.to_h[attribute.kind],
|
810
|
+
visit_String(attribute.savepoint_name),
|
865
811
|
)
|
866
812
|
end
|
867
813
|
|
868
|
-
def visit_TypeCast(
|
869
|
-
arg = visit(arg)
|
870
|
-
type_name = visit(type_name)
|
814
|
+
def visit_TypeCast(attribute)
|
815
|
+
arg = visit(attribute.arg)
|
816
|
+
type_name = visit(attribute.type_name)
|
871
817
|
|
872
818
|
Arel::Nodes::TypeCast.new(maybe_add_grouping(arg), type_name)
|
873
819
|
end
|
874
820
|
|
875
|
-
def visit_TypeName(
|
876
|
-
array_bounds = visit(array_bounds)
|
821
|
+
def visit_TypeName(attribute)
|
822
|
+
array_bounds = visit(attribute.array_bounds)
|
877
823
|
|
878
|
-
names = names.map do |name|
|
824
|
+
names = attribute.names.map do |name|
|
879
825
|
visit(name, :operator)
|
880
826
|
end
|
881
827
|
|
882
828
|
names = names.reject { |name| name == PG_CATALOG }
|
883
829
|
|
884
|
-
boom 'https://github.com/mvgijssel/arel_toolkit/issues/40' if typemod != -1
|
830
|
+
boom 'https://github.com/mvgijssel/arel_toolkit/issues/40' if attribute.typemod != -1
|
885
831
|
boom 'https://github.com/mvgijssel/arel_toolkit/issues/41' if names.length > 1
|
886
832
|
if array_bounds != [] && array_bounds != [-1]
|
887
833
|
boom 'https://github.com/mvgijssel/arel_toolkit/issues/86'
|
@@ -901,77 +847,70 @@ module Arel
|
|
901
847
|
type_name
|
902
848
|
end
|
903
849
|
|
904
|
-
type_name
|
850
|
+
type_name += '[]' if array_bounds == [-1]
|
905
851
|
type_name
|
906
852
|
end
|
907
853
|
|
908
|
-
def visit_UpdateStmt(
|
909
|
-
relation
|
910
|
-
target_list
|
911
|
-
where_clause: nil,
|
912
|
-
from_clause: [],
|
913
|
-
returning_list: [],
|
914
|
-
with_clause: nil
|
915
|
-
)
|
916
|
-
relation = visit(relation)
|
917
|
-
target_list = visit(target_list, :update)
|
854
|
+
def visit_UpdateStmt(attribute)
|
855
|
+
relation = visit(attribute.relation)
|
856
|
+
target_list = visit(attribute.target_list, :update)
|
918
857
|
|
919
858
|
update_manager = Arel::UpdateManager.new
|
920
859
|
update_statement = update_manager.ast
|
921
860
|
update_statement.relation = relation
|
922
|
-
update_statement.froms = visit(from_clause)
|
861
|
+
update_statement.froms = visit(attribute.from_clause)
|
923
862
|
update_statement.values = target_list
|
924
|
-
update_statement.wheres = where_clause ? [visit(where_clause)] : []
|
925
|
-
update_statement.with = visit(with_clause) if with_clause
|
926
|
-
update_statement.returning = visit(returning_list, :select)
|
863
|
+
update_statement.wheres = attribute.where_clause ? [visit(attribute.where_clause)] : []
|
864
|
+
update_statement.with = visit(attribute.with_clause) if attribute.with_clause
|
865
|
+
update_statement.returning = visit(attribute.returning_list, :select)
|
927
866
|
update_manager
|
928
867
|
end
|
929
868
|
|
930
|
-
def visit_VariableSetStmt(
|
869
|
+
def visit_VariableSetStmt(attribute)
|
931
870
|
Arel::Nodes::VariableSet.new(
|
932
|
-
kind,
|
933
|
-
visit(args),
|
934
|
-
name,
|
935
|
-
is_local,
|
871
|
+
attribute.kind,
|
872
|
+
visit(attribute.args),
|
873
|
+
attribute.name,
|
874
|
+
attribute.is_local,
|
936
875
|
)
|
937
876
|
end
|
938
877
|
|
939
|
-
def visit_VariableShowStmt(
|
940
|
-
Arel::Nodes::VariableShow.new(name)
|
878
|
+
def visit_VariableShowStmt(attribute)
|
879
|
+
Arel::Nodes::VariableShow.new(attribute.name)
|
941
880
|
end
|
942
881
|
|
943
|
-
def visit_WindowDef(
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
start_offset: nil,
|
949
|
-
end_offset: nil
|
950
|
-
)
|
951
|
-
if name.present? && partition_clause.empty? && order_clause.empty?
|
952
|
-
return Arel::Nodes::SqlLiteral.new(name)
|
882
|
+
def visit_WindowDef(attribute)
|
883
|
+
if attribute.name.present? &&
|
884
|
+
attribute.partition_clause.empty? &&
|
885
|
+
attribute.order_clause.empty?
|
886
|
+
return Arel::Nodes::SqlLiteral.new(attribute.name)
|
953
887
|
end
|
954
888
|
|
955
|
-
instance = name.
|
889
|
+
instance = if attribute.name.blank?
|
890
|
+
Arel::Nodes::Window.new
|
891
|
+
else
|
892
|
+
Arel::Nodes::NamedWindow.new(attribute.name)
|
893
|
+
end
|
894
|
+
|
956
895
|
instance.tap do |window|
|
957
|
-
window.orders = visit order_clause
|
958
|
-
window.partitions = visit partition_clause
|
896
|
+
window.orders = visit attribute.order_clause
|
897
|
+
window.partitions = visit attribute.partition_clause
|
959
898
|
|
960
|
-
if frame_options
|
899
|
+
if attribute.frame_options
|
961
900
|
window.framing = FrameOptions.arel(
|
962
|
-
frame_options,
|
963
|
-
(visit(start_offset) if start_offset),
|
964
|
-
(visit(end_offset) if end_offset),
|
901
|
+
attribute.frame_options,
|
902
|
+
(visit(attribute.start_offset) if attribute.start_offset),
|
903
|
+
(visit(attribute.end_offset) if attribute.end_offset),
|
965
904
|
)
|
966
905
|
end
|
967
906
|
end
|
968
907
|
end
|
969
908
|
|
970
|
-
def visit_WithClause(
|
971
|
-
if recursive
|
972
|
-
Arel::Nodes::WithRecursive.new visit(ctes)
|
909
|
+
def visit_WithClause(attribute)
|
910
|
+
if attribute.recursive
|
911
|
+
Arel::Nodes::WithRecursive.new visit(attribute.ctes)
|
973
912
|
else
|
974
|
-
Arel::Nodes::With.new visit(ctes)
|
913
|
+
Arel::Nodes::With.new visit(attribute.ctes)
|
975
914
|
end
|
976
915
|
end
|
977
916
|
|
@@ -1098,50 +1037,25 @@ module Arel
|
|
1098
1037
|
end
|
1099
1038
|
end
|
1100
1039
|
|
1101
|
-
def visit_DeallocateStmt(name: nil)
|
1102
|
-
Arel::Nodes::Dealocate.new name
|
1103
|
-
end
|
1104
|
-
|
1105
|
-
def visit_PrepareStmt(name:, argtypes: nil, query:)
|
1106
|
-
Arel::Nodes::Prepare.new name, argtypes && visit(argtypes), visit(query)
|
1107
|
-
end
|
1108
|
-
|
1109
1040
|
def visit(attribute, context = nil)
|
1110
|
-
return attribute.map { |attr| visit(attr, context) } if
|
1111
|
-
|
1112
|
-
klass, attributes = klass_and_attributes(attribute)
|
1113
|
-
dispatch_method = "visit_#{klass}"
|
1114
|
-
method = method(dispatch_method)
|
1115
|
-
|
1116
|
-
arg_has_context = (method.parameters.include?(%i[opt context]) ||
|
1117
|
-
method.parameters.include?(%i[req context])) && context
|
1041
|
+
return attribute.map { |attr| visit(attr, context) } if
|
1042
|
+
attribute.is_a?(Google::Protobuf::RepeatedField) || attribute.is_a?(Array)
|
1118
1043
|
|
1119
|
-
|
1044
|
+
dispatch_method = "visit_#{attribute.class.name.demodulize}"
|
1120
1045
|
|
1121
|
-
if
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
.to_sym
|
1129
|
-
end
|
1130
|
-
|
1131
|
-
kwargs.delete(:location)
|
1132
|
-
|
1133
|
-
if (aliaz = kwargs.delete(:alias))
|
1134
|
-
kwargs[:aliaz] = aliaz
|
1046
|
+
if context.present?
|
1047
|
+
method = method(dispatch_method)
|
1048
|
+
if method.parameters.include?(%i[opt context]) ||
|
1049
|
+
method.parameters.include?(%i[req context])
|
1050
|
+
send dispatch_method, attribute, context
|
1051
|
+
else
|
1052
|
+
send dispatch_method, attribute
|
1135
1053
|
end
|
1136
|
-
|
1137
|
-
send dispatch_method,
|
1054
|
+
else
|
1055
|
+
send dispatch_method, attribute
|
1138
1056
|
end
|
1139
1057
|
end
|
1140
1058
|
|
1141
|
-
def klass_and_attributes(object)
|
1142
|
-
[object.keys.first, object.values.first]
|
1143
|
-
end
|
1144
|
-
|
1145
1059
|
def generate_boolean_expression(args, boolean_class)
|
1146
1060
|
chain = boolean_class.new(nil, nil)
|
1147
1061
|
|
@@ -1185,32 +1099,32 @@ module Arel
|
|
1185
1099
|
|
1186
1100
|
def generate_sublink(sub_link_type, subselect, testexpr, operator)
|
1187
1101
|
case sub_link_type
|
1188
|
-
when
|
1102
|
+
when :EXISTS_SUBLINK
|
1189
1103
|
Arel::Nodes::Exists.new subselect
|
1190
1104
|
|
1191
|
-
when
|
1105
|
+
when :ALL_SUBLINK
|
1192
1106
|
generate_operator(testexpr, Arel::Nodes::All.new(subselect), operator)
|
1193
1107
|
|
1194
|
-
when
|
1108
|
+
when :ANY_SUBLINK
|
1195
1109
|
if operator.nil?
|
1196
1110
|
Arel::Nodes::In.new(testexpr, subselect)
|
1197
1111
|
else
|
1198
1112
|
generate_operator(testexpr, Arel::Nodes::Any.new(subselect), operator)
|
1199
1113
|
end
|
1200
1114
|
|
1201
|
-
when
|
1115
|
+
when :ROWCOMPARE_SUBLINK
|
1202
1116
|
boom 'https://github.com/mvgijssel/arel_toolkit/issues/42'
|
1203
1117
|
|
1204
|
-
when
|
1118
|
+
when :EXPR_SUBLINK
|
1205
1119
|
Arel::Nodes::Grouping.new(subselect)
|
1206
1120
|
|
1207
|
-
when
|
1121
|
+
when :MULTIEXPR_SUBLINK
|
1208
1122
|
boom 'https://github.com/mvgijssel/arel_toolkit/issues/43'
|
1209
1123
|
|
1210
|
-
when
|
1124
|
+
when :ARRAY_SUBLINK
|
1211
1125
|
Arel::Nodes::ArraySubselect.new(subselect)
|
1212
1126
|
|
1213
|
-
when
|
1127
|
+
when :CTE_SUBLINK
|
1214
1128
|
boom 'https://github.com/mvgijssel/arel_toolkit/issues/44'
|
1215
1129
|
|
1216
1130
|
else
|
@@ -1229,12 +1143,9 @@ module Arel
|
|
1229
1143
|
|
1230
1144
|
def boom(message, backtrace = nil)
|
1231
1145
|
new_message = <<~STRING
|
1232
|
-
|
1233
|
-
|
1234
1146
|
SQL: #{sql}
|
1235
1147
|
BINDS: #{binds}
|
1236
1148
|
message: #{message}
|
1237
|
-
|
1238
1149
|
STRING
|
1239
1150
|
|
1240
1151
|
raise(Arel::SqlToArel::Error, new_message, backtrace) if backtrace
|
@@ -1249,5 +1160,3 @@ end
|
|
1249
1160
|
# rubocop:enable Naming/MethodName
|
1250
1161
|
# rubocop:enable Metrics/CyclomaticComplexity
|
1251
1162
|
# rubocop:enable Metrics/AbcSize
|
1252
|
-
# rubocop:enable Naming/UncommunicativeMethodParamName
|
1253
|
-
# rubocop:enable Metrics/ParameterLists
|