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
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
module ROM
|
|
2
|
-
module Plugins
|
|
3
|
-
module Relation
|
|
4
|
-
module SQL
|
|
5
|
-
# @api private
|
|
6
|
-
module AutoCombine
|
|
7
|
-
# @api private
|
|
8
|
-
def self.included(klass)
|
|
9
|
-
super
|
|
10
|
-
klass.class_eval do
|
|
11
|
-
include(InstanceInterface)
|
|
12
|
-
extend(ClassInterface)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# @api private
|
|
17
|
-
module ClassInterface
|
|
18
|
-
# @api private
|
|
19
|
-
def inherited(klass)
|
|
20
|
-
super
|
|
21
|
-
klass.auto_curry :for_combine
|
|
22
|
-
klass.auto_curry :preload
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# @api private
|
|
27
|
-
module InstanceInterface
|
|
28
|
-
# Default methods for fetching combined relation
|
|
29
|
-
#
|
|
30
|
-
# This method is used by default by `combine`
|
|
31
|
-
#
|
|
32
|
-
# @return [SQL::Relation]
|
|
33
|
-
#
|
|
34
|
-
# @api private
|
|
35
|
-
def for_combine(spec)
|
|
36
|
-
case spec
|
|
37
|
-
when ROM::SQL::Association
|
|
38
|
-
spec.call(__registry__, self).preload(spec)
|
|
39
|
-
else
|
|
40
|
-
preload(spec)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# @api private
|
|
45
|
-
def preload(spec, source)
|
|
46
|
-
case spec
|
|
47
|
-
when ROM::SQL::Association::ManyToOne
|
|
48
|
-
pk = source.source[source.source.primary_key].qualified
|
|
49
|
-
|
|
50
|
-
where(pk => source.pluck(pk.name))
|
|
51
|
-
when Hash, ROM::SQL::Association
|
|
52
|
-
source_key, target_key = spec.is_a?(Hash) ? spec.flatten(1) : spec.join_keys(__registry__).flatten(1)
|
|
53
|
-
|
|
54
|
-
target_pks = source.pluck(source_key.to_sym)
|
|
55
|
-
target_pks.uniq!
|
|
56
|
-
|
|
57
|
-
where(target_key => target_pks)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
ROM.plugins do
|
|
68
|
-
adapter :sql do
|
|
69
|
-
register :auto_combine, ROM::Plugins::Relation::SQL::AutoCombine, type: :relation
|
|
70
|
-
end
|
|
71
|
-
end
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
module ROM
|
|
2
|
-
module Plugins
|
|
3
|
-
module Relation
|
|
4
|
-
module SQL
|
|
5
|
-
# @api private
|
|
6
|
-
module AutoWrap
|
|
7
|
-
# @api private
|
|
8
|
-
def self.included(klass)
|
|
9
|
-
super
|
|
10
|
-
klass.class_eval do
|
|
11
|
-
include(InstanceInterface)
|
|
12
|
-
extend(ClassInterface)
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# @api private
|
|
17
|
-
module ClassInterface
|
|
18
|
-
# @api private
|
|
19
|
-
def inherited(klass)
|
|
20
|
-
super
|
|
21
|
-
klass.auto_curry :for_wrap
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# @api private
|
|
26
|
-
module InstanceInterface
|
|
27
|
-
# Default methods for fetching wrapped relation
|
|
28
|
-
#
|
|
29
|
-
# This method is used by default by `wrap` and `wrap_parents`
|
|
30
|
-
#
|
|
31
|
-
# @return [SQL::Relation]
|
|
32
|
-
#
|
|
33
|
-
# @api private
|
|
34
|
-
def for_wrap(keys, name)
|
|
35
|
-
rel, other =
|
|
36
|
-
if associations.key?(name)
|
|
37
|
-
assoc = associations[name]
|
|
38
|
-
other = __registry__[assoc.target.relation]
|
|
39
|
-
|
|
40
|
-
[assoc.join(__registry__, :inner_join, self, other), other]
|
|
41
|
-
else
|
|
42
|
-
# TODO: deprecate this before 2.0
|
|
43
|
-
other = __registry__[name]
|
|
44
|
-
other_dataset = other.name.dataset
|
|
45
|
-
|
|
46
|
-
[qualified.inner_join(other_dataset, keys), other]
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
rel.schema.merge(other.schema.wrap).qualified.(rel)
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
ROM.plugins do
|
|
59
|
-
adapter :sql do
|
|
60
|
-
register :auto_wrap, ROM::Plugins::Relation::SQL::AutoWrap, type: :relation
|
|
61
|
-
end
|
|
62
|
-
end
|
data/lib/rom/sql/association.rb
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
require 'dry/core/constants'
|
|
2
|
-
require 'dry/core/class_attributes'
|
|
3
|
-
|
|
4
|
-
require 'rom/types'
|
|
5
|
-
require 'rom/initializer'
|
|
6
|
-
require 'rom/sql/qualified_attribute'
|
|
7
|
-
require 'rom/sql/association/name'
|
|
8
|
-
|
|
9
|
-
module ROM
|
|
10
|
-
module SQL
|
|
11
|
-
# Abstract association class
|
|
12
|
-
#
|
|
13
|
-
# @api public
|
|
14
|
-
class Association
|
|
15
|
-
include Dry::Core::Constants
|
|
16
|
-
include Dry::Equalizer(:source, :target, :result)
|
|
17
|
-
extend Initializer
|
|
18
|
-
extend Dry::Core::ClassAttributes
|
|
19
|
-
|
|
20
|
-
defines :result
|
|
21
|
-
|
|
22
|
-
# @!attribute [r] source
|
|
23
|
-
# @return [ROM::Relation::Name] the source relation name
|
|
24
|
-
param :source
|
|
25
|
-
|
|
26
|
-
# @!attribute [r] target
|
|
27
|
-
# @return [ROM::Relation::Name] the target relation name
|
|
28
|
-
param :target
|
|
29
|
-
|
|
30
|
-
# @!attribute [r] relation
|
|
31
|
-
# @return [Symbol] an optional relation identifier for the target
|
|
32
|
-
option :relation, Types::Strict::Symbol, optional: true
|
|
33
|
-
|
|
34
|
-
# @!attribute [r] result
|
|
35
|
-
# @return [Symbol] either :one or :many
|
|
36
|
-
option :result, Types::Strict::Symbol, default: -> { self.class.result }
|
|
37
|
-
|
|
38
|
-
# @!attribute [r] as
|
|
39
|
-
# @return [Symbol] an optional association alias name
|
|
40
|
-
option :as, Types::Strict::Symbol, default: -> { target.to_sym }
|
|
41
|
-
|
|
42
|
-
# @!attribute [r] foreign_key
|
|
43
|
-
# @return [Symbol] an optional association alias name
|
|
44
|
-
option :foreign_key, Types::Optional::Strict::Symbol, optional: true
|
|
45
|
-
|
|
46
|
-
# @!attribute [r] view
|
|
47
|
-
# @return [Symbol] An optional view that should be used to extend assoc relation
|
|
48
|
-
option :view, optional: true
|
|
49
|
-
|
|
50
|
-
alias_method :name, :as
|
|
51
|
-
|
|
52
|
-
# @api public
|
|
53
|
-
def self.new(source, target, options = EMPTY_HASH)
|
|
54
|
-
super(
|
|
55
|
-
Name[source],
|
|
56
|
-
Name[options[:relation] || target, target, options[:as] || target],
|
|
57
|
-
options
|
|
58
|
-
)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# @api public
|
|
62
|
-
def join(relations, type, source = relations[self.source], target = relations[self.target])
|
|
63
|
-
source.__send__(type, target.name.dataset, join_keys(relations)).qualified
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Returns a qualified attribute name for a given dataset
|
|
67
|
-
#
|
|
68
|
-
# This is compatible with Sequel's SQL generator and can be used in query
|
|
69
|
-
# DSL methods
|
|
70
|
-
#
|
|
71
|
-
# @param name [ROM::Relation::Name]
|
|
72
|
-
# @param attribute [Symbol]
|
|
73
|
-
#
|
|
74
|
-
# @return [QualifiedAttribute]
|
|
75
|
-
#
|
|
76
|
-
# @api public
|
|
77
|
-
def qualify(name, attribute)
|
|
78
|
-
QualifiedAttribute[name.to_sym, attribute]
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# @api protected
|
|
82
|
-
def apply_view(schema, relation)
|
|
83
|
-
view_rel = relation.public_send(view)
|
|
84
|
-
schema.merge(view_rel.schema.qualified).uniq(&:to_sql_name).(view_rel)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# @api private
|
|
88
|
-
def join_key_map(relations)
|
|
89
|
-
join_keys(relations).to_a.flatten.map(&:to_sym)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def self_ref?
|
|
93
|
-
source.dataset == target.dataset
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
require 'rom/sql/association/one_to_many'
|
|
100
|
-
require 'rom/sql/association/one_to_one'
|
|
101
|
-
require 'rom/sql/association/many_to_many'
|
|
102
|
-
require 'rom/sql/association/many_to_one'
|
|
103
|
-
require 'rom/sql/association/one_to_one_through'
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
require 'rom/types'
|
|
2
|
-
|
|
3
|
-
module ROM
|
|
4
|
-
module SQL
|
|
5
|
-
class Association
|
|
6
|
-
class ManyToMany < Association
|
|
7
|
-
result :many
|
|
8
|
-
|
|
9
|
-
option :through, type: Types::Strict::Symbol.optional
|
|
10
|
-
|
|
11
|
-
# @api private
|
|
12
|
-
def initialize(*)
|
|
13
|
-
super
|
|
14
|
-
@through = Relation::Name[
|
|
15
|
-
options[:through] || options[:through_relation], options[:through]
|
|
16
|
-
]
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# @api public
|
|
20
|
-
def call(relations, target_rel = nil)
|
|
21
|
-
join_rel = join_relation(relations)
|
|
22
|
-
assocs = join_rel.associations
|
|
23
|
-
|
|
24
|
-
left = target_rel ? assocs[target].(relations, target_rel) : assocs[target].(relations)
|
|
25
|
-
right = relations[target.relation]
|
|
26
|
-
|
|
27
|
-
left_fk = foreign_key || join_rel.foreign_key(source.relation)
|
|
28
|
-
|
|
29
|
-
schema =
|
|
30
|
-
if left.schema.key?(left_fk)
|
|
31
|
-
if target_rel
|
|
32
|
-
target_rel.schema.merge(left.schema.project(left_fk))
|
|
33
|
-
else
|
|
34
|
-
left.schema.project(*(right.schema.map(&:name) + [left_fk]))
|
|
35
|
-
end
|
|
36
|
-
else
|
|
37
|
-
right.schema.merge(join_rel.schema.project(left_fk))
|
|
38
|
-
end.qualified
|
|
39
|
-
|
|
40
|
-
relation = left.inner_join(source, join_keys(relations))
|
|
41
|
-
|
|
42
|
-
if view
|
|
43
|
-
apply_view(schema, relation)
|
|
44
|
-
else
|
|
45
|
-
schema.(relation)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
# @api private
|
|
50
|
-
def persist(relations, children, parents)
|
|
51
|
-
join_tuples = associate(relations, children, parents)
|
|
52
|
-
join_relation = join_relation(relations)
|
|
53
|
-
join_relation.multi_insert(join_tuples)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# @api private
|
|
57
|
-
def parent_combine_keys(relations)
|
|
58
|
-
relations[target].associations[source].combine_keys(relations).to_a.flatten(1)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# @api public
|
|
62
|
-
def join(relations, type, source = relations[self.source], target = relations[self.target])
|
|
63
|
-
through_assoc = source.associations[through]
|
|
64
|
-
joined = through_assoc.join(relations, type, source)
|
|
65
|
-
joined.__send__(type, target.name.dataset, join_keys(relations)).qualified
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
# @api public
|
|
69
|
-
def join_keys(relations)
|
|
70
|
-
with_keys(relations) { |source_key, target_key|
|
|
71
|
-
{ qualify(source, source_key) => qualify(through, target_key) }
|
|
72
|
-
}
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
# @api public
|
|
76
|
-
def combine_keys(relations)
|
|
77
|
-
Hash[*with_keys(relations)]
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# @api private
|
|
81
|
-
def associate(relations, children, parent)
|
|
82
|
-
((spk, sfk), (tfk, tpk)) = join_key_map(relations)
|
|
83
|
-
|
|
84
|
-
case parent
|
|
85
|
-
when Array
|
|
86
|
-
parent.map { |p| associate(relations, children, p) }.flatten(1)
|
|
87
|
-
else
|
|
88
|
-
children.map { |tuple|
|
|
89
|
-
{ sfk => tuple.fetch(spk), tfk => parent.fetch(tpk) }
|
|
90
|
-
}
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
# @api private
|
|
95
|
-
def join_relation(relations)
|
|
96
|
-
relations[through.relation]
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
protected
|
|
100
|
-
|
|
101
|
-
# @api private
|
|
102
|
-
def with_keys(relations, &block)
|
|
103
|
-
source_key = relations[source.relation].primary_key
|
|
104
|
-
target_key = foreign_key || relations[through.relation].foreign_key(source.relation)
|
|
105
|
-
return [source_key, target_key] unless block
|
|
106
|
-
yield(source_key, target_key)
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
# @api private
|
|
110
|
-
def join_key_map(relations)
|
|
111
|
-
left = super
|
|
112
|
-
right = join_relation(relations).associations[target].join_key_map(relations)
|
|
113
|
-
|
|
114
|
-
[left, right]
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
module ROM
|
|
2
|
-
module SQL
|
|
3
|
-
class Association
|
|
4
|
-
class ManyToOne < Association
|
|
5
|
-
result :one
|
|
6
|
-
|
|
7
|
-
# @api public
|
|
8
|
-
def call(relations, left = relations[target.relation])
|
|
9
|
-
right = relations[source.relation]
|
|
10
|
-
|
|
11
|
-
left_pk = left.primary_key
|
|
12
|
-
right_fk = left.foreign_key(source.relation)
|
|
13
|
-
|
|
14
|
-
left_schema = left.schema
|
|
15
|
-
right_schema = right.schema.project_pk
|
|
16
|
-
|
|
17
|
-
schema =
|
|
18
|
-
if left.schema.key?(right_fk)
|
|
19
|
-
left_schema
|
|
20
|
-
else
|
|
21
|
-
left_schema.merge(right_schema.project_fk(left_pk => right_fk))
|
|
22
|
-
end.qualified
|
|
23
|
-
|
|
24
|
-
relation = left.inner_join(source_table, join_keys(relations))
|
|
25
|
-
|
|
26
|
-
if view
|
|
27
|
-
apply_view(schema, relation)
|
|
28
|
-
else
|
|
29
|
-
schema.(relation)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# @api public
|
|
34
|
-
def combine_keys(relations)
|
|
35
|
-
Hash[*with_keys(relations)]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# @api public
|
|
39
|
-
def join_keys(relations)
|
|
40
|
-
with_keys(relations) { |source_key, target_key|
|
|
41
|
-
{ qualify(source_alias, source_key) => qualify(target, target_key) }
|
|
42
|
-
}
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# @api private
|
|
46
|
-
def associate(relations, child, parent)
|
|
47
|
-
fk, pk = join_key_map(relations)
|
|
48
|
-
child.merge(fk => parent.fetch(pk))
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
protected
|
|
52
|
-
|
|
53
|
-
# @api private
|
|
54
|
-
def source_table
|
|
55
|
-
self_ref? ? Sequel.as(source.dataset, source_alias) : source
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
# @api private
|
|
59
|
-
def source_alias
|
|
60
|
-
self_ref? ? :"#{source.dataset.to_s[0]}_0" : source
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# @api private
|
|
64
|
-
def with_keys(relations, &block)
|
|
65
|
-
source_key = foreign_key || relations[source.relation].foreign_key(target.relation)
|
|
66
|
-
target_key = relations[target.relation].primary_key
|
|
67
|
-
return [source_key, target_key] unless block
|
|
68
|
-
yield(source_key, target_key)
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
require 'dry/equalizer'
|
|
2
|
-
require 'rom/relation/name'
|
|
3
|
-
require 'dry/core/cache'
|
|
4
|
-
|
|
5
|
-
module ROM
|
|
6
|
-
module SQL
|
|
7
|
-
class Association
|
|
8
|
-
class Name
|
|
9
|
-
include Dry::Equalizer.new(:relation_name, :key)
|
|
10
|
-
|
|
11
|
-
extend Dry::Core::Cache
|
|
12
|
-
|
|
13
|
-
attr_reader :relation_name
|
|
14
|
-
|
|
15
|
-
attr_reader :key
|
|
16
|
-
|
|
17
|
-
alias_method :to_sym, :key
|
|
18
|
-
|
|
19
|
-
def self.[](*args)
|
|
20
|
-
fetch_or_store(args) do
|
|
21
|
-
rel, ds, aliaz = args
|
|
22
|
-
|
|
23
|
-
if rel.is_a?(ROM::Relation::Name)
|
|
24
|
-
new(rel, rel.dataset)
|
|
25
|
-
elsif rel.is_a?(self)
|
|
26
|
-
rel
|
|
27
|
-
elsif aliaz
|
|
28
|
-
new(ROM::Relation::Name[rel, ds], aliaz)
|
|
29
|
-
elsif ds.nil?
|
|
30
|
-
new(ROM::Relation::Name[rel], rel)
|
|
31
|
-
else
|
|
32
|
-
new(ROM::Relation::Name[rel, ds], ds)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def initialize(relation_name, aliaz)
|
|
38
|
-
@relation_name = relation_name
|
|
39
|
-
@aliased = relation_name.dataset != aliaz
|
|
40
|
-
@key = aliased? ? aliaz : relation_name.dataset
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def aliased?
|
|
44
|
-
@aliased
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def inspect
|
|
48
|
-
if aliased?
|
|
49
|
-
"#{self.class}(#{relation_name.to_s} as #{key})"
|
|
50
|
-
else
|
|
51
|
-
"#{self.class}(#{relation_name.to_s})"
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
alias_method :to_s, :inspect
|
|
55
|
-
|
|
56
|
-
def dataset
|
|
57
|
-
relation_name.dataset
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def relation
|
|
61
|
-
relation_name.relation
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def as(aliaz)
|
|
65
|
-
Name[relation_name.relation, relation_name.dataset, aliaz]
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def to_sym
|
|
69
|
-
dataset
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def sql_literal(ds)
|
|
73
|
-
ds.literal(aliased? ? Sequel[dataset] : Sequel.as(dataset, key))
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|