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
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module SQL
|
|
5
|
+
# @api private
|
|
6
|
+
module AttributeAliasing
|
|
7
|
+
# Return a new attribute with an alias
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# users[:id].aliased(:user_id)
|
|
11
|
+
#
|
|
12
|
+
# @return [SQL::Attribute]
|
|
13
|
+
#
|
|
14
|
+
# @api public
|
|
15
|
+
def aliased(alias_name)
|
|
16
|
+
new_name, new_alias_name = extract_alias_names(alias_name)
|
|
17
|
+
|
|
18
|
+
super(new_alias_name).with(name: new_name).meta(
|
|
19
|
+
sql_expr: alias_sql_expr(sql_expr, new_alias_name)
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
alias as aliased
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# Return true if this attribute is an aliased projection
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
# class Tasks < ROM::Relation[:memory]
|
|
29
|
+
# schema do
|
|
30
|
+
# attribute :user_id, Types::Integer, alias: :id
|
|
31
|
+
# attribute :name, Types::String
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# Users.schema[:user_id].aliased?
|
|
36
|
+
# # => true
|
|
37
|
+
# Users.schema[:user_id].aliased_projection?
|
|
38
|
+
# # => false
|
|
39
|
+
#
|
|
40
|
+
# Users.schema[:user_id].qualified_projection.aliased?
|
|
41
|
+
# # => true
|
|
42
|
+
# Users.schema[:user_id].qualified_projection.aliased_projection?
|
|
43
|
+
# # => true
|
|
44
|
+
#
|
|
45
|
+
# @return [TrueClass,FalseClass]
|
|
46
|
+
#
|
|
47
|
+
# @api private
|
|
48
|
+
def aliased_projection?
|
|
49
|
+
self.meta[:sql_expr].is_a?(Sequel::SQL::AliasedExpression)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
# @api private
|
|
55
|
+
def alias_sql_expr(sql_expr, new_alias)
|
|
56
|
+
case sql_expr
|
|
57
|
+
when Sequel::SQL::AliasedExpression
|
|
58
|
+
Sequel::SQL::AliasedExpression.new(sql_expr.expression, new_alias, sql_expr.columns)
|
|
59
|
+
else
|
|
60
|
+
sql_expr.as(new_alias)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @api private
|
|
65
|
+
def extract_alias_names(alias_name)
|
|
66
|
+
new_name, new_alias_name = nil
|
|
67
|
+
|
|
68
|
+
if wrapped? && aliased?
|
|
69
|
+
# If the attribute is wrapped *and* aliased, make sure that we name the
|
|
70
|
+
# attribute in a way that will map the the requested alias name.
|
|
71
|
+
# Without this, the attribute will silently ignore the requested alias
|
|
72
|
+
# name and default to the pre-existing name.
|
|
73
|
+
new_name = "#{meta[:wrapped]}_#{options[:alias]}".to_sym
|
|
74
|
+
|
|
75
|
+
# Essentially, this makes it so "wrapped" attributes aren't true
|
|
76
|
+
# aliases, in that we actually alias the wrapped attribute, we use
|
|
77
|
+
# the old alias.
|
|
78
|
+
new_alias_name = options[:alias]
|
|
79
|
+
else
|
|
80
|
+
new_name = name || alias_name
|
|
81
|
+
new_alias_name = alias_name
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
[new_name, new_alias_name]
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module SQL
|
|
5
|
+
# @api private
|
|
6
|
+
module AttributeWrapping
|
|
7
|
+
# Return if the attribute type is from a wrapped relation
|
|
8
|
+
#
|
|
9
|
+
# Wrapped attributes are used when two schemas from different relations
|
|
10
|
+
# are merged together. This way we can identify them easily and handle
|
|
11
|
+
# correctly in places like auto-mapping.
|
|
12
|
+
#
|
|
13
|
+
# @api public
|
|
14
|
+
def wrapped?
|
|
15
|
+
!meta[:wrapped].nil?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Return attribute type wrapped for the specified relation name
|
|
19
|
+
#
|
|
20
|
+
# @param [Symbol] name The name of the source relation (defaults to source.dataset)
|
|
21
|
+
#
|
|
22
|
+
# @return [Attribute]
|
|
23
|
+
#
|
|
24
|
+
# @api public
|
|
25
|
+
def wrapped(name = source.dataset)
|
|
26
|
+
meta(wrapped: name).prefixed(name)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/rom/sql/commands.rb
CHANGED
data/lib/rom/sql/dsl.rb
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'concurrent/map'
|
|
1
4
|
require 'rom/support/inflector'
|
|
2
5
|
require 'rom/constants'
|
|
3
6
|
|
|
@@ -13,15 +16,26 @@ module ROM
|
|
|
13
16
|
# @return [Hash, RelationRegistry]
|
|
14
17
|
attr_reader :relations
|
|
15
18
|
|
|
19
|
+
# @!attribute [r] picked_relations
|
|
20
|
+
# @return [Concurrent::Map]
|
|
21
|
+
attr_reader :picked_relations
|
|
22
|
+
|
|
16
23
|
# @api private
|
|
17
24
|
def initialize(schema)
|
|
18
25
|
@schema = schema
|
|
19
26
|
@relations = schema.respond_to?(:relations) ? schema.relations : EMPTY_HASH
|
|
27
|
+
@picked_relations = ::Concurrent::Map.new
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
# @api private
|
|
23
31
|
def call(&block)
|
|
24
|
-
|
|
32
|
+
arg, kwargs = select_relations(block.parameters)
|
|
33
|
+
|
|
34
|
+
if kwargs.nil?
|
|
35
|
+
result = instance_exec(arg, &block)
|
|
36
|
+
else
|
|
37
|
+
result = instance_exec(**kwargs, &block)
|
|
38
|
+
end
|
|
25
39
|
|
|
26
40
|
if result.is_a?(::Array)
|
|
27
41
|
result
|
|
@@ -41,6 +55,17 @@ module ROM
|
|
|
41
55
|
::Sequel.lit(value)
|
|
42
56
|
end
|
|
43
57
|
|
|
58
|
+
# Returns a result of SQL EXISTS clause.
|
|
59
|
+
#
|
|
60
|
+
# @example
|
|
61
|
+
# users.where { exists(users.where(name: 'John')) }
|
|
62
|
+
# users.select_append { |r| exists(r[:posts].where(r[:posts][:user_id] => id)).as(:has_posts) }
|
|
63
|
+
#
|
|
64
|
+
# @api public
|
|
65
|
+
def exists(relation)
|
|
66
|
+
::ROM::SQL::Attribute[Types::Bool].meta(sql_expr: relation.dataset.exists)
|
|
67
|
+
end
|
|
68
|
+
|
|
44
69
|
# @api private
|
|
45
70
|
def respond_to_missing?(name, include_private = false)
|
|
46
71
|
super || schema.key?(name)
|
|
@@ -58,6 +83,19 @@ module ROM
|
|
|
58
83
|
def types
|
|
59
84
|
::ROM::SQL::Types
|
|
60
85
|
end
|
|
86
|
+
|
|
87
|
+
# @api private
|
|
88
|
+
def select_relations(parameters)
|
|
89
|
+
@picked_relations.fetch_or_store(parameters.hash) do
|
|
90
|
+
keys = parameters.select { |type, _| type == :keyreq }
|
|
91
|
+
|
|
92
|
+
if keys.empty?
|
|
93
|
+
[relations, nil]
|
|
94
|
+
else
|
|
95
|
+
[nil, keys.each_with_object({}) { |(_, k), rs| rs[k] = relations[k] }]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
61
99
|
end
|
|
62
100
|
end
|
|
63
101
|
end
|
data/lib/rom/sql/error.rb
CHANGED
data/lib/rom/sql/errors.rb
CHANGED
data/lib/rom/sql/extensions.rb
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/sql/extensions/postgres/commands'
|
|
2
4
|
require 'rom/sql/extensions/postgres/types'
|
|
3
5
|
require 'rom/sql/extensions/postgres/type_builder'
|
|
4
6
|
require 'rom/sql/extensions/postgres/type_serializer'
|
|
5
7
|
require 'rom/plugins/relation/sql/postgres/explain'
|
|
8
|
+
require 'rom/plugins/relation/sql/postgres/full_text_search'
|
|
9
|
+
require "rom/plugins/relation/sql/postgres/streaming"
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/sql/commands/create'
|
|
2
4
|
require 'rom/sql/commands/update'
|
|
3
5
|
|
|
@@ -15,7 +17,7 @@ module ROM
|
|
|
15
17
|
#
|
|
16
18
|
# @api private
|
|
17
19
|
def returning_dataset
|
|
18
|
-
relation.dataset.returning(*relation.
|
|
20
|
+
relation.dataset.returning(*relation.schema.qualified_projection)
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ROM
|
|
2
4
|
module SQL
|
|
3
5
|
module Postgres
|
|
4
6
|
class TypeBuilder < Schema::TypeBuilder
|
|
5
7
|
defines :db_numeric_types, :db_type_mapping, :db_array_type_matcher
|
|
6
8
|
|
|
7
|
-
db_numeric_types %w
|
|
9
|
+
db_numeric_types %w[
|
|
8
10
|
smallint integer bigint
|
|
9
11
|
decimal numeric real
|
|
10
12
|
double\ precision serial bigserial
|
|
11
|
-
|
|
13
|
+
].to_set.freeze
|
|
12
14
|
|
|
13
15
|
db_type_mapping(
|
|
14
16
|
'uuid' => Types::UUID,
|
|
@@ -39,11 +41,11 @@ module ROM
|
|
|
39
41
|
|
|
40
42
|
db_array_type_matcher '[]'.freeze
|
|
41
43
|
|
|
42
|
-
def map_pk_type(type, db_type, options
|
|
44
|
+
def map_pk_type(type, db_type, **options)
|
|
43
45
|
if numeric?(type, db_type)
|
|
44
46
|
type = self.class.numeric_pk_type
|
|
45
47
|
else
|
|
46
|
-
type = map_type(type, db_type, options)
|
|
48
|
+
type = map_type(type, db_type, **options)
|
|
47
49
|
end
|
|
48
50
|
|
|
49
51
|
type.meta(primary_key: true)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'sequel/core'
|
|
2
4
|
|
|
3
|
-
Sequel.extension(
|
|
5
|
+
Sequel.extension(:pg_array, :pg_array_ops)
|
|
4
6
|
|
|
5
7
|
require 'rom/sql/extensions/postgres/types/array_types'
|
|
6
8
|
|
|
@@ -66,7 +68,7 @@ module ROM
|
|
|
66
68
|
# # @!method length
|
|
67
69
|
# # Return array size
|
|
68
70
|
# #
|
|
69
|
-
# # @return [SQL::Attribute<Types::
|
|
71
|
+
# # @return [SQL::Attribute<Types::Integer>]
|
|
70
72
|
# #
|
|
71
73
|
# # @api public
|
|
72
74
|
#
|
|
@@ -120,7 +122,7 @@ module ROM
|
|
|
120
122
|
Attribute[type].meta(sql_expr: expr.pg_array[idx])
|
|
121
123
|
end
|
|
122
124
|
|
|
123
|
-
def any(
|
|
125
|
+
def any(_type, expr, value)
|
|
124
126
|
Attribute[SQL::Types::Bool].meta(sql_expr: { value => expr.pg_array.any })
|
|
125
127
|
end
|
|
126
128
|
|
|
@@ -128,8 +130,8 @@ module ROM
|
|
|
128
130
|
Attribute[SQL::Types::Bool].meta(sql_expr: expr.pg_array.contained_by(type[other]))
|
|
129
131
|
end
|
|
130
132
|
|
|
131
|
-
def length(
|
|
132
|
-
Attribute[SQL::Types::
|
|
133
|
+
def length(_type, expr)
|
|
134
|
+
Attribute[SQL::Types::Integer].meta(sql_expr: expr.pg_array.length)
|
|
133
135
|
end
|
|
134
136
|
|
|
135
137
|
def overlaps(type, expr, other_array)
|
|
@@ -140,7 +142,7 @@ module ROM
|
|
|
140
142
|
Attribute[type].meta(sql_expr: expr.pg_array.remove(cast(type, value)))
|
|
141
143
|
end
|
|
142
144
|
|
|
143
|
-
def join(
|
|
145
|
+
def join(_type, expr, delimiter = '', null = nil)
|
|
144
146
|
Attribute[SQL::Types::String].meta(sql_expr: expr.pg_array.join(delimiter, null))
|
|
145
147
|
end
|
|
146
148
|
|
|
@@ -151,8 +153,7 @@ module ROM
|
|
|
151
153
|
private
|
|
152
154
|
|
|
153
155
|
def cast(type, value)
|
|
154
|
-
|
|
155
|
-
Sequel.cast(value, db_type)
|
|
156
|
+
Sequel.cast(value, type.meta[:type])
|
|
156
157
|
end
|
|
157
158
|
end
|
|
158
159
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/sql/type_extensions'
|
|
2
4
|
|
|
3
5
|
module ROM
|
|
@@ -52,7 +54,7 @@ module ROM
|
|
|
52
54
|
end
|
|
53
55
|
end
|
|
54
56
|
|
|
55
|
-
def build_read_type(
|
|
57
|
+
def build_read_type(_db_type, member_type)
|
|
56
58
|
if member_type && member_type.meta[:read]
|
|
57
59
|
base_read_type.of(member_type.meta[:read])
|
|
58
60
|
else
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'sequel/core'
|
|
4
|
+
require 'singleton'
|
|
2
5
|
|
|
3
|
-
Sequel.extension(
|
|
6
|
+
Sequel.extension(:pg_json, :pg_json_ops)
|
|
4
7
|
|
|
5
8
|
module ROM
|
|
6
9
|
module SQL
|
|
@@ -16,16 +19,70 @@ module ROM
|
|
|
16
19
|
end
|
|
17
20
|
end
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
class JSONNullType
|
|
23
|
+
include ::Singleton
|
|
24
|
+
|
|
25
|
+
def to_s
|
|
26
|
+
'null'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def inspect
|
|
30
|
+
'null'
|
|
31
|
+
end
|
|
23
32
|
end
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
JSONNull = JSONNullType.instance.freeze
|
|
35
|
+
|
|
36
|
+
if ::Sequel.respond_to?(:pg_json_wrap)
|
|
37
|
+
primitive_json_types = [
|
|
38
|
+
SQL::Types::Array,
|
|
39
|
+
SQL::Types::Hash,
|
|
40
|
+
SQL::Types::Integer,
|
|
41
|
+
SQL::Types::Float,
|
|
42
|
+
SQL::Types::String,
|
|
43
|
+
SQL::Types::True,
|
|
44
|
+
SQL::Types::False
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
JSON = Type('json') do
|
|
48
|
+
casts = ::Hash.new(-> v { ::Sequel.pg_json(v) })
|
|
49
|
+
json_null = ::Sequel.pg_json_wrap(nil)
|
|
50
|
+
casts[JSONNullType] = -> _ { json_null }
|
|
51
|
+
casts[::NilClass] = -> _ { json_null }
|
|
52
|
+
primitive_json_types.each do |type|
|
|
53
|
+
casts[type.primitive] = -> v { ::Sequel.pg_json_wrap(v) }
|
|
54
|
+
end
|
|
55
|
+
casts.freeze
|
|
56
|
+
|
|
57
|
+
[*primitive_json_types, SQL::Types.Constant(JSONNull)]
|
|
58
|
+
.reduce(:|)
|
|
59
|
+
.constructor { |value| casts[value.class].(value) }
|
|
60
|
+
.meta(read: JSONRead)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
JSONB = Type('jsonb') do
|
|
64
|
+
casts = ::Hash.new(-> v { ::Sequel.pg_jsonb(v) })
|
|
65
|
+
jsonb_null = ::Sequel.pg_jsonb_wrap(nil)
|
|
66
|
+
casts[JSONNullType] = -> _ { jsonb_null }
|
|
67
|
+
casts[::NilClass] = -> _ { jsonb_null }
|
|
68
|
+
primitive_json_types.each do |type|
|
|
69
|
+
casts[type.primitive] = -> v { ::Sequel.pg_jsonb_wrap(v) }
|
|
70
|
+
end
|
|
71
|
+
casts.freeze
|
|
72
|
+
|
|
73
|
+
[*primitive_json_types, SQL::Types.Constant(JSONNull)]
|
|
74
|
+
.reduce(:|)
|
|
75
|
+
.constructor { |value| casts[value.class].(value) }
|
|
76
|
+
.meta(read: JSONRead)
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
JSON = Type('json') do
|
|
80
|
+
(SQL::Types::Array | SQL::Types::Hash).constructor(Sequel.method(:pg_json)).meta(read: JSONRead)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
JSONB = Type('jsonb') do
|
|
84
|
+
(SQL::Types::Array | SQL::Types::Hash).constructor(Sequel.method(:pg_jsonb)).meta(read: JSONRead)
|
|
85
|
+
end
|
|
29
86
|
end
|
|
30
87
|
|
|
31
88
|
# @!parse
|
|
@@ -173,11 +230,11 @@ module ROM
|
|
|
173
230
|
end
|
|
174
231
|
end
|
|
175
232
|
|
|
176
|
-
def get(
|
|
233
|
+
def get(_type, expr, *path)
|
|
177
234
|
Attribute[json_type].meta(sql_expr: wrap(expr)[path_args(path)])
|
|
178
235
|
end
|
|
179
236
|
|
|
180
|
-
def get_text(
|
|
237
|
+
def get_text(_type, expr, *path)
|
|
181
238
|
Attribute[SQL::Types::String].meta(sql_expr: wrap(expr).get_text(path_args(path)))
|
|
182
239
|
end
|
|
183
240
|
|
|
@@ -185,7 +242,7 @@ module ROM
|
|
|
185
242
|
|
|
186
243
|
def path_args(path)
|
|
187
244
|
case path.size
|
|
188
|
-
when 0 then raise ArgumentError,
|
|
245
|
+
when 0 then raise ArgumentError, 'wrong number of arguments (given 0, expected 1+)'
|
|
189
246
|
when 1 then path[0]
|
|
190
247
|
else path
|
|
191
248
|
end
|
|
@@ -199,32 +256,32 @@ module ROM
|
|
|
199
256
|
TypeExtensions.register(JSONB) do
|
|
200
257
|
include JSONMethods[JSONB, :pg_jsonb.to_proc]
|
|
201
258
|
|
|
202
|
-
def contain(
|
|
259
|
+
def contain(_type, expr, value)
|
|
203
260
|
Attribute[SQL::Types::Bool].meta(sql_expr: wrap(expr).contains(value))
|
|
204
261
|
end
|
|
205
262
|
|
|
206
|
-
def contained_by(
|
|
263
|
+
def contained_by(_type, expr, value)
|
|
207
264
|
Attribute[SQL::Types::Bool].meta(sql_expr: wrap(expr).contained_by(value))
|
|
208
265
|
end
|
|
209
266
|
|
|
210
|
-
def has_key(
|
|
267
|
+
def has_key(_type, expr, key)
|
|
211
268
|
Attribute[SQL::Types::Bool].meta(sql_expr: wrap(expr).has_key?(key))
|
|
212
269
|
end
|
|
213
270
|
|
|
214
|
-
def has_any_key(
|
|
271
|
+
def has_any_key(_type, expr, *keys)
|
|
215
272
|
Attribute[SQL::Types::Bool].meta(sql_expr: wrap(expr).contain_any(keys))
|
|
216
273
|
end
|
|
217
274
|
|
|
218
|
-
def has_all_keys(
|
|
275
|
+
def has_all_keys(_type, expr, *keys)
|
|
219
276
|
Attribute[SQL::Types::Bool].meta(sql_expr: wrap(expr).contain_all(keys))
|
|
220
277
|
end
|
|
221
278
|
|
|
222
|
-
def merge(
|
|
279
|
+
def merge(_type, expr, value)
|
|
223
280
|
Attribute[JSONB].meta(sql_expr: wrap(expr).concat(value))
|
|
224
281
|
end
|
|
225
282
|
alias_method :+, :merge
|
|
226
283
|
|
|
227
|
-
def delete(
|
|
284
|
+
def delete(_type, expr, *path)
|
|
228
285
|
sql_expr = path.size == 1 ? wrap(expr) - path : wrap(expr).delete_path(path)
|
|
229
286
|
Attribute[JSONB].meta(sql_expr: sql_expr)
|
|
230
287
|
end
|