rom-sql 3.7.0 → 4.0.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -65
  3. data/LICENSE +1 -1
  4. data/README.md +3 -2
  5. data/lib/rom/plugins/relation/sql/auto_restrictions.rb +10 -12
  6. data/lib/rom/plugins/relation/sql/default_views.rb +75 -0
  7. data/lib/rom/plugins/relation/sql/instrumentation.rb +8 -17
  8. data/lib/rom/plugins/relation/sql/postgres/explain.rb +5 -5
  9. data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +20 -37
  10. data/lib/rom/plugins/relation/sql/postgres/streaming.rb +17 -14
  11. data/lib/rom/sql/associations/many_to_many.rb +4 -7
  12. data/lib/rom/sql/associations/many_to_one.rb +3 -6
  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 +17 -31
  19. data/lib/rom/sql/attribute_aliasing.rb +4 -6
  20. data/lib/rom/sql/commands/create.rb +5 -5
  21. data/lib/rom/sql/commands/delete.rb +2 -2
  22. data/lib/rom/sql/commands/update.rb +5 -5
  23. data/lib/rom/sql/commands.rb +4 -4
  24. data/lib/rom/sql/dsl.rb +4 -6
  25. data/lib/rom/sql/errors.rb +3 -3
  26. data/lib/rom/sql/extensions/active_support_notifications.rb +3 -3
  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 +13 -31
  30. data/lib/rom/sql/extensions/postgres/type_builder.rb +28 -31
  31. data/lib/rom/sql/extensions/postgres/type_serializer.rb +24 -25
  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 +19 -19
  35. data/lib/rom/sql/extensions/postgres/types/json.rb +12 -18
  36. data/lib/rom/sql/extensions/postgres/types/ltree.rb +54 -97
  37. data/lib/rom/sql/extensions/postgres/types/network.rb +4 -17
  38. data/lib/rom/sql/extensions/postgres/types/range.rb +30 -30
  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 +6 -21
  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 +19 -42
  47. data/lib/rom/sql/gateway.rb +41 -15
  48. data/lib/rom/sql/group_dsl.rb +3 -8
  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/inline_runner.rb +2 -8
  53. data/lib/rom/sql/migration/migrator.rb +12 -12
  54. data/lib/rom/sql/migration/recorder.rb +4 -10
  55. data/lib/rom/sql/migration/runner.rb +4 -5
  56. data/lib/rom/sql/migration/schema_diff.rb +4 -10
  57. data/lib/rom/sql/migration/writer.rb +7 -7
  58. data/lib/rom/sql/migration.rb +9 -13
  59. data/lib/rom/sql/order_dsl.rb +3 -7
  60. data/lib/rom/sql/plugin/associates.rb +45 -21
  61. data/lib/rom/sql/plugin/pagination.rb +3 -1
  62. data/lib/rom/sql/plugin/schema_indexes.rb +35 -0
  63. data/lib/rom/sql/plugins.rb +9 -6
  64. data/lib/rom/sql/projection_dsl.rb +5 -5
  65. data/lib/rom/sql/rake_task.rb +2 -2
  66. data/lib/rom/sql/relation/reading.rb +78 -83
  67. data/lib/rom/sql/relation/writing.rb +4 -9
  68. data/lib/rom/sql/relation.rb +58 -136
  69. data/lib/rom/sql/restriction_dsl.rb +4 -8
  70. data/lib/rom/sql/schema/attributes_inferrer.rb +2 -2
  71. data/lib/rom/sql/schema/dsl.rb +6 -4
  72. data/lib/rom/sql/schema/index_dsl.rb +6 -7
  73. data/lib/rom/sql/schema/inferrer.rb +22 -24
  74. data/lib/rom/sql/schema/type_builder.rb +4 -20
  75. data/lib/rom/sql/schema.rb +17 -29
  76. data/lib/rom/sql/spec/support.rb +5 -5
  77. data/lib/rom/sql/tasks/migration_tasks.rake +14 -21
  78. data/lib/rom/sql/transaction.rb +4 -3
  79. data/lib/rom/sql/type_dsl.rb +3 -7
  80. data/lib/rom/sql/type_extensions.rb +6 -4
  81. data/lib/rom/sql/type_serializer.rb +9 -9
  82. data/lib/rom/sql/types.rb +6 -6
  83. data/lib/rom/sql/version.rb +1 -1
  84. data/lib/rom/sql/wrap.rb +1 -1
  85. data/lib/rom/sql.rb +13 -12
  86. data/lib/rom/types/values.rb +5 -3
  87. data/lib/rom-sql.rb +1 -1
  88. metadata +17 -12
@@ -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
@@ -9,22 +9,20 @@ module ROM
9
9
  # Query API for SQL::Relation
10
10
  #
11
11
  # @api public
12
- #
13
- # rubocop:disable Metrics/ModuleLength
14
12
  module Reading
15
13
  # Row-level lock modes
16
- ROW_LOCK_MODES = Hash.new({ update: 'FOR UPDATE' }).update(
14
+ ROW_LOCK_MODES = Hash.new(update: "FOR UPDATE").update(
17
15
  # https://www.postgresql.org/docs/current/static/sql-select.html#SQL-FOR-UPDATE-SHARE
18
16
  postgres: {
19
- update: 'FOR UPDATE',
20
- no_key_update: 'FOR NO KEY UPDATE',
21
- share: 'FOR SHARE',
22
- key_share: 'FOR KEY SHARE'
17
+ update: "FOR UPDATE",
18
+ no_key_update: "FOR NO KEY UPDATE",
19
+ share: "FOR SHARE",
20
+ key_share: "FOR KEY SHARE"
23
21
  },
24
22
  # https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
25
23
  mysql: {
26
- update: 'FOR UPDATE',
27
- share: 'LOCK IN SHARE MODE'
24
+ update: "FOR UPDATE",
25
+ share: "LOCK IN SHARE MODE"
28
26
  }
29
27
  ).freeze
30
28
 
@@ -142,11 +140,11 @@ module ROM
142
140
  # from tuples
143
141
  #
144
142
  # @api public
145
- def map(key = nil, &)
143
+ def map(key = nil, &block)
146
144
  if key
147
- dataset.map(key, &)
145
+ dataset.map(key, &block)
148
146
  else
149
- dataset.map(&)
147
+ dataset.map(&block)
150
148
  end
151
149
  end
152
150
 
@@ -273,8 +271,8 @@ module ROM
273
271
  # @return [Relation]
274
272
  #
275
273
  # @api public
276
- def distinct(...)
277
- new(dataset.__send__(__method__, ...))
274
+ def distinct(*args, &block)
275
+ new(dataset.__send__(__method__, *args, &block))
278
276
  end
279
277
 
280
278
  # Returns a result of SQL SUM clause.
@@ -361,9 +359,9 @@ module ROM
361
359
  # @return [Relation]
362
360
  #
363
361
  # @api public
364
- def where(*args, &)
365
- if block_given?
366
- where(*args).where(schema.canonical.restriction(&))
362
+ def where(*args, &block)
363
+ if block
364
+ where(*args).where(schema.canonical.restriction(&block))
367
365
  elsif args.size == 1 && args[0].is_a?(Hash)
368
366
  new(dataset.where(coerce_conditions(args[0])))
369
367
  elsif !args.empty?
@@ -383,8 +381,8 @@ module ROM
383
381
  # @return [Relation]
384
382
  #
385
383
  # @api public
386
- def exclude(...)
387
- new(dataset.__send__(__method__, ...))
384
+ def exclude(*args, &block)
385
+ new(dataset.__send__(__method__, *args, &block))
388
386
  end
389
387
 
390
388
  # Restrict a relation to match grouping criteria
@@ -420,9 +418,9 @@ module ROM
420
418
  # @return [Relation]
421
419
  #
422
420
  # @api public
423
- def having(*args, &)
424
- if block_given?
425
- new(dataset.having(*args, *schema.canonical.restriction(&)))
421
+ def having(*args, &block)
422
+ if block
423
+ new(dataset.having(*args, *schema.canonical.restriction(&block)))
426
424
  else
427
425
  new(dataset.__send__(__method__, *args))
428
426
  end
@@ -475,11 +473,11 @@ module ROM
475
473
  # @return [Relation]
476
474
  #
477
475
  # @api public
478
- def order(*args, &)
479
- if block_given?
480
- new(dataset.order(*args, *schema.canonical.order(&)))
476
+ def order(*args, &block)
477
+ if block
478
+ new(dataset.order(*args, *schema.canonical.order(&block)))
481
479
  else
482
- new(dataset.__send__(__method__, *args, &))
480
+ new(dataset.__send__(__method__, *args, &block))
483
481
  end
484
482
  end
485
483
 
@@ -503,8 +501,8 @@ module ROM
503
501
  # @return [Relation]
504
502
  #
505
503
  # @api public
506
- def reverse(...)
507
- new(dataset.__send__(__method__, ...))
504
+ def reverse(*args, &block)
505
+ new(dataset.__send__(__method__, *args, &block))
508
506
  end
509
507
 
510
508
  # Limit a relation to a specific number of tuples
@@ -592,8 +590,8 @@ module ROM
592
590
  # @return [Relation]
593
591
  #
594
592
  # @api public
595
- def join(...)
596
- __join__(__method__, ...)
593
+ def join(*args, &block)
594
+ __join__(__method__, *args, &block)
597
595
  end
598
596
  alias_method :inner_join, :join
599
597
 
@@ -642,8 +640,8 @@ module ROM
642
640
  # @return [Relation]
643
641
  #
644
642
  # @api public
645
- def left_join(...)
646
- __join__(__method__, ...)
643
+ def left_join(*args, &block)
644
+ __join__(__method__, *args, &block)
647
645
  end
648
646
 
649
647
  # Join with another relation using RIGHT JOIN
@@ -691,8 +689,8 @@ module ROM
691
689
  # @return [Relation]
692
690
  #
693
691
  # @api public
694
- def right_join(...)
695
- __join__(__method__, ...)
692
+ def right_join(*args, &block)
693
+ __join__(__method__, *args, &block)
696
694
  end
697
695
 
698
696
  # Group by specific columns
@@ -724,12 +722,12 @@ module ROM
724
722
  # @return [Relation]
725
723
  #
726
724
  # @api public
727
- def group(*args, &)
728
- if block_given?
725
+ def group(*args, &block)
726
+ if block
729
727
  if args.size.positive?
730
- group(*args).group_append(&)
728
+ group(*args).group_append(&block)
731
729
  else
732
- new(dataset.__send__(__method__, *schema.canonical.group(&)))
730
+ new(dataset.__send__(__method__, *schema.canonical.group(&block)))
733
731
  end
734
732
  else
735
733
  new(dataset.__send__(__method__, *schema.canonical.project(*args)))
@@ -763,12 +761,12 @@ module ROM
763
761
  # @return [Relation]
764
762
  #
765
763
  # @api public
766
- def group_append(*args, &)
767
- if block_given?
764
+ def group_append(*args, &block)
765
+ if block
768
766
  if args.size.positive?
769
- group_append(*args).group_append(&)
767
+ group_append(*args).group_append(&block)
770
768
  else
771
- new(dataset.group_append(*schema.canonical.group(&)))
769
+ new(dataset.group_append(*schema.canonical.group(&block)))
772
770
  end
773
771
  else
774
772
  new(dataset.group_append(*args))
@@ -786,8 +784,8 @@ module ROM
786
784
  # @return [Relation]
787
785
  #
788
786
  # @api public
789
- def group_and_count(...)
790
- new(dataset.__send__(__method__, ...))
787
+ def group_and_count(*args, &block)
788
+ new(dataset.__send__(__method__, *args, &block))
791
789
  end
792
790
 
793
791
  # Select and group by specific columns
@@ -801,8 +799,8 @@ module ROM
801
799
  # @return [Relation]
802
800
  #
803
801
  # @api public
804
- def select_group(...)
805
- new_schema = schema.project(...)
802
+ def select_group(*args, &block)
803
+ new_schema = schema.project(*args, &block)
806
804
  new_schema.(self).group(*new_schema)
807
805
  end
808
806
 
@@ -815,27 +813,26 @@ module ROM
815
813
  # @param [Relation] relation Another relation
816
814
  #
817
815
  # @param [Hash] options Options for union
818
- # @option options [Symbol] :alias
819
- # Use the given value as the #from_self alias
820
- # @option options [true, false] :all
821
- # Set to true to use UNION ALL instead of UNION, so duplicate rows can occur
822
- # @option options [true, false] :from_self
823
- # Set to false to not wrap the returned dataset in a #from_self, use with care.
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
+ # 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.
824
821
  #
825
822
  # @returRelation]
826
823
  #
827
824
  # @api public
828
- def union(relation, options = EMPTY_HASH, &)
825
+ def union(relation, options = EMPTY_HASH, &block)
829
826
  # We use the original relation name here if both relations have the
830
827
  # same name. This makes it so if the user at some point references
831
828
  # the relation directly by name later on things won't break in
832
829
  # confusing ways.
833
830
  same_relation = name == relation.name
834
831
  alias_name = same_relation ? name : "#{name.to_sym}__#{relation.name.to_sym}"
835
- opts = { alias: alias_name.to_sym, **options }
832
+ opts = {alias: alias_name.to_sym, **options}
836
833
 
837
834
  new_schema = schema.qualified(opts[:alias])
838
- new_schema.(new(dataset.__send__(__method__, relation.dataset, opts, &)))
835
+ new_schema.(new(dataset.__send__(__method__, relation.dataset, opts, &block)))
839
836
  end
840
837
 
841
838
  # Checks whether a relation has at least one tuple
@@ -910,12 +907,12 @@ module ROM
910
907
  # @yieldparam relation [Array]
911
908
  #
912
909
  # @api public
913
- def lock(**options, &)
910
+ def lock(**options, &block)
914
911
  clause = lock_clause(**options)
915
912
 
916
- if block_given?
913
+ if block
917
914
  transaction do
918
- yield(dataset.lock_style(clause).to_a)
915
+ block.call(dataset.lock_style(clause).to_a)
919
916
  end
920
917
  else
921
918
  new(dataset.lock_style(clause))
@@ -963,7 +960,7 @@ module ROM
963
960
  pks = schema.primary_key
964
961
 
965
962
  if pks.size > 1
966
- raise ArgumentError, 'Composite primary keys are not supported yet'
963
+ raise ArgumentError, "Composite primary keys are not supported yet"
967
964
  end
968
965
 
969
966
  source = order(pks[0]).limit(size)
@@ -1052,18 +1049,18 @@ module ROM
1052
1049
  # @api private
1053
1050
  def lock_clause(mode: :update, skip_locked: false, of: nil, wait: nil)
1054
1051
  stmt = ROW_LOCK_MODES[dataset.db.database_type].fetch(mode).dup
1055
- stmt << ' OF ' << Array(of).join(', ') if of
1052
+ stmt << " OF " << Array(of).join(", ") if of
1056
1053
 
1057
1054
  if skip_locked
1058
- raise ArgumentError, 'SKIP LOCKED cannot be used with (NO)WAIT clause' unless wait.nil?
1055
+ raise ArgumentError, "SKIP LOCKED cannot be used with (NO)WAIT clause" unless wait.nil?
1059
1056
 
1060
- stmt << ' SKIP LOCKED'
1057
+ stmt << " SKIP LOCKED"
1061
1058
  else
1062
1059
  case wait
1063
1060
  when Integer
1064
- stmt << ' WAIT ' << wait.to_s
1061
+ stmt << " WAIT " << wait.to_s
1065
1062
  when false
1066
- stmt << ' NOWAIT'
1063
+ stmt << " NOWAIT"
1067
1064
  else
1068
1065
  stmt
1069
1066
  end
@@ -1073,8 +1070,6 @@ module ROM
1073
1070
  # Apply input types to condition values
1074
1071
  #
1075
1072
  # @api private
1076
- #
1077
- # rubocop:disable Metrics/AbcSize
1078
1073
  def coerce_conditions(conditions)
1079
1074
  conditions.each_with_object({}) { |(k, v), h|
1080
1075
  if k.is_a?(Symbol) && schema.canonical.key?(k)
@@ -1087,31 +1082,31 @@ module ROM
1087
1082
  end
1088
1083
  }
1089
1084
  end
1090
- # rubocop:enable Metrics/AbcSize
1091
1085
 
1092
1086
  # Common join method used by other join methods
1093
1087
  #
1094
1088
  # @api private
1095
1089
  #
1096
- # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity
1097
- def __join__(type, other, join_cond = EMPTY_HASH, opts = EMPTY_HASH, &)
1090
+ # rubocop:disable Metrics/AbcSize
1091
+ # rubocop:disable Metrics/PerceivedComplexity
1092
+ def __join__(type, other, join_cond = EMPTY_HASH, opts = EMPTY_HASH, &block)
1098
1093
  if other.is_a?(Symbol) || other.is_a?(ROM::Relation::Name)
1099
- if join_cond.equal?(EMPTY_HASH) && !block_given?
1094
+ if join_cond.equal?(EMPTY_HASH) && !block
1100
1095
  assoc = associations[other]
1101
1096
  assoc.join(type, self)
1102
- elsif block_given?
1103
- __join__(type, other, JoinDSL.new(schema).(&), opts)
1097
+ elsif block
1098
+ __join__(type, other, JoinDSL.new(schema).(&block), opts)
1104
1099
  else
1105
- new(dataset.__send__(type, other.to_sym, join_cond, opts, &))
1100
+ new(dataset.__send__(type, other.to_sym, join_cond, opts, &block))
1106
1101
  end
1107
- elsif other.is_a?(::Sequel::SQL::AliasedExpression)
1108
- new(dataset.__send__(type, other, join_cond, opts, &))
1102
+ elsif other.is_a?(Sequel::SQL::AliasedExpression)
1103
+ new(dataset.__send__(type, other, join_cond, opts, &block))
1109
1104
  elsif other.respond_to?(:name) && other.name.is_a?(Relation::Name)
1110
- if block_given?
1111
- join_cond = JoinDSL.new(schema).(&)
1105
+ if block
1106
+ join_cond = JoinDSL.new(schema).(&block)
1112
1107
 
1113
1108
  if other.name.aliaz
1114
- join_opts = { table_alias: other.name.aliaz }
1109
+ join_opts = {table_alias: other.name.aliaz}
1115
1110
  else
1116
1111
  join_opts = EMPTY_HASH
1117
1112
  end
@@ -1121,12 +1116,12 @@ module ROM
1121
1116
  associations[other.name.key].join(type, self, other)
1122
1117
  end
1123
1118
  else
1124
- raise ArgumentError,
1125
- "+other+ must be either a symbol or a relation, #{other.class} given"
1119
+ raise ArgumentError, "+other+ must be either a symbol or a relation, #{other.class} given"
1126
1120
  end
1127
1121
  end
1122
+ # rubocop:enable Metrics/AbcSize
1123
+ # rubocop:enable Metrics/PerceivedComplexity
1128
1124
  end
1129
- # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/ModuleLength
1130
1125
  end
1131
1126
  end
1132
1127
  end
@@ -16,7 +16,7 @@ module ROM
16
16
  # @return [Integer] Number of affected rows
17
17
  #
18
18
  # @api public
19
- def upsert(*args, &)
19
+ def upsert(*args, &block)
20
20
  if args.size > 1 && args[-1].is_a?(Hash)
21
21
  *values, opts = args
22
22
  else
@@ -24,7 +24,7 @@ module ROM
24
24
  opts = EMPTY_HASH
25
25
  end
26
26
 
27
- dataset.insert_conflict(opts).insert(*values, &)
27
+ dataset.insert_conflict(opts).insert(*values, &block)
28
28
  end
29
29
 
30
30
  # Insert tuple into relation
@@ -119,13 +119,8 @@ module ROM
119
119
  dataset.import(columns, other.dataset, options)
120
120
  else
121
121
  keys = columns.map(&:to_sym)
122
- dataset.import(
123
- columns,
124
- other.to_a.map { |record|
125
- record.to_h.values_at(*keys)
126
- },
127
- options
128
- )
122
+
123
+ dataset.import(columns, other.to_a.map { |record| record.to_h.values_at(*keys) }, options)
129
124
  end
130
125
  end
131
126
  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,99 +18,36 @@ 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]
35
-
36
- relation.dataset do
37
- table = opts[:from].first
27
+ config.wrap_class = SQL::Wrap
38
28
 
39
- if db.table_exists?(table)
40
- select(*schema.qualified_projection).order(
41
- *schema.project(*schema.primary_key_names).qualified
42
- )
43
- else
44
- self
45
- end
46
- end
29
+ configure(:component) do |config|
30
+ config.adapter = :sql
47
31
  end
48
32
 
49
- subscribe('configuration.relations.dataset.allocated', adapter: :sql) do |event|
50
- 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
51
39
  end
52
40
 
53
- # @api private
54
- #
55
- # rubocop:disable Metrics/MethodLength
56
- def self.define_default_views!
57
- undef_method :by_pk if method_defined?(:by_pk)
41
+ dataset(abstract: true) do |schema|
42
+ table = opts[:from].first
58
43
 
59
- if schema.primary_key.size > 1
60
- pks = schema.primary_key
61
- # @!method by_pk(val1, val2)
62
- # Return a relation restricted by its composite primary key
63
- #
64
- # @param [Array] args A list with composite pk values
65
- #
66
- # @return [SQL::Relation]
67
- #
68
- # @api public
69
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
70
- def by_pk(#{pks.map(&:name).join(", ")}) # def by_pk(val1, val2)
71
- s = schema.canonical # s = schema.canonical
72
- where( # where(
73
- #{pks.map { "s[:#{_1.name}] => #{_1.name}" }.join(", ")} # s[:val1] => val1, s[:val2] => val2
74
- ) # )
75
- end # end
76
- RUBY
44
+ if db.table_exists?(table)
45
+ select(*schema.qualified_projection)
46
+ .order(*schema.project(*schema.primary_key_names).qualified)
77
47
  else
78
- # @!method by_pk(pk)
79
- # Return a relation restricted by its primary key
80
- #
81
- # @param [Object] pk The primary key value
82
- #
83
- # @return [SQL::Relation]
84
- #
85
- # @api public
86
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
87
- def by_pk(pk) # def by_pk(pk)
88
- s = schema.canonical # s = schema.canonical
89
- if primary_key.nil? # if primary_key.nil?
90
- raise MissingPrimaryKeyError.new( # raise MissingPrimaryKeyError.new(
91
- "Missing primary key for :\#{schema.name}" # "Missing primary key for :#{schema.name}"
92
- ) # )
93
- end # end
94
- where(s[s.primary_key_name].qualified => pk) # where(s[s.primary_key_name].qualified => pk)
95
- end # end
96
- RUBY
48
+ self
97
49
  end
98
50
  end
99
- # rubocop:enable Metrics/MethodLength
100
-
101
- # @api private
102
- def self.associations
103
- schema.associations
104
- end
105
-
106
- # @api private
107
- def self.primary_key_columns(db, table)
108
- names = db.respond_to?(:primary_key) ? Array(db.primary_key(table)) : [:id]
109
- names.map { |col| :"#{table}__#{col}" }
110
- end
111
51
 
112
52
  option :primary_key, default: -> { schema.primary_key_name }
113
53
 
@@ -131,62 +71,44 @@ module ROM
131
71
  # Open a database transaction
132
72
  #
133
73
  # @param [Hash] opts
134
- # @option opts [Boolean] :auto_savepoint
135
- # Automatically use a savepoint for Database#transaction
136
- # calls inside this transaction block.
137
- # @option opts [Symbol] :isolation
138
- # The transaction isolation level to use for this transaction,
139
- # should be :uncommitted, :committed, :repeatable, or :serializable,
140
- # used if given and the database/adapter supports customizable
141
- # transaction isolation levels.
142
- # @option opts [Integer] :num_retries
143
- # The number of times to retry if the :retry_on option is used.
144
- # The default is 5 times. Can be set to nil to retry indefinitely,
145
- # but that is not recommended.
146
- # @option opts [Proc] :before_retry
147
- # Proc to execute before rertrying if the :retry_on option is used.
148
- # Called with two arguments: the number of retry attempts (counting the
149
- # current one) and the error the last attempt failed with.
150
- # @option opts [String] :prepare
151
- # A string to use as the transaction identifier for a prepared transaction
152
- # (two-phase commit), if the database/adapter supports prepared transactions.
153
- # @option opts [Class] :retry_on
154
- # An exception class or array of exception classes for which to automatically
155
- # retry the transaction. Can only be set if not inside an existing transaction.
156
- # Note that this should not be used unless the entire transaction block is
157
- # idempotent, as otherwise it can cause non-idempotent behavior to execute
158
- # multiple times.
159
- # @option opts [Symbol] :rollback
160
- # Can be set to :reraise to reraise any Sequel::Rollback
161
- # exceptions raised, or :always to always rollback even if no
162
- # exceptions occur (useful for testing).
163
- # @option opts [Symbol] :server
164
- # The server to use for the transaction. Set to :default, :read_only,
165
- # or whatever symbol you used in the connect string when naming
166
- # your servers.
167
- # @option opts [Boolean] :savepoint
168
- # Whether to create a new savepoint for this transaction, only
169
- # respected if the database/adapter supports savepoints. By default
170
- # Sequel will reuse an existing transaction, so if you want to use a
171
- # savepoint you must use this option. If the surrounding transaction
172
- # uses :auto_savepoint, you can set this to false to not use a savepoint.
173
- # If the value given for this option is :only, it will only create a
174
- # savepoint if it is inside a transacation.
175
- # @option opts [Boolean] :deferrable
176
- # If present, set to DEFERRABLE if true or NOT DEFERRABLE if false.
177
- # @option opts [Boolean] :read_only
178
- # **PG only** If present, set to READ ONLY if true or READ WRITE if false.
179
- # @option opts [Symbol] :synchronous
180
- # **PG only** If non-nil, set synchronous_commit appropriately.
181
- # Valid values true, :on, false, :off, :local, and :remote_write.
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.
101
+ # @option opts [Boolean] :read_only **PG only** If present, set to READ ONLY if true or READ WRITE if false.
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+).
182
104
  #
183
105
  # @yield [t] Transaction
184
106
  #
185
107
  # @return [Mixed]
186
108
  #
187
109
  # @api public
188
- def transaction(opts = EMPTY_HASH, &)
189
- Transaction.new(dataset.db).run(opts, &)
110
+ def transaction(**opts, &block)
111
+ Transaction.new(dataset.db).run(**opts, &block)
190
112
  end
191
113
 
192
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
@@ -19,21 +19,17 @@ module ROM
19
19
 
20
20
  private
21
21
 
22
- def respond_to_missing?(_meth, _include_private = false)
23
- true
24
- end
25
-
26
22
  # @api private
27
- def method_missing(meth, ...)
23
+ def method_missing(meth, *args, &block)
28
24
  if schema.key?(meth)
29
25
  schema[meth]
30
26
  else
31
27
  type = type(meth)
32
28
 
33
29
  if type
34
- ::ROM::SQL::Function.new(type).meta(schema: schema)
30
+ ::ROM::SQL::Function.new(type)
35
31
  else
36
- ::Sequel::VIRTUAL_ROW.__send__(meth, ...)
32
+ ::Sequel::VIRTUAL_ROW.__send__(meth, *args, &block)
37
33
  end
38
34
  end
39
35
  end