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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -1
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +19 -6
- data/lib/rom/sql/attribute.rb +9 -0
- data/lib/rom/sql/commands/create.rb +0 -2
- data/lib/rom/sql/commands/delete.rb +0 -2
- data/lib/rom/sql/commands/update.rb +0 -2
- data/lib/rom/sql/extensions/postgres/attributes_inferrer.rb +1 -1
- data/lib/rom/sql/index.rb +16 -0
- data/lib/rom/sql/migration/inline_runner.rb +12 -4
- data/lib/rom/sql/migration/schema_diff.rb +23 -3
- data/lib/rom/sql/plugin/associates.rb +3 -3
- data/lib/rom/sql/plugin/timestamps.rb +2 -2
- data/lib/rom/sql/relation.rb +7 -0
- data/lib/rom/sql/relation/reading.rb +1 -1
- data/lib/rom/sql/schema.rb +2 -1
- data/lib/rom/sql/schema/dsl.rb +26 -0
- data/lib/rom/sql/schema/index_dsl.rb +50 -0
- data/lib/rom/sql/schema/inferrer.rb +11 -5
- data/lib/rom/sql/version.rb +1 -1
- data/spec/integration/auto_migrations/indexes_spec.rb +147 -3
- data/spec/integration/{graph_spec.rb → combine_with_spec.rb} +1 -1
- data/spec/integration/commands/create_spec.rb +37 -62
- data/spec/integration/commands/delete_spec.rb +6 -6
- data/spec/integration/commands/update_spec.rb +6 -8
- data/spec/integration/plugins/associates/many_to_many_spec.rb +2 -2
- data/spec/integration/plugins/associates_spec.rb +7 -7
- data/spec/integration/plugins/auto_restrictions_spec.rb +31 -0
- data/spec/integration/relation_schema_spec.rb +68 -0
- data/spec/integration/schema/inferrer_spec.rb +31 -6
- data/spec/support/helpers.rb +1 -1
- data/spec/unit/plugin/timestamp_spec.rb +2 -2
- data/spec/unit/types_spec.rb +1 -1
- metadata +6 -5
- data/lib/rom/sql/commands/transaction.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f6a088c5111442c8a6ac85b97315143395afd3a
|
4
|
+
data.tar.gz: 909c97090b071f2229b84055686ea34c0a31d9e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
42
|
+
methods = schema.indexes.each_with_object([]) do |index, generated|
|
43
|
+
next if index.partial?
|
43
44
|
|
44
|
-
|
45
|
-
meth_name = :"by_#{
|
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
|
-
|
49
|
-
|
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]
|
data/lib/rom/sql/attribute.rb
CHANGED
@@ -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
|
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 |
|
41
|
-
index
|
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.
|
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.
|
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
|
115
|
-
index.attributes
|
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
|
-
|
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.
|
76
|
+
# create_user = rom.command(:user).create.curry(name: 'Jane')
|
77
77
|
#
|
78
78
|
# create_tasks = rom.command(:tasks).create
|
79
|
-
# .
|
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.
|
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.
|
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
|
data/lib/rom/sql/relation.rb
CHANGED
@@ -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>]
|
data/lib/rom/sql/schema.rb
CHANGED
@@ -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: -> {
|
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
|
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,
|
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
|
-
|
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)
|