rom-sql 2.0.0.beta1 → 2.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|