Class: ROM::SQL::Attribute
- Inherits:
-
Attribute
- Object
- Attribute
- ROM::SQL::Attribute
- Extended by:
- Dry::Core::Cache
- Includes:
- AttributeAliasing, AttributeWrapping
- Defined in:
- lib/rom/sql/attribute.rb,
lib/rom/sql/extensions/postgres/types/json.rb,
lib/rom/sql/extensions/postgres/types/array.rb,
lib/rom/sql/extensions/postgres/types/ltree.rb
Overview
Extended schema attributes tailored for SQL databases
Constant Summary collapse
- OPERATORS =
%i[>= <= > <].freeze
- NONSTANDARD_EQUALITY_VALUES =
[true, false, nil].freeze
- META_KEYS =
%i[index foreign_key target sql_expr qualified].freeze
- QualifyError =
Error raised when an attribute cannot be qualified
Class.new(StandardError)
Class Method Summary collapse
Instance Method Summary collapse
-
#! ⇒ Attribute
Negate the attribute’s sql expression.
-
#+(value) ⇒ SQL::Attribute<Types::LTree>
Concatenate two LTree values Translates to ||.
-
#=~(other) ⇒ Attribute
Return a new attribute with an equality expression.
-
#any(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the array includes a value Translates to the ANY operator.
-
#ascendant(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree is a ascendant of the LTree value Translates to the @> operator.
-
#canonical ⇒ Object
Return a new attribute in its canonical form.
-
#case(mapping) ⇒ SQL::Attribute
Build a case expression based on attribute.
-
#concat(other, sep = ' ') ⇒ SQL::Function
Create a CONCAT function from the attribute.
-
#contain(other) ⇒ SQL::Attribute<Types::Bool>
Check whether the array includes another array Translates to the @> operator.
-
#contain_ancestor(value) ⇒ SQL::Attribute<Types::PG::Bool>
Does LTree array contain an ancestor of ltree Translates to @>.
-
#contain_any_ltextquery(value) ⇒ SQL::Attribute<Types::Bool>
Does LTree array contain any path matching ltxtquery Translates to @.
-
#contain_ascendant(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree is a ascendant of the LTree values Translates to the @> operator.
-
#contain_descendant(value) ⇒ SQL::Attribute<Types::PG::Bool>
Does LTree array contain an descendant of ltree Translates to <@.
-
#contained_by(other) ⇒ SQL::Attribute<Types::Bool>
Check whether the array is contained by another array Translates to the <@ operator.
-
#delete(*path) ⇒ SQL::Attribute<Types::PG::JSONB>
Deletes the specified value by key, index, or path Translates to - or #- depending on the number of arguments.
-
#descendant(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree is a descendant of the LTree value Translates to the <@ operator.
-
#find_ancestor(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that is an ancestor of ltree, NULL if none Translates to ?@>.
-
#find_descendant(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that is an descendant of ltree, NULL if none Translates to ?<@.
-
#foreign_key ⇒ SQL::Attribute
Return a new attribute marked as a FK.
-
#func(&block) ⇒ SQL::Function
Create a function DSL from the attribute.
-
#get(idx) ⇒ SQL::Attribute
Get element by index (PG uses 1-based indexing).
-
#get_text(*path) ⇒ SQL::Attribute<Types::String>
Extract the JSON value as text using at the specified path Translates to ->> or #>> depending on the number of arguments.
-
#has_all_keys(*keys) ⇒ SQL::Attribute<Types::Bool>
Does the JSON value have all the specified top-level keys Translates to ?&.
-
#has_any_key(*keys) ⇒ SQL::Attribute<Types::Bool>
Does the JSON value have any of the specified top-level keys Translates to ?|.
-
#has_key(key) ⇒ SQL::Attribute<Types::Bool>
Does the JSON value have the specified top-level key Translates to ?.
-
#in(*args) ⇒ Object
Return a boolean expression with an inclusion test.
-
#indexed ⇒ Object
Returns a new attribute marked as indexed.
- #indexed? ⇒ Boolean
-
#is(other) ⇒ Object
Return a boolean expression with an equality operator.
-
#join(delimiter, null_repr) ⇒ SQL::Attribute<Types::String>
Convert the array to a string by joining values with a delimiter (empty stirng by default) and optional filler for NULL values Translates to an ‘array_to_string` call.
-
#joined ⇒ SQL::Attribute
Return a new attribute marked as joined.
-
#joined? ⇒ Boolean
Return if an attribute was used in a join.
-
#length ⇒ SQL::Attribute<Types::Integer>
Return array size.
-
#match(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree match a lquery value Translates to the ~ operator.
-
#match_any(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree match any of the lquery values Translates to the ? operator.
-
#match_any_lquery(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that matches lquery, NULL if none Translates to ?~.
-
#match_any_ltextquery(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that matches ltextquery, NULL if none Translates to ?@.
-
#match_ltextquery(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree match a ltextquery Translates to the @ operator.
-
#merge(value) ⇒ SQL::Attribute<Types::PG::JSONB>
Concatenate two JSON values Translates to ||.
- #meta_options_ast ⇒ Object private
-
#not(other) ⇒ Object
Return a boolean expression with a negated equality operator.
-
#overlaps(other) ⇒ SQL::Attribute<Types::Bool>
Check whether the arrays have common values Translates to &&.
-
#qualifiable? ⇒ Boolean
Return if an attribute is qualifiable.
-
#qualified(table_alias = nil) ⇒ SQL::Attribute
Return a new attribute marked as qualified.
-
#qualified? ⇒ Boolean
Return if an attribute type is qualified.
-
#qualified_projection(table_alias = nil) ⇒ SQL::Attribute
Return a new attribute that is aliased and marked as qualified.
-
#remove_value(value) ⇒ SQL::Attribute<Types::PG::Array>
Remove elements by value.
-
#sql_literal(ds) ⇒ Object
private
Sequel calls this method to coerce an attribute into SQL string.
-
#to_sql_name ⇒ Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier
private
Sequel column representation.
-
#to_sym ⇒ Symbol
Return symbol representation of an attribute.
-
#unwrap ⇒ Object
private
Removes metadata from the type.
-
#value(value) ⇒ SQL::Attribute
Wrap a value with the type, it allows using attribute and type specific methods on literals and things like this.
Methods included from AttributeAliasing
#aliased, #aliased_projection?
Methods included from AttributeWrapping
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args, &block) ⇒ Object (private)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Delegate to sql expression if it responds to a given method
389 390 391 392 393 394 395 396 397 398 399 |
# File 'lib/rom/sql/attribute.rb', line 389 def method_missing(meth, *args, &block) if OPERATORS.include?(meth) __cmp__(meth, args[0]) elsif extensions.key?(meth) extensions[meth].(type, sql_expr, *args, &block) elsif sql_expr.respond_to?(meth) (sql_expr: sql_expr.__send__(meth, *args, &block)) else super end end |
Class Method Details
.[](type, options = EMPTY_HASH) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
33 34 35 |
# File 'lib/rom/sql/attribute.rb', line 33 def [](type, = EMPTY_HASH) fetch_or_store([type, ]) { new(type, **) } end |
Instance Method Details
#! ⇒ Attribute
Negate the attribute’s sql expression
224 225 226 |
# File 'lib/rom/sql/attribute.rb', line 224 def ! ~self end |
#+(value) ⇒ SQL::Attribute<Types::LTree>
Concatenate two LTree values Translates to ||
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 113
|
#=~(other) ⇒ Attribute
Return a new attribute with an equality expression
198 199 200 |
# File 'lib/rom/sql/attribute.rb', line 198 def =~(other) (sql_expr: sql_expr =~ binary_operation_arg(other)) end |
#any(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the array includes a value Translates to the ANY operator
|
# File 'lib/rom/sql/extensions/postgres/types/array.rb', line 21
|
#ascendant(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree is a ascendant of the LTree value Translates to the @> operator
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 83
|
#canonical ⇒ Object
Return a new attribute in its canonical form
41 42 43 44 45 46 47 |
# File 'lib/rom/sql/attribute.rb', line 41 def canonical if aliased? with(alias: nil).(sql_expr: nil) else self end end |
#case(mapping) ⇒ SQL::Attribute
Build a case expression based on attribute. See SQL::Function#case when you don’t have a specific expression after the CASE keyword. Pass the :else keyword to provide the catch-all case, it’s mandatory because of the Sequel’s API used underneath.
366 367 368 369 370 371 372 373 374 375 |
# File 'lib/rom/sql/attribute.rb', line 366 def case(mapping) mapping = mapping.dup otherwise = mapping.delete(:else) do raise ArgumentError, 'provide the default case using the :else keyword' end type = mapping.values[0].type Attribute[type].(sql_expr: ::Sequel.case(mapping, otherwise, self)) end |
#concat(other, sep = ' ') ⇒ SQL::Function
Create a CONCAT function from the attribute
283 284 285 |
# File 'lib/rom/sql/attribute.rb', line 283 def concat(other, sep = ' ') Function.new(type).concat(self, sep, other) end |
#contain(other) ⇒ SQL::Attribute<Types::Bool>
Check whether the array includes another array Translates to the @> operator
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 2
|
#contain_ancestor(value) ⇒ SQL::Attribute<Types::PG::Bool>
Does LTree array contain an ancestor of ltree Translates to @>
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 123
|
#contain_any_ltextquery(value) ⇒ SQL::Attribute<Types::Bool>
Does LTree array contain any path matching ltxtquery Translates to @
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 110
|
#contain_ascendant(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree is a ascendant of the LTree values Translates to the @> operator
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 69
|
#contain_descendant(value) ⇒ SQL::Attribute<Types::PG::Bool>
Does LTree array contain an descendant of ltree Translates to <@
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 42
|
#contained_by(other) ⇒ SQL::Attribute<Types::Bool>
Check whether the array is contained by another array Translates to the <@ operator
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 17
|
#delete(*path) ⇒ SQL::Attribute<Types::PG::JSONB>
Deletes the specified value by key, index, or path Translates to - or #- depending on the number of arguments
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 118
|
#descendant(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree is a descendant of the LTree value Translates to the <@ operator
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 56
|
#find_ancestor(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that is an ancestor of ltree, NULL if none Translates to ?@>
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 149
|
#find_descendant(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that is an descendant of ltree, NULL if none Translates to ?<@
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 162
|
#foreign_key ⇒ SQL::Attribute
Return a new attribute marked as a FK
141 142 143 |
# File 'lib/rom/sql/attribute.rb', line 141 def foreign_key (foreign_key: true) end |
#func(&block) ⇒ SQL::Function
Create a function DSL from the attribute
266 267 268 |
# File 'lib/rom/sql/attribute.rb', line 266 def func(&block) ProjectionDSL.new(name => self).call(&block).first end |
#get(idx) ⇒ SQL::Attribute
Get element by index (PG uses 1-based indexing)
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 30
|
#get_text(*path) ⇒ SQL::Attribute<Types::String>
Extract the JSON value as text using at the specified path Translates to ->> or #>> depending on the number of arguments
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 45
|
#has_all_keys(*keys) ⇒ SQL::Attribute<Types::Bool>
Does the JSON value have all the specified top-level keys Translates to ?&
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 86
|
#has_any_key(*keys) ⇒ SQL::Attribute<Types::Bool>
Does the JSON value have any of the specified top-level keys Translates to ?|
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 73
|
#has_key(key) ⇒ SQL::Attribute<Types::Bool>
Does the JSON value have the specified top-level key Translates to ?
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 60
|
#in(*args) ⇒ Object
Return a boolean expression with an inclusion test
If the single argument passed to the method is a Range object then the resulting expression will restrict the attribute value with range’s bounds. Upper bound condition will be inclusive/non-inclusive depending on the range type.
If more than one argument is passed to the method or the first argument is not Range then the result will be a simple IN check.
246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/rom/sql/attribute.rb', line 246 def in(*args) if args.first.is_a?(Range) range = args.first lower_cond = __cmp__(:>=, range.begin) upper_cond = __cmp__(range.exclude_end? ? :< : :<=, range.end) Sequel::SQL::BooleanExpression.new(:AND, lower_cond, upper_cond) else __cmp__(:IN, args) end end |
#indexed ⇒ Object
Returns a new attribute marked as indexed
322 323 324 |
# File 'lib/rom/sql/attribute.rb', line 322 def indexed (index: true) end |
#indexed? ⇒ Boolean
315 316 317 |
# File 'lib/rom/sql/attribute.rb', line 315 def indexed? [:index].equal?(true) end |
#is(other) ⇒ Object
Return a boolean expression with an equality operator
186 187 188 |
# File 'lib/rom/sql/attribute.rb', line 186 def is(other) self =~ other end |
#join(delimiter, null_repr) ⇒ SQL::Attribute<Types::String>
Convert the array to a string by joining values with a delimiter (empty stirng by default) and optional filler for NULL values Translates to an ‘array_to_string` call
|
# File 'lib/rom/sql/extensions/postgres/types/array.rb', line 67
|
#joined ⇒ SQL::Attribute
Return a new attribute marked as joined
Whenever you join two schemas, the right schema’s attribute will be marked as joined using this method
93 94 95 |
# File 'lib/rom/sql/attribute.rb', line 93 def joined (joined: true) end |
#joined? ⇒ Boolean
Return if an attribute was used in a join
108 109 110 |
# File 'lib/rom/sql/attribute.rb', line 108 def joined? [:joined].equal?(true) end |
#length ⇒ SQL::Attribute<Types::Integer>
Return array size
|
# File 'lib/rom/sql/extensions/postgres/types/array.rb', line 41
|
#match(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree match a lquery value Translates to the ~ operator
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 2
|
#match_any(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree match any of the lquery values Translates to the ? operator
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 15
|
#match_any_lquery(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that matches lquery, NULL if none Translates to ?~
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 175
|
#match_any_ltextquery(value) ⇒ SQL::Attribute<Types::PG::LTree>
Return first LTree array entry that matches ltextquery, NULL if none Translates to ?@
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 188
|
#match_ltextquery(value) ⇒ SQL::Attribute<Types::Bool>
Check whether the LTree match a ltextquery Translates to the @ operator
|
# File 'lib/rom/sql/extensions/postgres/types/ltree.rb', line 29
|
#merge(value) ⇒ SQL::Attribute<Types::PG::JSONB>
Concatenate two JSON values Translates to ||
|
# File 'lib/rom/sql/extensions/postgres/types/json.rb', line 99
|
#meta_options_ast ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
327 328 329 330 331 |
# File 'lib/rom/sql/attribute.rb', line 327 def = super [:index] = true if indexed? end |
#not(other) ⇒ Object
Return a boolean expression with a negated equality operator
212 213 214 |
# File 'lib/rom/sql/attribute.rb', line 212 def not(other) !is(other) end |
#overlaps(other) ⇒ SQL::Attribute<Types::Bool>
Check whether the arrays have common values Translates to &&
|
# File 'lib/rom/sql/extensions/postgres/types/array.rb', line 48
|
#qualifiable? ⇒ Boolean
Return if an attribute is qualifiable
132 133 134 |
# File 'lib/rom/sql/attribute.rb', line 132 def qualifiable? !source.nil? end |
#qualified(table_alias = nil) ⇒ SQL::Attribute
Return a new attribute marked as qualified
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/rom/sql/attribute.rb', line 57 def qualified(table_alias = nil) return self if qualified? && table_alias.nil? return (qualified: false) unless qualifiable? case sql_expr when Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier attr = (qualified: table_alias || true) attr.(sql_expr: attr.to_sql_name) else raise QualifyError, "can't qualify #{name.inspect} (#{sql_expr.inspect})" end end |
#qualified? ⇒ Boolean
Return if an attribute type is qualified
123 124 125 |
# File 'lib/rom/sql/attribute.rb', line 123 def qualified? [:qualified].equal?(true) || [:qualified].is_a?(Symbol) end |
#qualified_projection(table_alias = nil) ⇒ SQL::Attribute
Return a new attribute that is aliased and marked as qualified
Intended to be used when passing attributes to ‘dataset#select`
77 78 79 80 81 82 83 |
# File 'lib/rom/sql/attribute.rb', line 77 def qualified_projection(table_alias = nil) if aliased? qualified(table_alias).aliased(self.alias) else qualified(table_alias) end end |
#remove_value(value) ⇒ SQL::Attribute<Types::PG::Array>
Remove elements by value
|
# File 'lib/rom/sql/extensions/postgres/types/array.rb', line 58
|
#sql_literal(ds) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sequel calls this method to coerce an attribute into SQL string
292 293 294 |
# File 'lib/rom/sql/attribute.rb', line 292 def sql_literal(ds) ds.literal(sql_expr) end |
#to_sql_name ⇒ Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Sequel column representation
301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/rom/sql/attribute.rb', line 301 def to_sql_name @_to_sql_name ||= if qualified? && aliased_projection? Sequel.qualify(table_name, name).as(self.alias) elsif qualified? Sequel.qualify(table_name, name) elsif aliased_projection? Sequel.as(name, self.alias) else Sequel[name] end end |
#to_sym ⇒ Symbol
Return symbol representation of an attribute
This uses convention from sequel where double underscore in the name is used for qualifying, and triple underscore means aliasing
163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/rom/sql/attribute.rb', line 163 def to_sym @_to_sym ||= if qualified? && aliased? :"#{table_name}__#{name}___#{[:alias]}" elsif qualified? :"#{table_name}__#{name}" elsif aliased? :"#{name}___#{[:alias]}" else name end end |
#unwrap ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Removes metadata from the type
336 337 338 339 340 341 |
# File 'lib/rom/sql/attribute.rb', line 336 def unwrap = .reject { |k, _| META_KEYS.include?(k) } type = optional? ? right : self.type self.class.new(type.with(meta: ), **) end |
#value(value) ⇒ SQL::Attribute
Wrap a value with the type, it allows using attribute and type specific methods on literals and things like this
350 351 352 |
# File 'lib/rom/sql/attribute.rb', line 350 def value(value) (sql_expr: Sequel[value]) end |