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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -7
  3. data/Gemfile +7 -5
  4. data/lib/rom/plugins/relation/sql/auto_restrictions.rb +11 -17
  5. data/lib/rom/sql.rb +3 -2
  6. data/lib/rom/sql/associations.rb +5 -0
  7. data/lib/rom/sql/associations/core.rb +20 -0
  8. data/lib/rom/sql/associations/many_to_many.rb +83 -0
  9. data/lib/rom/sql/associations/many_to_one.rb +55 -0
  10. data/lib/rom/sql/associations/one_to_many.rb +31 -0
  11. data/lib/rom/sql/{association → associations}/one_to_one.rb +3 -2
  12. data/lib/rom/sql/{association → associations}/one_to_one_through.rb +3 -2
  13. data/lib/rom/sql/associations/self_ref.rb +39 -0
  14. data/lib/rom/sql/attribute.rb +44 -54
  15. data/lib/rom/sql/errors.rb +2 -0
  16. data/lib/rom/sql/extensions/mysql.rb +1 -1
  17. data/lib/rom/sql/extensions/mysql/attributes_inferrer.rb +10 -0
  18. data/lib/rom/sql/extensions/postgres.rb +1 -1
  19. data/lib/rom/sql/extensions/postgres/{inferrer.rb → attributes_inferrer.rb} +4 -4
  20. data/lib/rom/sql/extensions/postgres/types.rb +9 -19
  21. data/lib/rom/sql/extensions/sqlite.rb +1 -1
  22. data/lib/rom/sql/extensions/sqlite/{inferrer.rb → attributes_inferrer.rb} +2 -2
  23. data/lib/rom/sql/gateway.rb +29 -30
  24. data/lib/rom/sql/index.rb +13 -0
  25. data/lib/rom/sql/migration.rb +10 -0
  26. data/lib/rom/sql/migration/inline_runner.rb +86 -0
  27. data/lib/rom/sql/migration/migrator.rb +17 -0
  28. data/lib/rom/sql/migration/schema_diff.rb +177 -0
  29. data/lib/rom/sql/plugin/associates.rb +11 -45
  30. data/lib/rom/sql/plugin/pagination.rb +4 -4
  31. data/lib/rom/sql/relation.rb +22 -42
  32. data/lib/rom/sql/relation/reading.rb +3 -3
  33. data/lib/rom/sql/schema.rb +14 -21
  34. data/lib/rom/sql/schema/associations_dsl.rb +7 -6
  35. data/lib/rom/sql/schema/attributes_inferrer.rb +164 -0
  36. data/lib/rom/sql/schema/inferrer.rb +40 -141
  37. data/lib/rom/sql/type_extensions.rb +44 -0
  38. data/lib/rom/sql/version.rb +1 -1
  39. data/lib/rom/sql/wrap.rb +25 -0
  40. data/rom-sql.gemspec +2 -2
  41. data/spec/integration/{association → associations}/many_to_many/custom_fks_spec.rb +4 -2
  42. data/spec/integration/{association → associations}/many_to_many/from_view_spec.rb +2 -2
  43. data/spec/integration/{association → associations}/many_to_many_spec.rb +25 -30
  44. data/spec/integration/{association → associations}/many_to_one/custom_fks_spec.rb +5 -3
  45. data/spec/integration/{association → associations}/many_to_one/from_view_spec.rb +3 -3
  46. data/spec/integration/{association → associations}/many_to_one/self_ref_spec.rb +2 -2
  47. data/spec/integration/{association → associations}/many_to_one_spec.rb +20 -38
  48. data/spec/integration/{association → associations}/one_to_many/custom_fks_spec.rb +4 -2
  49. data/spec/integration/{association → associations}/one_to_many/from_view_spec.rb +2 -2
  50. data/spec/integration/{association → associations}/one_to_many/self_ref_spec.rb +2 -2
  51. data/spec/integration/{association → associations}/one_to_many_spec.rb +24 -11
  52. data/spec/integration/{association → associations}/one_to_one_spec.rb +13 -9
  53. data/spec/integration/{association → associations}/one_to_one_through_spec.rb +15 -11
  54. data/spec/integration/auto_migrations/errors_spec.rb +31 -0
  55. data/spec/integration/auto_migrations/indexes_spec.rb +109 -0
  56. data/spec/integration/auto_migrations/managing_columns_spec.rb +156 -0
  57. data/spec/integration/auto_migrations/postgres/column_types_spec.rb +63 -0
  58. data/spec/integration/commands/create_spec.rb +2 -4
  59. data/spec/integration/commands/delete_spec.rb +2 -2
  60. data/spec/integration/commands/update_spec.rb +2 -0
  61. data/spec/integration/graph_spec.rb +9 -3
  62. data/spec/integration/plugins/associates_spec.rb +16 -55
  63. data/spec/integration/plugins/auto_restrictions_spec.rb +0 -11
  64. data/spec/integration/relation_schema_spec.rb +49 -25
  65. data/spec/integration/schema/inferrer/postgres_spec.rb +1 -1
  66. data/spec/integration/schema/inferrer_spec.rb +7 -18
  67. data/spec/integration/setup_spec.rb +4 -0
  68. data/spec/integration/{plugins/auto_wrap_spec.rb → wrap_spec.rb} +13 -36
  69. data/spec/shared/accounts.rb +4 -0
  70. data/spec/shared/database_setup.rb +2 -1
  71. data/spec/shared/notes.rb +2 -0
  72. data/spec/shared/posts.rb +2 -0
  73. data/spec/shared/puppies.rb +2 -0
  74. data/spec/shared/relations.rb +2 -2
  75. data/spec/shared/users.rb +2 -0
  76. data/spec/shared/users_and_tasks.rb +4 -0
  77. data/spec/spec_helper.rb +3 -6
  78. data/spec/support/helpers.rb +11 -8
  79. data/spec/support/test_configuration.rb +16 -0
  80. data/spec/unit/plugin/associates_spec.rb +5 -10
  81. data/spec/unit/plugin/pagination_spec.rb +9 -9
  82. data/spec/unit/plugin/timestamp_spec.rb +9 -9
  83. data/spec/unit/relation/dataset_spec.rb +7 -5
  84. data/spec/unit/relation/inner_join_spec.rb +2 -15
  85. data/spec/unit/relation/primary_key_spec.rb +1 -1
  86. data/spec/unit/schema_spec.rb +6 -4
  87. metadata +65 -70
  88. data/lib/rom/plugins/relation/sql/auto_combine.rb +0 -71
  89. data/lib/rom/plugins/relation/sql/auto_wrap.rb +0 -62
  90. data/lib/rom/sql/association.rb +0 -103
  91. data/lib/rom/sql/association/many_to_many.rb +0 -119
  92. data/lib/rom/sql/association/many_to_one.rb +0 -73
  93. data/lib/rom/sql/association/name.rb +0 -78
  94. data/lib/rom/sql/association/one_to_many.rb +0 -60
  95. data/lib/rom/sql/extensions/mysql/inferrer.rb +0 -10
  96. data/lib/rom/sql/qualified_attribute.rb +0 -53
  97. data/lib/rom/sql/schema/dsl.rb +0 -75
  98. data/spec/unit/association/many_to_many_spec.rb +0 -89
  99. data/spec/unit/association/many_to_one_spec.rb +0 -81
  100. data/spec/unit/association/name_spec.rb +0 -68
  101. data/spec/unit/association/one_to_many_spec.rb +0 -82
  102. data/spec/unit/association/one_to_one_spec.rb +0 -83
  103. 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: 930bb93fc7cdf5236b363f9f1f343e400f567e92
4
- data.tar.gz: bc4abbac8eedc26e82b4599ce80657ad99dacab5
3
+ metadata.gz: ff0be19f60330b9224eaf421b85ad113000c1558
4
+ data.tar.gz: 3ccb799110fbc7543f3e9ef9ebd511193c700ab6
5
5
  SHA512:
6
- metadata.gz: 672c4a3ed57a3b3d2de8cb996fddfc0819da3de23af2dbdf6fdb6c962f4d2a5eda7e773e2e8768be403ed0643dd620124e0c3ac8f9c1e841e54d44d7887b0757
7
- data.tar.gz: 9c0573d506286947956602885042246478f1798ba82622f5574f959a7eca5b2eba4487de670cf3655d2ee50365011f487bca2b506c076fd8f0edf95045f54689
6
+ metadata.gz: fe36e8c1a886f3231385d3ff9709aa11a4ad13b63b313ec5fd07fc76af0537327184bef102af03c66331750b76d0edfd7838e1ec4e02e8189ac56f91c7749203
7
+ data.tar.gz: 3192a10d465305f01d780e4db7af846c14c3c09509afb59f5cdad770383234ab59fc80b49431270aa863adeb7a51f7f3867a05c48cdfde084c7ed1ac1ea83a19
data/CHANGELOG.md CHANGED
@@ -1,18 +1,24 @@
1
- ## v1.3.5 2017-10-12
1
+ ## v2.0.0 to-be-released
2
2
 
3
- ### Changed
3
+ ### Added
4
4
 
5
- * Added compatibility with `dry-types` 0.11 (flash-gordon)
5
+ * Support for schema plugins (flash-gordon)
6
+ * Support for auto migrations (flash-gordon)
6
7
 
7
- [Compare v1.3.4..v1.3.5](https://github.com/rom-rb/rom-sql/compare/v1.3.4...v1.3.5)
8
+ ### Changed
8
9
 
9
- ## v1.3.4 2017-09-12
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
- * A warning caused by using `EMPTY_BRACKET` from Sequel (flash-gordon)
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..v1.3.4](https://github.com/rom-rb/rom-sql/compare/v1.3.3...v1.3.4)
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 'rom', git: 'https://github.com/rom-rb/rom.git', branch: 'release-3.0'
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
- EmptySchemaError = Class.new(ArgumentError) do
30
- def initialize(klass)
31
- super("#{klass} relation has no schema. " \
32
- "Make sure :auto_restrictions is enabled after defining a schema")
33
- end
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
- def self.included(klass)
37
- super
38
- schema = klass.schema
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.select { |attr| attr.meta[:index] }
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-equalizer'
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,5 @@
1
+ require 'rom/sql/associations/many_to_many'
2
+ require 'rom/sql/associations/many_to_one'
3
+ require 'rom/sql/associations/one_to_many'
4
+ require 'rom/sql/associations/one_to_one'
5
+ require 'rom/sql/associations/one_to_one_through'
@@ -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
@@ -1,8 +1,9 @@
1
+ require 'rom/sql/associations/one_to_many'
2
+
1
3
  module ROM
2
4
  module SQL
3
- class Association
5
+ module Associations
4
6
  class OneToOne < OneToMany
5
- result :one
6
7
  end
7
8
  end
8
9
  end
@@ -1,8 +1,9 @@
1
+ require 'rom/sql/associations/many_to_many'
2
+
1
3
  module ROM
2
4
  module SQL
3
- class Association
5
+ module Associations
4
6
  class OneToOneThrough < ManyToMany
5
- result :one
6
7
  end
7
8
  end
8
9
  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
@@ -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
- :"#{source.dataset}__#{name}___#{meta[:alias]}"
147
+ :"#{table_name}__#{name}___#{meta[:alias]}"
192
148
  elsif qualified?
193
- :"#{source.dataset}__#{name}"
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(source.dataset, name).as(meta[:alias])
278
+ Sequel.qualify(table_name, name).as(meta[:alias])
323
279
  elsif qualified?
324
- Sequel.qualify(source.dataset, name)
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