rom-sql 2.5.0 → 3.3.0
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/CHANGELOG.md +456 -278
- data/LICENSE +20 -0
- data/README.md +14 -24
- data/lib/rom-sql.rb +2 -0
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +2 -0
- data/lib/rom/plugins/relation/sql/instrumentation.rb +2 -0
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +6 -7
- data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +53 -0
- data/lib/rom/plugins/relation/sql/postgres/streaming.rb +97 -0
- data/lib/rom/sql.rb +2 -0
- data/lib/rom/sql/associations.rb +2 -0
- data/lib/rom/sql/associations/core.rb +10 -0
- data/lib/rom/sql/associations/many_to_many.rb +10 -2
- data/lib/rom/sql/associations/many_to_one.rb +2 -0
- data/lib/rom/sql/associations/one_to_many.rb +2 -0
- data/lib/rom/sql/associations/one_to_one.rb +2 -0
- data/lib/rom/sql/associations/one_to_one_through.rb +2 -0
- data/lib/rom/sql/associations/self_ref.rb +2 -0
- data/lib/rom/sql/attribute.rb +87 -29
- data/lib/rom/sql/attribute_aliasing.rb +88 -0
- data/lib/rom/sql/attribute_wrapping.rb +30 -0
- data/lib/rom/sql/commands.rb +2 -0
- data/lib/rom/sql/commands/create.rb +2 -0
- data/lib/rom/sql/commands/delete.rb +2 -0
- data/lib/rom/sql/commands/error_wrapper.rb +2 -0
- data/lib/rom/sql/commands/update.rb +2 -0
- data/lib/rom/sql/dsl.rb +39 -1
- data/lib/rom/sql/error.rb +2 -0
- data/lib/rom/sql/errors.rb +2 -0
- data/lib/rom/sql/extensions.rb +2 -0
- data/lib/rom/sql/extensions/active_support_notifications.rb +2 -0
- data/lib/rom/sql/extensions/mysql.rb +2 -0
- data/lib/rom/sql/extensions/mysql/type_builder.rb +2 -0
- data/lib/rom/sql/extensions/postgres.rb +4 -0
- data/lib/rom/sql/extensions/postgres/commands.rb +3 -1
- data/lib/rom/sql/extensions/postgres/type_builder.rb +6 -4
- data/lib/rom/sql/extensions/postgres/type_serializer.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types/array.rb +9 -8
- data/lib/rom/sql/extensions/postgres/types/array_types.rb +3 -1
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types/json.rb +76 -19
- data/lib/rom/sql/extensions/postgres/types/ltree.rb +27 -25
- data/lib/rom/sql/extensions/postgres/types/network.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types/range.rb +6 -4
- data/lib/rom/sql/extensions/rails_log_subscriber.rb +2 -0
- data/lib/rom/sql/extensions/sqlite.rb +2 -0
- data/lib/rom/sql/extensions/sqlite/type_builder.rb +2 -0
- data/lib/rom/sql/extensions/sqlite/types.rb +2 -0
- data/lib/rom/sql/foreign_key.rb +3 -1
- data/lib/rom/sql/function.rb +84 -6
- data/lib/rom/sql/gateway.rb +9 -1
- data/lib/rom/sql/group_dsl.rb +2 -0
- data/lib/rom/sql/index.rb +2 -0
- data/lib/rom/sql/join_dsl.rb +11 -0
- data/lib/rom/sql/mapper_compiler.rb +14 -3
- data/lib/rom/sql/migration.rb +20 -3
- data/lib/rom/sql/migration/inline_runner.rb +2 -0
- data/lib/rom/sql/migration/migrator.rb +5 -3
- data/lib/rom/sql/migration/recorder.rb +2 -0
- data/lib/rom/sql/migration/runner.rb +4 -2
- data/lib/rom/sql/migration/schema_diff.rb +4 -2
- data/lib/rom/sql/migration/template.rb +2 -0
- data/lib/rom/sql/migration/writer.rb +12 -4
- data/lib/rom/sql/order_dsl.rb +2 -0
- data/lib/rom/sql/plugin/associates.rb +4 -3
- data/lib/rom/sql/plugin/nullify.rb +37 -0
- data/lib/rom/sql/plugin/pagination.rb +22 -0
- data/lib/rom/sql/plugins.rb +4 -0
- data/lib/rom/sql/projection_dsl.rb +10 -4
- data/lib/rom/sql/rake_task.rb +2 -0
- data/lib/rom/sql/relation.rb +3 -1
- data/lib/rom/sql/relation/reading.rb +105 -16
- data/lib/rom/sql/relation/writing.rb +2 -0
- data/lib/rom/sql/restriction_dsl.rb +8 -8
- data/lib/rom/sql/schema.rb +16 -2
- data/lib/rom/sql/schema/attributes_inferrer.rb +7 -5
- data/lib/rom/sql/schema/dsl.rb +3 -1
- data/lib/rom/sql/schema/index_dsl.rb +8 -3
- data/lib/rom/sql/schema/inferrer.rb +12 -8
- data/lib/rom/sql/schema/type_builder.rb +4 -2
- data/lib/rom/sql/spec/support.rb +5 -3
- data/lib/rom/sql/tasks/migration_tasks.rake +16 -11
- data/lib/rom/sql/transaction.rb +2 -0
- data/lib/rom/sql/type_dsl.rb +3 -1
- data/lib/rom/sql/type_extensions.rb +4 -4
- data/lib/rom/sql/type_serializer.rb +3 -1
- data/lib/rom/sql/types.rb +6 -4
- data/lib/rom/sql/version.rb +3 -1
- data/lib/rom/sql/wrap.rb +2 -0
- data/lib/rom/types/values.rb +2 -0
- metadata +39 -37
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/types/values'
|
|
2
4
|
|
|
3
5
|
module ROM
|
|
@@ -222,20 +224,20 @@ module ROM
|
|
|
222
224
|
#
|
|
223
225
|
# end
|
|
224
226
|
module LTreeMethods
|
|
225
|
-
ASCENDANT = [
|
|
226
|
-
FIND_ASCENDANT = [
|
|
227
|
-
DESCENDANT = [
|
|
228
|
-
FIND_DESCENDANT = [
|
|
229
|
-
MATCH_ANY = [
|
|
230
|
-
MATCH_ANY_LQUERY = [
|
|
231
|
-
MATCH_LTEXTQUERY = [
|
|
232
|
-
MATCH_ANY_LTEXTQUERY = [
|
|
227
|
+
ASCENDANT = ['(', ' @> ', ')'].freeze
|
|
228
|
+
FIND_ASCENDANT = ['(', ' ?@> ', ')'].freeze
|
|
229
|
+
DESCENDANT = ['(', ' <@ ', ')'].freeze
|
|
230
|
+
FIND_DESCENDANT = ['(', ' ?<@ ', ')'].freeze
|
|
231
|
+
MATCH_ANY = ['(', ' ? ', ')'].freeze
|
|
232
|
+
MATCH_ANY_LQUERY = ['(', ' ?~ ', ')'].freeze
|
|
233
|
+
MATCH_LTEXTQUERY = ['(', ' @ ', ')'].freeze
|
|
234
|
+
MATCH_ANY_LTEXTQUERY = ['(', ' ?@ ', ')'].freeze
|
|
233
235
|
|
|
234
|
-
def match(
|
|
236
|
+
def match(_type, expr, query)
|
|
235
237
|
Attribute[SQL::Types::Bool].meta(sql_expr: Sequel::SQL::BooleanExpression.new(:'~', expr, query))
|
|
236
238
|
end
|
|
237
239
|
|
|
238
|
-
def match_any(
|
|
240
|
+
def match_any(_type, expr, query)
|
|
239
241
|
array = build_array_query(query)
|
|
240
242
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(MATCH_ANY, expr, array))
|
|
241
243
|
end
|
|
@@ -248,9 +250,9 @@ module ROM
|
|
|
248
250
|
|
|
249
251
|
def build_array_query(query, array_type = 'lquery')
|
|
250
252
|
case query
|
|
251
|
-
when Array
|
|
253
|
+
when ::Array
|
|
252
254
|
ROM::SQL::Types::PG::Array(array_type)[query]
|
|
253
|
-
when String
|
|
255
|
+
when ::String
|
|
254
256
|
ROM::SQL::Types::PG::Array(array_type)[query.split(',')]
|
|
255
257
|
end
|
|
256
258
|
end
|
|
@@ -259,31 +261,31 @@ module ROM
|
|
|
259
261
|
TypeExtensions.register(ROM::SQL::Types::PG::Array('ltree', LTree)) do
|
|
260
262
|
include LTreeMethods
|
|
261
263
|
|
|
262
|
-
def contain_any_ltextquery(
|
|
264
|
+
def contain_any_ltextquery(_type, expr, query)
|
|
263
265
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::MATCH_LTEXTQUERY, expr, query))
|
|
264
266
|
end
|
|
265
267
|
|
|
266
|
-
def contain_ancestor(
|
|
268
|
+
def contain_ancestor(_type, expr, query)
|
|
267
269
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::ASCENDANT, expr, query))
|
|
268
270
|
end
|
|
269
271
|
|
|
270
|
-
def contain_descendant(
|
|
272
|
+
def contain_descendant(_type, expr, query)
|
|
271
273
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::DESCENDANT, expr, query))
|
|
272
274
|
end
|
|
273
275
|
|
|
274
|
-
def find_ancestor(
|
|
276
|
+
def find_ancestor(_type, expr, query)
|
|
275
277
|
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::FIND_ASCENDANT, expr, query))
|
|
276
278
|
end
|
|
277
279
|
|
|
278
|
-
def find_descendant(
|
|
280
|
+
def find_descendant(_type, expr, query)
|
|
279
281
|
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::FIND_DESCENDANT, expr, query))
|
|
280
282
|
end
|
|
281
283
|
|
|
282
|
-
def match_any_lquery(
|
|
284
|
+
def match_any_lquery(_type, expr, query)
|
|
283
285
|
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::MATCH_ANY_LQUERY, expr, query))
|
|
284
286
|
end
|
|
285
287
|
|
|
286
|
-
def match_any_ltextquery(
|
|
288
|
+
def match_any_ltextquery(_type, expr, query)
|
|
287
289
|
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::MATCH_ANY_LTEXTQUERY, expr, query))
|
|
288
290
|
end
|
|
289
291
|
end
|
|
@@ -291,29 +293,29 @@ module ROM
|
|
|
291
293
|
TypeExtensions.register(LTree) do
|
|
292
294
|
include LTreeMethods
|
|
293
295
|
|
|
294
|
-
def match_ltextquery(
|
|
296
|
+
def match_ltextquery(_type, expr, query)
|
|
295
297
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::MATCH_LTEXTQUERY, expr, query))
|
|
296
298
|
end
|
|
297
299
|
|
|
298
|
-
def contain_descendant(
|
|
300
|
+
def contain_descendant(_type, expr, query)
|
|
299
301
|
array = build_array_query(query, 'ltree')
|
|
300
302
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::DESCENDANT, expr, array))
|
|
301
303
|
end
|
|
302
304
|
|
|
303
|
-
def descendant(
|
|
305
|
+
def descendant(_type, expr, query)
|
|
304
306
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::DESCENDANT, expr, query))
|
|
305
307
|
end
|
|
306
308
|
|
|
307
|
-
def contain_ascendant(
|
|
309
|
+
def contain_ascendant(_type, expr, query)
|
|
308
310
|
array = build_array_query(query, 'ltree')
|
|
309
311
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::ASCENDANT, expr, array))
|
|
310
312
|
end
|
|
311
313
|
|
|
312
|
-
def ascendant(
|
|
314
|
+
def ascendant(_type, expr, query)
|
|
313
315
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(LTreeMethods::ASCENDANT, expr, query))
|
|
314
316
|
end
|
|
315
317
|
|
|
316
|
-
def +(
|
|
318
|
+
def +(_type, expr, other)
|
|
317
319
|
other_value = case other
|
|
318
320
|
when ROM::Types::Values::TreePath
|
|
319
321
|
other
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'sequel/core'
|
|
2
4
|
|
|
3
5
|
Sequel.extension(:pg_range, :pg_range_ops)
|
|
@@ -31,13 +33,13 @@ module ROM
|
|
|
31
33
|
|
|
32
34
|
@range_parsers = {
|
|
33
35
|
int4range: Sequel::Postgres::PGRange::Parser.new(
|
|
34
|
-
'int4range', SQL::Types::Coercible::
|
|
36
|
+
'int4range', SQL::Types::Coercible::Integer
|
|
35
37
|
),
|
|
36
38
|
int8range: Sequel::Postgres::PGRange::Parser.new(
|
|
37
|
-
'int8range', SQL::Types::Coercible::
|
|
39
|
+
'int8range', SQL::Types::Coercible::Integer
|
|
38
40
|
),
|
|
39
41
|
numrange: Sequel::Postgres::PGRange::Parser.new(
|
|
40
|
-
'numrange', SQL::Types::Coercible::
|
|
42
|
+
'numrange', SQL::Types::Coercible::Integer
|
|
41
43
|
),
|
|
42
44
|
tsrange: Sequel::Postgres::PGRange::Parser.new(
|
|
43
45
|
'tsrange', ::Time.method(:parse)
|
|
@@ -75,7 +77,7 @@ module ROM
|
|
|
75
77
|
# @api private
|
|
76
78
|
def self.range(name, read_type)
|
|
77
79
|
Type(name) do
|
|
78
|
-
type = SQL::Types.
|
|
80
|
+
type = SQL::Types.Nominal(Values::Range).constructor do |range|
|
|
79
81
|
format('%s%s,%s%s',
|
|
80
82
|
range.exclude_begin? ? :'(' : :'[',
|
|
81
83
|
range.lower,
|
data/lib/rom/sql/foreign_key.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ROM
|
|
2
4
|
module SQL
|
|
3
5
|
# @api private
|
|
@@ -5,7 +7,7 @@ module ROM
|
|
|
5
7
|
extend Initializer
|
|
6
8
|
include Dry::Equalizer(:attributes, :parent_table, :options)
|
|
7
9
|
|
|
8
|
-
DEFAULT_PARENT_KEYS = %i
|
|
10
|
+
DEFAULT_PARENT_KEYS = %i[id].freeze
|
|
9
11
|
|
|
10
12
|
param :attributes
|
|
11
13
|
|
data/lib/rom/sql/function.rb
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/attribute'
|
|
4
|
+
require 'rom/sql/attribute_wrapping'
|
|
2
5
|
|
|
3
6
|
module ROM
|
|
4
7
|
module SQL
|
|
@@ -6,6 +9,8 @@ module ROM
|
|
|
6
9
|
#
|
|
7
10
|
# @api public
|
|
8
11
|
class Function < ROM::Attribute
|
|
12
|
+
include AttributeWrapping
|
|
13
|
+
|
|
9
14
|
class << self
|
|
10
15
|
# @api private
|
|
11
16
|
def frame_limit(value)
|
|
@@ -37,6 +42,19 @@ module ROM
|
|
|
37
42
|
WINDOW_FRAMES[:rows] = WINDOW_FRAMES[rows: [:start, :current]]
|
|
38
43
|
WINDOW_FRAMES[range: :current] = WINDOW_FRAMES[range: [:current, :current]]
|
|
39
44
|
|
|
45
|
+
# Return a new attribute with an alias
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# string::coalesce(users[:name], users[:id]).aliased(:display_name)
|
|
49
|
+
#
|
|
50
|
+
# @return [SQL::Function]
|
|
51
|
+
#
|
|
52
|
+
# @api public
|
|
53
|
+
def aliased(alias_name)
|
|
54
|
+
super.with(name: name || alias_name)
|
|
55
|
+
end
|
|
56
|
+
alias_method :as, :aliased
|
|
57
|
+
|
|
40
58
|
# @api private
|
|
41
59
|
def sql_literal(ds)
|
|
42
60
|
if name
|
|
@@ -48,7 +66,7 @@ module ROM
|
|
|
48
66
|
|
|
49
67
|
# @api private
|
|
50
68
|
def name
|
|
51
|
-
|
|
69
|
+
self.alias || super
|
|
52
70
|
end
|
|
53
71
|
|
|
54
72
|
# @see Attribute#qualified
|
|
@@ -60,6 +78,22 @@ module ROM
|
|
|
60
78
|
)
|
|
61
79
|
end
|
|
62
80
|
|
|
81
|
+
# @see Attribute#qualified_projection
|
|
82
|
+
#
|
|
83
|
+
# @api private
|
|
84
|
+
def qualified_projection(table_alias = nil)
|
|
85
|
+
meta(
|
|
86
|
+
func: ::Sequel::SQL::Function.new(func.name, *func.args.map { |arg| arg.respond_to?(:qualified_projection) ? arg.qualified_projection(table_alias) : arg })
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @see Attribute#qualified?
|
|
91
|
+
#
|
|
92
|
+
# @api private
|
|
93
|
+
def qualified?(_table_alias = nil)
|
|
94
|
+
meta[:func].args.all?(&:qualified?)
|
|
95
|
+
end
|
|
96
|
+
|
|
63
97
|
# @see ROM::SQL::Attribute#is
|
|
64
98
|
#
|
|
65
99
|
# @api public
|
|
@@ -80,8 +114,8 @@ module ROM
|
|
|
80
114
|
# @see https://www.postgresql.org/docs/9.6/static/tutorial-window.html
|
|
81
115
|
#
|
|
82
116
|
# @example
|
|
83
|
-
# users.select { [id,
|
|
84
|
-
# users.select { [id,
|
|
117
|
+
# users.select { [id, integer::row_number().over(partition: name, order: id).as(:row_no)] }
|
|
118
|
+
# users.select { [id, integer::row_number().over(partition: [first_name, last_name], order: id).as(:row_no)] }
|
|
85
119
|
#
|
|
86
120
|
# @example frame variants
|
|
87
121
|
# # ROWS BETWEEN 3 PRECEDING AND CURRENT ROW
|
|
@@ -132,16 +166,36 @@ module ROM
|
|
|
132
166
|
Attribute[type].meta(sql_expr: ::Sequel.cast(expr, db_type))
|
|
133
167
|
end
|
|
134
168
|
|
|
169
|
+
# Add a CASE clause for handling if/then logic. This version of CASE search for the first
|
|
170
|
+
# branch which evaluates to `true`. See SQL::Attriubte#case if you're looking for the
|
|
171
|
+
# version that matches an expression result
|
|
172
|
+
#
|
|
173
|
+
# @example
|
|
174
|
+
# users.select { bool::case(status.is("active") => true, else: false).as(:activated) }
|
|
175
|
+
#
|
|
176
|
+
# @param [Hash] mapping mapping between boolean SQL expressions to arbitrary SQL expressions
|
|
177
|
+
# @return [ROM::SQL::Attribute]
|
|
178
|
+
#
|
|
179
|
+
# @api public
|
|
180
|
+
def case(mapping)
|
|
181
|
+
mapping = mapping.dup
|
|
182
|
+
otherwise = mapping.delete(:else) do
|
|
183
|
+
raise ArgumentError, 'provide the default case using the :else keyword'
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
Attribute[type].meta(sql_expr: ::Sequel.case(mapping, otherwise))
|
|
187
|
+
end
|
|
188
|
+
|
|
135
189
|
# Add a FILTER clause to aggregate function (supported by PostgreSQL 9.4+)
|
|
136
190
|
# @see https://www.postgresql.org/docs/current/static/sql-expressions.html
|
|
137
191
|
#
|
|
138
192
|
# Filter aggregate using the specified conditions
|
|
139
193
|
#
|
|
140
194
|
# @example
|
|
141
|
-
# users.project {
|
|
142
|
-
# users.project {
|
|
195
|
+
# users.project { integer::count(:id).filter(name.is("Jack")).as(:jacks) }.order(nil)
|
|
196
|
+
# users.project { integer::count(:id).filter { name.is("John") }).as(:johns) }.order(nil)
|
|
143
197
|
#
|
|
144
|
-
# @param [Hash,SQL::Attribute] Conditions
|
|
198
|
+
# @param condition [Hash,SQL::Attribute] Conditions
|
|
145
199
|
# @yield [block] A block with restrictions
|
|
146
200
|
#
|
|
147
201
|
# @return [SQL::Function]
|
|
@@ -158,6 +212,30 @@ module ROM
|
|
|
158
212
|
super(conditions)
|
|
159
213
|
end
|
|
160
214
|
|
|
215
|
+
# Add a WITHIN GROUP clause to aggregate function (supported by PostgreSQL)
|
|
216
|
+
# @see https://www.postgresql.org/docs/current/static/sql-expressions.html#SYNTAX-AGGREGATES
|
|
217
|
+
#
|
|
218
|
+
# Establishes an order for an ordered-set aggregate, see the docs for more details
|
|
219
|
+
#
|
|
220
|
+
# @example
|
|
221
|
+
# households.project { fload::percentile_cont(0.5).within_group(income).as(:percentile) }
|
|
222
|
+
#
|
|
223
|
+
# @param args [Array] A list of expressions for sorting within a group
|
|
224
|
+
# @yield [block] A block for getting the expressions using the Order DSL
|
|
225
|
+
#
|
|
226
|
+
# @return [SQL::Function]
|
|
227
|
+
#
|
|
228
|
+
# @api public
|
|
229
|
+
def within_group(*args, &block)
|
|
230
|
+
if block
|
|
231
|
+
group = args + ::ROM::SQL::OrderDSL.new(schema).(&block)
|
|
232
|
+
else
|
|
233
|
+
group = args
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
super(*group)
|
|
237
|
+
end
|
|
238
|
+
|
|
161
239
|
private
|
|
162
240
|
|
|
163
241
|
# @api private
|
data/lib/rom/sql/gateway.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'logger'
|
|
2
4
|
require 'sequel/core'
|
|
3
5
|
|
|
@@ -21,7 +23,7 @@ module ROM
|
|
|
21
23
|
adapter :sql
|
|
22
24
|
|
|
23
25
|
CONNECTION_EXTENSIONS = {
|
|
24
|
-
postgres: %i
|
|
26
|
+
postgres: %i[pg_array pg_json pg_enum]
|
|
25
27
|
}.freeze
|
|
26
28
|
|
|
27
29
|
# @!attribute [r] logger
|
|
@@ -79,6 +81,7 @@ module ROM
|
|
|
79
81
|
def initialize(uri, options = EMPTY_HASH)
|
|
80
82
|
@connection = connect(uri, options)
|
|
81
83
|
load_extensions(Array(options[:extensions]))
|
|
84
|
+
Notifications.trigger("configuration.gateway.connected", connection: @connection)
|
|
82
85
|
|
|
83
86
|
@options = options
|
|
84
87
|
|
|
@@ -234,6 +237,9 @@ module ROM
|
|
|
234
237
|
# this will be default in Sequel 5.0.0 and since we don't rely
|
|
235
238
|
# on dataset mutation it is safe to enable it already
|
|
236
239
|
connection.extension(:freeze_datasets) unless RUBY_ENGINE == 'rbx'
|
|
240
|
+
|
|
241
|
+
# for ROM::SQL::Relation#nullify
|
|
242
|
+
connection.extension(:null_dataset)
|
|
237
243
|
end
|
|
238
244
|
|
|
239
245
|
# @api private
|
|
@@ -242,4 +248,6 @@ module ROM
|
|
|
242
248
|
end
|
|
243
249
|
end
|
|
244
250
|
end
|
|
251
|
+
|
|
252
|
+
Configuration.register_event("configuration.gateway.connected")
|
|
245
253
|
end
|
data/lib/rom/sql/group_dsl.rb
CHANGED
data/lib/rom/sql/index.rb
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/mapper_compiler'
|
|
2
4
|
|
|
3
5
|
module ROM
|
|
4
6
|
module SQL
|
|
5
7
|
class MapperCompiler < ROM::MapperCompiler
|
|
6
8
|
def visit_attribute(node)
|
|
7
|
-
name, _,
|
|
9
|
+
name, _, meta_options = node
|
|
8
10
|
|
|
9
|
-
if
|
|
10
|
-
[
|
|
11
|
+
if meta_options[:wrapped]
|
|
12
|
+
[extract_wrapped_name(node), from: meta_options[:alias]]
|
|
11
13
|
else
|
|
12
14
|
[name]
|
|
13
15
|
end
|
|
14
16
|
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def extract_wrapped_name(node)
|
|
21
|
+
_, _, meta_options = node
|
|
22
|
+
unwrapped_name = meta_options[:alias].to_s.dup
|
|
23
|
+
unwrapped_name.slice!("#{meta_options[:wrapped]}_")
|
|
24
|
+
unwrapped_name.to_sym
|
|
25
|
+
end
|
|
15
26
|
end
|
|
16
27
|
end
|
|
17
28
|
end
|
data/lib/rom/sql/migration.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/sql/migration/migrator'
|
|
2
4
|
require 'rom/sql/migration/schema_diff'
|
|
3
5
|
|
|
@@ -97,8 +99,8 @@ module ROM
|
|
|
97
99
|
attr_reader :migrator
|
|
98
100
|
|
|
99
101
|
# @api private
|
|
100
|
-
def initialize(
|
|
101
|
-
@migrator = options
|
|
102
|
+
def initialize(_uri, options = EMPTY_HASH)
|
|
103
|
+
@migrator = create_migrator(options[:migrator])
|
|
102
104
|
|
|
103
105
|
self.class.instance ||= self
|
|
104
106
|
end
|
|
@@ -139,13 +141,28 @@ module ROM
|
|
|
139
141
|
end
|
|
140
142
|
|
|
141
143
|
# @api public
|
|
142
|
-
def auto_migrate!(conf, options = EMPTY_HASH
|
|
144
|
+
def auto_migrate!(conf, options = EMPTY_HASH)
|
|
143
145
|
schemas = conf.relation_classes(self).map do |klass|
|
|
144
146
|
klass.schema_proc.call.finalize_attributes!(gateway: self)
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
migrator.auto_migrate!(self, schemas, options)
|
|
148
150
|
end
|
|
151
|
+
|
|
152
|
+
private
|
|
153
|
+
|
|
154
|
+
# Create a `Migrator`. If `migrator_option` is a `Hash`, use it as options to `Migrator.new`.
|
|
155
|
+
#
|
|
156
|
+
# @api private
|
|
157
|
+
def create_migrator(migrator_option)
|
|
158
|
+
return Migrator.new(connection) unless migrator_option
|
|
159
|
+
|
|
160
|
+
if migrator_option.is_a?(Hash)
|
|
161
|
+
Migrator.new(connection, **migrator_option)
|
|
162
|
+
else
|
|
163
|
+
migrator_option
|
|
164
|
+
end
|
|
165
|
+
end
|
|
149
166
|
end
|
|
150
167
|
end
|
|
151
168
|
end
|