rom-sql 3.6.4 → 3.7.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 +17 -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 +19 -3
- 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 +10 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1a9c8d40ae3b5ea461ba889492c74ad82533ac881777d6aa2d8b120cb9c0196d
|
4
|
+
data.tar.gz: 3965d8abb7bf6a215b9c76ffe1acc4e697d9e9c4c07cd0ed1f33840cb089111f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10ccbbcb73895cb55a998ff673666878f7ae4d103aca84ba286fa0f0b4b0a0ce068524a6d110cf9ffd0139f5b9eef8a6c7b7f40e407d4f9b6a72eba314d6af28
|
7
|
+
data.tar.gz: 2c4aa7721bb02e20edd71d574ab878c405a6325a53602e77a71d30c72eb0c249033aa20944aca2460047c0a0be0def9534dd0ef611d627e4f6710743cb829df5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,22 @@
|
|
1
1
|
<!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
|
2
2
|
|
3
|
+
## 3.7.0 2025-01-08
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
|
7
|
+
- Minimum Ruby version is now 3.1 (@flash-gordon)
|
8
|
+
|
9
|
+
[Compare v3.6.5...v3.7.0](https://github.com/rom-rb/rom-sql/compare/v3.6.5...v3.7.0)
|
10
|
+
|
11
|
+
## 3.6.5 2024-12-25
|
12
|
+
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
- Fix syntax error under Ruby 3.4 (@flash-gordon)
|
17
|
+
|
18
|
+
[Compare v3.6.4...v3.6.5](https://github.com/rom-rb/rom-sql/compare/v3.6.4...v3.6.5)
|
19
|
+
|
3
20
|
## 3.6.4 2024-07-01
|
4
21
|
|
5
22
|
|
data/README.md
CHANGED
@@ -39,6 +39,8 @@ module ROM
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# @api private
|
42
|
+
#
|
43
|
+
# rubocop:disable Metrics/AbcSize
|
42
44
|
def self.restriction_methods(schema)
|
43
45
|
mod = Module.new
|
44
46
|
|
@@ -46,7 +48,7 @@ module ROM
|
|
46
48
|
next if index.partial?
|
47
49
|
|
48
50
|
attributes = index.to_a
|
49
|
-
meth_name = :"by_#{
|
51
|
+
meth_name = :"by_#{attributes.map(&:name).join("_and_")}"
|
50
52
|
|
51
53
|
next if generated.include?(meth_name)
|
52
54
|
|
@@ -72,6 +74,7 @@ module ROM
|
|
72
74
|
[methods, mod]
|
73
75
|
end
|
74
76
|
end
|
77
|
+
# rubocop:enable Metrics/AbcSize
|
75
78
|
end
|
76
79
|
end
|
77
80
|
end
|
@@ -31,8 +31,12 @@ module ROM
|
|
31
31
|
subscribe('configuration.relations.registry.created') do |event|
|
32
32
|
registry = event[:registry]
|
33
33
|
|
34
|
-
relations = registry.select { |_, r|
|
35
|
-
|
34
|
+
relations = registry.select { |_, r|
|
35
|
+
r.adapter == :sql && r.respond_to?(:notifications)
|
36
|
+
}.to_h
|
37
|
+
db_notifications = relations.values.map { |r|
|
38
|
+
[r.dataset.db, r.notifications]
|
39
|
+
}.uniq.to_h
|
36
40
|
|
37
41
|
db_notifications.each do |db, notifications|
|
38
42
|
next if db.respond_to?(:rom_instrumentation?)
|
@@ -26,7 +26,7 @@ module ROM
|
|
26
26
|
#
|
27
27
|
# @api public
|
28
28
|
def explain(format: :text, **options)
|
29
|
-
bool_options = options.map {
|
29
|
+
bool_options = options.map { "#{_1.to_s.upcase} #{!!_2}" } # rubocop:disable Style/DoubleNegation
|
30
30
|
format_option = "FORMAT #{format.to_s.upcase}"
|
31
31
|
explain_value = [format_option, *bool_options].join(', ')
|
32
32
|
|
@@ -13,31 +13,48 @@ module ROM
|
|
13
13
|
# By default, searching for the inclusion of any of the terms in any of the cols.
|
14
14
|
#
|
15
15
|
# @example
|
16
|
-
# posts.full_text_search([:title, :content], 'apples', language: 'english')
|
16
|
+
# posts.full_text_search([:title, :content], 'apples', language: 'english')
|
17
|
+
# # => Relation which match the 'apples' phrase
|
17
18
|
#
|
18
|
-
# @option :headline [String]
|
19
|
+
# @option :headline [String]
|
20
|
+
# Append a expression to the selected columns aliased
|
21
|
+
# to headline that contains an extract of the matched text.
|
19
22
|
#
|
20
|
-
# @option :language [String]
|
23
|
+
# @option :language [String]
|
24
|
+
# The language to use for the search (default: 'simple')
|
21
25
|
#
|
22
|
-
# @option :plain [Boolean]
|
26
|
+
# @option :plain [Boolean]
|
27
|
+
# Whether a plain search should be used (default: false).
|
28
|
+
# In this case, terms should be a single string, and it will do a search
|
29
|
+
# where cols contains all of the words in terms.
|
30
|
+
# This ignores search operators in terms.
|
23
31
|
#
|
24
|
-
# @option :phrase [Boolean]
|
32
|
+
# @option :phrase [Boolean]
|
33
|
+
# Similar to :plain, but also adding an ILIKE filter to ensure
|
34
|
+
# that returned rows also include the exact phrase used.
|
25
35
|
#
|
26
|
-
# @option :rank [Boolean]
|
36
|
+
# @option :rank [Boolean]
|
37
|
+
# Set to true to order by the rank, so that closer matches are returned first.
|
27
38
|
#
|
28
|
-
# @option :to_tsquery [Symbol]
|
39
|
+
# @option :to_tsquery [Symbol]
|
40
|
+
# Can be set to :plain or :phrase to specify the function to use
|
41
|
+
# to convert the terms to a ts_query.
|
29
42
|
#
|
30
|
-
# @option :tsquery [Boolean]
|
43
|
+
# @option :tsquery [Boolean]
|
44
|
+
# Specifies the terms argument is already a valid SQL expression returning a tsquery,
|
45
|
+
# and can be used directly in the query.
|
31
46
|
#
|
32
|
-
# @option :tsvector [Boolean]
|
47
|
+
# @option :tsvector [Boolean]
|
48
|
+
# Specifies the cols argument is already a valid SQL expression returning a tsvector,
|
49
|
+
# and can be used directly in the query.
|
33
50
|
#
|
34
51
|
# @return [Relation]
|
35
52
|
#
|
36
53
|
# @see https://www.postgresql.org/docs/current/textsearch.html PostgreSQL docs
|
37
54
|
#
|
38
55
|
# @api public
|
39
|
-
def full_text_search(
|
40
|
-
new dataset.__send__(__method__,
|
56
|
+
def full_text_search(...)
|
57
|
+
new dataset.__send__(__method__, ...)
|
41
58
|
end
|
42
59
|
end
|
43
60
|
end
|
@@ -48,6 +65,8 @@ end
|
|
48
65
|
|
49
66
|
ROM.plugins do
|
50
67
|
adapter :sql do
|
51
|
-
register :pg_full_text_search,
|
68
|
+
register :pg_full_text_search,
|
69
|
+
ROM::Plugins::Relation::SQL::Postgres::FullTextSearch,
|
70
|
+
type: :relation
|
52
71
|
end
|
53
72
|
end
|
@@ -13,7 +13,7 @@ module ROM
|
|
13
13
|
|
14
14
|
class StreamingNotSupportedError < StandardError; end
|
15
15
|
|
16
|
-
subscribe(
|
16
|
+
subscribe('configuration.gateway.connected') do |opts|
|
17
17
|
conn = opts[:connection]
|
18
18
|
|
19
19
|
next unless conn.database_type.to_sym == :postgres
|
@@ -21,13 +21,13 @@ module ROM
|
|
21
21
|
next if defined?(JRUBY_VERSION)
|
22
22
|
|
23
23
|
begin
|
24
|
-
require
|
24
|
+
require 'sequel_pg'
|
25
25
|
rescue LoadError
|
26
|
-
raise StreamingNotSupportedError,
|
26
|
+
raise StreamingNotSupportedError, 'add sequel_pg to Gemfile to use pg_streaming'
|
27
27
|
end
|
28
28
|
|
29
29
|
unless Sequel::Postgres.supports_streaming?
|
30
|
-
raise StreamingNotSupportedError,
|
30
|
+
raise StreamingNotSupportedError, 'postgres version does not support streaming'
|
31
31
|
end
|
32
32
|
|
33
33
|
conn.extension(:pg_streaming)
|
@@ -52,7 +52,7 @@ module ROM
|
|
52
52
|
#
|
53
53
|
# @api publicY_VERSION
|
54
54
|
def stream_each
|
55
|
-
raise StreamingNotSupportedError,
|
55
|
+
raise StreamingNotSupportedError, 'not supported on jruby'
|
56
56
|
end
|
57
57
|
else
|
58
58
|
# Allows you to stream returned rows one at a time, instead of
|
@@ -80,7 +80,7 @@ module ROM
|
|
80
80
|
|
81
81
|
module Combined
|
82
82
|
def stream_each
|
83
|
-
raise StreamingNotSupportedError,
|
83
|
+
raise StreamingNotSupportedError, 'not supported on combined relations'
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -12,15 +12,17 @@ module ROM
|
|
12
12
|
include Associations::SelfRef
|
13
13
|
|
14
14
|
# @api public
|
15
|
+
#
|
16
|
+
# rubocop:disable Metrics/AbcSize
|
15
17
|
def call(target: self.target)
|
16
18
|
left = join_assoc.(target: target)
|
17
19
|
|
18
20
|
schema =
|
19
21
|
if left.schema.key?(foreign_key)
|
20
|
-
if target
|
21
|
-
target.schema.merge(join_schema)
|
22
|
-
else
|
22
|
+
if target == self.target
|
23
23
|
left.schema.uniq.project(*columns)
|
24
|
+
else
|
25
|
+
target.schema.merge(join_schema)
|
24
26
|
end
|
25
27
|
else
|
26
28
|
target_schema
|
@@ -34,6 +36,7 @@ module ROM
|
|
34
36
|
schema.(relation)
|
35
37
|
end
|
36
38
|
end
|
39
|
+
# rubocop:enable Metrics/AbcSize
|
37
40
|
|
38
41
|
# @api public
|
39
42
|
def join(type, source = self.source, target = self.target)
|
@@ -12,6 +12,8 @@ module ROM
|
|
12
12
|
include Associations::SelfRef
|
13
13
|
|
14
14
|
# @api public
|
15
|
+
#
|
16
|
+
# rubocop:disable Metrics/AbcSize
|
15
17
|
def call(target: self.target, preload: false)
|
16
18
|
if preload
|
17
19
|
schema = target.schema.qualified
|
@@ -41,6 +43,7 @@ module ROM
|
|
41
43
|
schema.(relation)
|
42
44
|
end
|
43
45
|
end
|
46
|
+
# rubocop:enable Metrics/AbcSize
|
44
47
|
|
45
48
|
# @api public
|
46
49
|
def join(type, source = self.source, target = self.target)
|
data/lib/rom/sql/attribute.rb
CHANGED
@@ -15,6 +15,8 @@ module ROM
|
|
15
15
|
# Extended schema attributes tailored for SQL databases
|
16
16
|
#
|
17
17
|
# @api public
|
18
|
+
#
|
19
|
+
# rubocop:disable Metrics/ClassLength
|
18
20
|
class Attribute < ROM::Attribute
|
19
21
|
include AttributeWrapping
|
20
22
|
include AttributeAliasing
|
@@ -59,7 +61,9 @@ module ROM
|
|
59
61
|
return meta(qualified: false) unless qualifiable?
|
60
62
|
|
61
63
|
case sql_expr
|
62
|
-
when Sequel::SQL::AliasedExpression,
|
64
|
+
when ::Sequel::SQL::AliasedExpression,
|
65
|
+
::Sequel::SQL::Identifier,
|
66
|
+
::Sequel::SQL::QualifiedIdentifier
|
63
67
|
attr = meta(qualified: table_alias || true)
|
64
68
|
attr.meta(sql_expr: attr.to_sql_name)
|
65
69
|
else
|
@@ -263,8 +267,8 @@ module ROM
|
|
263
267
|
# @return [SQL::Function]
|
264
268
|
#
|
265
269
|
# @api public
|
266
|
-
def func(&
|
267
|
-
ProjectionDSL.new(name => self).call(&
|
270
|
+
def func(&)
|
271
|
+
ProjectionDSL.new(name => self).call(&).first
|
268
272
|
end
|
269
273
|
|
270
274
|
# Create a CONCAT function from the attribute
|
@@ -334,7 +338,7 @@ module ROM
|
|
334
338
|
#
|
335
339
|
# @api private
|
336
340
|
def unwrap
|
337
|
-
cleaned_meta = meta.
|
341
|
+
cleaned_meta = meta.except(*META_KEYS)
|
338
342
|
type = optional? ? right : self.type
|
339
343
|
|
340
344
|
self.class.new(type.with(meta: cleaned_meta), **options)
|
@@ -380,19 +384,28 @@ module ROM
|
|
380
384
|
#
|
381
385
|
# @api private
|
382
386
|
def sql_expr
|
383
|
-
@sql_expr ||=
|
387
|
+
@sql_expr ||= meta[:sql_expr] || to_sql_name
|
388
|
+
end
|
389
|
+
|
390
|
+
# @api private
|
391
|
+
def respond_to_missing?(meth, _include_private = false)
|
392
|
+
if OPERATORS.include?(meth) || extensions.key?(meth) || sql_expr.respond_to?(meth)
|
393
|
+
true
|
394
|
+
else
|
395
|
+
super
|
396
|
+
end
|
384
397
|
end
|
385
398
|
|
386
399
|
# Delegate to sql expression if it responds to a given method
|
387
400
|
#
|
388
401
|
# @api private
|
389
|
-
def method_missing(meth, *args, &
|
402
|
+
def method_missing(meth, *args, &)
|
390
403
|
if OPERATORS.include?(meth)
|
391
404
|
__cmp__(meth, args[0])
|
392
405
|
elsif extensions.key?(meth)
|
393
|
-
extensions[meth].(type, sql_expr, *args, &
|
406
|
+
extensions[meth].(type, sql_expr, *args, &)
|
394
407
|
elsif sql_expr.respond_to?(meth)
|
395
|
-
meta(sql_expr: sql_expr.__send__(meth, *args, &
|
408
|
+
meta(sql_expr: sql_expr.__send__(meth, *args, &))
|
396
409
|
else
|
397
410
|
super
|
398
411
|
end
|
@@ -436,5 +449,6 @@ module ROM
|
|
436
449
|
|
437
450
|
memoize :joined, :to_sql_name, :table_name, :canonical
|
438
451
|
end
|
452
|
+
# rubocop:enable Metrics/ClassLength
|
439
453
|
end
|
440
454
|
end
|
@@ -19,8 +19,7 @@ module ROM
|
|
19
19
|
sql_expr: alias_sql_expr(sql_expr, new_alias_name)
|
20
20
|
)
|
21
21
|
end
|
22
|
-
|
23
|
-
|
22
|
+
alias_method :as, :aliased
|
24
23
|
|
25
24
|
# Return true if this attribute is an aliased projection
|
26
25
|
#
|
@@ -46,7 +45,7 @@ module ROM
|
|
46
45
|
#
|
47
46
|
# @api private
|
48
47
|
def aliased_projection?
|
49
|
-
|
48
|
+
meta[:sql_expr].is_a?(::Sequel::SQL::AliasedExpression)
|
50
49
|
end
|
51
50
|
|
52
51
|
private
|
@@ -54,8 +53,10 @@ module ROM
|
|
54
53
|
# @api private
|
55
54
|
def alias_sql_expr(sql_expr, new_alias)
|
56
55
|
case sql_expr
|
57
|
-
when Sequel::SQL::AliasedExpression
|
58
|
-
Sequel::SQL::AliasedExpression.new(
|
56
|
+
when ::Sequel::SQL::AliasedExpression
|
57
|
+
::Sequel::SQL::AliasedExpression.new(
|
58
|
+
sql_expr.expression, new_alias, sql_expr.columns
|
59
|
+
)
|
59
60
|
else
|
60
61
|
sql_expr.as(new_alias)
|
61
62
|
end
|
@@ -70,7 +71,7 @@ module ROM
|
|
70
71
|
# attribute in a way that will map the the requested alias name.
|
71
72
|
# Without this, the attribute will silently ignore the requested alias
|
72
73
|
# name and default to the pre-existing name.
|
73
|
-
new_name = "#{meta[:wrapped]}_#{options[:alias]}"
|
74
|
+
new_name = :"#{meta[:wrapped]}_#{options[:alias]}"
|
74
75
|
|
75
76
|
# Essentially, this makes it so "wrapped" attributes aren't true
|
76
77
|
# aliases, in that we actually alias the wrapped attribute, we use
|
@@ -60,10 +60,11 @@ module ROM
|
|
60
60
|
# Yields tuples for insertion or return an enumerator
|
61
61
|
#
|
62
62
|
# @api private
|
63
|
-
def with_input_tuples(tuples)
|
64
|
-
input_tuples =
|
63
|
+
def with_input_tuples(tuples, &)
|
64
|
+
input_tuples = [tuples].flatten(1).map
|
65
65
|
return input_tuples unless block_given?
|
66
|
-
|
66
|
+
|
67
|
+
input_tuples.each(&)
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
@@ -52,10 +52,11 @@ module ROM
|
|
52
52
|
# Yields tuples for insertion or return an enumerator
|
53
53
|
#
|
54
54
|
# @api private
|
55
|
-
def with_input_tuples(tuples)
|
56
|
-
input_tuples =
|
55
|
+
def with_input_tuples(tuples, &)
|
56
|
+
input_tuples = [tuples].flatten(1).map
|
57
57
|
return input_tuples unless block_given?
|
58
|
-
|
58
|
+
|
59
|
+
input_tuples.each(&)
|
59
60
|
end
|
60
61
|
end
|
61
62
|
end
|
data/lib/rom/sql/dsl.rb
CHANGED
@@ -59,7 +59,9 @@ module ROM
|
|
59
59
|
#
|
60
60
|
# @example
|
61
61
|
# users.where { exists(users.where(name: 'John')) }
|
62
|
-
# users.select_append { |r|
|
62
|
+
# users.select_append { |r|
|
63
|
+
# exists(r[:posts].where(r[:posts][:user_id] => id)).as(:has_posts)
|
64
|
+
# }
|
63
65
|
#
|
64
66
|
# @api public
|
65
67
|
def exists(relation)
|
@@ -6,17 +6,17 @@ module ROM
|
|
6
6
|
class TypeBuilder < Schema::TypeBuilder
|
7
7
|
defines :db_numeric_types, :db_type_mapping, :db_array_type_matcher
|
8
8
|
|
9
|
-
db_numeric_types
|
10
|
-
smallint integer bigint
|
11
|
-
decimal numeric real
|
12
|
-
double
|
9
|
+
db_numeric_types [
|
10
|
+
'smallint', 'integer', 'bigint',
|
11
|
+
'decimal', 'numeric', 'real',
|
12
|
+
'double precision', 'serial', 'bigserial'
|
13
13
|
].to_set.freeze
|
14
14
|
|
15
15
|
db_type_mapping(
|
16
|
-
'uuid'
|
16
|
+
'uuid' => Types::UUID,
|
17
17
|
'money' => Types::Money,
|
18
18
|
'bytea' => Types::Bytea,
|
19
|
-
'json'
|
19
|
+
'json' => Types::JSON,
|
20
20
|
'jsonb' => Types::JSONB,
|
21
21
|
'xml' => Types::XML,
|
22
22
|
'inet' => Types::IPAddress,
|
@@ -39,7 +39,7 @@ module ROM
|
|
39
39
|
'ltree' => Types::LTree
|
40
40
|
).freeze
|
41
41
|
|
42
|
-
db_array_type_matcher '[]'
|
42
|
+
db_array_type_matcher '[]'
|
43
43
|
|
44
44
|
def map_pk_type(type, db_type, **options)
|
45
45
|
if numeric?(type, db_type)
|
@@ -36,8 +36,8 @@ module ROM
|
|
36
36
|
|
37
37
|
def call(type)
|
38
38
|
super do
|
39
|
-
if type.respond_to?(:primitive) && type.primitive.equal?(Array)
|
40
|
-
"#{
|
39
|
+
if type.respond_to?(:primitive) && type.primitive.equal?(::Array)
|
40
|
+
"#{type.meta[:type]}[]"
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
@@ -37,7 +37,7 @@ module ROM
|
|
37
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|
|
@@ -50,7 +50,7 @@ module ROM
|
|
50
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|
|
@@ -63,7 +63,7 @@ module ROM
|
|
63
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|
|
@@ -77,8 +77,8 @@ module ROM
|
|
77
77
|
Box = Type('box') do
|
78
78
|
SQL::Types.define(Values::Box) do
|
79
79
|
input do |box|
|
80
|
-
"((#{
|
81
|
-
|
80
|
+
"((#{box.upper_right.x},#{box.upper_right.y})," \
|
81
|
+
"(#{box.lower_left.x},#{box.lower_left.y}))"
|
82
82
|
end
|
83
83
|
|
84
84
|
output do |box|
|
@@ -93,8 +93,8 @@ module ROM
|
|
93
93
|
LineSegment = Type('lseg') do
|
94
94
|
SQL::Types.define(Values::LineSegment) do
|
95
95
|
input do |segment|
|
96
|
-
"[(#{
|
97
|
-
|
96
|
+
"[(#{segment.begin.x},#{segment.begin.y})," \
|
97
|
+
"(#{segment.end.x},#{segment.end.y})]"
|
98
98
|
end
|
99
99
|
|
100
100
|
output do |segment|
|
@@ -109,8 +109,8 @@ module ROM
|
|
109
109
|
Polygon = Type('polygon') do
|
110
110
|
SQL::Types.define(::Array) do
|
111
111
|
input do |points|
|
112
|
-
points_joined = points.map { |p| "(#{
|
113
|
-
"(#{
|
112
|
+
points_joined = points.map { |p| "(#{p.x},#{p.y})" }.join(',')
|
113
|
+
"(#{points_joined})"
|
114
114
|
end
|
115
115
|
|
116
116
|
output do |polygon|
|
@@ -123,12 +123,12 @@ module ROM
|
|
123
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| "(#{
|
126
|
+
points_joined = path.to_a.map { |p| "(#{p.x},#{p.y})" }.join(',')
|
127
127
|
|
128
128
|
if path.open?
|
129
|
-
"[#{
|
129
|
+
"[#{points_joined}]"
|
130
130
|
else
|
131
|
-
"(#{
|
131
|
+
"(#{points_joined})"
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
@@ -77,11 +77,15 @@ module ROM
|
|
77
77
|
end
|
78
78
|
else
|
79
79
|
JSON = Type('json') do
|
80
|
-
(SQL::Types::Array | SQL::Types::Hash).constructor(
|
80
|
+
(SQL::Types::Array | SQL::Types::Hash).constructor(
|
81
|
+
::Sequel.method(:pg_json)
|
82
|
+
).meta(read: JSONRead)
|
81
83
|
end
|
82
84
|
|
83
85
|
JSONB = Type('jsonb') do
|
84
|
-
(SQL::Types::Array | SQL::Types::Hash).constructor(
|
86
|
+
(SQL::Types::Array | SQL::Types::Hash).constructor(
|
87
|
+
::Sequel.method(:pg_jsonb)
|
88
|
+
).meta(read: JSONRead)
|
85
89
|
end
|
86
90
|
end
|
87
91
|
|
@@ -265,7 +269,9 @@ module ROM
|
|
265
269
|
end
|
266
270
|
|
267
271
|
def has_key(_type, expr, key)
|
268
|
-
Attribute[SQL::Types::Bool].meta(
|
272
|
+
Attribute[SQL::Types::Bool].meta(
|
273
|
+
sql_expr: wrap(expr).has_key?(key) # rubocop:disable Style/PreferredHashMethods
|
274
|
+
)
|
269
275
|
end
|
270
276
|
|
271
277
|
def has_any_key(_type, expr, *keys)
|