arel_toolkit 0.4.3 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/coverage.yml +48 -0
  3. data/.github/workflows/test.yml +68 -0
  4. data/.gitignore +3 -1
  5. data/.rubocop.yml +2 -0
  6. data/.ruby-version +1 -1
  7. data/.tool-versions +1 -0
  8. data/Appraisals +4 -0
  9. data/CHANGELOG.md +49 -3
  10. data/Gemfile.lock +134 -84
  11. data/README.md +20 -3
  12. data/arel_toolkit.gemspec +3 -5
  13. data/bin/console +2 -1
  14. data/bin/setup +23 -2
  15. data/docker-compose.yml +11 -0
  16. data/gemfiles/active_record_6.gemfile +3 -3
  17. data/gemfiles/active_record_6.gemfile.lock +9 -7
  18. data/gemfiles/active_record_6_1.gemfile +7 -0
  19. data/gemfiles/active_record_6_1.gemfile.lock +263 -0
  20. data/gemfiles/arel_gems.gemfile.lock +9 -7
  21. data/gemfiles/default.gemfile.lock +9 -7
  22. data/lib/arel/enhance/context_enhancer/arel_table.rb +20 -0
  23. data/lib/arel/enhance/node.rb +20 -12
  24. data/lib/arel/enhance/visitor.rb +1 -1
  25. data/lib/arel/enhance.rb +2 -2
  26. data/lib/arel/extensions/conflict.rb +3 -3
  27. data/lib/arel/extensions/delete_statement.rb +19 -14
  28. data/lib/arel/extensions/infer.rb +2 -2
  29. data/lib/arel/extensions/insert_statement.rb +3 -3
  30. data/lib/arel/extensions/overlaps.rb +7 -1
  31. data/lib/arel/extensions/table.rb +7 -2
  32. data/lib/arel/extensions/transaction.rb +9 -9
  33. data/lib/arel/extensions/tree_manager.rb +0 -5
  34. data/lib/arel/extensions/update_statement.rb +8 -22
  35. data/lib/arel/sql_to_arel/pg_query_visitor/frame_options.rb +37 -5
  36. data/lib/arel/sql_to_arel/pg_query_visitor.rb +430 -521
  37. data/lib/arel/transformer/prefix_schema_name.rb +5 -3
  38. data/lib/arel/transformer.rb +0 -1
  39. data/lib/arel_toolkit/version.rb +1 -1
  40. metadata +15 -12
  41. data/.github/workflows/develop.yml +0 -90
  42. data/.github/workflows/master.yml +0 -67
  43. 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(elements:)
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(val:)
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(kind:, lexpr: nil, rexpr: nil, name:)
49
- case kind
50
- when PgQuery::AEXPR_OP
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 PgQuery::AEXPR_OP_ANY
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 PgQuery::AEXPR_OP_ALL
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 PgQuery::AEXPR_DISTINCT
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 PgQuery::AEXPR_NOT_DISTINCT
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 PgQuery::AEXPR_NULLIF
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 PgQuery::AEXPR_OF
86
- boom 'https://github.com/mvgijssel/arel_toolkit/issues/34'
87
-
88
- when PgQuery::AEXPR_IN
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 PgQuery::AEXPR_LIKE
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 operator == '~~*'
132
- Arel::Nodes::Matches.new(left, right, escape, false)
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, false)
110
+ Arel::Nodes::DoesNotMatch.new(left, right, escape, attribute.kind == :AEXPR_LIKE)
135
111
  end
136
-
137
- when PgQuery::AEXPR_SIMILAR
138
- left = visit(lexpr) if lexpr
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
- escape = nil if escape == 'NULL'
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 PgQuery::AEXPR_BETWEEN
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 PgQuery::AEXPR_NOT_BETWEEN
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 PgQuery::AEXPR_BETWEEN_SYM
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 PgQuery::AEXPR_NOT_BETWEEN_SYM
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(context, uidx:)
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(arg:, 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(aliasname:)
198
- Arel.sql visit_String(nil, str: aliasname)
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(str:)
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, args:, boolop:)
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 PgQuery::BOOL_EXPR_AND
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(arg:, booltesttype:)
230
- arg = visit(arg)
201
+ def visit_BooleanTest(attribute)
202
+ arg = visit(attribute.arg)
231
203
 
232
- case booltesttype
233
- when PgQuery::BOOLEAN_TEST_TRUE
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(arg: nil, args:, defresult: nil)
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(expr:, result:)
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(args:)
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(fields:)
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(ctename:, ctequery:)
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(cursor_name:)
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(defname:, arg:, defaction:)
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(str:)
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
- funcname:,
345
- args: nil,
346
- agg_order: nil,
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 = (agg_distinct.nil? ? false : true) unless func.is_a?(::Array)
438
- func.orders = (agg_order ? visit(agg_order) : []) unless func.is_a?(::Array)
439
- func.filter = (agg_filter ? visit(agg_filter) : nil) unless func.is_a?(::Array)
440
- func.within_group = agg_within_group unless func.is_a?(::Array)
441
- func.variardic = func_variadic unless func.is_a?(::Array)
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(conname: nil, index_elems: nil)
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(name:, ordering:, nulls_ordering:)
457
- boom "Unknown ordering `#{ordering}`" unless ordering.zero?
458
- boom "Unknown nulls ordering `#{ordering}`" unless nulls_ordering.zero?
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(str: name)
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
- insert_statement.values = select_stmt.values_lists if select_stmt
487
- else
488
- insert_statement.values = Arel::Nodes::DefaultValues.new
489
- end
490
-
491
- insert_statement.returning = visit(returning_list, :select)
492
- insert_statement.conflict = visit(on_conflict_clause) if on_conflict_clause
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(ival:)
497
- ival
430
+ def visit_Integer(attribute)
431
+ attribute.ival
498
432
  end
499
433
 
500
- def visit_IntoClause(rel:, on_commit:)
501
- raise "Unknown on_commit `#{on_commit}`" unless on_commit.zero?
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(jointype:, is_natural: nil, larg:, rarg:, quals: nil)
507
- join_class = case jointype
508
- when 0
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 1
451
+ when :JOIN_LEFT
517
452
  Arel::Nodes::OuterJoin
518
- when 2
453
+ when :JOIN_FULL
519
454
  Arel::Nodes::FullOuterJoin
520
- when 3
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 = join_class.new(rarg, quals)
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(strength:, wait_policy:)
475
+ def visit_LockingClause(attribute)
539
476
  strength_clause = {
540
- 1 => 'FOR KEY SHARE',
541
- 2 => 'FOR SHARE',
542
- 3 => 'FOR NO KEY UPDATE',
543
- 4 => 'FOR UPDATE',
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
- 0 => '',
547
- 1 => ' SKIP LOCKED',
548
- 2 => ' NOWAIT',
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(op:, args:)
555
- case op
556
- when 0
557
- Arel::Nodes::Greatest.new visit(args)
558
- when 1
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(arg:, name:, argnumber:)
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
- Arel::Nodes::NamedArgument.new(name, arg)
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(arg:, nulltesttype:)
577
- arg = visit(arg)
520
+ def visit_NullTest(attribute)
521
+ arg = visit(attribute.arg)
578
522
 
579
- case nulltesttype
580
- when PgQuery::CONSTR_TYPE_NULL
523
+ case attribute.nulltesttype
524
+ when :IS_NULL
581
525
  Arel::Nodes::Equality.new(arg, nil)
582
- when PgQuery::CONSTR_TYPE_NOTNULL
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(action:, infer: nil, target_list: nil, where_clause: nil)
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(number: nil)
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 visit_RangeFunction(
603
- is_rowsfrom: nil,
604
- functions:,
605
- lateral: false,
606
- ordinality: false,
607
- aliaz: nil
608
- )
609
- functions = functions.map do |function_array|
610
- function, empty_value = function_array
611
- boom 'https://github.com/mvgijssel/arel_toolkit/issues/37' unless empty_value.nil?
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
- aliaz.nil? ? node : Arel::Nodes::As.new(node, visit(aliaz))
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(aliaz:, subquery:, lateral: false)
623
- aliaz = visit(aliaz)
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(aliaz: nil, relname:, inh: false, relpersistence:, schemaname: nil)
574
+ def visit_RangeVar(attribute)
630
575
  Arel::Table.new(
631
- relname,
632
- as: (visit(aliaz) if aliaz),
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(context, **args)
640
- visit(args.fetch(:stmt), context)
584
+ def visit_RawStmt(attribute, context)
585
+ visit(attribute.stmt, context)
641
586
  end
642
587
 
643
- def visit_ResTarget(context, val: nil, name: nil)
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(args:, row_format:)
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 limit_count
723
-
724
- if distinct_clause == [nil]
725
- select_core.set_quantifier = Arel::Nodes::Distinct.new
726
- elsif distinct_clause.is_a?(Array)
727
- select_core.set_quantifier = Arel::Nodes::DistinctOn.new(visit(distinct_clause))
728
- elsif distinct_clause.nil?
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
- select_statement.limit = ::Arel::Nodes::Limit.new visit(limit_count) if limit_count
735
- select_statement.offset = ::Arel::Nodes::Offset.new visit(limit_offset) if limit_offset
736
- select_statement.orders = visit(sort_clause.to_a)
737
- select_statement.with = visit(with_clause) if with_clause
738
- select_statement.lock = visit(locking_clause) if locking_clause
739
- if values_lists
740
- values_lists = visit(values_lists).map do |values_list|
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 0
699
+ union = case attribute.op
700
+ when :SET_OPERATION_UNDEFINED, :SETOP_NONE
763
701
  nil
764
- when 1
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 2
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 3
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(node:, sortby_dir:, sortby_nulls:)
804
- result = visit(node)
805
- case sortby_dir
806
- when 1
807
- Arel::Nodes::Ascending.new(result, sortby_nulls)
808
- when 2
809
- Arel::Nodes::Descending.new(result, sortby_nulls)
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(op:, typmod:)
816
- [
817
- -> { Arel::Nodes::CurrentDate.new },
818
- -> { Arel::Nodes::CurrentTime.new },
819
- -> { Arel::Nodes::CurrentTime.new(precision: typmod) },
820
- -> { Arel::Nodes::CurrentTimestamp.new },
821
- -> { Arel::Nodes::CurrentTimestamp.new(precision: typmod) },
822
- -> { Arel::Nodes::LocalTime.new },
823
- -> { Arel::Nodes::LocalTime.new(precision: typmod) },
824
- -> { Arel::Nodes::LocalTimestamp.new },
825
- -> { Arel::Nodes::LocalTimestamp.new(precision: typmod) },
826
- -> { Arel::Nodes::CurrentRole.new },
827
- -> { Arel::Nodes::CurrentUser.new },
828
- -> { Arel::Nodes::User.new },
829
- -> { Arel::Nodes::SessionUser.new },
830
- -> { Arel::Nodes::CurrentCatalog.new },
831
- -> { Arel::Nodes::CurrentSchema.new },
832
- ][op].call
833
- end
834
-
835
- def visit_String(context = nil, str:)
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
- "\"#{str}\""
790
+ "\"#{attribute}\""
843
791
  end
844
792
  end
845
793
 
846
- def visit_SubLink(subselect:, sub_link_type:, testexpr: nil, oper_name: nil)
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(kind:, options: nil)
807
+ def visit_TransactionStmt(attribute)
862
808
  Arel::Nodes::Transaction.new(
863
- kind,
864
- (visit(options) if options),
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(arg:, type_name:)
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(names:, typemod:, array_bounds: [])
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 << '[]' if array_bounds == [-1]
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(kind:, name:, args: [], is_local: false)
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(name:)
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
- partition_clause: [],
945
- order_clause: [],
946
- frame_options:,
947
- name: nil,
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.nil? ? Arel::Nodes::Window.new : Arel::Nodes::NamedWindow.new(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(ctes:, recursive: false)
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 attribute.is_a? Array
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
- args = arg_has_context ? [context] : nil
1044
+ dispatch_method = "visit_#{attribute.class.name.demodulize}"
1120
1045
 
1121
- if attributes.empty?
1122
- send dispatch_method, *args
1123
- else
1124
- kwargs = attributes.transform_keys do |key|
1125
- key
1126
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
1127
- .downcase
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, *args, **kwargs
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 PgQuery::SUBLINK_TYPE_EXISTS
1102
+ when :EXISTS_SUBLINK
1189
1103
  Arel::Nodes::Exists.new subselect
1190
1104
 
1191
- when PgQuery::SUBLINK_TYPE_ALL
1105
+ when :ALL_SUBLINK
1192
1106
  generate_operator(testexpr, Arel::Nodes::All.new(subselect), operator)
1193
1107
 
1194
- when PgQuery::SUBLINK_TYPE_ANY
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 PgQuery::SUBLINK_TYPE_ROWCOMPARE
1115
+ when :ROWCOMPARE_SUBLINK
1202
1116
  boom 'https://github.com/mvgijssel/arel_toolkit/issues/42'
1203
1117
 
1204
- when PgQuery::SUBLINK_TYPE_EXPR
1118
+ when :EXPR_SUBLINK
1205
1119
  Arel::Nodes::Grouping.new(subselect)
1206
1120
 
1207
- when PgQuery::SUBLINK_TYPE_MULTIEXPR
1121
+ when :MULTIEXPR_SUBLINK
1208
1122
  boom 'https://github.com/mvgijssel/arel_toolkit/issues/43'
1209
1123
 
1210
- when PgQuery::SUBLINK_TYPE_ARRAY
1124
+ when :ARRAY_SUBLINK
1211
1125
  Arel::Nodes::ArraySubselect.new(subselect)
1212
1126
 
1213
- when PgQuery::SUBLINK_TYPE_CTE
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