rom-sql 3.6.5 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +1 -2
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +4 -1
- data/lib/rom/plugins/relation/sql/instrumentation.rb +6 -2
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +1 -1
- data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +31 -12
- data/lib/rom/plugins/relation/sql/postgres/streaming.rb +6 -6
- data/lib/rom/sql/associations/many_to_many.rb +6 -3
- data/lib/rom/sql/associations/many_to_one.rb +3 -0
- data/lib/rom/sql/attribute.rb +22 -8
- data/lib/rom/sql/attribute_aliasing.rb +7 -6
- data/lib/rom/sql/commands/create.rb +4 -3
- data/lib/rom/sql/commands/update.rb +4 -3
- data/lib/rom/sql/dsl.rb +3 -1
- data/lib/rom/sql/extensions/active_support_notifications.rb +1 -1
- data/lib/rom/sql/extensions/postgres/type_builder.rb +7 -7
- data/lib/rom/sql/extensions/postgres/type_serializer.rb +2 -2
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +12 -12
- data/lib/rom/sql/extensions/postgres/types/json.rb +9 -3
- data/lib/rom/sql/extensions/postgres/types/ltree.rb +106 -36
- data/lib/rom/sql/extensions/postgres/types/range.rb +18 -18
- data/lib/rom/sql/extensions/rails_log_subscriber.rb +4 -4
- data/lib/rom/sql/function.rb +37 -18
- data/lib/rom/sql/gateway.rb +8 -7
- data/lib/rom/sql/group_dsl.rb +7 -2
- data/lib/rom/sql/migration/inline_runner.rb +8 -2
- data/lib/rom/sql/migration/migrator.rb +5 -5
- data/lib/rom/sql/migration/recorder.rb +10 -4
- data/lib/rom/sql/migration/runner.rb +5 -4
- data/lib/rom/sql/migration/schema_diff.rb +15 -10
- data/lib/rom/sql/migration/writer.rb +8 -8
- data/lib/rom/sql/migration.rb +5 -5
- data/lib/rom/sql/order_dsl.rb +6 -2
- data/lib/rom/sql/plugin/associates.rb +21 -7
- data/lib/rom/sql/plugin/pagination.rb +2 -2
- data/lib/rom/sql/projection_dsl.rb +1 -1
- data/lib/rom/sql/relation/reading.rb +83 -71
- data/lib/rom/sql/relation/writing.rb +19 -13
- data/lib/rom/sql/relation.rb +74 -28
- data/lib/rom/sql/restriction_dsl.rb +6 -2
- data/lib/rom/sql/schema/attributes_inferrer.rb +2 -2
- data/lib/rom/sql/schema/dsl.rb +2 -2
- data/lib/rom/sql/schema/index_dsl.rb +5 -6
- data/lib/rom/sql/schema/inferrer.rb +23 -19
- data/lib/rom/sql/schema/type_builder.rb +5 -2
- data/lib/rom/sql/schema.rb +10 -10
- data/lib/rom/sql/tasks/migration_tasks.rake +4 -5
- data/lib/rom/sql/transaction.rb +1 -0
- data/lib/rom/sql/type_dsl.rb +7 -3
- data/lib/rom/sql/type_extensions.rb +4 -4
- data/lib/rom/sql/type_serializer.rb +2 -2
- data/lib/rom/sql/types.rb +2 -2
- data/lib/rom/sql/version.rb +1 -1
- data/lib/rom/types/values.rb +2 -4
- metadata +9 -15
@@ -13,7 +13,7 @@ module ROM
|
|
13
13
|
|
14
14
|
def call(changes)
|
15
15
|
changes.each { |diff| apply_schema(diff) }
|
16
|
-
changes.each { |diff| apply_constraints(diff) }
|
16
|
+
changes.each { |diff| apply_constraints(diff) } # rubocop:disable Style/CombinableLoops
|
17
17
|
|
18
18
|
self
|
19
19
|
end
|
@@ -54,6 +54,7 @@ module ROM
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
57
58
|
def alter_table(diff)
|
58
59
|
return if diff.meta?
|
59
60
|
|
@@ -68,9 +69,8 @@ module ROM
|
|
68
69
|
when SchemaDiff::AttributeChanged
|
69
70
|
if attribute.type_changed?
|
70
71
|
from, to = attribute.current.unwrap, attribute.target.unwrap
|
71
|
-
raise UnsupportedConversion
|
72
|
-
|
73
|
-
)
|
72
|
+
raise UnsupportedConversion,
|
73
|
+
"Don't know how to convert #{from.inspect} to #{to.inspect}"
|
74
74
|
end
|
75
75
|
|
76
76
|
if attribute.nullability_changed?
|
@@ -94,6 +94,7 @@ module ROM
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
97
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
97
98
|
|
98
99
|
def alter_foreign_keys(diff, foreign_key_changes)
|
99
100
|
return if foreign_key_changes.empty?
|
@@ -46,7 +46,6 @@ module ROM
|
|
46
46
|
end
|
47
47
|
|
48
48
|
class TableAltered < TableDiff
|
49
|
-
|
50
49
|
option :attribute_changes, default: -> { EMPTY_ARRAY }
|
51
50
|
|
52
51
|
option :index_changes, default: -> { EMPTY_ARRAY }
|
@@ -133,20 +132,22 @@ module ROM
|
|
133
132
|
end
|
134
133
|
|
135
134
|
class IndexAdded < IndexDiff
|
135
|
+
# rubocop:disable Metrics/AbcSize
|
136
136
|
def options
|
137
137
|
options = {}
|
138
|
-
options[:name] = index.name
|
138
|
+
options[:name] = index.name unless index.name.nil?
|
139
139
|
options[:unique] = true if index.unique?
|
140
|
-
options[:type] = index.type
|
141
|
-
options[:where] = index.predicate
|
140
|
+
options[:type] = index.type unless index.type.nil?
|
141
|
+
options[:where] = index.predicate unless index.predicate.nil?
|
142
142
|
options
|
143
143
|
end
|
144
|
+
# rubocop:enable Metrics/AbcSize
|
144
145
|
end
|
145
146
|
|
146
147
|
class IndexRemoved < IndexDiff
|
147
148
|
def options
|
148
149
|
options = {}
|
149
|
-
options[:name] = index.name
|
150
|
+
options[:name] = index.name unless index.name.nil?
|
150
151
|
options
|
151
152
|
end
|
152
153
|
end
|
@@ -177,6 +178,7 @@ module ROM
|
|
177
178
|
class ForeignKeyRemoved < ForeignKeyDiff
|
178
179
|
end
|
179
180
|
|
181
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength
|
180
182
|
def call(current, target)
|
181
183
|
if current.empty?
|
182
184
|
TableCreated.new(
|
@@ -203,21 +205,23 @@ module ROM
|
|
203
205
|
end
|
204
206
|
end
|
205
207
|
end
|
208
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength
|
206
209
|
|
210
|
+
# rubocop:disable Style/MultilineBlockChain
|
207
211
|
def compare_attributes(current, target)
|
208
212
|
changed_attributes = target.select { |name, attr|
|
209
213
|
current.key?(name) && !attributes_equal?(current[name], attr)
|
210
|
-
}.
|
211
|
-
|
212
|
-
}
|
213
|
-
added_attributes = target.select { |name, _| !current.key?(name) }
|
214
|
-
removed_attributes = current.select { |name, _| !target.key?(name) }
|
214
|
+
}.to_h { |name, target_attr| [name, [target_attr, current[name]]] }
|
215
|
+
added_attributes = target.reject { |name, _| current.key?(name) }
|
216
|
+
removed_attributes = current.reject { |name, _| target.key?(name) }
|
215
217
|
|
216
218
|
map_attributes(removed_attributes, AttributeRemoved) +
|
217
219
|
map_attributes(added_attributes, AttributeAdded) +
|
218
220
|
map_attributes(changed_attributes, AttributeChanged)
|
219
221
|
end
|
222
|
+
# rubocop:enable Style/MultilineBlockChain
|
220
223
|
|
224
|
+
# rubocop:disable Metrics/AbcSize
|
221
225
|
def compare_indexes(current, target)
|
222
226
|
added_indexes = target.indexes.reject { |idx|
|
223
227
|
current.indexes.any? { |curr_idx| curr_idx.attributes == idx.attributes }
|
@@ -229,6 +233,7 @@ module ROM
|
|
229
233
|
removed_indexes.map { |idx| IndexRemoved.new(idx) } +
|
230
234
|
added_indexes.map { |idx| IndexAdded.new(idx) }
|
231
235
|
end
|
236
|
+
# rubocop:enable Metrics/AbcSize
|
232
237
|
|
233
238
|
def compare_foreign_key_constraints(current, target)
|
234
239
|
target_fks = target.foreign_keys
|
@@ -7,8 +7,8 @@ module ROM
|
|
7
7
|
module Migration
|
8
8
|
# @api private
|
9
9
|
class Writer
|
10
|
-
MIGRATION_BEGIN = "ROM::SQL.migration do\n change do"
|
11
|
-
MIGRATION_END = "\n end\nend\n"
|
10
|
+
MIGRATION_BEGIN = "ROM::SQL.migration do\n change do"
|
11
|
+
MIGRATION_END = "\n end\nend\n"
|
12
12
|
|
13
13
|
attr_reader :yield_migration
|
14
14
|
|
@@ -36,11 +36,11 @@ module ROM
|
|
36
36
|
buffer << indent << op.to_s << ' '
|
37
37
|
write_arguments(buffer, args)
|
38
38
|
|
39
|
-
if
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
39
|
+
next if nested.empty?
|
40
|
+
|
41
|
+
buffer << ' do'
|
42
|
+
write(nested, buffer, "#{indent} ")
|
43
|
+
buffer << indent << 'end'
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -61,7 +61,7 @@ module ROM
|
|
61
61
|
create_or_alter, args = op
|
62
62
|
table_name = args[0]
|
63
63
|
|
64
|
-
"#{create_or_alter.to_s.sub(
|
64
|
+
"#{create_or_alter.to_s.sub("_table", "")}_#{table_name}"
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
data/lib/rom/sql/migration.rb
CHANGED
@@ -54,12 +54,12 @@ module ROM
|
|
54
54
|
# @param [Symbol] gateway The gateway name, :default by default
|
55
55
|
#
|
56
56
|
# @api public
|
57
|
-
def migration(*args, &
|
57
|
+
def migration(*args, &)
|
58
58
|
if args.any?
|
59
59
|
container, gateway, * = args
|
60
|
-
with_gateway(container.gateways[gateway || :default]) { migration(&
|
60
|
+
with_gateway(container.gateways[gateway || :default]) { migration(&) }
|
61
61
|
else
|
62
|
-
current_gateway.migration(&
|
62
|
+
current_gateway.migration(&)
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -121,8 +121,8 @@ module ROM
|
|
121
121
|
# @see ROM::SQL.migration
|
122
122
|
#
|
123
123
|
# @api public
|
124
|
-
def migration(&
|
125
|
-
migrator.migration(&
|
124
|
+
def migration(&)
|
125
|
+
migrator.migration(&)
|
126
126
|
end
|
127
127
|
|
128
128
|
# Run migrations
|
data/lib/rom/sql/order_dsl.rb
CHANGED
@@ -8,12 +8,16 @@ module ROM
|
|
8
8
|
class OrderDSL < DSL
|
9
9
|
private
|
10
10
|
|
11
|
+
def respond_to_missing?(_meth, _include_private = false)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
11
15
|
# @api private
|
12
|
-
def method_missing(meth,
|
16
|
+
def method_missing(meth, ...)
|
13
17
|
if schema.key?(meth)
|
14
18
|
schema[meth]
|
15
19
|
else
|
16
|
-
::Sequel::VIRTUAL_ROW.__send__(meth.to_s.upcase,
|
20
|
+
::Sequel::VIRTUAL_ROW.__send__(meth.to_s.upcase, ...)
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -10,7 +10,11 @@ module ROM
|
|
10
10
|
# @api private
|
11
11
|
module Associates
|
12
12
|
class AssociateOptions
|
13
|
-
attr_reader :name
|
13
|
+
attr_reader :name
|
14
|
+
|
15
|
+
attr_reader :assoc
|
16
|
+
|
17
|
+
attr_reader :opts
|
14
18
|
|
15
19
|
# @api private
|
16
20
|
def initialize(name, relation, opts)
|
@@ -37,7 +41,7 @@ module ROM
|
|
37
41
|
|
38
42
|
defines :associations
|
39
43
|
|
40
|
-
associations
|
44
|
+
associations({})
|
41
45
|
|
42
46
|
option :associations, default: -> { self.class.associations }
|
43
47
|
option :configured_associations, default: -> { EMPTY_ARRAY }
|
@@ -57,16 +61,17 @@ module ROM
|
|
57
61
|
|
58
62
|
associate_options = command.associations.map { |(name, opts)|
|
59
63
|
next if configured_assocs.include?(name)
|
64
|
+
|
60
65
|
AssociateOptions.new(name, relation, opts)
|
61
66
|
}.compact
|
62
67
|
|
63
68
|
before_hooks = associate_options.reject(&:after?).map(&:to_hash)
|
64
69
|
after_hooks = associate_options.select(&:after?).map(&:to_hash)
|
65
70
|
|
66
|
-
command
|
67
|
-
with(configured_associations: configured_assocs + associate_options.map(&:name))
|
68
|
-
before(*before_hooks)
|
69
|
-
after(*after_hooks)
|
71
|
+
command
|
72
|
+
.with(configured_associations: configured_assocs + associate_options.map(&:name))
|
73
|
+
.before(*before_hooks)
|
74
|
+
.after(*after_hooks)
|
70
75
|
end
|
71
76
|
|
72
77
|
# Set command to associate tuples with a parent tuple using provided keys
|
@@ -109,7 +114,15 @@ module ROM
|
|
109
114
|
# @return [Array<Hash>]
|
110
115
|
#
|
111
116
|
# @api public
|
112
|
-
|
117
|
+
#
|
118
|
+
# rubocop:disable Metrics/PerceivedComplexity, Metrics/AbcSize
|
119
|
+
def associate(
|
120
|
+
tuples,
|
121
|
+
curried_parent = nil,
|
122
|
+
assoc:,
|
123
|
+
keys:, # rubocop:disable Lint/UnusedMethodArgument
|
124
|
+
parent: curried_parent
|
125
|
+
)
|
113
126
|
result_type = result
|
114
127
|
|
115
128
|
output_tuples =
|
@@ -137,6 +150,7 @@ module ROM
|
|
137
150
|
|
138
151
|
result_type == :one ? output_tuples[0] : output_tuples
|
139
152
|
end
|
153
|
+
# rubocop:enable Metrics/PerceivedComplexity, Metrics/AbcSize
|
140
154
|
|
141
155
|
# Return a new command with the provided association
|
142
156
|
#
|
@@ -53,7 +53,7 @@ module ROM
|
|
53
53
|
# @api public
|
54
54
|
def prev_page
|
55
55
|
num = current_page - 1
|
56
|
-
num if num
|
56
|
+
num if num.positive?
|
57
57
|
end
|
58
58
|
|
59
59
|
# Return total number of tuples
|
@@ -100,7 +100,7 @@ module ROM
|
|
100
100
|
per_page = per_page.to_i
|
101
101
|
|
102
102
|
self.class.new(
|
103
|
-
dataset.offset((current_page-1)*per_page).limit(per_page),
|
103
|
+
dataset.offset((current_page - 1) * per_page).limit(per_page),
|
104
104
|
current_page: current_page, per_page: per_page
|
105
105
|
)
|
106
106
|
end
|
@@ -9,20 +9,22 @@ module ROM
|
|
9
9
|
# Query API for SQL::Relation
|
10
10
|
#
|
11
11
|
# @api public
|
12
|
+
#
|
13
|
+
# rubocop:disable Metrics/ModuleLength
|
12
14
|
module Reading
|
13
15
|
# Row-level lock modes
|
14
|
-
ROW_LOCK_MODES = Hash.new({ update:
|
16
|
+
ROW_LOCK_MODES = Hash.new({ update: 'FOR UPDATE' }).update(
|
15
17
|
# https://www.postgresql.org/docs/current/static/sql-select.html#SQL-FOR-UPDATE-SHARE
|
16
18
|
postgres: {
|
17
|
-
update: 'FOR UPDATE'
|
18
|
-
no_key_update: 'FOR NO KEY UPDATE'
|
19
|
-
share: 'FOR SHARE'
|
20
|
-
key_share: 'FOR KEY SHARE'
|
19
|
+
update: 'FOR UPDATE',
|
20
|
+
no_key_update: 'FOR NO KEY UPDATE',
|
21
|
+
share: 'FOR SHARE',
|
22
|
+
key_share: 'FOR KEY SHARE'
|
21
23
|
},
|
22
24
|
# https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
|
23
25
|
mysql: {
|
24
|
-
update: 'FOR UPDATE'
|
25
|
-
share: 'LOCK IN SHARE MODE'
|
26
|
+
update: 'FOR UPDATE',
|
27
|
+
share: 'LOCK IN SHARE MODE'
|
26
28
|
}
|
27
29
|
).freeze
|
28
30
|
|
@@ -140,11 +142,11 @@ module ROM
|
|
140
142
|
# from tuples
|
141
143
|
#
|
142
144
|
# @api public
|
143
|
-
def map(key = nil, &
|
145
|
+
def map(key = nil, &)
|
144
146
|
if key
|
145
|
-
dataset.map(key, &
|
147
|
+
dataset.map(key, &)
|
146
148
|
else
|
147
|
-
dataset.map(&
|
149
|
+
dataset.map(&)
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
@@ -235,8 +237,8 @@ module ROM
|
|
235
237
|
# @return [Relation]
|
236
238
|
#
|
237
239
|
# @api public
|
238
|
-
def select(
|
239
|
-
schema.project(
|
240
|
+
def select(...)
|
241
|
+
schema.project(...).(self)
|
240
242
|
end
|
241
243
|
alias_method :project, :select
|
242
244
|
|
@@ -247,8 +249,8 @@ module ROM
|
|
247
249
|
# @return [Relation]
|
248
250
|
#
|
249
251
|
# @api public
|
250
|
-
def select_append(
|
251
|
-
schema.merge(schema.canonical.project(
|
252
|
+
def select_append(...)
|
253
|
+
schema.merge(schema.canonical.project(...)).(self)
|
252
254
|
end
|
253
255
|
|
254
256
|
# Returns a copy of the relation with a SQL DISTINCT clause.
|
@@ -271,8 +273,8 @@ module ROM
|
|
271
273
|
# @return [Relation]
|
272
274
|
#
|
273
275
|
# @api public
|
274
|
-
def distinct(
|
275
|
-
new(dataset.__send__(__method__,
|
276
|
+
def distinct(...)
|
277
|
+
new(dataset.__send__(__method__, ...))
|
276
278
|
end
|
277
279
|
|
278
280
|
# Returns a result of SQL SUM clause.
|
@@ -359,9 +361,9 @@ module ROM
|
|
359
361
|
# @return [Relation]
|
360
362
|
#
|
361
363
|
# @api public
|
362
|
-
def where(*args, &
|
363
|
-
if
|
364
|
-
where(*args).where(schema.canonical.restriction(&
|
364
|
+
def where(*args, &)
|
365
|
+
if block_given?
|
366
|
+
where(*args).where(schema.canonical.restriction(&))
|
365
367
|
elsif args.size == 1 && args[0].is_a?(Hash)
|
366
368
|
new(dataset.where(coerce_conditions(args[0])))
|
367
369
|
elsif !args.empty?
|
@@ -381,8 +383,8 @@ module ROM
|
|
381
383
|
# @return [Relation]
|
382
384
|
#
|
383
385
|
# @api public
|
384
|
-
def exclude(
|
385
|
-
new(dataset.__send__(__method__,
|
386
|
+
def exclude(...)
|
387
|
+
new(dataset.__send__(__method__, ...))
|
386
388
|
end
|
387
389
|
|
388
390
|
# Restrict a relation to match grouping criteria
|
@@ -418,9 +420,9 @@ module ROM
|
|
418
420
|
# @return [Relation]
|
419
421
|
#
|
420
422
|
# @api public
|
421
|
-
def having(*args, &
|
422
|
-
if
|
423
|
-
new(dataset.having(*args, *schema.canonical.restriction(&
|
423
|
+
def having(*args, &)
|
424
|
+
if block_given?
|
425
|
+
new(dataset.having(*args, *schema.canonical.restriction(&)))
|
424
426
|
else
|
425
427
|
new(dataset.__send__(__method__, *args))
|
426
428
|
end
|
@@ -473,11 +475,11 @@ module ROM
|
|
473
475
|
# @return [Relation]
|
474
476
|
#
|
475
477
|
# @api public
|
476
|
-
def order(*args, &
|
477
|
-
if
|
478
|
-
new(dataset.order(*args, *schema.canonical.order(&
|
478
|
+
def order(*args, &)
|
479
|
+
if block_given?
|
480
|
+
new(dataset.order(*args, *schema.canonical.order(&)))
|
479
481
|
else
|
480
|
-
new(dataset.__send__(__method__, *args, &
|
482
|
+
new(dataset.__send__(__method__, *args, &))
|
481
483
|
end
|
482
484
|
end
|
483
485
|
|
@@ -501,8 +503,8 @@ module ROM
|
|
501
503
|
# @return [Relation]
|
502
504
|
#
|
503
505
|
# @api public
|
504
|
-
def reverse(
|
505
|
-
new(dataset.__send__(__method__,
|
506
|
+
def reverse(...)
|
507
|
+
new(dataset.__send__(__method__, ...))
|
506
508
|
end
|
507
509
|
|
508
510
|
# Limit a relation to a specific number of tuples
|
@@ -590,8 +592,8 @@ module ROM
|
|
590
592
|
# @return [Relation]
|
591
593
|
#
|
592
594
|
# @api public
|
593
|
-
def join(
|
594
|
-
__join__(__method__,
|
595
|
+
def join(...)
|
596
|
+
__join__(__method__, ...)
|
595
597
|
end
|
596
598
|
alias_method :inner_join, :join
|
597
599
|
|
@@ -640,8 +642,8 @@ module ROM
|
|
640
642
|
# @return [Relation]
|
641
643
|
#
|
642
644
|
# @api public
|
643
|
-
def left_join(
|
644
|
-
__join__(__method__,
|
645
|
+
def left_join(...)
|
646
|
+
__join__(__method__, ...)
|
645
647
|
end
|
646
648
|
|
647
649
|
# Join with another relation using RIGHT JOIN
|
@@ -689,8 +691,8 @@ module ROM
|
|
689
691
|
# @return [Relation]
|
690
692
|
#
|
691
693
|
# @api public
|
692
|
-
def right_join(
|
693
|
-
__join__(__method__,
|
694
|
+
def right_join(...)
|
695
|
+
__join__(__method__, ...)
|
694
696
|
end
|
695
697
|
|
696
698
|
# Group by specific columns
|
@@ -722,12 +724,12 @@ module ROM
|
|
722
724
|
# @return [Relation]
|
723
725
|
#
|
724
726
|
# @api public
|
725
|
-
def group(*args, &
|
726
|
-
if
|
727
|
-
if args.size
|
728
|
-
group(*args).group_append(&
|
727
|
+
def group(*args, &)
|
728
|
+
if block_given?
|
729
|
+
if args.size.positive?
|
730
|
+
group(*args).group_append(&)
|
729
731
|
else
|
730
|
-
new(dataset.__send__(__method__, *schema.canonical.group(&
|
732
|
+
new(dataset.__send__(__method__, *schema.canonical.group(&)))
|
731
733
|
end
|
732
734
|
else
|
733
735
|
new(dataset.__send__(__method__, *schema.canonical.project(*args)))
|
@@ -761,12 +763,12 @@ module ROM
|
|
761
763
|
# @return [Relation]
|
762
764
|
#
|
763
765
|
# @api public
|
764
|
-
def group_append(*args, &
|
765
|
-
if
|
766
|
-
if args.size
|
767
|
-
group_append(*args).group_append(&
|
766
|
+
def group_append(*args, &)
|
767
|
+
if block_given?
|
768
|
+
if args.size.positive?
|
769
|
+
group_append(*args).group_append(&)
|
768
770
|
else
|
769
|
-
new(dataset.group_append(*schema.canonical.group(&
|
771
|
+
new(dataset.group_append(*schema.canonical.group(&)))
|
770
772
|
end
|
771
773
|
else
|
772
774
|
new(dataset.group_append(*args))
|
@@ -784,8 +786,8 @@ module ROM
|
|
784
786
|
# @return [Relation]
|
785
787
|
#
|
786
788
|
# @api public
|
787
|
-
def group_and_count(
|
788
|
-
new(dataset.__send__(__method__,
|
789
|
+
def group_and_count(...)
|
790
|
+
new(dataset.__send__(__method__, ...))
|
789
791
|
end
|
790
792
|
|
791
793
|
# Select and group by specific columns
|
@@ -799,8 +801,8 @@ module ROM
|
|
799
801
|
# @return [Relation]
|
800
802
|
#
|
801
803
|
# @api public
|
802
|
-
def select_group(
|
803
|
-
new_schema = schema.project(
|
804
|
+
def select_group(...)
|
805
|
+
new_schema = schema.project(...)
|
804
806
|
new_schema.(self).group(*new_schema)
|
805
807
|
end
|
806
808
|
|
@@ -813,14 +815,17 @@ module ROM
|
|
813
815
|
# @param [Relation] relation Another relation
|
814
816
|
#
|
815
817
|
# @param [Hash] options Options for union
|
816
|
-
# @option options [Symbol] :alias
|
817
|
-
#
|
818
|
-
# @option options [
|
818
|
+
# @option options [Symbol] :alias
|
819
|
+
# Use the given value as the #from_self alias
|
820
|
+
# @option options [true, false] :all
|
821
|
+
# Set to true to use UNION ALL instead of UNION, so duplicate rows can occur
|
822
|
+
# @option options [true, false] :from_self
|
823
|
+
# Set to false to not wrap the returned dataset in a #from_self, use with care.
|
819
824
|
#
|
820
825
|
# @returRelation]
|
821
826
|
#
|
822
827
|
# @api public
|
823
|
-
def union(relation, options = EMPTY_HASH, &
|
828
|
+
def union(relation, options = EMPTY_HASH, &)
|
824
829
|
# We use the original relation name here if both relations have the
|
825
830
|
# same name. This makes it so if the user at some point references
|
826
831
|
# the relation directly by name later on things won't break in
|
@@ -830,7 +835,7 @@ module ROM
|
|
830
835
|
opts = { alias: alias_name.to_sym, **options }
|
831
836
|
|
832
837
|
new_schema = schema.qualified(opts[:alias])
|
833
|
-
new_schema.(new(dataset.__send__(__method__, relation.dataset, opts, &
|
838
|
+
new_schema.(new(dataset.__send__(__method__, relation.dataset, opts, &)))
|
834
839
|
end
|
835
840
|
|
836
841
|
# Checks whether a relation has at least one tuple
|
@@ -848,8 +853,8 @@ module ROM
|
|
848
853
|
# @return [TrueClass, FalseClass]
|
849
854
|
#
|
850
855
|
# @api public
|
851
|
-
def exist?(
|
852
|
-
!where(
|
856
|
+
def exist?(...)
|
857
|
+
!where(...).limit(1).count.zero?
|
853
858
|
end
|
854
859
|
|
855
860
|
# Return if a restricted relation has 0 tuples
|
@@ -905,12 +910,12 @@ module ROM
|
|
905
910
|
# @yieldparam relation [Array]
|
906
911
|
#
|
907
912
|
# @api public
|
908
|
-
def lock(**options, &
|
913
|
+
def lock(**options, &)
|
909
914
|
clause = lock_clause(**options)
|
910
915
|
|
911
|
-
if
|
916
|
+
if block_given?
|
912
917
|
transaction do
|
913
|
-
|
918
|
+
yield(dataset.lock_style(clause).to_a)
|
914
919
|
end
|
915
920
|
else
|
916
921
|
new(dataset.lock_style(clause))
|
@@ -1050,7 +1055,7 @@ module ROM
|
|
1050
1055
|
stmt << ' OF ' << Array(of).join(', ') if of
|
1051
1056
|
|
1052
1057
|
if skip_locked
|
1053
|
-
raise ArgumentError, 'SKIP LOCKED cannot be used with (NO)WAIT clause'
|
1058
|
+
raise ArgumentError, 'SKIP LOCKED cannot be used with (NO)WAIT clause' unless wait.nil?
|
1054
1059
|
|
1055
1060
|
stmt << ' SKIP LOCKED'
|
1056
1061
|
else
|
@@ -1068,6 +1073,8 @@ module ROM
|
|
1068
1073
|
# Apply input types to condition values
|
1069
1074
|
#
|
1070
1075
|
# @api private
|
1076
|
+
#
|
1077
|
+
# rubocop:disable Metrics/AbcSize
|
1071
1078
|
def coerce_conditions(conditions)
|
1072
1079
|
conditions.each_with_object({}) { |(k, v), h|
|
1073
1080
|
if k.is_a?(Symbol) && schema.canonical.key?(k)
|
@@ -1080,25 +1087,28 @@ module ROM
|
|
1080
1087
|
end
|
1081
1088
|
}
|
1082
1089
|
end
|
1090
|
+
# rubocop:enable Metrics/AbcSize
|
1083
1091
|
|
1084
1092
|
# Common join method used by other join methods
|
1085
1093
|
#
|
1086
1094
|
# @api private
|
1087
|
-
|
1095
|
+
#
|
1096
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
1097
|
+
def __join__(type, other, join_cond = EMPTY_HASH, opts = EMPTY_HASH, &)
|
1088
1098
|
if other.is_a?(Symbol) || other.is_a?(ROM::Relation::Name)
|
1089
|
-
if join_cond.equal?(EMPTY_HASH) && !
|
1099
|
+
if join_cond.equal?(EMPTY_HASH) && !block_given?
|
1090
1100
|
assoc = associations[other]
|
1091
1101
|
assoc.join(type, self)
|
1092
|
-
elsif
|
1093
|
-
__join__(type, other, JoinDSL.new(schema).(&
|
1102
|
+
elsif block_given?
|
1103
|
+
__join__(type, other, JoinDSL.new(schema).(&), opts)
|
1094
1104
|
else
|
1095
|
-
new(dataset.__send__(type, other.to_sym, join_cond, opts, &
|
1105
|
+
new(dataset.__send__(type, other.to_sym, join_cond, opts, &))
|
1096
1106
|
end
|
1097
|
-
elsif other.is_a?(Sequel::SQL::AliasedExpression)
|
1098
|
-
new(dataset.__send__(type, other, join_cond, opts, &
|
1107
|
+
elsif other.is_a?(::Sequel::SQL::AliasedExpression)
|
1108
|
+
new(dataset.__send__(type, other, join_cond, opts, &))
|
1099
1109
|
elsif other.respond_to?(:name) && other.name.is_a?(Relation::Name)
|
1100
|
-
if
|
1101
|
-
join_cond = JoinDSL.new(schema).(&
|
1110
|
+
if block_given?
|
1111
|
+
join_cond = JoinDSL.new(schema).(&)
|
1102
1112
|
|
1103
1113
|
if other.name.aliaz
|
1104
1114
|
join_opts = { table_alias: other.name.aliaz }
|
@@ -1111,10 +1121,12 @@ module ROM
|
|
1111
1121
|
associations[other.name.key].join(type, self, other)
|
1112
1122
|
end
|
1113
1123
|
else
|
1114
|
-
raise ArgumentError,
|
1124
|
+
raise ArgumentError,
|
1125
|
+
"+other+ must be either a symbol or a relation, #{other.class} given"
|
1115
1126
|
end
|
1116
1127
|
end
|
1117
1128
|
end
|
1129
|
+
# rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/ModuleLength
|
1118
1130
|
end
|
1119
1131
|
end
|
1120
1132
|
end
|