rom-sql 1.3.5 → 2.0.0.beta1
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 +13 -7
- data/Gemfile +7 -5
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +11 -17
- data/lib/rom/sql.rb +3 -2
- data/lib/rom/sql/associations.rb +5 -0
- data/lib/rom/sql/associations/core.rb +20 -0
- data/lib/rom/sql/associations/many_to_many.rb +83 -0
- data/lib/rom/sql/associations/many_to_one.rb +55 -0
- data/lib/rom/sql/associations/one_to_many.rb +31 -0
- data/lib/rom/sql/{association → associations}/one_to_one.rb +3 -2
- data/lib/rom/sql/{association → associations}/one_to_one_through.rb +3 -2
- data/lib/rom/sql/associations/self_ref.rb +39 -0
- data/lib/rom/sql/attribute.rb +44 -54
- data/lib/rom/sql/errors.rb +2 -0
- data/lib/rom/sql/extensions/mysql.rb +1 -1
- data/lib/rom/sql/extensions/mysql/attributes_inferrer.rb +10 -0
- data/lib/rom/sql/extensions/postgres.rb +1 -1
- data/lib/rom/sql/extensions/postgres/{inferrer.rb → attributes_inferrer.rb} +4 -4
- data/lib/rom/sql/extensions/postgres/types.rb +9 -19
- data/lib/rom/sql/extensions/sqlite.rb +1 -1
- data/lib/rom/sql/extensions/sqlite/{inferrer.rb → attributes_inferrer.rb} +2 -2
- data/lib/rom/sql/gateway.rb +29 -30
- data/lib/rom/sql/index.rb +13 -0
- data/lib/rom/sql/migration.rb +10 -0
- data/lib/rom/sql/migration/inline_runner.rb +86 -0
- data/lib/rom/sql/migration/migrator.rb +17 -0
- data/lib/rom/sql/migration/schema_diff.rb +177 -0
- data/lib/rom/sql/plugin/associates.rb +11 -45
- data/lib/rom/sql/plugin/pagination.rb +4 -4
- data/lib/rom/sql/relation.rb +22 -42
- data/lib/rom/sql/relation/reading.rb +3 -3
- data/lib/rom/sql/schema.rb +14 -21
- data/lib/rom/sql/schema/associations_dsl.rb +7 -6
- data/lib/rom/sql/schema/attributes_inferrer.rb +164 -0
- data/lib/rom/sql/schema/inferrer.rb +40 -141
- data/lib/rom/sql/type_extensions.rb +44 -0
- data/lib/rom/sql/version.rb +1 -1
- data/lib/rom/sql/wrap.rb +25 -0
- data/rom-sql.gemspec +2 -2
- data/spec/integration/{association → associations}/many_to_many/custom_fks_spec.rb +4 -2
- data/spec/integration/{association → associations}/many_to_many/from_view_spec.rb +2 -2
- data/spec/integration/{association → associations}/many_to_many_spec.rb +25 -30
- data/spec/integration/{association → associations}/many_to_one/custom_fks_spec.rb +5 -3
- data/spec/integration/{association → associations}/many_to_one/from_view_spec.rb +3 -3
- data/spec/integration/{association → associations}/many_to_one/self_ref_spec.rb +2 -2
- data/spec/integration/{association → associations}/many_to_one_spec.rb +20 -38
- data/spec/integration/{association → associations}/one_to_many/custom_fks_spec.rb +4 -2
- data/spec/integration/{association → associations}/one_to_many/from_view_spec.rb +2 -2
- data/spec/integration/{association → associations}/one_to_many/self_ref_spec.rb +2 -2
- data/spec/integration/{association → associations}/one_to_many_spec.rb +24 -11
- data/spec/integration/{association → associations}/one_to_one_spec.rb +13 -9
- data/spec/integration/{association → associations}/one_to_one_through_spec.rb +15 -11
- data/spec/integration/auto_migrations/errors_spec.rb +31 -0
- data/spec/integration/auto_migrations/indexes_spec.rb +109 -0
- data/spec/integration/auto_migrations/managing_columns_spec.rb +156 -0
- data/spec/integration/auto_migrations/postgres/column_types_spec.rb +63 -0
- data/spec/integration/commands/create_spec.rb +2 -4
- data/spec/integration/commands/delete_spec.rb +2 -2
- data/spec/integration/commands/update_spec.rb +2 -0
- data/spec/integration/graph_spec.rb +9 -3
- data/spec/integration/plugins/associates_spec.rb +16 -55
- data/spec/integration/plugins/auto_restrictions_spec.rb +0 -11
- data/spec/integration/relation_schema_spec.rb +49 -25
- data/spec/integration/schema/inferrer/postgres_spec.rb +1 -1
- data/spec/integration/schema/inferrer_spec.rb +7 -18
- data/spec/integration/setup_spec.rb +4 -0
- data/spec/integration/{plugins/auto_wrap_spec.rb → wrap_spec.rb} +13 -36
- data/spec/shared/accounts.rb +4 -0
- data/spec/shared/database_setup.rb +2 -1
- data/spec/shared/notes.rb +2 -0
- data/spec/shared/posts.rb +2 -0
- data/spec/shared/puppies.rb +2 -0
- data/spec/shared/relations.rb +2 -2
- data/spec/shared/users.rb +2 -0
- data/spec/shared/users_and_tasks.rb +4 -0
- data/spec/spec_helper.rb +3 -6
- data/spec/support/helpers.rb +11 -8
- data/spec/support/test_configuration.rb +16 -0
- data/spec/unit/plugin/associates_spec.rb +5 -10
- data/spec/unit/plugin/pagination_spec.rb +9 -9
- data/spec/unit/plugin/timestamp_spec.rb +9 -9
- data/spec/unit/relation/dataset_spec.rb +7 -5
- data/spec/unit/relation/inner_join_spec.rb +2 -15
- data/spec/unit/relation/primary_key_spec.rb +1 -1
- data/spec/unit/schema_spec.rb +6 -4
- metadata +65 -70
- data/lib/rom/plugins/relation/sql/auto_combine.rb +0 -71
- data/lib/rom/plugins/relation/sql/auto_wrap.rb +0 -62
- data/lib/rom/sql/association.rb +0 -103
- data/lib/rom/sql/association/many_to_many.rb +0 -119
- data/lib/rom/sql/association/many_to_one.rb +0 -73
- data/lib/rom/sql/association/name.rb +0 -78
- data/lib/rom/sql/association/one_to_many.rb +0 -60
- data/lib/rom/sql/extensions/mysql/inferrer.rb +0 -10
- data/lib/rom/sql/qualified_attribute.rb +0 -53
- data/lib/rom/sql/schema/dsl.rb +0 -75
- data/spec/unit/association/many_to_many_spec.rb +0 -89
- data/spec/unit/association/many_to_one_spec.rb +0 -81
- data/spec/unit/association/name_spec.rb +0 -68
- data/spec/unit/association/one_to_many_spec.rb +0 -82
- data/spec/unit/association/one_to_one_spec.rb +0 -83
- data/spec/unit/association/one_to_one_through_spec.rb +0 -69
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff0be19f60330b9224eaf421b85ad113000c1558
|
|
4
|
+
data.tar.gz: 3ccb799110fbc7543f3e9ef9ebd511193c700ab6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fe36e8c1a886f3231385d3ff9709aa11a4ad13b63b313ec5fd07fc76af0537327184bef102af03c66331750b76d0edfd7838e1ec4e02e8189ac56f91c7749203
|
|
7
|
+
data.tar.gz: 3192a10d465305f01d780e4db7af846c14c3c09509afb59f5cdad770383234ab59fc80b49431270aa863adeb7a51f7f3867a05c48cdfde084c7ed1ac1ea83a19
|
data/CHANGELOG.md
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
##
|
|
1
|
+
## v2.0.0 to-be-released
|
|
2
2
|
|
|
3
|
-
###
|
|
3
|
+
### Added
|
|
4
4
|
|
|
5
|
-
*
|
|
5
|
+
* Support for schema plugins (flash-gordon)
|
|
6
|
+
* Support for auto migrations (flash-gordon)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
### Changed
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
* [BREAKING] based on rom 4.0 now
|
|
11
|
+
* [BREAKING] `Associates` command plugin requires associations now (solnic)
|
|
12
|
+
* `ManyToOne` no longer uses a join (solnic)
|
|
13
|
+
* `AutoCombine` and `AutoWrap` plugins were removed as this functionality is provided by core API (solnic)
|
|
10
14
|
|
|
11
15
|
### Fixed
|
|
12
16
|
|
|
13
|
-
*
|
|
17
|
+
* Self-ref associations work correctly with custom FKs (solnic)
|
|
18
|
+
* Aliased associations with custom FKs work correctly (solnic)
|
|
19
|
+
* Defining a custom dataset block no longer prevents default views like `by_pk` to be defined (solnic)
|
|
14
20
|
|
|
15
|
-
[Compare v1.3.3
|
|
21
|
+
[Compare v1.3.3...master](https://github.com/rom-rb/rom-sql/compare/v1.3.3...master)
|
|
16
22
|
|
|
17
23
|
## v1.3.3 2017-05-30
|
|
18
24
|
|
data/Gemfile
CHANGED
|
@@ -2,7 +2,13 @@ source 'https://rubygems.org'
|
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem '
|
|
5
|
+
gem 'dry-types', git: 'https://github.com/dry-rb/dry-types', branch: 'master'
|
|
6
|
+
|
|
7
|
+
gem 'rom', git: 'https://github.com/rom-rb/rom', branch: 'master' do
|
|
8
|
+
gem 'rom-core'
|
|
9
|
+
gem 'rom-mapper'
|
|
10
|
+
gem 'rom-repository', group: :tools
|
|
11
|
+
end
|
|
6
12
|
|
|
7
13
|
group :test do
|
|
8
14
|
gem 'pry-byebug', platforms: :mri
|
|
@@ -25,7 +31,3 @@ group :test do
|
|
|
25
31
|
gem 'jdbc-sqlite3', platforms: :jruby
|
|
26
32
|
gem 'ruby-oci8', platforms: :mri if ENV['ROM_USE_ORACLE']
|
|
27
33
|
end
|
|
28
|
-
|
|
29
|
-
group :tools do
|
|
30
|
-
gem 'rom-repository', git: 'https://github.com/rom-rb/rom-repository.git', branch: 'master'
|
|
31
|
-
end
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
+
require 'rom/support/notifications'
|
|
2
|
+
|
|
1
3
|
module ROM
|
|
2
4
|
module Plugins
|
|
3
5
|
module Relation
|
|
4
6
|
module SQL
|
|
5
7
|
# Generates methods for restricting relations by their indexed attributes
|
|
6
8
|
#
|
|
7
|
-
# This plugin must be enabled for the whole adapter, `use` won't work as
|
|
8
|
-
# schema is not yet available, unless it was defined explicitly.
|
|
9
|
-
#
|
|
10
9
|
# @example
|
|
11
10
|
# rom = ROM.container(:sql, 'sqlite::memory') do |config|
|
|
12
11
|
# config.create_table(:users) do
|
|
@@ -26,26 +25,21 @@ module ROM
|
|
|
26
25
|
#
|
|
27
26
|
# @api public
|
|
28
27
|
module AutoRestrictions
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
end
|
|
28
|
+
extend Notifications::Listener
|
|
29
|
+
|
|
30
|
+
subscribe('configuration.relations.schema.set', adapter: :sql) do |event|
|
|
31
|
+
schema = event[:schema]
|
|
32
|
+
relation = event[:relation]
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
raise EmptySchemaError, klass if schema.nil?
|
|
40
|
-
methods, mod = restriction_methods(schema)
|
|
41
|
-
klass.include(mod)
|
|
42
|
-
methods.each { |meth| klass.auto_curry(meth) }
|
|
34
|
+
methods, mod = AutoRestrictions.restriction_methods(schema)
|
|
35
|
+
relation.include(mod)
|
|
36
|
+
methods.each { |meth| relation.auto_curry(meth) }
|
|
43
37
|
end
|
|
44
38
|
|
|
45
39
|
def self.restriction_methods(schema)
|
|
46
40
|
mod = Module.new
|
|
47
41
|
|
|
48
|
-
indexed_attrs = schema.
|
|
42
|
+
indexed_attrs = schema.indexes.map { |index| index.attributes[0] }.uniq
|
|
49
43
|
|
|
50
44
|
methods = indexed_attrs.map do |attr|
|
|
51
45
|
meth_name = :"by_#{attr.name}"
|
data/lib/rom/sql.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
require 'dry
|
|
1
|
+
require 'dry/equalizer'
|
|
2
2
|
require 'sequel'
|
|
3
|
-
require 'rom'
|
|
3
|
+
require 'rom/core'
|
|
4
4
|
|
|
5
5
|
require 'rom/sql/version'
|
|
6
6
|
require 'rom/sql/errors'
|
|
@@ -9,6 +9,7 @@ require 'rom/configuration_dsl'
|
|
|
9
9
|
|
|
10
10
|
require 'rom/sql/plugins'
|
|
11
11
|
require 'rom/sql/relation'
|
|
12
|
+
require 'rom/sql/associations'
|
|
12
13
|
require 'rom/sql/gateway'
|
|
13
14
|
require 'rom/sql/migration'
|
|
14
15
|
require 'rom/sql/extensions'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module ROM
|
|
2
|
+
module SQL
|
|
3
|
+
module Associations
|
|
4
|
+
# Core SQL association API
|
|
5
|
+
#
|
|
6
|
+
# @api private
|
|
7
|
+
module Core
|
|
8
|
+
# @api private
|
|
9
|
+
def preload(target, loaded)
|
|
10
|
+
source_key, target_key = join_keys.flatten(1)
|
|
11
|
+
|
|
12
|
+
target_pks = loaded.pluck(source_key.key)
|
|
13
|
+
target_pks.uniq!
|
|
14
|
+
|
|
15
|
+
target.where(target_key => target_pks)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'rom/associations/many_to_many'
|
|
2
|
+
require 'rom/sql/associations/core'
|
|
3
|
+
|
|
4
|
+
module ROM
|
|
5
|
+
module SQL
|
|
6
|
+
module Associations
|
|
7
|
+
class ManyToMany < ROM::Associations::ManyToMany
|
|
8
|
+
include Associations::Core
|
|
9
|
+
|
|
10
|
+
# @api public
|
|
11
|
+
def call(target: self.target)
|
|
12
|
+
left = join_assoc.(target: target)
|
|
13
|
+
|
|
14
|
+
schema =
|
|
15
|
+
if left.schema.key?(foreign_key)
|
|
16
|
+
if target != self.target
|
|
17
|
+
target.schema.merge(join_schema)
|
|
18
|
+
else
|
|
19
|
+
left.schema.project(*columns)
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
target_schema
|
|
23
|
+
end.qualified
|
|
24
|
+
|
|
25
|
+
relation = left.join(source.name.dataset, join_keys)
|
|
26
|
+
|
|
27
|
+
if view
|
|
28
|
+
apply_view(schema, relation)
|
|
29
|
+
else
|
|
30
|
+
schema.(relation)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @api public
|
|
35
|
+
def join(type, source = self.source, target = self.target)
|
|
36
|
+
through_assoc = source.associations[through]
|
|
37
|
+
joined = through_assoc.join(type, source)
|
|
38
|
+
joined.__send__(type, target.name.dataset, join_keys).qualified
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @api public
|
|
42
|
+
def join_keys
|
|
43
|
+
{ source_attr => target_attr }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# @api public
|
|
47
|
+
def source_attr
|
|
48
|
+
source[source_key].qualified
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @api public
|
|
52
|
+
def target_attr
|
|
53
|
+
join_relation[target_key].qualified
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @api private
|
|
57
|
+
def persist(children, parents)
|
|
58
|
+
join_tuples = associate(children, parents)
|
|
59
|
+
join_relation.multi_insert(join_tuples)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
# @api private
|
|
65
|
+
def target_schema
|
|
66
|
+
target.schema.merge(join_schema)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @api private
|
|
70
|
+
def join_schema
|
|
71
|
+
join_relation.schema.project(foreign_key)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @api private
|
|
75
|
+
def columns
|
|
76
|
+
target_schema.map(&:name)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
memoize :join_keys, :target_schema, :join_schema, :columns
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require 'rom/associations/many_to_one'
|
|
2
|
+
require 'rom/sql/associations/core'
|
|
3
|
+
require 'rom/sql/associations/self_ref'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module SQL
|
|
7
|
+
module Associations
|
|
8
|
+
class ManyToOne < ROM::Associations::ManyToOne
|
|
9
|
+
include Associations::Core
|
|
10
|
+
include Associations::SelfRef
|
|
11
|
+
|
|
12
|
+
# @api public
|
|
13
|
+
def call(target: self.target, preload: false)
|
|
14
|
+
if preload
|
|
15
|
+
schema = target.schema.qualified
|
|
16
|
+
relation = target
|
|
17
|
+
else
|
|
18
|
+
right = source
|
|
19
|
+
|
|
20
|
+
target_pk = target.schema.primary_key_name
|
|
21
|
+
right_fk = target.foreign_key(source.name)
|
|
22
|
+
|
|
23
|
+
target_schema = target.schema
|
|
24
|
+
right_schema = right.schema.project_pk
|
|
25
|
+
|
|
26
|
+
schema =
|
|
27
|
+
if target.schema.key?(right_fk)
|
|
28
|
+
target_schema
|
|
29
|
+
else
|
|
30
|
+
target_schema.merge(right_schema.project_fk(target_pk => right_fk))
|
|
31
|
+
end.qualified
|
|
32
|
+
|
|
33
|
+
relation = target.join(source_table, join_keys)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if view
|
|
37
|
+
apply_view(schema, relation)
|
|
38
|
+
else
|
|
39
|
+
schema.(relation)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @api public
|
|
44
|
+
def join(type, source = self.source, target = self.target)
|
|
45
|
+
source.__send__(type, target.name.dataset, join_keys).qualified
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @api private
|
|
49
|
+
def prepare(target)
|
|
50
|
+
call(target: target, preload: true)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'rom/associations/one_to_many'
|
|
2
|
+
require 'rom/sql/associations/core'
|
|
3
|
+
require 'rom/sql/associations/self_ref'
|
|
4
|
+
|
|
5
|
+
module ROM
|
|
6
|
+
module SQL
|
|
7
|
+
module Associations
|
|
8
|
+
class OneToMany < ROM::Associations::OneToMany
|
|
9
|
+
include Associations::Core
|
|
10
|
+
include Associations::SelfRef
|
|
11
|
+
|
|
12
|
+
# @api public
|
|
13
|
+
def call(target: self.target)
|
|
14
|
+
schema = target.schema.qualified
|
|
15
|
+
relation = target.join(source_table, join_keys)
|
|
16
|
+
|
|
17
|
+
if view
|
|
18
|
+
apply_view(schema, relation)
|
|
19
|
+
else
|
|
20
|
+
schema.(relation)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @api public
|
|
25
|
+
def join(type, source = self.source, target = self.target)
|
|
26
|
+
source.__send__(type, target.name.dataset, join_keys).qualified
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module ROM
|
|
2
|
+
module SQL
|
|
3
|
+
module Associations
|
|
4
|
+
module SelfRef
|
|
5
|
+
def self.included(klass)
|
|
6
|
+
super
|
|
7
|
+
klass.memoize :join_keys, :source_table, :source_alias, :source_attr, :target_attr
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @api public
|
|
11
|
+
def join_keys
|
|
12
|
+
{ source_attr => target_attr }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @api public
|
|
16
|
+
def source_attr
|
|
17
|
+
source[source_key].qualified(source_alias)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @api public
|
|
21
|
+
def target_attr
|
|
22
|
+
target[target_key].qualified
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
protected
|
|
26
|
+
|
|
27
|
+
# @api private
|
|
28
|
+
def source_table
|
|
29
|
+
self_ref? ? Sequel.as(source.name.dataset, source_alias) : source.name.dataset
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @api private
|
|
33
|
+
def source_alias
|
|
34
|
+
self_ref? ? :"#{source.name.dataset.to_s[0]}_0" : source.name.dataset
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/rom/sql/attribute.rb
CHANGED
|
@@ -2,6 +2,8 @@ require 'sequel/core'
|
|
|
2
2
|
require 'dry/core/cache'
|
|
3
3
|
|
|
4
4
|
require 'rom/schema/attribute'
|
|
5
|
+
|
|
6
|
+
require 'rom/sql/type_extensions'
|
|
5
7
|
require 'rom/sql/projection_dsl'
|
|
6
8
|
|
|
7
9
|
module ROM
|
|
@@ -12,57 +14,11 @@ module ROM
|
|
|
12
14
|
class Attribute < ROM::Schema::Attribute
|
|
13
15
|
OPERATORS = %i[>= <= > <].freeze
|
|
14
16
|
NONSTANDARD_EQUALITY_VALUES = [true, false, nil].freeze
|
|
17
|
+
INDEXED = Set.new([true]).freeze
|
|
15
18
|
|
|
16
19
|
# Error raised when an attribute cannot be qualified
|
|
17
20
|
QualifyError = Class.new(StandardError)
|
|
18
21
|
|
|
19
|
-
# Type-specific methods
|
|
20
|
-
#
|
|
21
|
-
# @api public
|
|
22
|
-
module TypeExtensions
|
|
23
|
-
class << self
|
|
24
|
-
# Gets extensions for a type
|
|
25
|
-
#
|
|
26
|
-
# @param [Dry::Types::Type] type
|
|
27
|
-
#
|
|
28
|
-
# @return [Hash]
|
|
29
|
-
#
|
|
30
|
-
# @api public
|
|
31
|
-
def [](wrapped)
|
|
32
|
-
type = wrapped.default? ? wrapped.type : wrapped
|
|
33
|
-
type = type.optional? ? type.right : type
|
|
34
|
-
@types[type.meta[:database]][type.meta[:db_type]] || EMPTY_HASH
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Registers a set of operations supported for a specific type
|
|
38
|
-
#
|
|
39
|
-
# @example
|
|
40
|
-
# ROM::SQL::Attribute::TypeExtensions.register(ROM::SQL::Types::PG::JSONB) do
|
|
41
|
-
# def contain(type, expr, keys)
|
|
42
|
-
# Attribute[Types::Bool].meta(sql_expr: expr.pg_jsonb.contains(value))
|
|
43
|
-
# end
|
|
44
|
-
# end
|
|
45
|
-
#
|
|
46
|
-
# @param [Dry::Types::Type] type Type
|
|
47
|
-
#
|
|
48
|
-
# @api public
|
|
49
|
-
def register(type, &block)
|
|
50
|
-
extensions = @types[type.meta[:database]]
|
|
51
|
-
db_type = type.meta[:db_type]
|
|
52
|
-
|
|
53
|
-
raise ArgumentError, "Type #{ type } already registered" if @types.key?(type)
|
|
54
|
-
mod = Module.new(&block)
|
|
55
|
-
ctx = Object.new.extend(mod)
|
|
56
|
-
functions = mod.public_instance_methods.each_with_object({}) { |m, ms| ms[m] = ctx.method(m) }
|
|
57
|
-
extensions[db_type] = functions
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
@types = ::Hash.new do |hash, database|
|
|
62
|
-
hash[database] = {}
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
22
|
extend Dry::Core::Cache
|
|
67
23
|
|
|
68
24
|
# @api private
|
|
@@ -104,12 +60,12 @@ module ROM
|
|
|
104
60
|
# @return [SQL::Attribute]
|
|
105
61
|
#
|
|
106
62
|
# @api public
|
|
107
|
-
def qualified
|
|
63
|
+
def qualified(table_alias = nil)
|
|
108
64
|
return self if qualified?
|
|
109
65
|
|
|
110
66
|
case sql_expr
|
|
111
67
|
when Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier
|
|
112
|
-
type = meta(qualified: true)
|
|
68
|
+
type = meta(qualified: table_alias || true)
|
|
113
69
|
type.meta(sql_expr: type.to_sql_name)
|
|
114
70
|
else
|
|
115
71
|
raise QualifyError, "can't qualify #{name.inspect} (#{sql_expr.inspect})"
|
|
@@ -155,7 +111,7 @@ module ROM
|
|
|
155
111
|
#
|
|
156
112
|
# @api public
|
|
157
113
|
def qualified?
|
|
158
|
-
meta[:qualified].equal?(true)
|
|
114
|
+
meta[:qualified].equal?(true) || meta[:qualified].is_a?(Symbol)
|
|
159
115
|
end
|
|
160
116
|
|
|
161
117
|
# Return a new attribute marked as a FK
|
|
@@ -188,9 +144,9 @@ module ROM
|
|
|
188
144
|
def to_sym
|
|
189
145
|
@_to_sym ||=
|
|
190
146
|
if qualified? && aliased?
|
|
191
|
-
:"#{
|
|
147
|
+
:"#{table_name}__#{name}___#{meta[:alias]}"
|
|
192
148
|
elsif qualified?
|
|
193
|
-
:"#{
|
|
149
|
+
:"#{table_name}__#{name}"
|
|
194
150
|
elsif aliased?
|
|
195
151
|
:"#{name}___#{meta[:alias]}"
|
|
196
152
|
else
|
|
@@ -319,9 +275,9 @@ module ROM
|
|
|
319
275
|
def to_sql_name
|
|
320
276
|
@_to_sql_name ||=
|
|
321
277
|
if qualified? && aliased?
|
|
322
|
-
Sequel.qualify(
|
|
278
|
+
Sequel.qualify(table_name, name).as(meta[:alias])
|
|
323
279
|
elsif qualified?
|
|
324
|
-
Sequel.qualify(
|
|
280
|
+
Sequel.qualify(table_name, name)
|
|
325
281
|
elsif aliased?
|
|
326
282
|
Sequel.as(name, meta[:alias])
|
|
327
283
|
else
|
|
@@ -329,6 +285,27 @@ module ROM
|
|
|
329
285
|
end
|
|
330
286
|
end
|
|
331
287
|
|
|
288
|
+
# @api public
|
|
289
|
+
def indexed?
|
|
290
|
+
!indexes.empty?
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# @api public
|
|
294
|
+
def indexes
|
|
295
|
+
if meta[:index] == true
|
|
296
|
+
INDEXED
|
|
297
|
+
else
|
|
298
|
+
meta[:index] || EMPTY_SET
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
# @api private
|
|
303
|
+
def meta_ast
|
|
304
|
+
meta = super
|
|
305
|
+
meta[:index] = indexes if indexed?
|
|
306
|
+
meta
|
|
307
|
+
end
|
|
308
|
+
|
|
332
309
|
private
|
|
333
310
|
|
|
334
311
|
# Return Sequel Expression object for an attribute
|
|
@@ -372,6 +349,19 @@ module ROM
|
|
|
372
349
|
type[value]
|
|
373
350
|
end
|
|
374
351
|
end
|
|
352
|
+
|
|
353
|
+
# Return source table name or its alias
|
|
354
|
+
#
|
|
355
|
+
# @api private
|
|
356
|
+
def table_name
|
|
357
|
+
if qualified? && meta[:qualified].is_a?(Symbol)
|
|
358
|
+
meta[:qualified]
|
|
359
|
+
else
|
|
360
|
+
source.dataset
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
memoize :joined, :to_sql_name, :table_name, :canonical
|
|
375
365
|
end
|
|
376
366
|
end
|
|
377
367
|
end
|