rom-sql 3.3.3 → 4.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/LICENSE +1 -1
  4. data/README.md +1 -1
  5. data/lib/rom/plugins/relation/sql/auto_restrictions.rb +11 -10
  6. data/lib/rom/plugins/relation/sql/default_views.rb +75 -0
  7. data/lib/rom/plugins/relation/sql/instrumentation.rb +11 -10
  8. data/lib/rom/plugins/relation/sql/postgres/explain.rb +4 -4
  9. data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +18 -16
  10. data/lib/rom/plugins/relation/sql/postgres/streaming.rb +12 -9
  11. data/lib/rom/sql/associations/many_to_many.rb +7 -7
  12. data/lib/rom/sql/associations/many_to_one.rb +3 -3
  13. data/lib/rom/sql/associations/one_to_many.rb +3 -3
  14. data/lib/rom/sql/associations/one_to_one.rb +1 -1
  15. data/lib/rom/sql/associations/one_to_one_through.rb +1 -1
  16. data/lib/rom/sql/associations/self_ref.rb +1 -1
  17. data/lib/rom/sql/associations.rb +5 -5
  18. data/lib/rom/sql/attribute.rb +9 -9
  19. data/lib/rom/sql/attribute_aliasing.rb +2 -3
  20. data/lib/rom/sql/commands/create.rb +5 -4
  21. data/lib/rom/sql/commands/delete.rb +2 -2
  22. data/lib/rom/sql/commands/update.rb +5 -4
  23. data/lib/rom/sql/commands.rb +4 -4
  24. data/lib/rom/sql/dsl.rb +3 -3
  25. data/lib/rom/sql/errors.rb +3 -3
  26. data/lib/rom/sql/extensions/active_support_notifications.rb +4 -4
  27. data/lib/rom/sql/extensions/mysql/type_builder.rb +5 -5
  28. data/lib/rom/sql/extensions/mysql.rb +1 -1
  29. data/lib/rom/sql/extensions/postgres/commands.rb +17 -30
  30. data/lib/rom/sql/extensions/postgres/type_builder.rb +28 -31
  31. data/lib/rom/sql/extensions/postgres/type_serializer.rb +24 -24
  32. data/lib/rom/sql/extensions/postgres/types/array.rb +4 -4
  33. data/lib/rom/sql/extensions/postgres/types/array_types.rb +1 -1
  34. data/lib/rom/sql/extensions/postgres/types/geometric.rb +27 -27
  35. data/lib/rom/sql/extensions/postgres/types/json.rb +9 -9
  36. data/lib/rom/sql/extensions/postgres/types/ltree.rb +61 -34
  37. data/lib/rom/sql/extensions/postgres/types/network.rb +2 -2
  38. data/lib/rom/sql/extensions/postgres/types/range.rb +25 -25
  39. data/lib/rom/sql/extensions/postgres/types.rb +14 -14
  40. data/lib/rom/sql/extensions/postgres.rb +6 -6
  41. data/lib/rom/sql/extensions/rails_log_subscriber.rb +3 -3
  42. data/lib/rom/sql/extensions/sqlite/types.rb +1 -1
  43. data/lib/rom/sql/extensions/sqlite.rb +2 -2
  44. data/lib/rom/sql/extensions.rb +6 -6
  45. data/lib/rom/sql/foreign_key.rb +3 -1
  46. data/lib/rom/sql/function.rb +30 -24
  47. data/lib/rom/sql/gateway.rb +44 -17
  48. data/lib/rom/sql/group_dsl.rb +1 -1
  49. data/lib/rom/sql/index.rb +2 -0
  50. data/lib/rom/sql/join_dsl.rb +1 -1
  51. data/lib/rom/sql/mapper_compiler.rb +2 -2
  52. data/lib/rom/sql/migration/migrator.rb +11 -11
  53. data/lib/rom/sql/migration/runner.rb +3 -3
  54. data/lib/rom/sql/migration/schema_diff.rb +7 -8
  55. data/lib/rom/sql/migration/writer.rb +12 -12
  56. data/lib/rom/sql/migration.rb +4 -8
  57. data/lib/rom/sql/order_dsl.rb +1 -1
  58. data/lib/rom/sql/plugin/associates.rb +49 -11
  59. data/lib/rom/sql/plugin/pagination.rb +5 -3
  60. data/lib/rom/sql/plugin/schema_indexes.rb +35 -0
  61. data/lib/rom/sql/plugins.rb +9 -6
  62. data/lib/rom/sql/projection_dsl.rb +2 -2
  63. data/lib/rom/sql/rake_task.rb +2 -2
  64. data/lib/rom/sql/relation/reading.rb +46 -27
  65. data/lib/rom/sql/relation/writing.rb +11 -10
  66. data/lib/rom/sql/relation.rb +57 -89
  67. data/lib/rom/sql/restriction_dsl.rb +1 -1
  68. data/lib/rom/sql/schema/attributes_inferrer.rb +3 -3
  69. data/lib/rom/sql/schema/dsl.rb +4 -2
  70. data/lib/rom/sql/schema/index_dsl.rb +3 -5
  71. data/lib/rom/sql/schema/inferrer.rb +25 -23
  72. data/lib/rom/sql/schema/type_builder.rb +2 -2
  73. data/lib/rom/sql/schema.rb +9 -21
  74. data/lib/rom/sql/spec/support.rb +5 -5
  75. data/lib/rom/sql/tasks/migration_tasks.rake +12 -12
  76. data/lib/rom/sql/transaction.rb +4 -2
  77. data/lib/rom/sql/type_extensions.rb +3 -1
  78. data/lib/rom/sql/type_serializer.rb +10 -10
  79. data/lib/rom/sql/types.rb +4 -4
  80. data/lib/rom/sql/version.rb +1 -1
  81. data/lib/rom/sql/wrap.rb +1 -1
  82. data/lib/rom/sql.rb +13 -14
  83. data/lib/rom/types/values.rb +2 -2
  84. data/lib/rom-sql.rb +1 -1
  85. metadata +14 -24
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rom/support/inflector'
4
- require 'rom/sql/join_dsl'
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(update: 'FOR UPDATE'.freeze).update(
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: 'FOR UPDATE'.freeze,
18
- no_key_update: 'FOR NO KEY UPDATE'.freeze,
19
- share: 'FOR SHARE'.freeze,
20
- key_share: 'FOR KEY SHARE'.freeze
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: 'FOR UPDATE'.freeze,
25
- share: 'LOCK IN SHARE MODE'.freeze
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(*args, &block)
239
- schema.project(*args, &block).(self)
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(*args, &block)
251
- schema.merge(schema.canonical.project(*args, &block)).(self)
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.
@@ -481,6 +481,18 @@ module ROM
481
481
  end
482
482
  end
483
483
 
484
+ # Removes ordering for the relation
485
+ #
486
+ # @example
487
+ # users.unordered
488
+ #
489
+ # @return [Relation]
490
+ #
491
+ # @api public
492
+ def unordered
493
+ new(dataset.unordered)
494
+ end
495
+
484
496
  # Reverse the order of the relation
485
497
  #
486
498
  # @example
@@ -712,7 +724,7 @@ module ROM
712
724
  # @api public
713
725
  def group(*args, &block)
714
726
  if block
715
- if args.size > 0
727
+ if args.size.positive?
716
728
  group(*args).group_append(&block)
717
729
  else
718
730
  new(dataset.__send__(__method__, *schema.canonical.group(&block)))
@@ -751,7 +763,7 @@ module ROM
751
763
  # @api public
752
764
  def group_append(*args, &block)
753
765
  if block
754
- if args.size > 0
766
+ if args.size.positive?
755
767
  group_append(*args).group_append(&block)
756
768
  else
757
769
  new(dataset.group_append(*schema.canonical.group(&block)))
@@ -802,8 +814,10 @@ module ROM
802
814
  #
803
815
  # @param [Hash] options Options for union
804
816
  # @option options [Symbol] :alias Use the given value as the #from_self alias
805
- # @option options [TrueClass, FalseClass] :all Set to true to use UNION ALL instead of UNION, so duplicate rows can occur
806
- # @option options [TrueClass, FalseClass] :from_self Set to false to not wrap the returned dataset in a #from_self, use with care.
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.
807
821
  #
808
822
  # @returRelation]
809
823
  #
@@ -815,7 +829,7 @@ module ROM
815
829
  # confusing ways.
816
830
  same_relation = name == relation.name
817
831
  alias_name = same_relation ? name : "#{name.to_sym}__#{relation.name.to_sym}"
818
- opts = { alias: alias_name.to_sym, **options }
832
+ opts = {alias: alias_name.to_sym, **options}
819
833
 
820
834
  new_schema = schema.qualified(opts[:alias])
821
835
  new_schema.(new(dataset.__send__(__method__, relation.dataset, opts, &block)))
@@ -836,8 +850,8 @@ module ROM
836
850
  # @return [TrueClass, FalseClass]
837
851
  #
838
852
  # @api public
839
- def exist?(*args, &block)
840
- !where(*args, &block).limit(1).count.zero?
853
+ def exist?(...)
854
+ !where(...).limit(1).count.zero?
841
855
  end
842
856
 
843
857
  # Return if a restricted relation has 0 tuples
@@ -946,7 +960,7 @@ module ROM
946
960
  pks = schema.primary_key
947
961
 
948
962
  if pks.size > 1
949
- raise ArgumentError, 'Composite primary keys are not supported yet'
963
+ raise ArgumentError, "Composite primary keys are not supported yet"
950
964
  end
951
965
 
952
966
  source = order(pks[0]).limit(size)
@@ -1035,18 +1049,18 @@ module ROM
1035
1049
  # @api private
1036
1050
  def lock_clause(mode: :update, skip_locked: false, of: nil, wait: nil)
1037
1051
  stmt = ROW_LOCK_MODES[dataset.db.database_type].fetch(mode).dup
1038
- stmt << ' OF ' << Array(of).join(', ') if of
1052
+ stmt << " OF " << Array(of).join(", ") if of
1039
1053
 
1040
1054
  if skip_locked
1041
- raise ArgumentError, 'SKIP LOCKED cannot be used with (NO)WAIT clause' if !wait.nil?
1055
+ raise ArgumentError, "SKIP LOCKED cannot be used with (NO)WAIT clause" unless wait.nil?
1042
1056
 
1043
- stmt << ' SKIP LOCKED'
1057
+ stmt << " SKIP LOCKED"
1044
1058
  else
1045
1059
  case wait
1046
1060
  when Integer
1047
- stmt << ' WAIT ' << wait.to_s
1061
+ stmt << " WAIT " << wait.to_s
1048
1062
  when false
1049
- stmt << ' NOWAIT'
1063
+ stmt << " NOWAIT"
1050
1064
  else
1051
1065
  stmt
1052
1066
  end
@@ -1072,6 +1086,9 @@ module ROM
1072
1086
  # Common join method used by other join methods
1073
1087
  #
1074
1088
  # @api private
1089
+ #
1090
+ # rubocop:disable Metrics/AbcSize
1091
+ # rubocop:disable Metrics/PerceivedComplexity
1075
1092
  def __join__(type, other, join_cond = EMPTY_HASH, opts = EMPTY_HASH, &block)
1076
1093
  if other.is_a?(Symbol) || other.is_a?(ROM::Relation::Name)
1077
1094
  if join_cond.equal?(EMPTY_HASH) && !block
@@ -1089,7 +1106,7 @@ module ROM
1089
1106
  join_cond = JoinDSL.new(schema).(&block)
1090
1107
 
1091
1108
  if other.name.aliaz
1092
- join_opts = { table_alias: other.name.aliaz }
1109
+ join_opts = {table_alias: other.name.aliaz}
1093
1110
  else
1094
1111
  join_opts = EMPTY_HASH
1095
1112
  end
@@ -1102,6 +1119,8 @@ module ROM
1102
1119
  raise ArgumentError, "+other+ must be either a symbol or a relation, #{other.class} given"
1103
1120
  end
1104
1121
  end
1122
+ # rubocop:enable Metrics/AbcSize
1123
+ # rubocop:enable Metrics/PerceivedComplexity
1105
1124
  end
1106
1125
  end
1107
1126
  end
@@ -37,8 +37,8 @@ module ROM
37
37
  # @return [Hash] Inserted tuple
38
38
  #
39
39
  # @api public
40
- def insert(*args, &block)
41
- dataset.insert(*args, &block)
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(*args, &block)
55
- dataset.multi_insert(*args, &block)
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(*args, &block)
68
- dataset.update(*args, &block)
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(*args, &block)
82
- dataset.delete(*args, &block)
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
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rom/sql/types'
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 'rom/sql/relation/reading'
10
- require 'rom/sql/relation/writing'
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
- adapter :sql
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
- extend Notifications::Listener
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
- relation.dataset do
37
- table = opts[:from].first
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
- subscribe('configuration.relations.dataset.allocated', adapter: :sql) do |event|
48
- event[:relation].define_default_views!
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
- # @api private
52
- def self.define_default_views!
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 schema.primary_key.size > 1
56
- # @!method by_pk(val1, val2)
57
- # Return a relation restricted by its composite primary key
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
- # @!method by_pk(pk)
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 this transaction block.
125
- # @option opts [Symbol] :isolation The transaction isolation level to use for this transaction, should be :uncommitted, :committed, :repeatable, or :serializable, used if given and the database/adapter supports customizable transaction isolation levels.
126
- # @option opts [Integer] :num_retries The number of times to retry if the :retry_on option is used. The default is 5 times. Can be set to nil to retry indefinitely, but that is not recommended.
127
- # @option opts [Proc] :before_retry Proc to execute before rertrying if the :retry_on option is used. Called with two arguments: the number of retry attempts (counting the current one) and the error the last attempt failed with.
128
- # @option opts [String] :prepare A string to use as the transaction identifier for a prepared transaction (two-phase commit), if the database/adapter supports prepared transactions.
129
- # @option opts [Class] :retry_on An exception class or array of exception classes for which to automatically retry the transaction. Can only be set if not inside an existing transaction. Note that this should not be used unless the entire transaction block is idempotent, as otherwise it can cause non-idempotent behavior to execute multiple times.
130
- # @option opts [Symbol] :rollback Can the set to :reraise to reraise any Sequel::Rollback exceptions raised, or :always to always rollback even if no exceptions occur (useful for testing).
131
- # @option opts [Symbol] :server The server to use for the transaction. Set to :default, :read_only, or whatever symbol you used in the connect string when naming your servers.
132
- # @option opts [Boolean] :savepoint Whether to create a new savepoint for this transaction, only respected if the database/adapter supports savepoints. By default Sequel will reuse an existing transaction, so if you want to use a savepoint you must use this option. If the surrounding transaction uses :auto_savepoint, you can set this to false to not use a savepoint. If the value given for this option is :only, it will only create a savepoint if it is inside a transacation.
133
- # @option opts [Boolean] :deferrable **PG 9.1+ only** If present, set to DEFERRABLE if true or NOT DEFERRABLE if false.
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 true, :on, false, :off, :local (9.1+), and :remote_write (9.2+).
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 = EMPTY_HASH, &block)
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 'rom/sql/dsl'
3
+ require "rom/sql/dsl"
4
4
 
5
5
  module ROM
6
6
  module SQL
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/core/class_attributes'
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 = 'add_constraint'.freeze
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 { |attr| attr.name }
33
+ missing = columns.map(&:first) - inferred.map(&:name)
34
34
 
35
35
  [inferred, missing]
36
36
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rom/sql/schema/index_dsl'
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
- { **opts, indexes: index_dsl.(relation, opts[:attributes]) }
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 'set'
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 # < BasicObject
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 'set'
3
+ require "set"
4
4
 
5
- require 'rom/sql/schema/type_builder'
6
- require 'rom/sql/schema/attributes_inferrer'
7
- require 'rom/sql/attribute'
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 => error
42
- on_error(schema.name, error)
43
- { **FALLBACK_SCHEMA, indexes: schema.indexes }
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
- { **rest,
53
- attributes: attributes.map { |attr| mark_fk(mark_indexed(attr, indexes), foreign_keys) },
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
- { **rest,
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
- 'Make sure tables exist before ROM container is set up. ' \
155
- 'This may also happen when your migration tasks load ROM container, ' \
156
- 'which is not needed for migrations as only the connection is required ' \
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?('numeric') || db_type.include?('decimal')
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?('char') && kw[:max_length]
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