rom-sql 3.6.4 → 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 -48
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +11 -10
- data/lib/rom/plugins/relation/sql/default_views.rb +75 -0
- data/lib/rom/plugins/relation/sql/instrumentation.rb +8 -13
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +4 -4
- data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +18 -16
- data/lib/rom/plugins/relation/sql/postgres/streaming.rb +12 -9
- data/lib/rom/sql/associations/many_to_many.rb +7 -7
- data/lib/rom/sql/associations/many_to_one.rb +3 -3
- 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 +9 -9
- data/lib/rom/sql/attribute_aliasing.rb +2 -3
- data/lib/rom/sql/commands/create.rb +5 -4
- data/lib/rom/sql/commands/delete.rb +2 -2
- data/lib/rom/sql/commands/update.rb +5 -4
- data/lib/rom/sql/commands.rb +4 -4
- data/lib/rom/sql/dsl.rb +3 -3
- data/lib/rom/sql/errors.rb +3 -3
- data/lib/rom/sql/extensions/active_support_notifications.rb +4 -4
- 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 +27 -27
- data/lib/rom/sql/extensions/postgres/types/json.rb +9 -9
- data/lib/rom/sql/extensions/postgres/types/ltree.rb +61 -34
- data/lib/rom/sql/extensions/postgres/types/network.rb +4 -17
- data/lib/rom/sql/extensions/postgres/types/range.rb +25 -25
- 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 +18 -22
- data/lib/rom/sql/gateway.rb +44 -17
- data/lib/rom/sql/group_dsl.rb +1 -1
- 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/migrator.rb +11 -11
- data/lib/rom/sql/migration/runner.rb +3 -3
- data/lib/rom/sql/migration/schema_diff.rb +7 -8
- data/lib/rom/sql/migration/writer.rb +12 -12
- data/lib/rom/sql/migration.rb +4 -8
- data/lib/rom/sql/order_dsl.rb +1 -1
- data/lib/rom/sql/plugin/associates.rb +49 -11
- data/lib/rom/sql/plugin/pagination.rb +5 -3
- 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 +4 -4
- data/lib/rom/sql/rake_task.rb +2 -2
- data/lib/rom/sql/relation/reading.rb +34 -27
- data/lib/rom/sql/relation/writing.rb +11 -10
- data/lib/rom/sql/relation.rb +57 -89
- data/lib/rom/sql/restriction_dsl.rb +2 -2
- data/lib/rom/sql/schema/attributes_inferrer.rb +3 -3
- data/lib/rom/sql/schema/dsl.rb +4 -2
- data/lib/rom/sql/schema/index_dsl.rb +3 -5
- data/lib/rom/sql/schema/inferrer.rb +25 -23
- data/lib/rom/sql/schema/type_builder.rb +2 -2
- data/lib/rom/sql/schema.rb +9 -21
- data/lib/rom/sql/spec/support.rb +5 -5
- data/lib/rom/sql/tasks/migration_tasks.rake +13 -21
- data/lib/rom/sql/transaction.rb +4 -2
- data/lib/rom/sql/type_extensions.rb +3 -1
- data/lib/rom/sql/type_serializer.rb +10 -10
- data/lib/rom/sql/types.rb +4 -4
- 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 +2 -2
- data/lib/rom-sql.rb +1 -1
- metadata +13 -17
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "rom/support/inflector"
|
4
|
+
require "rom/sql/join_dsl"
|
5
5
|
|
6
6
|
module ROM
|
7
7
|
module SQL
|
@@ -11,18 +11,18 @@ module ROM
|
|
11
11
|
# @api public
|
12
12
|
module Reading
|
13
13
|
# Row-level lock modes
|
14
|
-
ROW_LOCK_MODES = Hash.new(
|
14
|
+
ROW_LOCK_MODES = Hash.new(update: "FOR UPDATE").update(
|
15
15
|
# https://www.postgresql.org/docs/current/static/sql-select.html#SQL-FOR-UPDATE-SHARE
|
16
16
|
postgres: {
|
17
|
-
update:
|
18
|
-
no_key_update:
|
19
|
-
share:
|
20
|
-
key_share:
|
17
|
+
update: "FOR UPDATE",
|
18
|
+
no_key_update: "FOR NO KEY UPDATE",
|
19
|
+
share: "FOR SHARE",
|
20
|
+
key_share: "FOR KEY SHARE"
|
21
21
|
},
|
22
22
|
# https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
|
23
23
|
mysql: {
|
24
|
-
update:
|
25
|
-
share:
|
24
|
+
update: "FOR UPDATE",
|
25
|
+
share: "LOCK IN SHARE MODE"
|
26
26
|
}
|
27
27
|
).freeze
|
28
28
|
|
@@ -235,8 +235,8 @@ module ROM
|
|
235
235
|
# @return [Relation]
|
236
236
|
#
|
237
237
|
# @api public
|
238
|
-
def select(
|
239
|
-
schema.project(
|
238
|
+
def select(...)
|
239
|
+
schema.project(...).(self)
|
240
240
|
end
|
241
241
|
alias_method :project, :select
|
242
242
|
|
@@ -247,8 +247,8 @@ module ROM
|
|
247
247
|
# @return [Relation]
|
248
248
|
#
|
249
249
|
# @api public
|
250
|
-
def select_append(
|
251
|
-
schema.merge(schema.canonical.project(
|
250
|
+
def select_append(...)
|
251
|
+
schema.merge(schema.canonical.project(...)).(self)
|
252
252
|
end
|
253
253
|
|
254
254
|
# Returns a copy of the relation with a SQL DISTINCT clause.
|
@@ -724,7 +724,7 @@ module ROM
|
|
724
724
|
# @api public
|
725
725
|
def group(*args, &block)
|
726
726
|
if block
|
727
|
-
if args.size
|
727
|
+
if args.size.positive?
|
728
728
|
group(*args).group_append(&block)
|
729
729
|
else
|
730
730
|
new(dataset.__send__(__method__, *schema.canonical.group(&block)))
|
@@ -763,7 +763,7 @@ module ROM
|
|
763
763
|
# @api public
|
764
764
|
def group_append(*args, &block)
|
765
765
|
if block
|
766
|
-
if args.size
|
766
|
+
if args.size.positive?
|
767
767
|
group_append(*args).group_append(&block)
|
768
768
|
else
|
769
769
|
new(dataset.group_append(*schema.canonical.group(&block)))
|
@@ -814,8 +814,10 @@ module ROM
|
|
814
814
|
#
|
815
815
|
# @param [Hash] options Options for union
|
816
816
|
# @option options [Symbol] :alias Use the given value as the #from_self alias
|
817
|
-
# @option options [TrueClass, FalseClass] :all Set to true to use UNION ALL instead of UNION, so duplicate rows
|
818
|
-
#
|
817
|
+
# @option options [TrueClass, FalseClass] :all Set to true to use UNION ALL instead of UNION, so duplicate rows
|
818
|
+
# can occur
|
819
|
+
# @option options [TrueClass, FalseClass] :from_self Set to false to not wrap the returned dataset in a
|
820
|
+
# #from_self, use with care.
|
819
821
|
#
|
820
822
|
# @returRelation]
|
821
823
|
#
|
@@ -827,7 +829,7 @@ module ROM
|
|
827
829
|
# confusing ways.
|
828
830
|
same_relation = name == relation.name
|
829
831
|
alias_name = same_relation ? name : "#{name.to_sym}__#{relation.name.to_sym}"
|
830
|
-
opts = {
|
832
|
+
opts = {alias: alias_name.to_sym, **options}
|
831
833
|
|
832
834
|
new_schema = schema.qualified(opts[:alias])
|
833
835
|
new_schema.(new(dataset.__send__(__method__, relation.dataset, opts, &block)))
|
@@ -848,8 +850,8 @@ module ROM
|
|
848
850
|
# @return [TrueClass, FalseClass]
|
849
851
|
#
|
850
852
|
# @api public
|
851
|
-
def exist?(
|
852
|
-
!where(
|
853
|
+
def exist?(...)
|
854
|
+
!where(...).limit(1).count.zero?
|
853
855
|
end
|
854
856
|
|
855
857
|
# Return if a restricted relation has 0 tuples
|
@@ -958,7 +960,7 @@ module ROM
|
|
958
960
|
pks = schema.primary_key
|
959
961
|
|
960
962
|
if pks.size > 1
|
961
|
-
raise ArgumentError,
|
963
|
+
raise ArgumentError, "Composite primary keys are not supported yet"
|
962
964
|
end
|
963
965
|
|
964
966
|
source = order(pks[0]).limit(size)
|
@@ -1047,18 +1049,18 @@ module ROM
|
|
1047
1049
|
# @api private
|
1048
1050
|
def lock_clause(mode: :update, skip_locked: false, of: nil, wait: nil)
|
1049
1051
|
stmt = ROW_LOCK_MODES[dataset.db.database_type].fetch(mode).dup
|
1050
|
-
stmt <<
|
1052
|
+
stmt << " OF " << Array(of).join(", ") if of
|
1051
1053
|
|
1052
1054
|
if skip_locked
|
1053
|
-
raise ArgumentError,
|
1055
|
+
raise ArgumentError, "SKIP LOCKED cannot be used with (NO)WAIT clause" unless wait.nil?
|
1054
1056
|
|
1055
|
-
stmt <<
|
1057
|
+
stmt << " SKIP LOCKED"
|
1056
1058
|
else
|
1057
1059
|
case wait
|
1058
1060
|
when Integer
|
1059
|
-
stmt <<
|
1061
|
+
stmt << " WAIT " << wait.to_s
|
1060
1062
|
when false
|
1061
|
-
stmt <<
|
1063
|
+
stmt << " NOWAIT"
|
1062
1064
|
else
|
1063
1065
|
stmt
|
1064
1066
|
end
|
@@ -1084,6 +1086,9 @@ module ROM
|
|
1084
1086
|
# Common join method used by other join methods
|
1085
1087
|
#
|
1086
1088
|
# @api private
|
1089
|
+
#
|
1090
|
+
# rubocop:disable Metrics/AbcSize
|
1091
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
1087
1092
|
def __join__(type, other, join_cond = EMPTY_HASH, opts = EMPTY_HASH, &block)
|
1088
1093
|
if other.is_a?(Symbol) || other.is_a?(ROM::Relation::Name)
|
1089
1094
|
if join_cond.equal?(EMPTY_HASH) && !block
|
@@ -1101,7 +1106,7 @@ module ROM
|
|
1101
1106
|
join_cond = JoinDSL.new(schema).(&block)
|
1102
1107
|
|
1103
1108
|
if other.name.aliaz
|
1104
|
-
join_opts = {
|
1109
|
+
join_opts = {table_alias: other.name.aliaz}
|
1105
1110
|
else
|
1106
1111
|
join_opts = EMPTY_HASH
|
1107
1112
|
end
|
@@ -1114,6 +1119,8 @@ module ROM
|
|
1114
1119
|
raise ArgumentError, "+other+ must be either a symbol or a relation, #{other.class} given"
|
1115
1120
|
end
|
1116
1121
|
end
|
1122
|
+
# rubocop:enable Metrics/AbcSize
|
1123
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
1117
1124
|
end
|
1118
1125
|
end
|
1119
1126
|
end
|
@@ -37,8 +37,8 @@ module ROM
|
|
37
37
|
# @return [Hash] Inserted tuple
|
38
38
|
#
|
39
39
|
# @api public
|
40
|
-
def insert(
|
41
|
-
dataset.insert(
|
40
|
+
def insert(...)
|
41
|
+
dataset.insert(...)
|
42
42
|
end
|
43
43
|
|
44
44
|
# Multi insert tuples into relation
|
@@ -51,8 +51,8 @@ module ROM
|
|
51
51
|
# @return [Array<String>] A list of executed SQL statements
|
52
52
|
#
|
53
53
|
# @api public
|
54
|
-
def multi_insert(
|
55
|
-
dataset.multi_insert(
|
54
|
+
def multi_insert(...)
|
55
|
+
dataset.multi_insert(...)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Update tuples in the relation
|
@@ -64,8 +64,8 @@ module ROM
|
|
64
64
|
# @return [Integer] Number of updated rows
|
65
65
|
#
|
66
66
|
# @api public
|
67
|
-
def update(
|
68
|
-
dataset.update(
|
67
|
+
def update(...)
|
68
|
+
dataset.update(...)
|
69
69
|
end
|
70
70
|
|
71
71
|
# Delete tuples from the relation
|
@@ -78,8 +78,8 @@ module ROM
|
|
78
78
|
# @return [Integer] Number of deleted tuples
|
79
79
|
#
|
80
80
|
# @api public
|
81
|
-
def delete(
|
82
|
-
dataset.delete(
|
81
|
+
def delete(...)
|
82
|
+
dataset.delete(...)
|
83
83
|
end
|
84
84
|
|
85
85
|
# Insert tuples from other relation
|
@@ -113,12 +113,13 @@ module ROM
|
|
113
113
|
#
|
114
114
|
# @api public
|
115
115
|
def import(other, options = EMPTY_HASH)
|
116
|
+
columns = other.schema.map { |a| a.alias || a.name }
|
117
|
+
|
116
118
|
if other.gateway.eql?(gateway)
|
117
|
-
columns = other.schema.map { |a| a.alias || a.name }
|
118
119
|
dataset.import(columns, other.dataset, options)
|
119
120
|
else
|
120
|
-
columns = other.schema.map { |a| a.alias || a.name }
|
121
121
|
keys = columns.map(&:to_sym)
|
122
|
+
|
122
123
|
dataset.import(columns, other.to_a.map { |record| record.to_h.values_at(*keys) }, options)
|
123
124
|
end
|
124
125
|
end
|
data/lib/rom/sql/relation.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'rom/sql/schema'
|
5
|
-
require 'rom/sql/attribute'
|
6
|
-
require 'rom/sql/wrap'
|
7
|
-
require 'rom/sql/transaction'
|
3
|
+
require "rom/relation"
|
8
4
|
|
9
|
-
require
|
10
|
-
require
|
5
|
+
require "rom/sql/types"
|
6
|
+
require "rom/sql/schema"
|
7
|
+
require "rom/sql/attribute"
|
8
|
+
require "rom/sql/wrap"
|
9
|
+
require "rom/sql/transaction"
|
10
|
+
|
11
|
+
require "rom/sql/relation/reading"
|
12
|
+
require "rom/sql/relation/writing"
|
13
|
+
require "rom/sql/schema/dsl"
|
11
14
|
|
12
15
|
module ROM
|
13
16
|
module SQL
|
@@ -15,90 +18,37 @@ module ROM
|
|
15
18
|
#
|
16
19
|
# @api public
|
17
20
|
class Relation < ROM::Relation
|
18
|
-
|
21
|
+
extend Dry::Core::ClassAttributes # TODO: only needed by pagination plugin
|
19
22
|
|
20
23
|
include SQL
|
21
24
|
include Writing
|
22
25
|
include Reading
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
schema_class SQL::Schema
|
27
|
-
schema_attr_class SQL::Attribute
|
28
|
-
schema_inferrer ROM::SQL::Schema::Inferrer.new.freeze
|
29
|
-
schema_dsl SQL::Schema::DSL
|
30
|
-
wrap_class SQL::Wrap
|
31
|
-
|
32
|
-
subscribe('configuration.relations.schema.set', adapter: :sql) do |event|
|
33
|
-
schema = event[:schema]
|
34
|
-
relation = event[:relation]
|
27
|
+
config.wrap_class = SQL::Wrap
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if db.table_exists?(table)
|
40
|
-
select(*schema.qualified_projection).order(*schema.project(*schema.primary_key_names).qualified)
|
41
|
-
else
|
42
|
-
self
|
43
|
-
end
|
44
|
-
end
|
29
|
+
configure(:component) do |config|
|
30
|
+
config.adapter = :sql
|
45
31
|
end
|
46
32
|
|
47
|
-
|
48
|
-
|
33
|
+
configure(:schema) do |config|
|
34
|
+
config.constant = SQL::Schema
|
35
|
+
config.attr_class = SQL::Attribute
|
36
|
+
config.inferrer = ROM::SQL::Schema::Inferrer.new.freeze
|
37
|
+
config.plugins << :indexes
|
38
|
+
config.dsl_class = SQL::Schema::DSL
|
49
39
|
end
|
50
40
|
|
51
|
-
|
52
|
-
|
53
|
-
undef_method :by_pk if method_defined?(:by_pk)
|
41
|
+
dataset(abstract: true) do |schema|
|
42
|
+
table = opts[:from].first
|
54
43
|
|
55
|
-
if
|
56
|
-
|
57
|
-
|
58
|
-
#
|
59
|
-
# @param [Array] args A list with composite pk values
|
60
|
-
#
|
61
|
-
# @return [SQL::Relation]
|
62
|
-
#
|
63
|
-
# @api public
|
64
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
65
|
-
def by_pk(#{schema.primary_key.map(&:name).join(', ')})
|
66
|
-
where(#{schema.primary_key.map { |attr| "schema.canonical[:#{attr.name}] => #{attr.name}" }.join(', ')})
|
67
|
-
end
|
68
|
-
RUBY
|
44
|
+
if db.table_exists?(table)
|
45
|
+
select(*schema.qualified_projection)
|
46
|
+
.order(*schema.project(*schema.primary_key_names).qualified)
|
69
47
|
else
|
70
|
-
|
71
|
-
# Return a relation restricted by its primary key
|
72
|
-
#
|
73
|
-
# @param [Object] pk The primary key value
|
74
|
-
#
|
75
|
-
# @return [SQL::Relation]
|
76
|
-
#
|
77
|
-
# @api public
|
78
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
79
|
-
def by_pk(pk)
|
80
|
-
if primary_key.nil?
|
81
|
-
raise MissingPrimaryKeyError.new(
|
82
|
-
"Missing primary key for :\#{schema.name}"
|
83
|
-
)
|
84
|
-
end
|
85
|
-
where(schema.canonical[schema.canonical.primary_key_name].qualified => pk)
|
86
|
-
end
|
87
|
-
RUBY
|
48
|
+
self
|
88
49
|
end
|
89
50
|
end
|
90
51
|
|
91
|
-
# @api private
|
92
|
-
def self.associations
|
93
|
-
schema.associations
|
94
|
-
end
|
95
|
-
|
96
|
-
# @api private
|
97
|
-
def self.primary_key_columns(db, table)
|
98
|
-
names = db.respond_to?(:primary_key) ? Array(db.primary_key(table)) : [:id]
|
99
|
-
names.map { |col| :"#{table}__#{col}" }
|
100
|
-
end
|
101
|
-
|
102
52
|
option :primary_key, default: -> { schema.primary_key_name }
|
103
53
|
|
104
54
|
# Return relation that will load associated tuples of this relation
|
@@ -121,26 +71,44 @@ module ROM
|
|
121
71
|
# Open a database transaction
|
122
72
|
#
|
123
73
|
# @param [Hash] opts
|
124
|
-
# @option opts [Boolean] :auto_savepoint Automatically use a savepoint for Database#transaction calls inside
|
125
|
-
#
|
126
|
-
# @option opts [
|
127
|
-
#
|
128
|
-
#
|
129
|
-
# @option opts [
|
130
|
-
#
|
131
|
-
# @option opts [
|
132
|
-
#
|
133
|
-
#
|
74
|
+
# @option opts [Boolean] :auto_savepoint Automatically use a savepoint for Database#transaction calls inside
|
75
|
+
# this transaction block.
|
76
|
+
# @option opts [Symbol] :isolation The transaction isolation level to use for this transaction, should be
|
77
|
+
# :uncommitted, :committed, :repeatable, or :serializable, used if given and the database/adapter supports
|
78
|
+
# customizable transaction isolation levels.
|
79
|
+
# @option opts [Integer] :num_retries The number of times to retry if the :retry_on option is used. The default is
|
80
|
+
# 5 times. Can be set to nil to retry indefinitely, but that is not recommended.
|
81
|
+
# @option opts [Proc] :before_retry Proc to execute before rertrying if the :retry_on option is used. Called with
|
82
|
+
# two arguments: the number of retry attempts (counting the current one) and the error the last attempt failed
|
83
|
+
# with.
|
84
|
+
# @option opts [String] :prepare A string to use as the transaction identifier for a prepared transaction
|
85
|
+
# (two-phase commit), if the database/adapter supports prepared transactions.
|
86
|
+
# @option opts [Class] :retry_on An exception class or array of exception classes for which to automatically retry
|
87
|
+
# the transaction. Can only be set if not inside an existing transaction. Note that this should not be used
|
88
|
+
# unless the entire transaction block is idempotent, as otherwise it can cause non-idempotent behavior to
|
89
|
+
# execute multiple times.
|
90
|
+
# @option opts [Symbol] :rollback Can the set to :reraise to reraise any Sequel::Rollback exceptions raised, or
|
91
|
+
# :always to always rollback even if no exceptions occur (useful for testing).
|
92
|
+
# @option opts [Symbol] :server The server to use for the transaction. Set to :default, :read_only, or whatever
|
93
|
+
# symbol you used in the connect string when naming your servers.
|
94
|
+
# @option opts [Boolean] :savepoint Whether to create a new savepoint for this transaction, only respected if the
|
95
|
+
# database/adapter supports savepoints. By default Sequel will reuse an existing transaction, so if you want to
|
96
|
+
# use a savepoint you must use this option. If the surrounding transaction uses :auto_savepoint, you can set
|
97
|
+
# this to false to not use a savepoint. If the value given for this option is :only, it will only create
|
98
|
+
# a savepoint if it is inside a transacation.
|
99
|
+
# @option opts [Boolean] :deferrable **PG 9.1+ only** If present, set to DEFERRABLE if true or NOT DEFERRABLE if
|
100
|
+
# false.
|
134
101
|
# @option opts [Boolean] :read_only **PG only** If present, set to READ ONLY if true or READ WRITE if false.
|
135
|
-
# @option opts [Symbol] :synchronous **PG only** if non-nil, set synchronous_commit appropriately. Valid values
|
102
|
+
# @option opts [Symbol] :synchronous **PG only** if non-nil, set synchronous_commit appropriately. Valid values
|
103
|
+
# true, :on, false, :off, :local (9.1+), and :remote_write (9.2+).
|
136
104
|
#
|
137
105
|
# @yield [t] Transaction
|
138
106
|
#
|
139
107
|
# @return [Mixed]
|
140
108
|
#
|
141
109
|
# @api public
|
142
|
-
def transaction(opts
|
143
|
-
Transaction.new(dataset.db).run(opts, &block)
|
110
|
+
def transaction(**opts, &block)
|
111
|
+
Transaction.new(dataset.db).run(**opts, &block)
|
144
112
|
end
|
145
113
|
|
146
114
|
# Return raw column names
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rom/sql/dsl"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module SQL
|
@@ -27,7 +27,7 @@ module ROM
|
|
27
27
|
type = type(meth)
|
28
28
|
|
29
29
|
if type
|
30
|
-
::ROM::SQL::Function.new(type)
|
30
|
+
::ROM::SQL::Function.new(type)
|
31
31
|
else
|
32
32
|
::Sequel::VIRTUAL_ROW.__send__(meth, *args, &block)
|
33
33
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dry/core/class_attributes"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module SQL
|
@@ -12,7 +12,7 @@ module ROM
|
|
12
12
|
|
13
13
|
defines :type_builders
|
14
14
|
|
15
|
-
CONSTRAINT_DB_TYPE =
|
15
|
+
CONSTRAINT_DB_TYPE = "add_constraint"
|
16
16
|
|
17
17
|
option :type_builder
|
18
18
|
|
@@ -30,7 +30,7 @@ module ROM
|
|
30
30
|
attr_class.new(type.meta(source: schema.name), name: name) if type
|
31
31
|
end.compact
|
32
32
|
|
33
|
-
missing = columns.map(&:first) - inferred.map
|
33
|
+
missing = columns.map(&:first) - inferred.map(&:name)
|
34
34
|
|
35
35
|
[inferred, missing]
|
36
36
|
end
|
data/lib/rom/sql/schema/dsl.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rom/compat/schema/dsl"
|
4
|
+
require_relative "index_dsl"
|
4
5
|
|
5
6
|
module ROM
|
6
7
|
module SQL
|
@@ -8,6 +9,7 @@ module ROM
|
|
8
9
|
# Specialized schema DSL with SQL-specific features
|
9
10
|
#
|
10
11
|
# @api public
|
12
|
+
# @deprecated
|
11
13
|
class DSL < ROM::Schema::DSL
|
12
14
|
# @!attribute [r] index_dsl
|
13
15
|
# @return [IndexDSL] Index DSL instance (created only if indexes block is called)
|
@@ -29,7 +31,7 @@ module ROM
|
|
29
31
|
if index_dsl
|
30
32
|
opts = super
|
31
33
|
|
32
|
-
{
|
34
|
+
{**opts, indexes: index_dsl.(relation, opts[:attributes])}
|
33
35
|
else
|
34
36
|
super
|
35
37
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "set"
|
4
4
|
|
5
5
|
module ROM
|
6
6
|
module SQL
|
7
7
|
class Schema < ROM::Schema
|
8
8
|
# @api public
|
9
|
-
class IndexDSL
|
9
|
+
class IndexDSL
|
10
10
|
extend Initializer
|
11
11
|
|
12
12
|
option :attr_class
|
@@ -16,10 +16,8 @@ module ROM
|
|
16
16
|
# @api private
|
17
17
|
def initialize(*, &block)
|
18
18
|
super
|
19
|
-
|
20
19
|
@registry = []
|
21
|
-
|
22
|
-
instance_exec(&block)
|
20
|
+
instance_exec(&block) if block
|
23
21
|
end
|
24
22
|
ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
|
25
23
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "set"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
5
|
+
require "rom/sql/schema/type_builder"
|
6
|
+
require "rom/sql/schema/attributes_inferrer"
|
7
|
+
require "rom/sql/attribute"
|
8
8
|
|
9
9
|
module ROM
|
10
10
|
module SQL
|
@@ -38,9 +38,9 @@ module ROM
|
|
38
38
|
else
|
39
39
|
infer_from_attributes(gateway, schema, **super)
|
40
40
|
end
|
41
|
-
rescue Sequel::Error =>
|
42
|
-
on_error(schema.name,
|
43
|
-
{
|
41
|
+
rescue Sequel::Error => e
|
42
|
+
on_error(schema.name, e)
|
43
|
+
{**FALLBACK_SCHEMA, indexes: schema.indexes}
|
44
44
|
end
|
45
45
|
|
46
46
|
# @api private
|
@@ -49,10 +49,12 @@ module ROM
|
|
49
49
|
indexes = indexes_from_database(gateway, schema, idx)
|
50
50
|
foreign_keys = foreign_keys_from_database(gateway, schema, idx)
|
51
51
|
|
52
|
-
{
|
53
|
-
attributes: attributes.map { |attr|
|
52
|
+
{**rest,
|
53
|
+
attributes: attributes.map { |attr|
|
54
|
+
mark_fk(mark_indexed(attr, indexes), foreign_keys)
|
55
|
+
},
|
54
56
|
foreign_keys: foreign_keys,
|
55
|
-
indexes: indexes
|
57
|
+
indexes: indexes}
|
56
58
|
end
|
57
59
|
|
58
60
|
# @api private
|
@@ -60,10 +62,10 @@ module ROM
|
|
60
62
|
indexes = schema.indexes | indexes_from_attributes(attributes)
|
61
63
|
foreign_keys = foreign_keys_from_attributes(attributes)
|
62
64
|
|
63
|
-
{
|
65
|
+
{**rest,
|
64
66
|
attributes: attributes.map { |attr| mark_indexed(attr, indexes) },
|
65
67
|
foreign_keys: foreign_keys,
|
66
|
-
indexes: indexes
|
68
|
+
indexes: indexes}
|
67
69
|
end
|
68
70
|
|
69
71
|
# @api private
|
@@ -96,18 +98,18 @@ module ROM
|
|
96
98
|
|
97
99
|
# @api private
|
98
100
|
def indexes_from_attributes(attributes)
|
99
|
-
attributes
|
100
|
-
select(&:indexed?)
|
101
|
-
map { |attr| SQL::Index.new([attr.unwrap]) }
|
102
|
-
to_set
|
101
|
+
attributes
|
102
|
+
.select(&:indexed?)
|
103
|
+
.map { |attr| SQL::Index.new([attr.unwrap]) }
|
104
|
+
.to_set
|
103
105
|
end
|
104
106
|
|
105
107
|
# @api private
|
106
108
|
def foreign_keys_from_attributes(attributes)
|
107
|
-
attributes
|
108
|
-
select(&:foreign_key?)
|
109
|
-
map { |attr| SQL::ForeignKey.new([attr.unwrap], attr.target) }
|
110
|
-
to_set
|
109
|
+
attributes
|
110
|
+
.select(&:foreign_key?)
|
111
|
+
.map { |attr| SQL::ForeignKey.new([attr.unwrap], attr.target) }
|
112
|
+
.to_set
|
111
113
|
end
|
112
114
|
|
113
115
|
# @api private
|
@@ -151,9 +153,9 @@ module ROM
|
|
151
153
|
raise e
|
152
154
|
elsif !silent
|
153
155
|
warn "[#{dataset}] failed to infer schema. " \
|
154
|
-
|
155
|
-
|
156
|
-
|
156
|
+
"Make sure tables exist before ROM container is set up. " \
|
157
|
+
"This may also happen when your migration tasks load ROM container, " \
|
158
|
+
"which is not needed for migrations as only the connection is required " \
|
157
159
|
"(#{e.message})"
|
158
160
|
end
|
159
161
|
end
|
@@ -66,9 +66,9 @@ module ROM
|
|
66
66
|
def map_type(ruby_type, db_type, **kw)
|
67
67
|
type = self.class.ruby_type_mapping[ruby_type]
|
68
68
|
|
69
|
-
if db_type.is_a?(String) && db_type.include?(
|
69
|
+
if (db_type.is_a?(String) && db_type.include?("numeric")) || db_type.include?("decimal")
|
70
70
|
map_decimal_type(db_type)
|
71
|
-
elsif db_type.is_a?(String) && db_type.include?(
|
71
|
+
elsif db_type.is_a?(String) && db_type.include?("char") && kw[:max_length]
|
72
72
|
type.meta(limit: kw[:max_length])
|
73
73
|
else
|
74
74
|
type
|