rom-sql 2.0.0.beta1 → 2.0.0.beta2

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2 -1
  3. data/lib/rom/plugins/relation/sql/auto_restrictions.rb +19 -6
  4. data/lib/rom/sql/attribute.rb +9 -0
  5. data/lib/rom/sql/commands/create.rb +0 -2
  6. data/lib/rom/sql/commands/delete.rb +0 -2
  7. data/lib/rom/sql/commands/update.rb +0 -2
  8. data/lib/rom/sql/extensions/postgres/attributes_inferrer.rb +1 -1
  9. data/lib/rom/sql/index.rb +16 -0
  10. data/lib/rom/sql/migration/inline_runner.rb +12 -4
  11. data/lib/rom/sql/migration/schema_diff.rb +23 -3
  12. data/lib/rom/sql/plugin/associates.rb +3 -3
  13. data/lib/rom/sql/plugin/timestamps.rb +2 -2
  14. data/lib/rom/sql/relation.rb +7 -0
  15. data/lib/rom/sql/relation/reading.rb +1 -1
  16. data/lib/rom/sql/schema.rb +2 -1
  17. data/lib/rom/sql/schema/dsl.rb +26 -0
  18. data/lib/rom/sql/schema/index_dsl.rb +50 -0
  19. data/lib/rom/sql/schema/inferrer.rb +11 -5
  20. data/lib/rom/sql/version.rb +1 -1
  21. data/spec/integration/auto_migrations/indexes_spec.rb +147 -3
  22. data/spec/integration/{graph_spec.rb → combine_with_spec.rb} +1 -1
  23. data/spec/integration/commands/create_spec.rb +37 -62
  24. data/spec/integration/commands/delete_spec.rb +6 -6
  25. data/spec/integration/commands/update_spec.rb +6 -8
  26. data/spec/integration/plugins/associates/many_to_many_spec.rb +2 -2
  27. data/spec/integration/plugins/associates_spec.rb +7 -7
  28. data/spec/integration/plugins/auto_restrictions_spec.rb +31 -0
  29. data/spec/integration/relation_schema_spec.rb +68 -0
  30. data/spec/integration/schema/inferrer_spec.rb +31 -6
  31. data/spec/support/helpers.rb +1 -1
  32. data/spec/unit/plugin/timestamp_spec.rb +2 -2
  33. data/spec/unit/types_spec.rb +1 -1
  34. metadata +6 -5
  35. data/lib/rom/sql/commands/transaction.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ff0be19f60330b9224eaf421b85ad113000c1558
4
- data.tar.gz: 3ccb799110fbc7543f3e9ef9ebd511193c700ab6
3
+ metadata.gz: 8f6a088c5111442c8a6ac85b97315143395afd3a
4
+ data.tar.gz: 909c97090b071f2229b84055686ea34c0a31d9e2
5
5
  SHA512:
6
- metadata.gz: fe36e8c1a886f3231385d3ff9709aa11a4ad13b63b313ec5fd07fc76af0537327184bef102af03c66331750b76d0edfd7838e1ec4e02e8189ac56f91c7749203
7
- data.tar.gz: 3192a10d465305f01d780e4db7af846c14c3c09509afb59f5cdad770383234ab59fc80b49431270aa863adeb7a51f7f3867a05c48cdfde084c7ed1ac1ea83a19
6
+ metadata.gz: ebaf850abe38152fad88f59e91a50ecd2ea882b5e9159a252f30b32da5b383dfd8a8079095454daf7c5cffefd8e72da20f7c7c86094f50a4109b0f5fd00bbd09
7
+ data.tar.gz: 36d28232439734adc2de2f440a28cc57374250efbd001bb4291939ea39c01d7e9cddf1020833bf840baf450ae2f8bee9319b0fd5a8bc93cfcb5eacfb4c26efc7
data/CHANGELOG.md CHANGED
@@ -7,8 +7,9 @@
7
7
 
8
8
  ### Changed
9
9
 
10
- * [BREAKING] based on rom 4.0 now
10
+ * [BREAKING] based on rom 4.0 now (flash-gordon + solnic)
11
11
  * [BREAKING] `Associates` command plugin requires associations now (solnic)
12
+ * [BREAKING] `Command#transaction` is gone in favor of `Relation#transaction` (solnic)
12
13
  * `ManyToOne` no longer uses a join (solnic)
13
14
  * `AutoCombine` and `AutoWrap` plugins were removed as this functionality is provided by core API (solnic)
14
15
 
@@ -39,18 +39,31 @@ module ROM
39
39
  def self.restriction_methods(schema)
40
40
  mod = Module.new
41
41
 
42
- indexed_attrs = schema.indexes.map { |index| index.attributes[0] }.uniq
42
+ methods = schema.indexes.each_with_object([]) do |index, generated|
43
+ next if index.partial?
43
44
 
44
- methods = indexed_attrs.map do |attr|
45
- meth_name = :"by_#{attr.name}"
45
+ attributes = index.to_a
46
+ meth_name = :"by_#{ attributes.map(&:name).join('_and_') }"
47
+
48
+ next if generated.include?(meth_name)
46
49
 
47
50
  mod.module_eval do
48
- define_method(meth_name) do |value|
49
- where(attr.is(value))
51
+ if attributes.size == 1
52
+ attribute = attributes[0]
53
+
54
+ define_method(meth_name) do |value|
55
+ where(attribute.is(value))
56
+ end
57
+ else
58
+ indexed_attributes = attributes.map.with_index.to_a
59
+
60
+ define_method(meth_name) do |*values|
61
+ where(indexed_attributes.map { |attr, idx| attr.is(values[idx]) }.reduce(:&))
62
+ end
50
63
  end
51
64
  end
52
65
 
53
- meth_name
66
+ generated << meth_name
54
67
  end
55
68
 
56
69
  [methods, mod]
@@ -306,6 +306,15 @@ module ROM
306
306
  meta
307
307
  end
308
308
 
309
+ # @api private
310
+ def unwrap
311
+ if optional?
312
+ self.class.new(right, options).meta(meta)
313
+ else
314
+ self
315
+ end
316
+ end
317
+
309
318
  private
310
319
 
311
320
  # Return Sequel Expression object for an attribute
@@ -1,5 +1,4 @@
1
1
  require 'rom/sql/commands/error_wrapper'
2
- require 'rom/sql/commands/transaction'
3
2
 
4
3
  module ROM
5
4
  module SQL
@@ -10,7 +9,6 @@ module ROM
10
9
  class Create < ROM::Commands::Create
11
10
  adapter :sql
12
11
 
13
- include Transaction
14
12
  include ErrorWrapper
15
13
 
16
14
  use :associates
@@ -1,5 +1,4 @@
1
1
  require 'rom/sql/commands/error_wrapper'
2
- require 'rom/sql/commands/transaction'
3
2
 
4
3
  module ROM
5
4
  module SQL
@@ -10,7 +9,6 @@ module ROM
10
9
  class Delete < ROM::Commands::Delete
11
10
  adapter :sql
12
11
 
13
- include Transaction
14
12
  include ErrorWrapper
15
13
 
16
14
  # Deletes tuples from a relation
@@ -1,5 +1,4 @@
1
1
  require 'rom/sql/commands/error_wrapper'
2
- require 'rom/sql/commands/transaction'
3
2
 
4
3
  module ROM
5
4
  module SQL
@@ -10,7 +9,6 @@ module ROM
10
9
  class Update < ROM::Commands::Update
11
10
  adapter :sql
12
11
 
13
- include Transaction
14
12
  include ErrorWrapper
15
13
 
16
14
  use :schema
@@ -34,7 +34,7 @@ module ROM
34
34
  'path' => Types::PG::PathT
35
35
  ).freeze
36
36
 
37
- db_array_type_matcher Sequel::Postgres::PGArray::EMPTY_BRACKET
37
+ db_array_type_matcher '[]'.freeze
38
38
 
39
39
  private
40
40
 
data/lib/rom/sql/index.rb CHANGED
@@ -8,6 +8,22 @@ module ROM
8
8
  param :attributes
9
9
 
10
10
  option :name, optional: true
11
+
12
+ option :unique, default: -> { false }
13
+
14
+ alias_method :unique?, :unique
15
+
16
+ option :type, optional: true
17
+
18
+ option :predicate, optional: true
19
+
20
+ def to_a
21
+ attributes
22
+ end
23
+
24
+ def partial?
25
+ !predicate.nil?
26
+ end
11
27
  end
12
28
  end
13
29
  end
@@ -37,8 +37,12 @@ module ROM
37
37
  end
38
38
  end
39
39
 
40
- diff.indexes.each do |idx|
41
- index idx.attribute
40
+ diff.indexes.each do |index|
41
+ index index.attributes,
42
+ name: index.name,
43
+ unique: index.unique?,
44
+ type: index.type,
45
+ where: index.predicate
42
46
  end
43
47
  end
44
48
  end
@@ -72,9 +76,13 @@ module ROM
72
76
  diff.index_changes.each do |index|
73
77
  case index
74
78
  when SchemaDiff::IndexAdded
75
- add_index index.attribute
79
+ add_index index.attributes,
80
+ name: index.name,
81
+ unique: index.unique?,
82
+ type: index.type,
83
+ where: index.predicate
76
84
  when SchemaDiff::IndexRemoved
77
- drop_index index.attribute
85
+ drop_index index.attributes, name: index.name
78
86
  end
79
87
  end
80
88
  end
@@ -111,8 +111,28 @@ module ROM
111
111
  @index = index
112
112
  end
113
113
 
114
- def attribute
115
- index.attributes[0].name
114
+ def attributes
115
+ index.attributes.map(&:name)
116
+ end
117
+
118
+ def name
119
+ index.name
120
+ end
121
+
122
+ def unique?
123
+ index.unique?
124
+ end
125
+
126
+ def type
127
+ index.type
128
+ end
129
+
130
+ def predicate
131
+ index.predicate
132
+ end
133
+
134
+ def partial?
135
+ !predicate.nil?
116
136
  end
117
137
  end
118
138
 
@@ -165,7 +185,7 @@ module ROM
165
185
  current.indexes.any? { |curr_idx| curr_idx.attributes == idx.attributes }
166
186
  }
167
187
  removed_indexes = current.indexes.select { |idx|
168
- target.indexes.none? { |tgt_idx| idx.attributes == tgt_idx }
188
+ target.indexes.none? { |tgt_idx| idx.attributes == tgt_idx.attributes }
169
189
  }
170
190
 
171
191
  removed_indexes.map { |idx| IndexRemoved.new(idx) } +
@@ -60,7 +60,7 @@ module ROM
60
60
  after_hooks = associate_options.select(&:after?).map(&:to_hash)
61
61
 
62
62
  command.
63
- with_opts(configured_associations: configured_assocs + associate_options.map(&:name)).
63
+ with(configured_associations: configured_assocs + associate_options.map(&:name)).
64
64
  before(*before_hooks).
65
65
  after(*after_hooks)
66
66
  end
@@ -73,10 +73,10 @@ module ROM
73
73
  # associates :user, key: [:user_id, :id]
74
74
  # end
75
75
  #
76
- # create_user = rom.command(:user).create.with(name: 'Jane')
76
+ # create_user = rom.command(:user).create.curry(name: 'Jane')
77
77
  #
78
78
  # create_tasks = rom.command(:tasks).create
79
- # .with [{ title: 'One' }, { title: 'Two' } ]
79
+ # .curry [{ title: 'One' }, { title: 'Two' } ]
80
80
  #
81
81
  # command = create_user >> create_tasks
82
82
  # command.call
@@ -33,7 +33,7 @@ module ROM
33
33
  # timestamps :created_at, :updated_at
34
34
  # end
35
35
  #
36
- # create_user = rom.command(:user).create.with(name: 'Jane')
36
+ # create_user = rom.command(:user).create.curry(name: 'Jane')
37
37
  #
38
38
  # result = create_user.call
39
39
  # result[:created_at] #=> Time.now.utc
@@ -57,7 +57,7 @@ module ROM
57
57
  # datestamps :created_on, :updated_on
58
58
  # end
59
59
  #
60
- # create_user = rom.command(:user).create.with(name: 'Jane')
60
+ # create_user = rom.command(:user).create.curry(name: 'Jane')
61
61
  #
62
62
  # result = create_user.call
63
63
  # result[:created_at] #=> Date.today
@@ -2,6 +2,7 @@ require 'rom/sql/types'
2
2
  require 'rom/sql/schema'
3
3
  require 'rom/sql/attribute'
4
4
  require 'rom/sql/wrap'
5
+ require 'rom/sql/transaction'
5
6
 
6
7
  require 'rom/sql/relation/reading'
7
8
  require 'rom/sql/relation/writing'
@@ -24,6 +25,7 @@ module ROM
24
25
  schema_class SQL::Schema
25
26
  schema_attr_class SQL::Attribute
26
27
  schema_inferrer ROM::SQL::Schema::Inferrer.new.freeze
28
+ schema_dsl SQL::Schema::DSL
27
29
  wrap_class SQL::Wrap
28
30
 
29
31
  subscribe('configuration.relations.schema.set', adapter: :sql) do |event|
@@ -113,6 +115,11 @@ module ROM
113
115
  associations[name].()
114
116
  end
115
117
 
118
+ # @api public
119
+ def transaction(opts = EMPTY_HASH, &block)
120
+ Transaction.new(dataset.db).run(opts, &block)
121
+ end
122
+
116
123
  # Return raw column names
117
124
  #
118
125
  # @return [Array<Symbol>]
@@ -851,7 +851,7 @@ module ROM
851
851
  clause = lock_clause(options)
852
852
 
853
853
  if block
854
- dataset.db.transaction do
854
+ transaction do
855
855
  block.call(dataset.lock_style(clause).to_a)
856
856
  end
857
857
  else
@@ -1,5 +1,6 @@
1
1
  require 'rom/schema'
2
2
 
3
+ require 'rom/sql/schema/dsl'
3
4
  require 'rom/sql/order_dsl'
4
5
  require 'rom/sql/group_dsl'
5
6
  require 'rom/sql/projection_dsl'
@@ -12,7 +13,7 @@ module ROM
12
13
  class Schema < ROM::Schema
13
14
  # @!attribute [r] attributes
14
15
  # @return [Array<Index>] Array with schema indexes
15
- option :indexes, default: -> { EMPTY_ARRAY }
16
+ option :indexes, default: -> { EMPTY_SET }
16
17
 
17
18
  # @api public
18
19
  def restriction(&block)
@@ -0,0 +1,26 @@
1
+ require 'rom/sql/schema/index_dsl'
2
+
3
+ module ROM
4
+ module SQL
5
+ class Schema < ROM::Schema
6
+ # @api public
7
+ class DSL < ROM::Schema::DSL
8
+ attr_reader :index_dsl
9
+
10
+ def indexes(&block)
11
+ @index_dsl = IndexDSL.new(options, &block)
12
+ end
13
+
14
+ def opts
15
+ if index_dsl
16
+ opts = super
17
+
18
+ { **opts, indexes: index_dsl.(relation, opts[:attributes]) }
19
+ else
20
+ super
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ require 'set'
2
+
3
+ module ROM
4
+ module SQL
5
+ class Schema < ROM::Schema
6
+ # @api public
7
+ class IndexDSL # < BasicObject
8
+ extend Initializer
9
+
10
+ option :attr_class
11
+
12
+ attr_reader :registry
13
+
14
+ # @api private
15
+ def initialize(*, &block)
16
+ super
17
+
18
+ @registry = []
19
+
20
+ instance_exec(&block)
21
+ end
22
+
23
+ # @api public
24
+ def index(*attributes, **options)
25
+ registry << [attributes, options]
26
+ end
27
+
28
+ # @api private
29
+ def call(schema_name, types)
30
+ attributes = types.map { |type| attr_class.new(type).meta(source: schema_name) }
31
+
32
+ registry.map { |attr_names, options|
33
+ build_index(attributes, attr_names, options)
34
+ }.to_set
35
+ end
36
+
37
+ private
38
+
39
+ # @api private
40
+ def build_index(attributes, attr_names, options)
41
+ index_attributes = attr_names.map do |name|
42
+ attributes.find { |a| a.name == name }.unwrap
43
+ end
44
+
45
+ Index.new(index_attributes, options)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -24,7 +24,7 @@ module ROM
24
24
  def call(schema, gateway)
25
25
  inferred = super
26
26
 
27
- indexes = get_indexes(gateway, schema.name.dataset, inferred[:attributes])
27
+ indexes = get_indexes(gateway, schema, inferred[:attributes])
28
28
 
29
29
  { **inferred, indexes: indexes }
30
30
  rescue Sequel::Error => error
@@ -33,20 +33,26 @@ module ROM
33
33
  end
34
34
 
35
35
  # @api private
36
- def get_indexes(gateway, dataset, attributes)
36
+ def get_indexes(gateway, schema, attributes)
37
+ dataset = schema.name.dataset
38
+
37
39
  if enabled? && gateway.connection.respond_to?(:indexes)
38
40
  gateway.connection.indexes(dataset).map { |name, body|
39
41
  columns = body[:columns].map { |name|
40
- attributes.find { |attr| attr.name == name }
42
+ attributes.find { |attr| attr.name == name }.unwrap
41
43
  }
42
44
 
43
- SQL::Index.new(columns, name: name)
45
+ SQL::Index.new(columns, name: name, unique: body[:unique])
44
46
  }.to_set
45
47
  else
46
- attributes.select(&:indexed?).map { |attr| SQL::Index.new([attr]) }.to_set
48
+ schema.indexes | indexes_from_attributes(attributes)
47
49
  end
48
50
  end
49
51
 
52
+ def indexes_from_attributes(attributes)
53
+ attributes.select(&:indexed?).map { |attr| SQL::Index.new([attr.unwrap]) }.to_set
54
+ end
55
+
50
56
  # @api private
51
57
  def suppress_errors
52
58
  with(raise_on_error: false, silent: true)