rom-sql 1.3.1 → 1.3.2
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 +20 -0
- data/lib/rom/sql/association.rb +1 -1
- data/lib/rom/sql/association/many_to_one.rb +1 -1
- data/lib/rom/sql/association/name.rb +1 -1
- data/lib/rom/sql/association/one_to_many.rb +1 -1
- data/lib/rom/sql/attribute.rb +23 -9
- data/lib/rom/sql/dsl.rb +13 -0
- data/lib/rom/sql/extensions/postgres/commands.rb +4 -4
- data/lib/rom/sql/extensions/postgres/types.rb +262 -110
- data/lib/rom/sql/function.rb +2 -2
- data/lib/rom/sql/projection_dsl.rb +1 -12
- data/lib/rom/sql/relation.rb +1 -1
- data/lib/rom/sql/relation/reading.rb +8 -4
- data/lib/rom/sql/restriction_dsl.rb +7 -1
- data/lib/rom/sql/types.rb +2 -0
- data/lib/rom/sql/version.rb +1 -1
- data/spec/extensions/postgres/attribute_spec.rb +78 -0
- data/spec/integration/association/many_to_many/custom_fks_spec.rb +8 -3
- data/spec/integration/association/many_to_many/from_view_spec.rb +9 -3
- data/spec/integration/association/many_to_many_spec.rb +8 -2
- data/spec/integration/association/many_to_one/custom_fks_spec.rb +8 -4
- data/spec/integration/association/many_to_one/from_view_spec.rb +10 -4
- data/spec/integration/association/many_to_one/self_ref_spec.rb +4 -2
- data/spec/integration/association/many_to_one_spec.rb +8 -4
- data/spec/integration/association/one_to_many/custom_fks_spec.rb +5 -2
- data/spec/integration/association/one_to_many/from_view_spec.rb +5 -2
- data/spec/integration/association/one_to_many/self_ref_spec.rb +4 -2
- data/spec/integration/association/one_to_many_spec.rb +1 -1
- data/spec/integration/commands/upsert_spec.rb +2 -2
- data/spec/integration/plugins/auto_wrap_spec.rb +1 -1
- data/spec/integration/sequel_api_spec.rb +3 -2
- data/spec/unit/function_spec.rb +1 -1
- data/spec/unit/order_dsl_spec.rb +4 -4
- data/spec/unit/projection_dsl_spec.rb +8 -0
- data/spec/unit/relation/dataset_spec.rb +3 -3
- data/spec/unit/relation/project_spec.rb +1 -1
- data/spec/unit/relation/qualified_columns_spec.rb +3 -2
- data/spec/unit/relation/where_spec.rb +20 -0
- data/spec/unit/restriction_dsl_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfb29b79f9b58b2fc9b30752951636130b525440
|
4
|
+
data.tar.gz: 2f6b70d93abf536152d991cb689bd77c699a6e83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac6401a56919535a010c3ad049d63df969873c73169f629c5875edd343b404cf02ffc81f3458e9bbb6d3c20edc066fa5e26b2db30840a321f5ea10d5a86c5de4
|
7
|
+
data.tar.gz: d9e27f5a201c515fcd2d2d0a2f5cacae6cfdd2f44d1dfd5c0260c2121714c0491f8c49f87ed6120690d8d7f1603dcbc7308598c7e1000c4da4b775cf8d5494fa
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
## v1.3.2 to-be-released
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
* Support for filtering with a SQL function in the `WHERE` clause. Be sure you're using it wisely and don't call it on large datasets ;) (flash-gordon)
|
6
|
+
* `Void` type for calling functions without returning value (flash-gordon)
|
7
|
+
* Support for `PG::Array` transformations and queries (flash-gordon)
|
8
|
+
|
9
|
+
## Fixed
|
10
|
+
|
11
|
+
* A bunch of warnings from Sequel 4.46
|
12
|
+
|
13
|
+
## v1.3.1 2017-05-05
|
14
|
+
|
15
|
+
## Changed
|
16
|
+
|
17
|
+
* [internal] Compatibility with `dry-core` v0.3.0 (flash-gordon)
|
18
|
+
|
19
|
+
[Compare v1.3.0...v1.3.1](https://github.com/rom-rb/rom-sql/compare/v1.3.0...v1.3.1)
|
20
|
+
|
1
21
|
## v1.3.0 2017-05-02
|
2
22
|
|
3
23
|
### Added
|
data/lib/rom/sql/association.rb
CHANGED
@@ -81,7 +81,7 @@ module ROM
|
|
81
81
|
# @api protected
|
82
82
|
def apply_view(schema, relation)
|
83
83
|
view_rel = relation.public_send(view)
|
84
|
-
schema.merge(view_rel.schema.qualified).uniq(&:
|
84
|
+
schema.merge(view_rel.schema.qualified).uniq(&:to_sql_name).(view_rel)
|
85
85
|
end
|
86
86
|
|
87
87
|
# @api private
|
data/lib/rom/sql/attribute.rb
CHANGED
@@ -37,8 +37,8 @@ module ROM
|
|
37
37
|
#
|
38
38
|
# @example
|
39
39
|
# ROM::SQL::Attribute::TypeExtensions.register(ROM::SQL::Types::PG::JSONB) do
|
40
|
-
# def
|
41
|
-
#
|
40
|
+
# def contain(type, expr, keys)
|
41
|
+
# Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.contains(value))
|
42
42
|
# end
|
43
43
|
# end
|
44
44
|
#
|
@@ -104,7 +104,7 @@ module ROM
|
|
104
104
|
case sql_expr
|
105
105
|
when Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier
|
106
106
|
type = meta(qualified: true)
|
107
|
-
type.meta(
|
107
|
+
type.meta(sql_expr: type.to_sql_name)
|
108
108
|
else
|
109
109
|
raise QualifyError, "can't qualify #{name.inspect} (#{sql_expr.inspect})"
|
110
110
|
end
|
@@ -302,11 +302,25 @@ module ROM
|
|
302
302
|
#
|
303
303
|
# @api private
|
304
304
|
def sql_literal(ds)
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
305
|
+
ds.literal(sql_expr)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Sequel column representation
|
309
|
+
#
|
310
|
+
# @return [Sequel::SQL::AliasedExpression,Sequel::SQL::Identifier]
|
311
|
+
#
|
312
|
+
# @api private
|
313
|
+
def to_sql_name
|
314
|
+
@_to_sql_name ||=
|
315
|
+
if qualified? && aliased?
|
316
|
+
Sequel.qualify(source.dataset, name).as(meta[:alias])
|
317
|
+
elsif qualified?
|
318
|
+
Sequel.qualify(source.dataset, name)
|
319
|
+
elsif aliased?
|
320
|
+
Sequel.as(name, meta[:alias])
|
321
|
+
else
|
322
|
+
Sequel[name]
|
323
|
+
end
|
310
324
|
end
|
311
325
|
|
312
326
|
private
|
@@ -315,7 +329,7 @@ module ROM
|
|
315
329
|
#
|
316
330
|
# @api private
|
317
331
|
def sql_expr
|
318
|
-
@sql_expr ||= (meta[:sql_expr] ||
|
332
|
+
@sql_expr ||= (meta[:sql_expr] || to_sql_name)
|
319
333
|
end
|
320
334
|
|
321
335
|
# Delegate to sql expression if it responds to a given method
|
data/lib/rom/sql/dsl.rb
CHANGED
@@ -25,6 +25,19 @@ module ROM
|
|
25
25
|
def respond_to_missing?(name, include_private = false)
|
26
26
|
super || schema.key?(name)
|
27
27
|
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# @api private
|
32
|
+
def type(identifier)
|
33
|
+
type_name = ::Dry::Core::Inflector.classify(identifier)
|
34
|
+
types.const_get(type_name) if types.const_defined?(type_name)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api private
|
38
|
+
def types
|
39
|
+
::ROM::SQL::Types
|
40
|
+
end
|
28
41
|
end
|
29
42
|
end
|
30
43
|
end
|
@@ -11,7 +11,7 @@ module ROM
|
|
11
11
|
# @api private
|
12
12
|
def insert(tuples)
|
13
13
|
dataset = tuples.map do |tuple|
|
14
|
-
relation.dataset.returning
|
14
|
+
relation.dataset.returning.insert(tuple)
|
15
15
|
end.flatten(1)
|
16
16
|
|
17
17
|
wrap_dataset(dataset)
|
@@ -21,7 +21,7 @@ module ROM
|
|
21
21
|
#
|
22
22
|
# @api private
|
23
23
|
def multi_insert(tuples)
|
24
|
-
relation.dataset.returning
|
24
|
+
relation.dataset.returning.multi_insert(tuples)
|
25
25
|
end
|
26
26
|
|
27
27
|
# Executes upsert statement (INSERT with ON CONFLICT clause)
|
@@ -29,7 +29,7 @@ module ROM
|
|
29
29
|
#
|
30
30
|
# @api private
|
31
31
|
def upsert(tuple, opts = EMPTY_HASH)
|
32
|
-
relation.dataset.returning
|
32
|
+
relation.dataset.returning.insert_conflict(opts).insert(tuple)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -38,7 +38,7 @@ module ROM
|
|
38
38
|
#
|
39
39
|
# @api private
|
40
40
|
def update(tuple)
|
41
|
-
dataset = relation.dataset.returning
|
41
|
+
dataset = relation.dataset.returning.update(tuple)
|
42
42
|
wrap_dataset(dataset)
|
43
43
|
end
|
44
44
|
end
|
@@ -20,6 +20,133 @@ module ROM
|
|
20
20
|
Array.constructor(-> (v) { Sequel.pg_array(v, db_type) }).meta(type: db_type)
|
21
21
|
end
|
22
22
|
|
23
|
+
# @!parse
|
24
|
+
# class ROM::SQL::Attribute
|
25
|
+
# # @!method contain(other)
|
26
|
+
# # Check whether the array includes another array
|
27
|
+
# # Translates to the @> operator
|
28
|
+
# #
|
29
|
+
# # @param [Array] other
|
30
|
+
# #
|
31
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
32
|
+
# #
|
33
|
+
# # @api public
|
34
|
+
#
|
35
|
+
# # @!method get(idx)
|
36
|
+
# # Get element by index (PG uses 1-based indexing)
|
37
|
+
# #
|
38
|
+
# # @param [Integer] idx
|
39
|
+
# #
|
40
|
+
# # @return [SQL::Attribute]
|
41
|
+
# #
|
42
|
+
# # @api public
|
43
|
+
#
|
44
|
+
# # @!method any(value)
|
45
|
+
# # Check whether the array includes a value
|
46
|
+
# # Translates to the ANY operator
|
47
|
+
# #
|
48
|
+
# # @param [Object] value
|
49
|
+
# #
|
50
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
51
|
+
# #
|
52
|
+
# # @api public
|
53
|
+
#
|
54
|
+
# # @!method contained_by(other)
|
55
|
+
# # Check whether the array is contained by another array
|
56
|
+
# # Translates to the <@ operator
|
57
|
+
# #
|
58
|
+
# # @param [Array] other
|
59
|
+
# #
|
60
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
61
|
+
# #
|
62
|
+
# # @api public
|
63
|
+
#
|
64
|
+
# # @!method length
|
65
|
+
# # Return array size
|
66
|
+
# #
|
67
|
+
# # @return [SQL::Attribute<Types::Int>]
|
68
|
+
# #
|
69
|
+
# # @api public
|
70
|
+
#
|
71
|
+
# # @!method overlaps(other)
|
72
|
+
# # Check whether the arrays have common values
|
73
|
+
# # Translates to &&
|
74
|
+
# #
|
75
|
+
# # @param [Array] other
|
76
|
+
# #
|
77
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
78
|
+
# #
|
79
|
+
# # @api public
|
80
|
+
#
|
81
|
+
# # @!method remove_value(value)
|
82
|
+
# # Remove elements by value
|
83
|
+
# #
|
84
|
+
# # @param [Object] value
|
85
|
+
# #
|
86
|
+
# # @return [SQL::Attribute<Types::PG::Array>]
|
87
|
+
# #
|
88
|
+
# # @api public
|
89
|
+
#
|
90
|
+
# # @!method join(delimiter, null_repr)
|
91
|
+
# # Convert the array to a string by joining
|
92
|
+
# # values with a delimiter (empty stirng by default)
|
93
|
+
# # and optional filler for NULL values
|
94
|
+
# # Translates to an `array_to_string` call
|
95
|
+
# #
|
96
|
+
# # @param [Object] delimiter
|
97
|
+
# # @param [Object] null
|
98
|
+
# #
|
99
|
+
# # @return [SQL::Attribute<Types::String>]
|
100
|
+
# #
|
101
|
+
# # @api public
|
102
|
+
#
|
103
|
+
# # @!method +(other)
|
104
|
+
# # Concatenate two arrays
|
105
|
+
# #
|
106
|
+
# # @param [Array] other
|
107
|
+
# #
|
108
|
+
# # @return [SQL::Attribute<Types::PG::Array>]
|
109
|
+
# #
|
110
|
+
# # @api public
|
111
|
+
# end
|
112
|
+
Attribute::TypeExtensions.register(Array.constructor -> { }) do
|
113
|
+
def contain(type, expr, other)
|
114
|
+
Attribute[Types::Bool].meta(sql_expr: expr.pg_array.contains(type[other]))
|
115
|
+
end
|
116
|
+
|
117
|
+
def get(type, expr, idx)
|
118
|
+
Attribute[type].meta(sql_expr: expr.pg_array[idx])
|
119
|
+
end
|
120
|
+
|
121
|
+
def any(type, expr, value)
|
122
|
+
Attribute[Types::Bool].meta(sql_expr: { value => expr.pg_array.any })
|
123
|
+
end
|
124
|
+
|
125
|
+
def contained_by(type, expr, other)
|
126
|
+
Attribute[Types::Bool].meta(sql_expr: expr.pg_array.contained_by(type[other]))
|
127
|
+
end
|
128
|
+
|
129
|
+
def length(type, expr)
|
130
|
+
Attribute[Types::Int].meta(sql_expr: expr.pg_array.length)
|
131
|
+
end
|
132
|
+
|
133
|
+
def overlaps(type, expr, other_array)
|
134
|
+
Attribute[Types::Bool].meta(sql_expr: expr.pg_array.overlaps(type[other_array]))
|
135
|
+
end
|
136
|
+
|
137
|
+
def remove_value(type, expr, value)
|
138
|
+
Attribute[type].meta(sql_expr: expr.pg_array.remove(value))
|
139
|
+
end
|
140
|
+
|
141
|
+
def join(type, expr, delimiter = '', null = nil)
|
142
|
+
Attribute[Types::String].meta(sql_expr: expr.pg_array.join(delimiter, null))
|
143
|
+
end
|
144
|
+
|
145
|
+
def +(type, expr, other)
|
146
|
+
Attribute[type].meta(sql_expr: expr.pg_array.concat(other))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
23
150
|
# JSON
|
24
151
|
|
25
152
|
JSONArray = Types.Constructor(Sequel::Postgres::JSONArray, &Sequel.method(:pg_json))
|
@@ -40,150 +167,175 @@ module ROM
|
|
40
167
|
|
41
168
|
JSONB = JSONBArray | JSONBHash | JSONBOp
|
42
169
|
|
170
|
+
# @!parse
|
171
|
+
# class ROM::SQL::Attribute
|
172
|
+
# # @!method contain(value)
|
173
|
+
# # Check whether the JSON value includes a json value
|
174
|
+
# # Translates to the @> operator
|
175
|
+
# #
|
176
|
+
# # @example
|
177
|
+
# # people.where { fields.contain(gender: 'Female') }
|
178
|
+
# # people.where(people[:fields].contain([name: 'age']))
|
179
|
+
# # people.select { fields.contain(gender: 'Female').as(:is_female) }
|
180
|
+
# #
|
181
|
+
# # @param [Hash,Array,Object] value
|
182
|
+
# #
|
183
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
184
|
+
# #
|
185
|
+
# # @api public
|
186
|
+
#
|
187
|
+
# # @!method contained_by(value)
|
188
|
+
# # Check whether the JSON value is contained by other value
|
189
|
+
# # Translates to the <@ operator
|
190
|
+
# #
|
191
|
+
# # @example
|
192
|
+
# # people.where { custom_values.contained_by(age: 25, foo: 'bar') }
|
193
|
+
# #
|
194
|
+
# # @param [Hash,Array] value
|
195
|
+
# #
|
196
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
197
|
+
# #
|
198
|
+
# # @api public
|
199
|
+
#
|
200
|
+
# # @!method get(*path)
|
201
|
+
# # Extract the JSON value using at the specified path
|
202
|
+
# # Translates to -> or #> depending on the number of arguments
|
203
|
+
# #
|
204
|
+
# # @example
|
205
|
+
# # people.select { data.get('age').as(:person_age) }
|
206
|
+
# # people.select { fields.get(0).as(:first_field) }
|
207
|
+
# # people.select { fields.get('0', 'value').as(:first_field_value) }
|
208
|
+
# #
|
209
|
+
# # @param [Array<Integer>,Array<String>] path Path to extract
|
210
|
+
# #
|
211
|
+
# # @return [SQL::Attribute<Types::PG::JSONB>]
|
212
|
+
# #
|
213
|
+
# # @api public
|
214
|
+
#
|
215
|
+
# # @!method get_text(*path)
|
216
|
+
# # Extract the JSON value as text using at the specified path
|
217
|
+
# # Translates to ->> or #>> depending on the number of arguments
|
218
|
+
# #
|
219
|
+
# # @example
|
220
|
+
# # people.select { data.get('age').as(:person_age) }
|
221
|
+
# # people.select { fields.get(0).as(:first_field) }
|
222
|
+
# # people.select { fields.get('0', 'value').as(:first_field_value) }
|
223
|
+
# #
|
224
|
+
# # @param [Array<Integer>,Array<String>] path Path to extract
|
225
|
+
# #
|
226
|
+
# # @return [SQL::Attribute<Types::String>]
|
227
|
+
# #
|
228
|
+
# # @api public
|
229
|
+
#
|
230
|
+
# # @!method has_key(key)
|
231
|
+
# # Does the JSON value has the specified top-level key
|
232
|
+
# # Translates to ?
|
233
|
+
# #
|
234
|
+
# # @example
|
235
|
+
# # people.where { data.has_key('age') }
|
236
|
+
# #
|
237
|
+
# # @param [String] key
|
238
|
+
# #
|
239
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
240
|
+
# #
|
241
|
+
# # @api public
|
242
|
+
#
|
243
|
+
# # @!method has_any_key(*keys)
|
244
|
+
# # Does the JSON value has any of the specified top-level keys
|
245
|
+
# # Translates to ?|
|
246
|
+
# #
|
247
|
+
# # @example
|
248
|
+
# # people.where { data.has_any_key('age', 'height') }
|
249
|
+
# #
|
250
|
+
# # @param [Array<String>] keys
|
251
|
+
# #
|
252
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
253
|
+
# #
|
254
|
+
# # @api public
|
255
|
+
#
|
256
|
+
# # @!method has_all_keys(*keys)
|
257
|
+
# # Does the JSON value has all the specified top-level keys
|
258
|
+
# # Translates to ?&
|
259
|
+
# #
|
260
|
+
# # @example
|
261
|
+
# # people.where { data.has_all_keys('age', 'height') }
|
262
|
+
# #
|
263
|
+
# # @param [Array<String>] keys
|
264
|
+
# #
|
265
|
+
# # @return [SQL::Attribute<Types::Bool>]
|
266
|
+
# #
|
267
|
+
# # @api public
|
268
|
+
#
|
269
|
+
# # @!method merge(value)
|
270
|
+
# # Concatenate two JSON values
|
271
|
+
# # Translates to ||
|
272
|
+
# #
|
273
|
+
# # @example
|
274
|
+
# # people.select { data.merge(fetched_at: Time.now).as(:data) }
|
275
|
+
# # people.select { (fields + [name: 'height', value: 165]).as(:fields) }
|
276
|
+
# #
|
277
|
+
# # @param [Hash,Array] value
|
278
|
+
# #
|
279
|
+
# # @return [SQL::Attribute<Types::PG::JSONB>]
|
280
|
+
# #
|
281
|
+
# # @api public
|
282
|
+
#
|
283
|
+
# # @!method +(value)
|
284
|
+
# # An alias for ROM::SQL::Attribute<JSONB>#merge
|
285
|
+
# #
|
286
|
+
# # @api public
|
287
|
+
#
|
288
|
+
# # @!method delete(*path)
|
289
|
+
# # Deletes the specified value by key, index, or path
|
290
|
+
# # Translates to - or #- depending on the number of arguments
|
291
|
+
# #
|
292
|
+
# # @example
|
293
|
+
# # people.select { data.delete('age').as(:data_without_age) }
|
294
|
+
# # people.select { fields.delete(0).as(:fields_without_first) }
|
295
|
+
# # people.select { fields.delete(-1).as(:fields_without_last) }
|
296
|
+
# # people.select { data.delete('deeply', 'nested', 'value').as(:data) }
|
297
|
+
# # people.select { fields.delete('0', 'name').as(:data) }
|
298
|
+
# #
|
299
|
+
# # @param [Array<String>] path
|
300
|
+
# #
|
301
|
+
# # @return [SQL::Attribute<Types::PG::JSONB>]
|
302
|
+
# #
|
303
|
+
# # @api public
|
304
|
+
# end
|
43
305
|
Attribute::TypeExtensions.register(JSONB) do
|
44
|
-
# Checks whether the JSON value includes a json value
|
45
|
-
# Translates to the @> operator
|
46
|
-
#
|
47
|
-
# @example
|
48
|
-
# people.where { fields.contain(gender: 'Female') }
|
49
|
-
# people.where(people[:fields].contain([name: 'age']))
|
50
|
-
# people.select { fields.contain(gender: 'Female').as(:is_female) }
|
51
|
-
#
|
52
|
-
# @param [Hash,Array,Object] value
|
53
|
-
#
|
54
|
-
# @return [SQL::Attribute<Types::Bool>]
|
55
|
-
#
|
56
|
-
# @api public
|
57
306
|
def contain(type, expr, value)
|
58
307
|
Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.contains(value))
|
59
308
|
end
|
60
309
|
|
61
|
-
# Checks whether the JSON value is contained by other value
|
62
|
-
# Translates to the <@ operator
|
63
|
-
#
|
64
|
-
# @example
|
65
|
-
# people.where { custom_values.contained_by(age: 25, foo: 'bar') }
|
66
|
-
#
|
67
|
-
# @param [Hash,Array] value
|
68
|
-
#
|
69
|
-
# @return [SQL::Attribute<Types::Bool>]
|
70
|
-
#
|
71
|
-
# @api public
|
72
310
|
def contained_by(type, expr, value)
|
73
311
|
Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.contained_by(value))
|
74
312
|
end
|
75
313
|
|
76
|
-
# Extracts the JSON value using at the specified path
|
77
|
-
# Translates to -> or #> depending on the number of arguments
|
78
|
-
#
|
79
|
-
# @example
|
80
|
-
# people.select { data.get('age').as(:person_age) }
|
81
|
-
# people.select { fields.get(0).as(:first_field) }
|
82
|
-
# people.select { fields.get('0', 'value').as(:first_field_value) }
|
83
|
-
#
|
84
|
-
# @param [Array<Integer>,Array<String>] path Path to extract
|
85
|
-
#
|
86
|
-
# @return [SQL::Attribute<Types::PG::JSONB>]
|
87
|
-
#
|
88
|
-
# @api public
|
89
314
|
def get(type, expr, *path)
|
90
315
|
Attribute[JSONB].meta(sql_expr: expr.pg_jsonb[path_args(path)])
|
91
316
|
end
|
92
317
|
|
93
|
-
# Extracts the JSON value as text using at the specified path
|
94
|
-
# Translates to ->> or #>> depending on the number of arguments
|
95
|
-
#
|
96
|
-
# @example
|
97
|
-
# people.select { data.get('age').as(:person_age) }
|
98
|
-
# people.select { fields.get(0).as(:first_field) }
|
99
|
-
# people.select { fields.get('0', 'value').as(:first_field_value) }
|
100
|
-
#
|
101
|
-
# @param [Array<Integer>,Array<String>] path Path to extract
|
102
|
-
#
|
103
|
-
# @return [SQL::Attribute<Types::String>]
|
104
|
-
#
|
105
|
-
# @api public
|
106
318
|
def get_text(type, expr, *path)
|
107
319
|
Attribute[Types::String].meta(sql_expr: expr.pg_jsonb.get_text(path_args(path)))
|
108
320
|
end
|
109
321
|
|
110
|
-
# Does the JSON value has the specified top-level key
|
111
|
-
# Translates to ?
|
112
|
-
#
|
113
|
-
# @example
|
114
|
-
# people.where { data.has_key('age') }
|
115
|
-
#
|
116
|
-
# @param [String] key
|
117
|
-
#
|
118
|
-
# @return [SQL::Attribute<Types::Bool>]
|
119
|
-
#
|
120
|
-
# @api public
|
121
322
|
def has_key(type, expr, key)
|
122
323
|
Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.has_key?(key))
|
123
324
|
end
|
124
325
|
|
125
|
-
# Does the JSON value has any of the specified top-level keys
|
126
|
-
# Translates to ?|
|
127
|
-
#
|
128
|
-
# @example
|
129
|
-
# people.where { data.has_any_key('age', 'height') }
|
130
|
-
#
|
131
|
-
# @param [Array<String>] keys
|
132
|
-
#
|
133
|
-
# @return [SQL::Attribute<Types::Bool>]
|
134
|
-
#
|
135
|
-
# @api public
|
136
326
|
def has_any_key(type, expr, *keys)
|
137
327
|
Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.contain_any(keys))
|
138
328
|
end
|
139
329
|
|
140
|
-
# Does the JSON value has all the specified top-level keys
|
141
|
-
# Translates to ?&
|
142
|
-
#
|
143
|
-
# @example
|
144
|
-
# people.where { data.has_all_keys('age', 'height') }
|
145
|
-
#
|
146
|
-
# @param [Array<String>] keys
|
147
|
-
#
|
148
|
-
# @return [SQL::Attribute<Types::Bool>]
|
149
|
-
#
|
150
|
-
# @api public
|
151
330
|
def has_all_keys(type, expr, *keys)
|
152
331
|
Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.contain_all(keys))
|
153
332
|
end
|
154
333
|
|
155
|
-
# Concatenates two JSON values
|
156
|
-
# Translates to ||
|
157
|
-
#
|
158
|
-
# @example
|
159
|
-
# people.select { data.merge(fetched_at: Time.now).as(:data) }
|
160
|
-
# people.select { (fields + [name: 'height', value: 165]).as(:fields) }
|
161
|
-
#
|
162
|
-
# @param [Hash,Array] value
|
163
|
-
#
|
164
|
-
# @return [SQL::Attribute<Types::PG::JSONB>]
|
165
|
-
#
|
166
|
-
# @api public
|
167
334
|
def merge(type, expr, value)
|
168
335
|
Attribute[JSONB].meta(sql_expr: expr.pg_jsonb.concat(value))
|
169
336
|
end
|
170
337
|
alias_method :+, :merge
|
171
338
|
|
172
|
-
# Deletes the specified value by key, index, or path
|
173
|
-
# Translates to - or #- depending on the number of arguments
|
174
|
-
#
|
175
|
-
# @example
|
176
|
-
# people.select { data.delete('age').as(:data_without_age) }
|
177
|
-
# people.select { fields.delete(0).as(:fields_without_first) }
|
178
|
-
# people.select { fields.delete(-1).as(:fields_without_last) }
|
179
|
-
# people.select { data.delete('deeply', 'nested', 'value').as(:data) }
|
180
|
-
# people.select { fields.delete('0', 'name').as(:data) }
|
181
|
-
#
|
182
|
-
# @param [Array<String>] path
|
183
|
-
#
|
184
|
-
# @return [SQL::Attribute<Types::PG::JSONB>]
|
185
|
-
#
|
186
|
-
# @api public
|
187
339
|
def delete(type, expr, *path)
|
188
340
|
sql_expr = path.size == 1 ? expr.pg_jsonb - path : expr.pg_jsonb.delete_path(path)
|
189
341
|
Attribute[JSONB].meta(sql_expr: sql_expr)
|