rom-sql 3.0.1 → 3.3.2
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 +428 -297
- data/LICENSE +20 -0
- data/README.md +14 -56
- data/lib/rom-sql.rb +2 -0
- data/lib/rom/plugins/relation/sql/auto_restrictions.rb +2 -0
- data/lib/rom/plugins/relation/sql/instrumentation.rb +2 -0
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +6 -7
- data/lib/rom/plugins/relation/sql/postgres/full_text_search.rb +53 -0
- data/lib/rom/plugins/relation/sql/postgres/streaming.rb +97 -0
- data/lib/rom/sql.rb +2 -0
- data/lib/rom/sql/associations.rb +2 -0
- data/lib/rom/sql/associations/core.rb +10 -0
- data/lib/rom/sql/associations/many_to_many.rb +3 -1
- data/lib/rom/sql/associations/many_to_one.rb +2 -0
- data/lib/rom/sql/associations/one_to_many.rb +2 -0
- data/lib/rom/sql/associations/one_to_one.rb +2 -0
- data/lib/rom/sql/associations/one_to_one_through.rb +2 -0
- data/lib/rom/sql/associations/self_ref.rb +2 -0
- data/lib/rom/sql/attribute.rb +31 -22
- data/lib/rom/sql/attribute_aliasing.rb +88 -0
- data/lib/rom/sql/attribute_wrapping.rb +30 -0
- data/lib/rom/sql/commands.rb +2 -0
- data/lib/rom/sql/commands/create.rb +2 -0
- data/lib/rom/sql/commands/delete.rb +2 -0
- data/lib/rom/sql/commands/error_wrapper.rb +2 -0
- data/lib/rom/sql/commands/update.rb +2 -0
- data/lib/rom/sql/dsl.rb +11 -3
- data/lib/rom/sql/error.rb +2 -0
- data/lib/rom/sql/errors.rb +2 -0
- data/lib/rom/sql/extensions.rb +2 -0
- data/lib/rom/sql/extensions/active_support_notifications.rb +2 -0
- data/lib/rom/sql/extensions/mysql.rb +2 -0
- data/lib/rom/sql/extensions/mysql/type_builder.rb +2 -0
- data/lib/rom/sql/extensions/postgres.rb +3 -0
- data/lib/rom/sql/extensions/postgres/commands.rb +3 -1
- data/lib/rom/sql/extensions/postgres/type_builder.rb +6 -4
- data/lib/rom/sql/extensions/postgres/type_serializer.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types/array.rb +7 -6
- data/lib/rom/sql/extensions/postgres/types/array_types.rb +3 -1
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types/json.rb +76 -19
- data/lib/rom/sql/extensions/postgres/types/ltree.rb +25 -23
- data/lib/rom/sql/extensions/postgres/types/network.rb +2 -0
- data/lib/rom/sql/extensions/postgres/types/range.rb +2 -0
- data/lib/rom/sql/extensions/rails_log_subscriber.rb +2 -0
- data/lib/rom/sql/extensions/sqlite.rb +2 -0
- data/lib/rom/sql/extensions/sqlite/type_builder.rb +2 -0
- data/lib/rom/sql/extensions/sqlite/types.rb +2 -0
- data/lib/rom/sql/foreign_key.rb +3 -1
- data/lib/rom/sql/function.rb +38 -6
- data/lib/rom/sql/gateway.rb +9 -1
- data/lib/rom/sql/group_dsl.rb +2 -0
- data/lib/rom/sql/index.rb +2 -0
- data/lib/rom/sql/join_dsl.rb +2 -0
- data/lib/rom/sql/mapper_compiler.rb +12 -1
- data/lib/rom/sql/migration.rb +5 -3
- data/lib/rom/sql/migration/inline_runner.rb +2 -0
- data/lib/rom/sql/migration/migrator.rb +4 -2
- data/lib/rom/sql/migration/recorder.rb +2 -0
- data/lib/rom/sql/migration/runner.rb +4 -2
- data/lib/rom/sql/migration/schema_diff.rb +2 -0
- data/lib/rom/sql/migration/template.rb +2 -0
- data/lib/rom/sql/migration/writer.rb +12 -4
- data/lib/rom/sql/order_dsl.rb +2 -0
- data/lib/rom/sql/plugin/associates.rb +4 -2
- data/lib/rom/sql/plugin/nullify.rb +37 -0
- data/lib/rom/sql/plugin/pagination.rb +2 -0
- data/lib/rom/sql/plugins.rb +4 -0
- data/lib/rom/sql/projection_dsl.rb +3 -1
- data/lib/rom/sql/rake_task.rb +2 -0
- data/lib/rom/sql/relation.rb +3 -1
- data/lib/rom/sql/relation/reading.rb +32 -6
- data/lib/rom/sql/relation/writing.rb +2 -0
- data/lib/rom/sql/restriction_dsl.rb +9 -1
- data/lib/rom/sql/schema.rb +16 -2
- data/lib/rom/sql/schema/attributes_inferrer.rb +5 -3
- data/lib/rom/sql/schema/dsl.rb +3 -1
- data/lib/rom/sql/schema/index_dsl.rb +5 -2
- data/lib/rom/sql/schema/inferrer.rb +12 -8
- data/lib/rom/sql/schema/type_builder.rb +4 -2
- data/lib/rom/sql/spec/support.rb +5 -3
- data/lib/rom/sql/tasks/migration_tasks.rake +16 -11
- data/lib/rom/sql/transaction.rb +2 -0
- data/lib/rom/sql/type_dsl.rb +2 -0
- data/lib/rom/sql/type_extensions.rb +4 -4
- data/lib/rom/sql/type_serializer.rb +2 -0
- data/lib/rom/sql/types.rb +2 -0
- data/lib/rom/sql/version.rb +3 -1
- data/lib/rom/sql/wrap.rb +2 -0
- data/lib/rom/types/values.rb +2 -0
- metadata +34 -32
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2015-2021 rom-rb team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,70 +1,28 @@
|
|
|
1
1
|
[gem]: https://rubygems.org/gems/rom-sql
|
|
2
|
-
[
|
|
3
|
-
[
|
|
4
|
-
[inchpages]: http://inch-ci.org/github/rom-rb/rom-sql
|
|
2
|
+
[actions]: https://github.com/rom-rb/rom-sql/actions
|
|
3
|
+
[codacy]: https://www.codacy.com/gh/rom-rb/rom-sql
|
|
5
4
|
[chat]: https://rom-rb.zulipchat.com
|
|
5
|
+
[inchpages]: http://inch-ci.org/github/rom-rb/rom-sql
|
|
6
6
|
|
|
7
|
-
# rom-sql [][chat]
|
|
8
8
|
|
|
9
9
|
[][gem]
|
|
10
|
-
[][actions]
|
|
11
|
+
[][codacy]
|
|
12
|
+
[][codacy]
|
|
13
13
|
[][inchpages]
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Resources:
|
|
18
|
-
|
|
19
|
-
- [User Documentation](http://rom-rb.org/learn/sql/)
|
|
20
|
-
- [API Documentation](http://rubydoc.info/gems/rom-sql)
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
Add this line to your application's Gemfile:
|
|
25
|
-
|
|
26
|
-
```ruby
|
|
27
|
-
gem 'rom-sql'
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
And then execute:
|
|
31
|
-
|
|
32
|
-
$ bundle
|
|
33
|
-
|
|
34
|
-
Or install it yourself as:
|
|
35
|
-
|
|
36
|
-
$ gem install rom-sql
|
|
37
|
-
|
|
38
|
-
## Docker
|
|
39
|
-
|
|
40
|
-
### Development
|
|
41
|
-
|
|
42
|
-
In order to have reproducible environment for development, Docker can be used. Provided it's installed, in order to start developing, one can simply execute:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
docker-compose run --rm gem "bash"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
If this is the first time this command is executed, it will take some time to set up the dependencies and build the rom-sql container. This should happen only on first execution and in case dependency images are removed.
|
|
49
|
-
|
|
50
|
-
After dependencies are set container will be started in a bash shell.
|
|
51
|
-
|
|
52
|
-
### Testing
|
|
53
|
-
|
|
54
|
-
In order to test the changes, execute:
|
|
15
|
+
## Links
|
|
55
16
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
docker-compose run --rm gem 'rspec'
|
|
59
|
-
```
|
|
17
|
+
* [User documentation](http://rom-rb.org/learn/sql)
|
|
18
|
+
* [API documentation](http://rubydoc.info/gems/rom-sql)
|
|
60
19
|
|
|
61
|
-
|
|
20
|
+
## Supported Ruby versions
|
|
62
21
|
|
|
63
|
-
|
|
22
|
+
This library officially supports the following Ruby versions:
|
|
64
23
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
```
|
|
24
|
+
* MRI >= `2.5`
|
|
25
|
+
* jruby >= `9.2`
|
|
68
26
|
|
|
69
27
|
## License
|
|
70
28
|
|
data/lib/rom-sql.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ROM
|
|
2
4
|
module Plugins
|
|
3
5
|
module Relation
|
|
@@ -24,14 +26,11 @@ module ROM
|
|
|
24
26
|
#
|
|
25
27
|
# @api public
|
|
26
28
|
def explain(format: :text, **options)
|
|
27
|
-
bool_options = options.map { |opt, value| "#{
|
|
28
|
-
format_option = "FORMAT #{
|
|
29
|
+
bool_options = options.map { |opt, value| "#{opt.to_s.upcase} #{!!value}" }
|
|
30
|
+
format_option = "FORMAT #{format.to_s.upcase}"
|
|
31
|
+
explain_value = [format_option, *bool_options].join(', ')
|
|
29
32
|
|
|
30
|
-
query =
|
|
31
|
-
"EXPLAIN (" <<
|
|
32
|
-
[format_option, *bool_options].join(', ') <<
|
|
33
|
-
") " <<
|
|
34
|
-
dataset.sql
|
|
33
|
+
query = "EXPLAIN (#{explain_value}) #{dataset.sql}"
|
|
35
34
|
|
|
36
35
|
rows = dataset.with_sql(query).map(:'QUERY PLAN')
|
|
37
36
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module Plugins
|
|
5
|
+
module Relation
|
|
6
|
+
module SQL
|
|
7
|
+
module Postgres
|
|
8
|
+
# PG-specific extensions which adds `Relation#full_text_search` method
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module FullTextSearch
|
|
12
|
+
# Run a full text search on PostgreSQL.
|
|
13
|
+
# By default, searching for the inclusion of any of the terms in any of the cols.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# posts.full_text_search([:title, :content], 'apples', language: 'english') # => Relation which match the 'apples' phrase
|
|
17
|
+
#
|
|
18
|
+
# @option :headline [String] Append a expression to the selected columns aliased to headline that contains an extract of the matched text.
|
|
19
|
+
#
|
|
20
|
+
# @option :language [String] The language to use for the search (default: 'simple')
|
|
21
|
+
#
|
|
22
|
+
# @option :plain [Boolean] Whether a plain search should be used (default: false). In this case, terms should be a single string, and it will do a search where cols contains all of the words in terms. This ignores search operators in terms.
|
|
23
|
+
#
|
|
24
|
+
# @option :phrase [Boolean] Similar to :plain, but also adding an ILIKE filter to ensure that returned rows also include the exact phrase used.
|
|
25
|
+
#
|
|
26
|
+
# @option :rank [Boolean] Set to true to order by the rank, so that closer matches are returned first.
|
|
27
|
+
#
|
|
28
|
+
# @option :to_tsquery [Symbol] Can be set to :plain or :phrase to specify the function to use to convert the terms to a ts_query.
|
|
29
|
+
#
|
|
30
|
+
# @option :tsquery [Boolean] Specifies the terms argument is already a valid SQL expression returning a tsquery, and can be used directly in the query.
|
|
31
|
+
#
|
|
32
|
+
# @option :tsvector [Boolean] Specifies the cols argument is already a valid SQL expression returning a tsvector, and can be used directly in the query.
|
|
33
|
+
#
|
|
34
|
+
# @return [Relation]
|
|
35
|
+
#
|
|
36
|
+
# @see https://www.postgresql.org/docs/current/textsearch.html PostgreSQL docs
|
|
37
|
+
#
|
|
38
|
+
# @api public
|
|
39
|
+
def full_text_search(*args, &block)
|
|
40
|
+
new dataset.__send__(__method__, *args, &block)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
ROM.plugins do
|
|
50
|
+
adapter :sql do
|
|
51
|
+
register :pg_full_text_search, ROM::Plugins::Relation::SQL::Postgres::FullTextSearch, type: :relation
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module Plugins
|
|
5
|
+
module Relation
|
|
6
|
+
module SQL
|
|
7
|
+
module Postgres
|
|
8
|
+
# PG-specific extensions which adds `Relation#stream` method
|
|
9
|
+
#
|
|
10
|
+
# @api public
|
|
11
|
+
module Streaming
|
|
12
|
+
extend Notifications::Listener
|
|
13
|
+
|
|
14
|
+
class StreamingNotSupportedError < StandardError; end
|
|
15
|
+
|
|
16
|
+
subscribe("configuration.gateway.connected") do |opts|
|
|
17
|
+
conn = opts[:connection]
|
|
18
|
+
|
|
19
|
+
next unless conn.database_type.to_sym == :postgres
|
|
20
|
+
|
|
21
|
+
next if defined?(JRUBY_VERSION)
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
require "sequel_pg"
|
|
25
|
+
rescue LoadError
|
|
26
|
+
raise StreamingNotSupportedError, "add sequel_pg to Gemfile to use pg_streaming"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
unless Sequel::Postgres.supports_streaming?
|
|
30
|
+
raise StreamingNotSupportedError, "postgres version does not support streaming"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
conn.extension(:pg_streaming)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.included(klass)
|
|
37
|
+
super
|
|
38
|
+
ROM::Relation::Graph.include(Combined)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if defined?(JRUBY_VERSION)
|
|
42
|
+
# Allows you to stream returned rows one at a time, instead of
|
|
43
|
+
# collecting the entire result set in memory. Requires the `sequel_pg` gem
|
|
44
|
+
#
|
|
45
|
+
# @see https://github.com/jeremyevans/sequel_pg#streaming- sequel_pg docs
|
|
46
|
+
#
|
|
47
|
+
# @example
|
|
48
|
+
# posts.steam_each { |post| puts CSV.generate_line(post) }
|
|
49
|
+
#
|
|
50
|
+
# @return [Relation]
|
|
51
|
+
#
|
|
52
|
+
# @api publicY_VERSION
|
|
53
|
+
def stream_each
|
|
54
|
+
raise StreamingNotSupportedError, "not supported on jruby"
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
# Allows you to stream returned rows one at a time, instead of
|
|
58
|
+
# collecting the entire result set in memory. Requires the `sequel_pg` gem
|
|
59
|
+
#
|
|
60
|
+
# @see https://github.com/jeremyevans/sequel_pg#streaming- sequel_pg docs
|
|
61
|
+
#
|
|
62
|
+
# @example
|
|
63
|
+
# posts.steam_each { |post| puts CSV.generate_line(post) }
|
|
64
|
+
#
|
|
65
|
+
# @return [Relation]
|
|
66
|
+
#
|
|
67
|
+
# @api public
|
|
68
|
+
def stream_each
|
|
69
|
+
return to_enum unless block_given?
|
|
70
|
+
|
|
71
|
+
ds = dataset.stream
|
|
72
|
+
|
|
73
|
+
if auto_map?
|
|
74
|
+
ds.each { |tuple| yield(mapper.([output_schema[tuple]]).first) }
|
|
75
|
+
else
|
|
76
|
+
ds.each { |tuple| yield(output_schema[tuple]) }
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
module Combined
|
|
81
|
+
def stream_each
|
|
82
|
+
raise StreamingNotSupportedError, "not supported on combined relations"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
ROM.plugins do
|
|
94
|
+
adapter :sql do
|
|
95
|
+
register :pg_streaming, ROM::Plugins::Relation::SQL::Postgres::Streaming, type: :relation
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/rom/sql.rb
CHANGED
data/lib/rom/sql/associations.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ROM
|
|
2
4
|
module SQL
|
|
3
5
|
module Associations
|
|
@@ -14,6 +16,14 @@ module ROM
|
|
|
14
16
|
|
|
15
17
|
target.where(target_key => target_pks)
|
|
16
18
|
end
|
|
19
|
+
|
|
20
|
+
# @api private
|
|
21
|
+
def wrapped
|
|
22
|
+
new_target = view ? target.send(view) : target
|
|
23
|
+
to_wrap = self.class.allocate
|
|
24
|
+
to_wrap.send(:initialize, definition, **options, target: new_target)
|
|
25
|
+
to_wrap.wrap
|
|
26
|
+
end
|
|
17
27
|
end
|
|
18
28
|
end
|
|
19
29
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'rom/associations/many_to_many'
|
|
2
4
|
require 'rom/sql/associations/core'
|
|
3
5
|
require 'rom/sql/associations/self_ref'
|
|
@@ -18,7 +20,7 @@ module ROM
|
|
|
18
20
|
if target != self.target
|
|
19
21
|
target.schema.merge(join_schema)
|
|
20
22
|
else
|
|
21
|
-
left.schema.project(*columns)
|
|
23
|
+
left.schema.uniq.project(*columns)
|
|
22
24
|
end
|
|
23
25
|
else
|
|
24
26
|
target_schema
|
data/lib/rom/sql/attribute.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'sequel/core'
|
|
2
4
|
require 'dry/core/cache'
|
|
3
5
|
|
|
@@ -5,6 +7,8 @@ require 'rom/attribute'
|
|
|
5
7
|
|
|
6
8
|
require 'rom/sql/type_extensions'
|
|
7
9
|
require 'rom/sql/projection_dsl'
|
|
10
|
+
require 'rom/sql/attribute_wrapping'
|
|
11
|
+
require 'rom/sql/attribute_aliasing'
|
|
8
12
|
|
|
9
13
|
module ROM
|
|
10
14
|
module SQL
|
|
@@ -12,34 +16,24 @@ module ROM
|
|
|
12
16
|
#
|
|
13
17
|
# @api public
|
|
14
18
|
class Attribute < ROM::Attribute
|
|
19
|
+
include AttributeWrapping
|
|
20
|
+
include AttributeAliasing
|
|
21
|
+
|
|
15
22
|
OPERATORS = %i[>= <= > <].freeze
|
|
16
23
|
NONSTANDARD_EQUALITY_VALUES = [true, false, nil].freeze
|
|
17
|
-
META_KEYS = %i
|
|
24
|
+
META_KEYS = %i[index foreign_key target sql_expr qualified].freeze
|
|
18
25
|
|
|
19
26
|
# Error raised when an attribute cannot be qualified
|
|
20
27
|
QualifyError = Class.new(StandardError)
|
|
21
28
|
|
|
22
29
|
extend Dry::Core::Cache
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# Return a new attribute with an alias
|
|
30
|
-
#
|
|
31
|
-
# @example
|
|
32
|
-
# users[:id].aliased(:user_id)
|
|
33
|
-
#
|
|
34
|
-
# @return [SQL::Attribute]
|
|
35
|
-
#
|
|
36
|
-
# @api public
|
|
37
|
-
def aliased(alias_name)
|
|
38
|
-
super.with(name: name || alias_name).meta(
|
|
39
|
-
sql_expr: sql_expr.as(alias_name)
|
|
40
|
-
)
|
|
31
|
+
class << self
|
|
32
|
+
# @api private
|
|
33
|
+
def [](type, options = EMPTY_HASH)
|
|
34
|
+
fetch_or_store([type, options]) { new(type, **options) }
|
|
35
|
+
end
|
|
41
36
|
end
|
|
42
|
-
alias_method :as, :aliased
|
|
43
37
|
|
|
44
38
|
# Return a new attribute in its canonical form
|
|
45
39
|
#
|
|
@@ -73,6 +67,21 @@ module ROM
|
|
|
73
67
|
end
|
|
74
68
|
end
|
|
75
69
|
|
|
70
|
+
# Return a new attribute that is aliased and marked as qualified
|
|
71
|
+
#
|
|
72
|
+
# Intended to be used when passing attributes to `dataset#select`
|
|
73
|
+
#
|
|
74
|
+
# @return [SQL::Attribute]
|
|
75
|
+
#
|
|
76
|
+
# @api public
|
|
77
|
+
def qualified_projection(table_alias = nil)
|
|
78
|
+
if aliased?
|
|
79
|
+
qualified(table_alias).aliased(self.alias)
|
|
80
|
+
else
|
|
81
|
+
qualified(table_alias)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
76
85
|
# Return a new attribute marked as joined
|
|
77
86
|
#
|
|
78
87
|
# Whenever you join two schemas, the right schema's attribute
|
|
@@ -291,11 +300,11 @@ module ROM
|
|
|
291
300
|
# @api private
|
|
292
301
|
def to_sql_name
|
|
293
302
|
@_to_sql_name ||=
|
|
294
|
-
if qualified? &&
|
|
303
|
+
if qualified? && aliased_projection?
|
|
295
304
|
Sequel.qualify(table_name, name).as(self.alias)
|
|
296
305
|
elsif qualified?
|
|
297
306
|
Sequel.qualify(table_name, name)
|
|
298
|
-
elsif
|
|
307
|
+
elsif aliased_projection?
|
|
299
308
|
Sequel.as(name, self.alias)
|
|
300
309
|
else
|
|
301
310
|
Sequel[name]
|
|
@@ -328,7 +337,7 @@ module ROM
|
|
|
328
337
|
cleaned_meta = meta.reject { |k, _| META_KEYS.include?(k) }
|
|
329
338
|
type = optional? ? right : self.type
|
|
330
339
|
|
|
331
|
-
self.class.new(type.with(meta: cleaned_meta), options)
|
|
340
|
+
self.class.new(type.with(meta: cleaned_meta), **options)
|
|
332
341
|
end
|
|
333
342
|
|
|
334
343
|
# Wrap a value with the type, it allows using attribute and type specific methods
|