Module: ROM::SQL::Relation::Reading
- Included in:
- ROM::SQL::Relation
- Defined in:
- lib/rom/sql/relation/reading.rb
Overview
Query API for SQL::Relation
Constant Summary collapse
- ROW_LOCK_MODES =
Row-level lock modes
Hash.new(update: 'FOR UPDATE'.freeze).update( # https://www.postgresql.org/docs/current/static/sql-select.html#SQL-FOR-UPDATE-SHARE postgres: { update: 'FOR UPDATE'.freeze, no_key_update: 'FOR NO KEY UPDATE'.freeze, share: 'FOR SHARE'.freeze, key_share: 'FOR KEY SHARE'.freeze }, # https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html mysql: { update: 'FOR UPDATE'.freeze, share: 'LOCK IN SHARE MODE'.freeze } ).freeze
Instance Method Summary collapse
-
#as_hash(attribute = primary_key) ⇒ Hash
Returns hash with all tuples being the key of each the provided attribute.
-
#avg(*args) ⇒ Object
Returns a result of SQL AVG clause.
-
#count ⇒ Relation
Return relation count.
-
#distinct(*args, &block) ⇒ Relation
Returns a copy of the relation with a SQL DISTINCT clause.
-
#each_batch(size: 1000) {|| ... } ⇒ Object
Process the dataset in batches.
-
#exclude(*args, &block) ⇒ Relation
Restrict a relation to not match criteria.
-
#exist?(*args, &block) ⇒ TrueClass, FalseClass
Checks whether a relation has at least one tuple.
-
#exists(other, condition = nil) ⇒ SQL::Relation
Restrict with rows from another relation.
-
#fetch(pk) ⇒ Relation
Fetch a tuple identified by the pk.
-
#first ⇒ Hash
Get first tuple from the relation.
-
#group(*args, &block) ⇒ Relation
Group by specific columns.
-
#group_and_count(*args, &block) ⇒ Relation
Group by specific columns and count by group.
-
#group_append(*args, &block) ⇒ Relation
Group by more columns.
-
#having(*args, &block) ⇒ Relation
Restrict a relation to match grouping criteria.
-
#invert ⇒ Relation
Inverts the current WHERE and HAVING clauses.
-
#join(*args, &block) ⇒ Relation
(also: #inner_join)
Join with another relation using INNER JOIN.
-
#last ⇒ Hash
Get last tuple from the relation.
-
#left_join(*args, &block) ⇒ Relation
Join with another relation using LEFT OUTER JOIN.
-
#limit(*args) ⇒ Relation
Limit a relation to a specific number of tuples.
-
#lock(options = EMPTY_HASH, &block) ⇒ Object
Lock rows with in the specified mode.
-
#map(key = nil, &block) ⇒ Object
Map tuples from the relation.
-
#max(*args) ⇒ Object
Returns a result of SQL MAX clause.
-
#min(*args) ⇒ Object
Returns a result of SQL MIN clause.
-
#offset(num) ⇒ Relation
Set offset for the relation.
-
#order(*args, &block) ⇒ Relation
Set order for the relation.
-
#pluck(*names) ⇒ Array
Pluck values from a specific column.
-
#prefix(name = Inflector.singularize(schema.name.dataset)) ⇒ Relation
Prefix all columns in a relation.
-
#qualified(table_alias = nil) ⇒ Relation
Qualifies all columns in a relation.
-
#qualified_columns ⇒ Array<Symbol>
Return a list of qualified column names.
-
#query ⇒ SQL::Attribute
Turn a relation into a subquery.
-
#read(sql) ⇒ SQL::Relation
Return a new relation from a raw SQL string.
-
#rename(options) ⇒ Relation
Rename columns in a relation.
-
#reverse(*args, &block) ⇒ Relation
Reverse the order of the relation.
-
#right_join(*args, &block) ⇒ Relation
Join with another relation using RIGHT JOIN.
-
#select(*args, &block) ⇒ Relation
(also: #project)
Select specific columns for select clause.
-
#select_append(*args, &block) ⇒ Relation
Append specific columns to select clause.
-
#select_group(*args, &block) ⇒ Relation
Select and group by specific columns.
-
#sum(*args) ⇒ Integer
Returns a result of SQL SUM clause.
-
#unfiltered ⇒ SQL::Relation
Discard restrictions in ‘WHERE` and `HAVING` clauses.
-
#union(relation, options = EMPTY_HASH, &block) ⇒ Object
Adds a UNION clause for relation dataset using second relation dataset.
-
#unique?(criteria) ⇒ TrueClass, FalseClass
Return if a restricted relation has 0 tuples.
-
#where(*args, &block) ⇒ Relation
Restrict a relation to match criteria.
Instance Method Details
#as_hash(attribute = primary_key) ⇒ Hash
Returns hash with all tuples being the key of each the provided attribute
971 972 973 |
# File 'lib/rom/sql/relation/reading.rb', line 971 def as_hash(attribute = primary_key) dataset.as_hash(attribute) end |
#avg(*args) ⇒ Object
Returns a result of SQL AVG clause.
328 329 330 |
# File 'lib/rom/sql/relation/reading.rb', line 328 def avg(*args) dataset.__send__(__method__, *args) end |
#count ⇒ Relation
Return relation count
51 52 53 |
# File 'lib/rom/sql/relation/reading.rb', line 51 def count dataset.count end |
#distinct(*columns) ⇒ Relation #distinct(&block) ⇒ Relation
Returns a copy of the relation with a SQL DISTINCT clause.
272 273 274 |
# File 'lib/rom/sql/relation/reading.rb', line 272 def distinct(*args, &block) new(dataset.__send__(__method__, *args, &block)) end |
#each_batch(size: 1000) {|| ... } ⇒ Object
Process the dataset in batches. The method yields a relation restricted by a primary key value. This means it discards any order internally and uses the PK sort. Currently, works only with a single-column primary key.
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
# File 'lib/rom/sql/relation/reading.rb', line 934 def each_batch(size: 1000) pks = schema.primary_key if pks.size > 1 raise ArgumentError, 'Composite primary keys are not supported yet' end source = order(pks[0]).limit(size) rel = source loop do ids = rel.pluck(primary_key) break if ids.empty? yield(rel) break if ids.size < size rel = source.where(pks[0] > ids.last) end end |
#exclude(*args, &block) ⇒ Relation
Restrict a relation to not match criteria
382 383 384 |
# File 'lib/rom/sql/relation/reading.rb', line 382 def exclude(*args, &block) new(dataset.__send__(__method__, *args, &block)) end |
#exist?(*args, &block) ⇒ TrueClass, FalseClass
Checks whether a relation has at least one tuple
@example
users.where(name: 'John').exist? # => true
users.exist?(name: 'Klaus') # => false
users.exist? { name.is('klaus') } # => false
@param [Array<Object>] args Optional restrictions to filter the relation
@yield An optional block filters the relation using `where DSL`
828 829 830 |
# File 'lib/rom/sql/relation/reading.rb', line 828 def exist?(*args, &block) !where(*args, &block).limit(1).count.zero? end |
#exists(other, condition = nil) ⇒ SQL::Relation
Restrict with rows from another relation. Accepts only SQL relations and uses the EXISTS clause under the hood
913 914 915 916 |
# File 'lib/rom/sql/relation/reading.rb', line 913 def exists(other, condition = nil) join_condition = condition || associations[other.name].join_keys where(other.where(join_condition).dataset.exists) end |
#fetch(pk) ⇒ Relation
Fetch a tuple identified by the pk
38 39 40 |
# File 'lib/rom/sql/relation/reading.rb', line 38 def fetch(pk) by_pk(pk).one! end |
#first ⇒ Hash
Get first tuple from the relation
64 65 66 |
# File 'lib/rom/sql/relation/reading.rb', line 64 def first limit(1).to_a.first end |
#group(*columns) ⇒ Relation #group(*attributes) ⇒ Relation #group(*attributes, &block) ⇒ Relation
Group by specific columns
711 712 713 714 715 716 717 718 719 720 721 |
# File 'lib/rom/sql/relation/reading.rb', line 711 def group(*args, &block) if block if args.size > 0 group(*args).group_append(&block) else new(dataset.__send__(__method__, *schema.canonical.group(&block))) end else new(dataset.__send__(__method__, *schema.canonical.project(*args))) end end |
#group_and_count(*args, &block) ⇒ Relation
Group by specific columns and count by group
773 774 775 |
# File 'lib/rom/sql/relation/reading.rb', line 773 def group_and_count(*args, &block) new(dataset.__send__(__method__, *args, &block)) end |
#group_append(*columns) ⇒ Relation #group_append(*attributes) ⇒ Relation #group_append(*attributes, &block) ⇒ Relation
Group by more columns
750 751 752 753 754 755 756 757 758 759 760 |
# File 'lib/rom/sql/relation/reading.rb', line 750 def group_append(*args, &block) if block if args.size > 0 group_append(*args).group_append(&block) else new(dataset.group_append(*schema.canonical.group(&block))) end else new(dataset.group_append(*args)) end end |
#having(conditions) ⇒ Relation #having(&block) ⇒ Relation
Restrict a relation to match grouping criteria
419 420 421 422 423 424 425 |
# File 'lib/rom/sql/relation/reading.rb', line 419 def having(*args, &block) if block new(dataset.having(*args, *schema.canonical.restriction(&block))) else new(dataset.__send__(__method__, *args)) end end |
#invert ⇒ Relation
Inverts the current WHERE and HAVING clauses. If there is neither a WHERE or HAVING clause, adds a WHERE clause that is always false.
439 440 441 |
# File 'lib/rom/sql/relation/reading.rb', line 439 def invert new(dataset.invert) end |
#join(dataset, join_conditions) ⇒ Relation #join(dataset, join_conditions, options) ⇒ Relation #join(relation) ⇒ Relation #join(relation, &block) ⇒ Relation Also known as: inner_join
Join with another relation using INNER JOIN
579 580 581 |
# File 'lib/rom/sql/relation/reading.rb', line 579 def join(*args, &block) __join__(__method__, *args, &block) end |
#last ⇒ Hash
Get last tuple from the relation
77 78 79 |
# File 'lib/rom/sql/relation/reading.rb', line 77 def last reverse.limit(1).first end |
#left_join(dataset, left_join_conditions) ⇒ Relation #left_join(dataset, left_join_conditions, options) ⇒ Relation #left_join(relation) ⇒ Relation #join(relation, &block) ⇒ Relation
Join with another relation using LEFT OUTER JOIN
629 630 631 |
# File 'lib/rom/sql/relation/reading.rb', line 629 def left_join(*args, &block) __join__(__method__, *args, &block) end |
#limit(num) ⇒ Relation #limit(num, offset) ⇒ Relation
Limit a relation to a specific number of tuples
516 517 518 |
# File 'lib/rom/sql/relation/reading.rb', line 516 def limit(*args) new(dataset.__send__(__method__, *args)) end |
#lock(options) ⇒ SQL::Relation #lock(options) {|relation| ... } ⇒ Object
Lock rows with in the specified mode. Check out ROW_LOCK_MODES for the list of supported modes, keep in mind available lock modes heavily depend on the database type+version you’re running on.
885 886 887 888 889 890 891 892 893 894 895 |
# File 'lib/rom/sql/relation/reading.rb', line 885 def lock( = EMPTY_HASH, &block) clause = lock_clause() if block transaction do block.call(dataset.lock_style(clause).to_a) end else new(dataset.lock_style(clause)) end end |
#map(key = nil, &block) ⇒ Object
Map tuples from the relation
141 142 143 144 145 146 147 |
# File 'lib/rom/sql/relation/reading.rb', line 141 def map(key = nil, &block) if key dataset.map(key, &block) else dataset.map(&block) end end |
#max(*args) ⇒ Object
Returns a result of SQL MAX clause.
314 315 316 |
# File 'lib/rom/sql/relation/reading.rb', line 314 def max(*args) dataset.__send__(__method__, *args) end |
#min(*args) ⇒ Object
Returns a result of SQL MIN clause.
300 301 302 |
# File 'lib/rom/sql/relation/reading.rb', line 300 def min(*args) dataset.__send__(__method__, *args) end |
#offset(num) ⇒ Relation
Set offset for the relation
530 531 532 |
# File 'lib/rom/sql/relation/reading.rb', line 530 def offset(num) new(dataset.__send__(__method__, num)) end |
#order(*columns) ⇒ Relation #order(*attributes) ⇒ Relation #order(&block) ⇒ Relation
Set order for the relation
474 475 476 477 478 479 480 |
# File 'lib/rom/sql/relation/reading.rb', line 474 def order(*args, &block) if block new(dataset.order(*args, *schema.canonical.order(&block))) else new(dataset.__send__(__method__, *args, &block)) end end |
#pluck(*names) ⇒ Array
Pluck values from a specific column
162 163 164 |
# File 'lib/rom/sql/relation/reading.rb', line 162 def pluck(*names) select(*names).map(names.length == 1 ? names.first : names) end |
#prefix(name = Inflector.singularize(schema.name.dataset)) ⇒ Relation
Prefix all columns in a relation
This method is intended to be used internally within a relation object
94 95 96 |
# File 'lib/rom/sql/relation/reading.rb', line 94 def prefix(name = Inflector.singularize(schema.name.dataset)) schema.prefix(name).(self) end |
#qualified(table_alias = nil) ⇒ Relation
Qualifies all columns in a relation
This method is intended to be used internally within a relation object
109 110 111 |
# File 'lib/rom/sql/relation/reading.rb', line 109 def qualified(table_alias = nil) schema.qualified(table_alias).(self) end |
#qualified_columns ⇒ Array<Symbol>
Return a list of qualified column names
This method is intended to be used internally within a relation object
124 125 126 |
# File 'lib/rom/sql/relation/reading.rb', line 124 def qualified_columns schema.qualified.map(&:to_sql_name) end |
#query ⇒ SQL::Attribute
Turn a relation into a subquery. Can be used for selecting a column with a subquery or restricting the result set with a IN (SELECT …) condtion.
987 988 989 990 991 |
# File 'lib/rom/sql/relation/reading.rb', line 987 def query attr = schema.to_a[0] subquery = schema.project(attr).(self).dataset.unordered SQL::Attribute[attr.type].(sql_expr: subquery) end |
#read(sql) ⇒ SQL::Relation
Return a new relation from a raw SQL string
860 861 862 |
# File 'lib/rom/sql/relation/reading.rb', line 860 def read(sql) new(dataset.db[sql], schema: schema.empty) end |
#rename(options) ⇒ Relation
Rename columns in a relation
This method is intended to be used internally within a relation object
179 180 181 |
# File 'lib/rom/sql/relation/reading.rb', line 179 def rename() schema.rename().(self) end |
#reverse(*args, &block) ⇒ Relation
Reverse the order of the relation
490 491 492 |
# File 'lib/rom/sql/relation/reading.rb', line 490 def reverse(*args, &block) new(dataset.__send__(__method__, *args, &block)) end |
#right_join(dataset, right_join_conditions) ⇒ Relation #right_join(dataset, right_join_conditions, options) ⇒ Relation #right_join(relation) ⇒ Relation #join(relation, &block) ⇒ Relation
Join with another relation using RIGHT JOIN
678 679 680 |
# File 'lib/rom/sql/relation/reading.rb', line 678 def right_join(*args, &block) __join__(__method__, *args, &block) end |
#select(*columns) ⇒ Relation #select(*attributes) ⇒ Relation #select(&block) ⇒ Relation #select(*columns, &block) ⇒ Relation Also known as: project
Select specific columns for select clause
236 237 238 |
# File 'lib/rom/sql/relation/reading.rb', line 236 def select(*args, &block) schema.project(*args, &block).(self) end |
#select_append(*args, &block) ⇒ Relation
Append specific columns to select clause
248 249 250 |
# File 'lib/rom/sql/relation/reading.rb', line 248 def select_append(*args, &block) schema.merge(schema.canonical.project(*args, &block)).(self) end |
#select_group(*args, &block) ⇒ Relation
Select and group by specific columns
788 789 790 791 |
# File 'lib/rom/sql/relation/reading.rb', line 788 def select_group(*args, &block) new_schema = schema.project(*args, &block) new_schema.(self).group(*new_schema) end |
#sum(*args) ⇒ Integer
Returns a result of SQL SUM clause.
286 287 288 |
# File 'lib/rom/sql/relation/reading.rb', line 286 def sum(*args) dataset.__send__(__method__, *args) end |
#unfiltered ⇒ SQL::Relation
Discard restrictions in ‘WHERE` and `HAVING` clauses
1001 1002 1003 |
# File 'lib/rom/sql/relation/reading.rb', line 1001 def unfiltered new(dataset.__send__(__method__)) end |
#union(relation, options = EMPTY_HASH, &block) ⇒ Object
Adds a UNION clause for relation dataset using second relation dataset
@returRelation]
809 810 811 |
# File 'lib/rom/sql/relation/reading.rb', line 809 def union(relation, = EMPTY_HASH, &block) new(dataset.__send__(__method__, relation.dataset, , &block)) end |
#unique?(criteria) ⇒ TrueClass, FalseClass
Return if a restricted relation has 0 tuples
846 847 848 |
# File 'lib/rom/sql/relation/reading.rb', line 846 def unique?(criteria) !exist?(criteria) end |
#where(conditions) ⇒ Relation #where(conditions, &block) ⇒ Relation #where(&block) ⇒ Relation
Restrict a relation to match criteria
360 361 362 363 364 365 366 367 368 369 370 |
# File 'lib/rom/sql/relation/reading.rb', line 360 def where(*args, &block) if block where(*args).where(schema.canonical.restriction(&block)) elsif args.size == 1 && args[0].is_a?(Hash) new(dataset.where(coerce_conditions(args[0]))) elsif !args.empty? new(dataset.where(*args)) else self end end |