rom-sql 3.7.0 → 4.0.0.alpha1
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 +11 -65
- data/LICENSE +1 -1
- data/README.md +3 -2
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +10 -12
- data/lib/rom/plugins/relation/sql/default_views.rb +75 -0
- data/lib/rom/plugins/relation/sql/instrumentation.rb +8 -17
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +5 -5
- data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +20 -37
- data/lib/rom/plugins/relation/sql/postgres/streaming.rb +17 -14
- data/lib/rom/sql/associations/many_to_many.rb +4 -7
- data/lib/rom/sql/associations/many_to_one.rb +3 -6
- data/lib/rom/sql/associations/one_to_many.rb +3 -3
- data/lib/rom/sql/associations/one_to_one.rb +1 -1
- data/lib/rom/sql/associations/one_to_one_through.rb +1 -1
- data/lib/rom/sql/associations/self_ref.rb +1 -1
- data/lib/rom/sql/associations.rb +5 -5
- data/lib/rom/sql/attribute.rb +17 -31
- data/lib/rom/sql/attribute_aliasing.rb +4 -6
- data/lib/rom/sql/commands/create.rb +5 -5
- data/lib/rom/sql/commands/delete.rb +2 -2
- data/lib/rom/sql/commands/update.rb +5 -5
- data/lib/rom/sql/commands.rb +4 -4
- data/lib/rom/sql/dsl.rb +4 -6
- data/lib/rom/sql/errors.rb +3 -3
- data/lib/rom/sql/extensions/active_support_notifications.rb +3 -3
- data/lib/rom/sql/extensions/mysql/type_builder.rb +5 -5
- data/lib/rom/sql/extensions/mysql.rb +1 -1
- data/lib/rom/sql/extensions/postgres/commands.rb +13 -31
- data/lib/rom/sql/extensions/postgres/type_builder.rb +28 -31
- data/lib/rom/sql/extensions/postgres/type_serializer.rb +24 -25
- data/lib/rom/sql/extensions/postgres/types/array.rb +4 -4
- data/lib/rom/sql/extensions/postgres/types/array_types.rb +1 -1
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +19 -19
- data/lib/rom/sql/extensions/postgres/types/json.rb +12 -18
- data/lib/rom/sql/extensions/postgres/types/ltree.rb +54 -97
- data/lib/rom/sql/extensions/postgres/types/network.rb +4 -17
- data/lib/rom/sql/extensions/postgres/types/range.rb +30 -30
- data/lib/rom/sql/extensions/postgres/types.rb +14 -14
- data/lib/rom/sql/extensions/postgres.rb +6 -6
- data/lib/rom/sql/extensions/rails_log_subscriber.rb +6 -21
- data/lib/rom/sql/extensions/sqlite/types.rb +1 -1
- data/lib/rom/sql/extensions/sqlite.rb +2 -2
- data/lib/rom/sql/extensions.rb +6 -6
- data/lib/rom/sql/foreign_key.rb +3 -1
- data/lib/rom/sql/function.rb +19 -42
- data/lib/rom/sql/gateway.rb +41 -15
- data/lib/rom/sql/group_dsl.rb +3 -8
- data/lib/rom/sql/index.rb +2 -0
- data/lib/rom/sql/join_dsl.rb +1 -1
- data/lib/rom/sql/mapper_compiler.rb +2 -2
- data/lib/rom/sql/migration/inline_runner.rb +2 -8
- data/lib/rom/sql/migration/migrator.rb +12 -12
- data/lib/rom/sql/migration/recorder.rb +4 -10
- data/lib/rom/sql/migration/runner.rb +4 -5
- data/lib/rom/sql/migration/schema_diff.rb +4 -10
- data/lib/rom/sql/migration/writer.rb +7 -7
- data/lib/rom/sql/migration.rb +9 -13
- data/lib/rom/sql/order_dsl.rb +3 -7
- data/lib/rom/sql/plugin/associates.rb +45 -21
- data/lib/rom/sql/plugin/pagination.rb +3 -1
- data/lib/rom/sql/plugin/schema_indexes.rb +35 -0
- data/lib/rom/sql/plugins.rb +9 -6
- data/lib/rom/sql/projection_dsl.rb +5 -5
- data/lib/rom/sql/rake_task.rb +2 -2
- data/lib/rom/sql/relation/reading.rb +78 -83
- data/lib/rom/sql/relation/writing.rb +4 -9
- data/lib/rom/sql/relation.rb +58 -136
- data/lib/rom/sql/restriction_dsl.rb +4 -8
- data/lib/rom/sql/schema/attributes_inferrer.rb +2 -2
- data/lib/rom/sql/schema/dsl.rb +6 -4
- data/lib/rom/sql/schema/index_dsl.rb +6 -7
- data/lib/rom/sql/schema/inferrer.rb +22 -24
- data/lib/rom/sql/schema/type_builder.rb +4 -20
- data/lib/rom/sql/schema.rb +17 -29
- data/lib/rom/sql/spec/support.rb +5 -5
- data/lib/rom/sql/tasks/migration_tasks.rake +14 -21
- data/lib/rom/sql/transaction.rb +4 -3
- data/lib/rom/sql/type_dsl.rb +3 -7
- data/lib/rom/sql/type_extensions.rb +6 -4
- data/lib/rom/sql/type_serializer.rb +9 -9
- data/lib/rom/sql/types.rb +6 -6
- data/lib/rom/sql/version.rb +1 -1
- data/lib/rom/sql/wrap.rb +1 -1
- data/lib/rom/sql.rb +13 -12
- data/lib/rom/types/values.rb +5 -3
- data/lib/rom-sql.rb +1 -1
- metadata +17 -12
@@ -34,55 +34,55 @@ module ROM
|
|
34
34
|
# The list of geometric data types supported by PostgreSQL
|
35
35
|
# @see https://www.postgresql.org/docs/current/static/datatype-geometric.html
|
36
36
|
|
37
|
-
Point = Type(
|
37
|
+
Point = Type("point") do
|
38
38
|
SQL::Types.define(Values::Point) do
|
39
39
|
input do |point|
|
40
40
|
"(#{point.x},#{point.y})"
|
41
41
|
end
|
42
42
|
|
43
43
|
output do |point|
|
44
|
-
x, y = point.to_s[1...-1].split(
|
44
|
+
x, y = point.to_s[1...-1].split(",", 2)
|
45
45
|
Values::Point.new(Float(x), Float(y))
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
Line = Type(
|
50
|
+
Line = Type("line") do
|
51
51
|
SQL::Types.define(Values::Line) do
|
52
52
|
input do |line|
|
53
53
|
"{#{line.a},#{line.b},#{line.c}}"
|
54
54
|
end
|
55
55
|
|
56
56
|
output do |line|
|
57
|
-
a, b, c = line.to_s[1..-2].split(
|
57
|
+
a, b, c = line.to_s[1..-2].split(",", 3)
|
58
58
|
Values::Line.new(Float(a), Float(b), Float(c))
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
Circle = Type(
|
63
|
+
Circle = Type("circle") do
|
64
64
|
SQL::Types.define(Values::Circle) do
|
65
65
|
input do |circle|
|
66
66
|
"<(#{circle.center.x},#{circle.center.y}),#{circle.radius}>"
|
67
67
|
end
|
68
68
|
|
69
69
|
output do |circle|
|
70
|
-
x, y, r = circle.to_s.tr(
|
70
|
+
x, y, r = circle.to_s.tr("()<>", "").split(",", 3)
|
71
71
|
center = Values::Point.new(Float(x), Float(y))
|
72
72
|
Values::Circle.new(center, Float(r))
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
Box = Type(
|
77
|
+
Box = Type("box") do
|
78
78
|
SQL::Types.define(Values::Box) do
|
79
79
|
input do |box|
|
80
|
-
"((#{box.upper_right.x},#{box.upper_right.y}),"
|
80
|
+
"((#{box.upper_right.x},#{box.upper_right.y}),"\
|
81
81
|
"(#{box.lower_left.x},#{box.lower_left.y}))"
|
82
82
|
end
|
83
83
|
|
84
84
|
output do |box|
|
85
|
-
x_right, y_right, x_left, y_left = box.to_s.tr(
|
85
|
+
x_right, y_right, x_left, y_left = box.to_s.tr("()", "").split(",", 4)
|
86
86
|
upper_right = Values::Point.new(Float(x_right), Float(y_right))
|
87
87
|
lower_left = Values::Point.new(Float(x_left), Float(y_left))
|
88
88
|
Values::Box.new(upper_right, lower_left)
|
@@ -90,15 +90,15 @@ module ROM
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
LineSegment = Type(
|
93
|
+
LineSegment = Type("lseg") do
|
94
94
|
SQL::Types.define(Values::LineSegment) do
|
95
95
|
input do |segment|
|
96
|
-
"[(#{segment.begin.x},#{segment.begin.y}),"
|
96
|
+
"[(#{segment.begin.x},#{segment.begin.y}),"\
|
97
97
|
"(#{segment.end.x},#{segment.end.y})]"
|
98
98
|
end
|
99
99
|
|
100
100
|
output do |segment|
|
101
|
-
x_begin, y_begin, x_end, y_end = segment.to_s.tr(
|
101
|
+
x_begin, y_begin, x_end, y_end = segment.to_s.tr("()[]", "").split(",", 4)
|
102
102
|
point_begin = Values::Point.new(Float(x_begin), Float(y_begin))
|
103
103
|
point_end = Values::Point.new(Float(x_end), Float(y_end))
|
104
104
|
Values::LineSegment.new(point_begin, point_end)
|
@@ -106,24 +106,24 @@ module ROM
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
-
Polygon = Type(
|
109
|
+
Polygon = Type("polygon") do
|
110
110
|
SQL::Types.define(::Array) do
|
111
111
|
input do |points|
|
112
|
-
points_joined = points.map { |p| "(#{p.x},#{p.y})" }.join(
|
112
|
+
points_joined = points.map { |p| "(#{p.x},#{p.y})" }.join(",")
|
113
113
|
"(#{points_joined})"
|
114
114
|
end
|
115
115
|
|
116
116
|
output do |polygon|
|
117
|
-
coordinates = polygon.to_s.tr(
|
117
|
+
coordinates = polygon.to_s.tr("()", "").split(",").each_slice(2)
|
118
118
|
coordinates.map { |x, y| Values::Point.new(Float(x), Float(y)) }
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
123
|
-
Path = Type(
|
123
|
+
Path = Type("path") do
|
124
124
|
SQL::Types.define(Values::Path) do
|
125
125
|
input do |path|
|
126
|
-
points_joined = path.to_a.map { |p| "(#{p.x},#{p.y})" }.join(
|
126
|
+
points_joined = path.to_a.map { |p| "(#{p.x},#{p.y})" }.join(",")
|
127
127
|
|
128
128
|
if path.open?
|
129
129
|
"[#{points_joined}]"
|
@@ -133,8 +133,8 @@ module ROM
|
|
133
133
|
end
|
134
134
|
|
135
135
|
output do |path|
|
136
|
-
open = path.to_s.start_with?(
|
137
|
-
coordinates = path.to_s.tr(
|
136
|
+
open = path.to_s.start_with?("[") && path.to_s.end_with?("]")
|
137
|
+
coordinates = path.to_s.tr("()[]", "").split(",").each_slice(2)
|
138
138
|
points = coordinates.map { |x, y| Values::Point.new(Float(x), Float(y)) }
|
139
139
|
|
140
140
|
if open
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "sequel/core"
|
4
|
+
require "singleton"
|
5
5
|
|
6
6
|
Sequel.extension(:pg_json, :pg_json_ops)
|
7
7
|
|
@@ -23,11 +23,11 @@ module ROM
|
|
23
23
|
include ::Singleton
|
24
24
|
|
25
25
|
def to_s
|
26
|
-
|
26
|
+
"null"
|
27
27
|
end
|
28
28
|
|
29
29
|
def inspect
|
30
|
-
|
30
|
+
"null"
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -44,7 +44,7 @@ module ROM
|
|
44
44
|
SQL::Types::False
|
45
45
|
]
|
46
46
|
|
47
|
-
JSON = Type(
|
47
|
+
JSON = Type("json") do
|
48
48
|
casts = ::Hash.new(-> v { ::Sequel.pg_json(v) })
|
49
49
|
json_null = ::Sequel.pg_json_wrap(nil)
|
50
50
|
casts[JSONNullType] = -> _ { json_null }
|
@@ -60,7 +60,7 @@ module ROM
|
|
60
60
|
.meta(read: JSONRead)
|
61
61
|
end
|
62
62
|
|
63
|
-
JSONB = Type(
|
63
|
+
JSONB = Type("jsonb") do
|
64
64
|
casts = ::Hash.new(-> v { ::Sequel.pg_jsonb(v) })
|
65
65
|
jsonb_null = ::Sequel.pg_jsonb_wrap(nil)
|
66
66
|
casts[JSONNullType] = -> _ { jsonb_null }
|
@@ -76,16 +76,12 @@ module ROM
|
|
76
76
|
.meta(read: JSONRead)
|
77
77
|
end
|
78
78
|
else
|
79
|
-
JSON = Type(
|
80
|
-
(SQL::Types::Array | SQL::Types::Hash).constructor(
|
81
|
-
::Sequel.method(:pg_json)
|
82
|
-
).meta(read: JSONRead)
|
79
|
+
JSON = Type("json") do
|
80
|
+
(SQL::Types::Array | SQL::Types::Hash).constructor(Sequel.method(:pg_json)).meta(read: JSONRead)
|
83
81
|
end
|
84
82
|
|
85
|
-
JSONB = Type(
|
86
|
-
(SQL::Types::Array | SQL::Types::Hash).constructor(
|
87
|
-
::Sequel.method(:pg_jsonb)
|
88
|
-
).meta(read: JSONRead)
|
83
|
+
JSONB = Type("jsonb") do
|
84
|
+
(SQL::Types::Array | SQL::Types::Hash).constructor(Sequel.method(:pg_jsonb)).meta(read: JSONRead)
|
89
85
|
end
|
90
86
|
end
|
91
87
|
|
@@ -246,7 +242,7 @@ module ROM
|
|
246
242
|
|
247
243
|
def path_args(path)
|
248
244
|
case path.size
|
249
|
-
when 0 then raise ArgumentError,
|
245
|
+
when 0 then raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
|
250
246
|
when 1 then path[0]
|
251
247
|
else path
|
252
248
|
end
|
@@ -269,9 +265,7 @@ module ROM
|
|
269
265
|
end
|
270
266
|
|
271
267
|
def has_key(_type, expr, key)
|
272
|
-
Attribute[SQL::Types::Bool].meta(
|
273
|
-
sql_expr: wrap(expr).has_key?(key) # rubocop:disable Style/PreferredHashMethods
|
274
|
-
)
|
268
|
+
Attribute[SQL::Types::Bool].meta(sql_expr: wrap(expr).has_key?(key))
|
275
269
|
end
|
276
270
|
|
277
271
|
def has_any_key(_type, expr, *keys)
|
@@ -1,17 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rom/types/values"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module SQL
|
7
7
|
module Postgres
|
8
8
|
# @api public
|
9
|
-
#
|
10
|
-
# rubocop:disable Metrics/ModuleLength
|
11
9
|
module Types
|
12
10
|
# @see https://www.postgresql.org/docs/current/static/ltree.html
|
13
11
|
|
14
|
-
LTree = Type(
|
12
|
+
LTree = Type("ltree") do
|
15
13
|
SQL::Types.define(ROM::Types::Values::TreePath) do
|
16
14
|
input(&:to_s)
|
17
15
|
|
@@ -41,12 +39,8 @@ module ROM
|
|
41
39
|
# # Translates to the ? operator
|
42
40
|
# #
|
43
41
|
# # @example
|
44
|
-
# # people.select(:name).where {
|
45
|
-
# #
|
46
|
-
# # }
|
47
|
-
# # people.select(:name).where {
|
48
|
-
# # ltree_tags.match_any('Bottom,Bottom.Cities.*')
|
49
|
-
# # }
|
42
|
+
# # people.select(:name).where { ltree_tags.match_any(['Bottom', 'Bottom.Cities.*']) }
|
43
|
+
# # people.select(:name).where { ltree_tags.match_any('Bottom,Bottom.Cities.*') }
|
50
44
|
# #
|
51
45
|
# # @param [Array,String] value
|
52
46
|
# #
|
@@ -73,9 +67,7 @@ module ROM
|
|
73
67
|
# #
|
74
68
|
# # @example
|
75
69
|
# # people.select(:name).where { ltree_tags.contain_descendant(['Bottom.Cities']) }
|
76
|
-
# # people.select(:name).where {
|
77
|
-
# # ltree_tags.contain_descendant('Bottom.Cities, Bottom.Parks')
|
78
|
-
# # }
|
70
|
+
# # people.select(:name).where { ltree_tags.contain_descendant('Bottom.Cities, Bottom.Parks') }
|
79
71
|
# #
|
80
72
|
# # @param [Array<String>, String] value
|
81
73
|
# #
|
@@ -102,9 +94,7 @@ module ROM
|
|
102
94
|
# #
|
103
95
|
# # @example
|
104
96
|
# # people.select(:name).where { ltree_tags.contain_ascendant(['Bottom.Cities']) }
|
105
|
-
# # people.select(:name).where {
|
106
|
-
# # ltree_tags.contain_ascendant('Bottom.Cities, Bottom.Parks')
|
107
|
-
# # }
|
97
|
+
# # people.select(:name).where { ltree_tags.contain_ascendant('Bottom.Cities, Bottom.Parks') }
|
108
98
|
# #
|
109
99
|
# # @param [Array<String>, String] value
|
110
100
|
# #
|
@@ -133,9 +123,11 @@ module ROM
|
|
133
123
|
# # people.select {
|
134
124
|
# # (ltree_tags + ROM::Types::Values::TreePath.new('Moscu')).as(:ltree_tags)
|
135
125
|
# # }.where { name.is('Jade Doe') }
|
126
|
+
# #
|
136
127
|
# # people.select {
|
137
128
|
# # (ltree_tags + 'Moscu').as(:ltree_tags)
|
138
|
-
# # }
|
129
|
+
# # }
|
130
|
+
# # .where { name.is('Jade Doe') }
|
139
131
|
# #
|
140
132
|
# # @param [LTree, String] keys
|
141
133
|
# #
|
@@ -161,9 +153,7 @@ module ROM
|
|
161
153
|
# # Translates to @>
|
162
154
|
# #
|
163
155
|
# # @example
|
164
|
-
# # people.select(:name).where {
|
165
|
-
# # parents_tags.contain_ancestor('Top.Building.EmpireState.381')
|
166
|
-
# # }
|
156
|
+
# # people.select(:name).where { parents_tags.contain_ancestor('Top.Building.EmpireState.381')}
|
167
157
|
# #
|
168
158
|
# # @param [String] value
|
169
159
|
# #
|
@@ -176,9 +166,7 @@ module ROM
|
|
176
166
|
# # Translates to <@
|
177
167
|
# #
|
178
168
|
# # @example
|
179
|
-
# # people.select(:name).where {
|
180
|
-
# # parents_tags.contain_descendant('Top.Building.EmpireState.381')
|
181
|
-
# # }
|
169
|
+
# # people.select(:name).where { parents_tags.contain_descendant('Top.Building.EmpireState.381')}
|
182
170
|
# #
|
183
171
|
# # @param [String] value
|
184
172
|
# #
|
@@ -191,9 +179,7 @@ module ROM
|
|
191
179
|
# # Translates to ?@>
|
192
180
|
# #
|
193
181
|
# # @example
|
194
|
-
# # people.select(:name).where {
|
195
|
-
# # parents_tags.find_ancestor('Left.Parks').not(nil)
|
196
|
-
# # }
|
182
|
+
# # people.select(:name).where { parents_tags.find_ancestor('Left.Parks').not(nil)}
|
197
183
|
# #
|
198
184
|
# # @param [String] value
|
199
185
|
# #
|
@@ -206,9 +192,7 @@ module ROM
|
|
206
192
|
# # Translates to ?<@
|
207
193
|
# #
|
208
194
|
# # @example
|
209
|
-
# # people.select(:name).where {
|
210
|
-
# # parents_tags.find_descendant('Left.Parks').not(nil)
|
211
|
-
# # }
|
195
|
+
# # people.select(:name).where { parents_tags.find_descendant('Left.Parks').not(nil)}
|
212
196
|
# #
|
213
197
|
# # @param [String] value
|
214
198
|
# #
|
@@ -221,9 +205,7 @@ module ROM
|
|
221
205
|
# # Translates to ?~
|
222
206
|
# #
|
223
207
|
# # @example
|
224
|
-
# # people.select(:name).where {
|
225
|
-
# # parents_tags.match_any_lquery('Right.*').not(nil)
|
226
|
-
# # }
|
208
|
+
# # people.select(:name).where { parents_tags.match_any_lquery('Right.*').not(nil)}
|
227
209
|
# #
|
228
210
|
# # @param [String] value
|
229
211
|
# #
|
@@ -236,9 +218,7 @@ module ROM
|
|
236
218
|
# # Translates to ?@
|
237
219
|
# #
|
238
220
|
# # @example
|
239
|
-
# # people.select(:name).where {
|
240
|
-
# # parents_tags.match_any_ltextquery('EmpireState').not(nil)
|
241
|
-
# # }
|
221
|
+
# # people.select(:name).where { parents_tags.match_any_ltextquery('EmpireState').not(nil)}
|
242
222
|
# #
|
243
223
|
# # @param [String] value
|
244
224
|
# #
|
@@ -248,26 +228,23 @@ module ROM
|
|
248
228
|
#
|
249
229
|
# end
|
250
230
|
module LTreeMethods
|
251
|
-
ASCENDANT = [
|
252
|
-
FIND_ASCENDANT = [
|
253
|
-
DESCENDANT = [
|
254
|
-
FIND_DESCENDANT = [
|
255
|
-
MATCH_ANY = [
|
256
|
-
MATCH_ANY_LQUERY = [
|
257
|
-
MATCH_LTEXTQUERY = [
|
258
|
-
MATCH_ANY_LTEXTQUERY = [
|
231
|
+
ASCENDANT = ["(", " @> ", ")"].freeze
|
232
|
+
FIND_ASCENDANT = ["(", " ?@> ", ")"].freeze
|
233
|
+
DESCENDANT = ["(", " <@ ", ")"].freeze
|
234
|
+
FIND_DESCENDANT = ["(", " ?<@ ", ")"].freeze
|
235
|
+
MATCH_ANY = ["(", " ? ", ")"].freeze
|
236
|
+
MATCH_ANY_LQUERY = ["(", " ?~ ", ")"].freeze
|
237
|
+
MATCH_LTEXTQUERY = ["(", " @ ", ")"].freeze
|
238
|
+
MATCH_ANY_LTEXTQUERY = ["(", " ?@ ", ")"].freeze
|
259
239
|
|
260
240
|
def match(_type, expr, query)
|
261
|
-
Attribute[SQL::Types::Bool].meta(
|
262
|
-
|
263
|
-
)
|
241
|
+
Attribute[SQL::Types::Bool].meta(sql_expr: Sequel::SQL::BooleanExpression.new(:~,
|
242
|
+
expr, query))
|
264
243
|
end
|
265
244
|
|
266
245
|
def match_any(_type, expr, query)
|
267
246
|
array = build_array_query(query)
|
268
|
-
Attribute[SQL::Types::Bool].meta(
|
269
|
-
sql_expr: custom_operator_expr(MATCH_ANY, expr, array)
|
270
|
-
)
|
247
|
+
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(MATCH_ANY, expr, array))
|
271
248
|
end
|
272
249
|
|
273
250
|
private
|
@@ -276,65 +253,50 @@ module ROM
|
|
276
253
|
Sequel::SQL::PlaceholderLiteralString.new(string, [expr, query])
|
277
254
|
end
|
278
255
|
|
279
|
-
def build_array_query(query, array_type =
|
256
|
+
def build_array_query(query, array_type = "lquery")
|
280
257
|
case query
|
281
258
|
when ::Array
|
282
259
|
ROM::SQL::Types::PG::Array(array_type)[query]
|
283
260
|
when ::String
|
284
|
-
ROM::SQL::Types::PG::Array(array_type)[query.split(
|
261
|
+
ROM::SQL::Types::PG::Array(array_type)[query.split(",")]
|
285
262
|
end
|
286
263
|
end
|
287
264
|
end
|
288
265
|
|
289
|
-
TypeExtensions.register(ROM::SQL::Types::PG::Array(
|
266
|
+
TypeExtensions.register(ROM::SQL::Types::PG::Array("ltree", LTree)) do
|
290
267
|
include LTreeMethods
|
291
268
|
|
292
269
|
def contain_any_ltextquery(_type, expr, query)
|
293
|
-
Attribute[SQL::Types::Bool].meta(
|
294
|
-
|
295
|
-
|
296
|
-
)
|
297
|
-
)
|
270
|
+
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(
|
271
|
+
LTreeMethods::MATCH_LTEXTQUERY, expr, query
|
272
|
+
))
|
298
273
|
end
|
299
274
|
|
300
275
|
def contain_ancestor(_type, expr, query)
|
301
|
-
Attribute[SQL::Types::Bool].meta(
|
302
|
-
|
303
|
-
|
304
|
-
)
|
305
|
-
)
|
276
|
+
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(
|
277
|
+
LTreeMethods::ASCENDANT, expr, query
|
278
|
+
))
|
306
279
|
end
|
307
280
|
|
308
281
|
def contain_descendant(_type, expr, query)
|
309
|
-
Attribute[SQL::Types::Bool].meta(
|
310
|
-
|
311
|
-
|
312
|
-
)
|
313
|
-
)
|
282
|
+
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(
|
283
|
+
LTreeMethods::DESCENDANT, expr, query
|
284
|
+
))
|
314
285
|
end
|
315
286
|
|
316
287
|
def find_ancestor(_type, expr, query)
|
317
|
-
Attribute[LTree].meta(
|
318
|
-
|
319
|
-
LTreeMethods::FIND_ASCENDANT, expr, query
|
320
|
-
)
|
321
|
-
)
|
288
|
+
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::FIND_ASCENDANT,
|
289
|
+
expr, query))
|
322
290
|
end
|
323
291
|
|
324
292
|
def find_descendant(_type, expr, query)
|
325
|
-
Attribute[LTree].meta(
|
326
|
-
|
327
|
-
LTreeMethods::FIND_DESCENDANT, expr, query
|
328
|
-
)
|
329
|
-
)
|
293
|
+
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::FIND_DESCENDANT,
|
294
|
+
expr, query))
|
330
295
|
end
|
331
296
|
|
332
297
|
def match_any_lquery(_type, expr, query)
|
333
|
-
Attribute[LTree].meta(
|
334
|
-
|
335
|
-
LTreeMethods::MATCH_ANY_LQUERY, expr, query
|
336
|
-
)
|
337
|
-
)
|
298
|
+
Attribute[LTree].meta(sql_expr: custom_operator_expr(LTreeMethods::MATCH_ANY_LQUERY,
|
299
|
+
expr, query))
|
338
300
|
end
|
339
301
|
|
340
302
|
def match_any_ltextquery(_type, expr, query)
|
@@ -354,7 +316,7 @@ module ROM
|
|
354
316
|
end
|
355
317
|
|
356
318
|
def contain_descendant(_type, expr, query)
|
357
|
-
array = build_array_query(query,
|
319
|
+
array = build_array_query(query, "ltree")
|
358
320
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(
|
359
321
|
LTreeMethods::DESCENDANT, expr, array
|
360
322
|
))
|
@@ -367,7 +329,7 @@ module ROM
|
|
367
329
|
end
|
368
330
|
|
369
331
|
def contain_ascendant(_type, expr, query)
|
370
|
-
array = build_array_query(query,
|
332
|
+
array = build_array_query(query, "ltree")
|
371
333
|
Attribute[SQL::Types::Bool].meta(sql_expr: custom_operator_expr(
|
372
334
|
LTreeMethods::ASCENDANT, expr, array
|
373
335
|
))
|
@@ -380,22 +342,17 @@ module ROM
|
|
380
342
|
end
|
381
343
|
|
382
344
|
def +(_type, expr, other)
|
383
|
-
other_value =
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
sql_expr: ::Sequel::SQL::StringExpression.new(
|
392
|
-
:'||', expr, other_value.to_s
|
393
|
-
)
|
394
|
-
)
|
345
|
+
other_value = case other
|
346
|
+
when ROM::Types::Values::TreePath
|
347
|
+
other
|
348
|
+
else
|
349
|
+
ROM::Types::Values::TreePath.new(other)
|
350
|
+
end
|
351
|
+
Attribute[LTree].meta(sql_expr: Sequel::SQL::StringExpression.new(:"||", expr,
|
352
|
+
other_value.to_s))
|
395
353
|
end
|
396
354
|
end
|
397
355
|
end
|
398
356
|
end
|
399
|
-
# rubocop:enable Metrics/ModuleLength
|
400
357
|
end
|
401
358
|
end
|
@@ -1,28 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "ipaddr"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module SQL
|
7
7
|
module Postgres
|
8
8
|
module Types
|
9
|
-
IPAddress = Type(
|
10
|
-
read = SQL::Types.Constructor(IPAddr) { |ip|
|
9
|
+
IPAddress = Type("inet") do
|
10
|
+
read = SQL::Types.Constructor(IPAddr) { |ip| IPAddr.new(ip.to_s) }
|
11
11
|
|
12
|
-
SQL::Types.Constructor(
|
13
|
-
end
|
14
|
-
|
15
|
-
IPNetwork = Type('cidr') do
|
16
|
-
read = SQL::Types.Constructor(IPAddr) do |ip|
|
17
|
-
case ip
|
18
|
-
when ::IPAddr
|
19
|
-
ip
|
20
|
-
when String
|
21
|
-
::IPAddr.new(ip)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
SQL::Types.Constructor(::IPAddr) { |ip| "#{ip}/#{ip.prefix}" }.meta(read: read)
|
12
|
+
SQL::Types.Constructor(IPAddr, &:to_s).meta(read: read)
|
26
13
|
end
|
27
14
|
end
|
28
15
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "sequel/core"
|
4
4
|
|
5
5
|
Sequel.extension(:pg_range, :pg_range_ops)
|
6
6
|
|
@@ -9,16 +9,19 @@ module ROM
|
|
9
9
|
module Postgres
|
10
10
|
module Values
|
11
11
|
Range = ::Struct.new(:lower, :upper, :bounds) do
|
12
|
-
|
12
|
+
PAREN_LEFT = "("
|
13
|
+
PAREN_RIGHT = ")"
|
14
|
+
|
15
|
+
def initialize(lower, upper, bounds = :"[)")
|
13
16
|
super
|
14
17
|
end
|
15
18
|
|
16
19
|
def exclude_begin?
|
17
|
-
bounds[0] ==
|
20
|
+
bounds[0] == PAREN_LEFT
|
18
21
|
end
|
19
22
|
|
20
23
|
def exclude_end?
|
21
|
-
bounds[1] ==
|
24
|
+
bounds[1] == PAREN_RIGHT
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -30,22 +33,22 @@ module ROM
|
|
30
33
|
|
31
34
|
@range_parsers = {
|
32
35
|
int4range: Sequel::Postgres::PGRange::Parser.new(
|
33
|
-
|
36
|
+
"int4range", SQL::Types::Coercible::Integer
|
34
37
|
),
|
35
38
|
int8range: Sequel::Postgres::PGRange::Parser.new(
|
36
|
-
|
39
|
+
"int8range", SQL::Types::Coercible::Integer
|
37
40
|
),
|
38
41
|
numrange: Sequel::Postgres::PGRange::Parser.new(
|
39
|
-
|
42
|
+
"numrange", SQL::Types::Coercible::Integer
|
40
43
|
),
|
41
44
|
tsrange: Sequel::Postgres::PGRange::Parser.new(
|
42
|
-
|
45
|
+
"tsrange", ::Time.method(:parse)
|
43
46
|
),
|
44
47
|
tstzrange: Sequel::Postgres::PGRange::Parser.new(
|
45
|
-
|
48
|
+
"tstzrange", ::Time.method(:parse)
|
46
49
|
),
|
47
50
|
daterange: Sequel::Postgres::PGRange::Parser.new(
|
48
|
-
|
51
|
+
"daterange", ::Date.method(:parse)
|
49
52
|
)
|
50
53
|
}.freeze
|
51
54
|
|
@@ -53,21 +56,20 @@ module ROM
|
|
53
56
|
def self.range_read_type(name)
|
54
57
|
SQL::Types.Constructor(Values::Range) do |value|
|
55
58
|
pg_range =
|
56
|
-
if value.is_a?(
|
59
|
+
if value.is_a?(Sequel::Postgres::PGRange)
|
57
60
|
value
|
58
|
-
elsif value
|
61
|
+
elsif value.respond_to?(:to_s)
|
59
62
|
@range_parsers[name].(value.to_s)
|
60
|
-
else
|
63
|
+
else
|
61
64
|
value
|
62
65
|
end
|
63
66
|
|
64
67
|
Values::Range.new(
|
65
68
|
pg_range.begin,
|
66
69
|
pg_range.end,
|
67
|
-
[
|
68
|
-
|
69
|
-
|
70
|
-
].join.to_sym
|
70
|
+
[pg_range.exclude_begin? ? :"(" : :"[",
|
71
|
+
pg_range.exclude_end? ? :")" : :"]"]
|
72
|
+
.join("").to_sym
|
71
73
|
)
|
72
74
|
end
|
73
75
|
end
|
@@ -76,25 +78,23 @@ module ROM
|
|
76
78
|
def self.range(name, read_type)
|
77
79
|
Type(name) do
|
78
80
|
type = SQL::Types.Nominal(Values::Range).constructor do |range|
|
79
|
-
format(
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end: range.exclude_end? ? :')' : :']'
|
85
|
-
)
|
81
|
+
format("%s%s,%s%s",
|
82
|
+
range.exclude_begin? ? :"(" : :"[",
|
83
|
+
range.lower,
|
84
|
+
range.upper,
|
85
|
+
range.exclude_end? ? :")" : :"]")
|
86
86
|
end
|
87
87
|
|
88
88
|
type.meta(read: read_type)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
|
-
Int4Range = range(
|
93
|
-
Int8Range = range(
|
94
|
-
NumRange = range(
|
95
|
-
TsRange = range(
|
96
|
-
TsTzRange = range(
|
97
|
-
DateRange = range(
|
92
|
+
Int4Range = range("int4range", range_read_type(:int4range))
|
93
|
+
Int8Range = range("int8range", range_read_type(:int8range))
|
94
|
+
NumRange = range("numrange", range_read_type(:numrange))
|
95
|
+
TsRange = range("tsrange", range_read_type(:tsrange))
|
96
|
+
TsTzRange = range("tstzrange", range_read_type(:tstzrange))
|
97
|
+
DateRange = range("daterange", range_read_type(:daterange))
|
98
98
|
|
99
99
|
module RangeOperators
|
100
100
|
def contain(_type, expr, value)
|