Parent

Included Modules

Class/Module Index [+]

Quicksearch

DataMapper::Query

Query class represents a query which will be run against the data-store. Generally Query objects can be found inside Collection objects.

Constants

OPTIONS

Attributes

conditions[R]

Returns the conditions of the query

In the following example:

@example

Team.all(:wins.gt => 30, :conference => 'East')

Conditions are "greater than" operator for "wins" field and exact match operator for "conference".

@return [Array]

the conditions that will be used to scope the results

@api semipublic

fields[R]

Returns the fields

Set in cases like the following:

@example

Document.all(:fields => [:title, :vernacular_title, :abstract])

@return [PropertySet]

the properties in the Model that will be retrieved

@api semipublic

limit[R]

Returns the limit query uses

Set in cases like the following:

@example

Document.all(:limit => 10)

@return [Integer, nil]

the maximum number of results

@api semipublic

model[R]

Returns model (class) that is used to instantiate objects from query result returned by adapter

@return [Model]

the Model to retrieve results from

@api semipublic

offset[R]

Returns the offset query uses

Set in cases like the following:

@example

Document.all(:offset => page.offset)

@return [Integer]

the offset of the results

@api semipublic

options[R]

Returns the original options

@return [Hash]

the original options

@api private

order[R]

Returns the order

Set in cases like the following:

@example

Document.all(:order => [:created_at.desc, :length.desc])

query order is a set of two ordering rules, descending on “created_at” field and descending again on “length” field

@return [Array]

the order of results

@api semipublic

repository[R]

Returns the repository query should be executed in

Set in cases like the following:

@example

Document.all(:repository => :medline)

@return [Repository]

the Repository to retrieve results from

@api semipublic

Public Class Methods

new(repository, model, options = {}) click to toggle source

Initializes a Query instance

@example

JournalIssue.all(:repository => :medline, :created_on.gte => Date.today - 7)

initialized a query with repository defined with name :medline, model JournalIssue and options { :created_on.gte => Date.today - 7 }

@param [Repository] repository

the Repository to retrieve results from

@param [Model] model

the Model to retrieve results from

@param [Hash] options

the conditions and scope

@api semipublic

# File lib/dm-core/query.rb, line 714
def initialize(repository, model, options = {})
  assert_kind_of 'repository', repository, Repository
  assert_kind_of 'model',      model,      Model

  @repository = repository
  @model      = model
  @options    = options.dup.freeze

  repository_name = repository.name

  @properties    = @model.properties(repository_name)
  @relationships = @model.relationships(repository_name)

  assert_valid_options(@options)

  @fields       = @options.fetch :fields,       @properties.defaults
  @links        = @options.key?(:links) ? @options[:links].dup : []
  @conditions   = Conditions::Operation.new(:null)
  @offset       = @options.fetch :offset,       0
  @limit        = @options.fetch :limit,        nil
  @order        = @options.fetch :order,        @model.default_order(repository_name)
  @unique       = @options.fetch :unique,       true
  @add_reversed = @options.fetch :add_reversed, false
  @reload       = @options.fetch :reload,       false
  @raw          = false

  merge_conditions([ DataMapper::Ext::Hash.except(@options, *OPTIONS), @options[:conditions] ])
  normalize_options
end
target_conditions(source, source_key, target_key) click to toggle source

Extract conditions to match a Resource or Collection

@param [Array, Collection, Resource] source

the source to extract the values from

@param [ProperySet] source_key

the key to extract the value from the resource

@param [ProperySet] target_key

the key to match the resource with

@return [AbstractComparison, AbstractOperation]

the conditions to match the resources with

@api private

# File lib/dm-core/query.rb, line 49
def self.target_conditions(source, source_key, target_key)
  target_key_size = target_key.size
  source_values   = []

  if source.nil?
    source_values << [ nil ] * target_key_size
  else
    Array(source).each do |resource|
      next unless source_key.loaded?(resource)
      source_value = source_key.get!(resource)
      next unless target_key.valid?(source_value)
      source_values << source_value
    end
  end

  source_values.uniq!

  if target_key_size == 1
    target_key = target_key.first
    source_values.flatten!

    if source_values.size == 1
      Conditions::EqualToComparison.new(target_key, source_values.first)
    else
      Conditions::InclusionComparison.new(target_key, source_values)
    end
  else
    or_operation = Conditions::OrOperation.new

    source_values.each do |source_value|
      and_operation = Conditions::AndOperation.new

      target_key.zip(source_value) do |property, value|
        and_operation << Conditions::EqualToComparison.new(property, value)
      end

      or_operation << and_operation
    end

    or_operation
  end
end
target_query(repository, model, source) click to toggle source

@param [Repository] repository

the default repository to scope the query within

@param [Model] model

the default model for the query

@param [query, Enumerable] source

the source to generate the query with

@return [Query]

the query to match the resources with

@api private

# File lib/dm-core/query.rb, line 103
def self.target_query(repository, model, source)
  if source.respond_to?(:query)
    source.query
  elsif source.kind_of?(Enumerable)
    key        = model.key(repository.name)
    conditions = Query.target_conditions(source, key, key)
    repository.new_query(model, :conditions => conditions)
  else
    raise ArgumentError, "+source+ must respond to #query or be an Enumerable, but was #{source.class}"
  end
end

Public Instance Methods

&(other) click to toggle source
Alias for: intersection
+(other) click to toggle source
Alias for: union
-(other) click to toggle source
Alias for: difference
[](*args) click to toggle source
Alias for: slice
add_reversed?() click to toggle source

Indicates if each result should be returned in reverse order

Set in cases like the following:

@example

Document.all(:limit => 5).reverse

Note that :add_reversed option may be used in conditions directly, but this is rarely the case

@return [Boolean]

true if the results should be reversed, false if not

@api private

# File lib/dm-core/query.rb, line 248
def add_reversed?
  @add_reversed
end
clear() click to toggle source

Clear conditions

@return [self]

@api semipublic

# File lib/dm-core/query.rb, line 472
def clear
  @conditions = Conditions::Operation.new(:null)
  self
end
condition_properties() click to toggle source

Get the properties used in the conditions

@return [Set<Property>]

Set of properties used in the conditions

@api private

# File lib/dm-core/query.rb, line 627
def condition_properties
  properties = Set.new

  each_comparison do |comparison|
    next unless comparison.respond_to?(:subject)
    subject = comparison.subject
    properties << subject if subject.kind_of?(Property)
  end

  properties
end
difference(other) click to toggle source

Return the difference with another query

@param [Query] other

the other query

@return [Query]

the difference of the query and other

@api semipublic

# File lib/dm-core/query.rb, line 461
def difference(other)
  set_operation(:difference, other)
end
Also aliased as: -
filter_records(records) click to toggle source

Takes an Enumerable of records, and destructively filters it. First finds all matching conditions, then sorts it, then does offset & limit

@param [Enumerable] records

The set of records to be filtered

@return [Enumerable]

Whats left of the given array after the filtering

@api semipublic

# File lib/dm-core/query.rb, line 488
def filter_records(records)
  records = records.uniq           if unique?
  records = match_records(records) if conditions
  records = sort_records(records)  if order
  records = limit_records(records) if limit || offset > 0
  records
end
inspect() click to toggle source

Returns detailed human readable string representation of the query

@return [String] detailed string representation of the query

@api semipublic

# File lib/dm-core/query.rb, line 604
def inspect
  attrs = [
    [ :repository, repository.name ],
    [ :model,      model           ],
    [ :fields,     fields          ],
    [ :links,      links           ],
    [ :conditions, conditions      ],
    [ :order,      order           ],
    [ :limit,      limit           ],
    [ :offset,     offset          ],
    [ :reload,     reload?         ],
    [ :unique,     unique?         ],
  ]

  "#<#{self.class.name} #{attrs.map { |key, value| "@#{key}=#{value.inspect}" }.join(' ')}>"
end
intersection(other) click to toggle source

Return the intersection with another query

@param [Query] other

the other query

@return [Query]

the intersection of the query and other

@api semipublic

# File lib/dm-core/query.rb, line 445
def intersection(other)
  return dup if self == other
  set_operation(:intersection, other)
end
Also aliased as: &
limit_records(records) click to toggle source

Limits a set of records by the offset and/or limit

@param [Enumerable] records

A list of records to sort

@return [Enumerable]

The offset & limited records

@api semipublic

# File lib/dm-core/query.rb, line 538
def limit_records(records)
  offset = self.offset
  limit  = self.limit
  size   = records.size

  if offset > size - 1
    []
  elsif (limit && limit != size) || offset > 0
    records[offset, limit || size] || []
  else
    records.dup
  end
end
match_records(records) click to toggle source

Filter a set of records by the conditions

@param [Enumerable] records

The set of records to be filtered

@return [Enumerable]

Whats left of the given array after the matching

@api semipublic

# File lib/dm-core/query.rb, line 505
def match_records(records)
  conditions = self.conditions
  records.select { |record| conditions.matches?(record) }
end
merge(other) click to toggle source

Similar to Query#update, but acts on a duplicate.

@param [Query, Hash] other

other query to merge with

@return [Query]

updated duplicate of original query

@api semipublic

# File lib/dm-core/query.rb, line 385
def merge(other)
  dup.update(other)
end
raw?() click to toggle source

Indicates if the Query has raw conditions

@return [Boolean]

true if the query has raw conditions, false if not

@api semipublic

# File lib/dm-core/query.rb, line 282
def raw?
  @raw
end
relative(options) click to toggle source

Builds and returns new query that merges original with one given, and slices the result with respect to :limit and :offset options

This method is used by Collection to concatenate options from multiple chained calls in cases like the following:

@example

author.books.all(:year => 2009).all(:published => false)

@api semipublic

# File lib/dm-core/query.rb, line 402
def relative(options)
  options = options.to_hash

  offset = nil
  limit  = self.limit

  if options.key?(:offset) && (options.key?(:limit) || limit)
    options = options.dup
    offset  = options.delete(:offset)
    limit   = options.delete(:limit) || limit - offset
  end

  query = merge(options)
  query = query.slice!(offset, limit) if offset
  query
end
reload?() click to toggle source

Indicates if the Query results should replace the results in the Identity Map

TODO: needs example

@return [Boolean]

true if the results should be reloaded, false if not

@api semipublic

# File lib/dm-core/query.rb, line 260
def reload?
  @reload
end
reverse() click to toggle source

Returns a new Query with a reversed order

@example

Document.all(:limit => 5).reverse

Will execute a single query with correct order

@return [Query]

new Query with reversed order

@api semipublic

# File lib/dm-core/query.rb, line 308
def reverse
  dup.reverse!
end
reverse!() click to toggle source

Reverses the sort order of the Query

@example

Document.all(:limit => 5).reverse

Will execute a single query with original order and then reverse collection in the Ruby space

@return [Query]

self

@api semipublic

# File lib/dm-core/query.rb, line 325
def reverse!
  # reverse the sort order
  @order.map! { |direction| direction.dup.reverse! }

  # copy the order to the options
  @options = @options.merge(:order => @order).freeze

  self
end
slice(*args) click to toggle source

Slices collection by adding limit and offset to the query, so a single query is executed

@example

Journal.all(:limit => 10).slice(3, 5)

will execute query with the following limit and offset (when repository uses DataObjects adapter, and thus queries use SQL):

LIMIT 5 OFFSET 3

@api semipublic

# File lib/dm-core/query.rb, line 566
def slice(*args)
  dup.slice!(*args)
end
Also aliased as: []
slice!(*args) click to toggle source

Slices collection by adding limit and offset to the query, so a single query is executed

@example

Journal.all(:limit => 10).slice!(3, 5)

will execute query with the following limit (when repository uses DataObjects adapter, and thus queries use SQL):

LIMIT 10

and then takes a slice of collection in the Ruby space

@api semipublic

# File lib/dm-core/query.rb, line 588
def slice!(*args)
  offset, limit = extract_slice_arguments(*args)

  if self.limit || self.offset > 0
    offset, limit = get_relative_position(offset, limit)
  end

  update(:offset => offset, :limit => limit)
end
sort_records(records) click to toggle source

Sorts a list of Records by the order

@param [Enumerable] records

A list of Resources to sort

@return [Enumerable]

The sorted records

@api semipublic

# File lib/dm-core/query.rb, line 519
def sort_records(records)
  sort_order = order.map { |direction| [ direction.target, direction.operator == :asc ] }

  records.sort_by do |record|
    sort_order.map do |(property, ascending)|
      Sort.new(record_value(record, property), ascending)
    end
  end
end
sorted_fields() click to toggle source

Return a list of fields in predictable order

@return [Array<Property>]

list of fields sorted in deterministic order

@api private

# File lib/dm-core/query.rb, line 645
def sorted_fields
  fields.sort_by { |property| property.hash }
end
to_hash() click to toggle source

Hash representation of a Query

@return [Hash]

Hash representation of a Query

@api private

# File lib/dm-core/query.rb, line 666
def to_hash
  {
    :repository   => repository.name,
    :model        => model.name,
    :fields       => fields,
    :links        => links,
    :conditions   => conditions,
    :offset       => offset,
    :limit        => limit,
    :order        => order,
    :unique       => unique?,
    :add_reversed => add_reversed?,
    :reload       => reload?,
  }
end
to_relative_hash() click to toggle source

Extract options from a Query

@param [Query] query

the query to extract options from

@return [Hash]

the options to use to initialize the new query

@api private

# File lib/dm-core/query.rb, line 691
def to_relative_hash
  DataMapper::Ext::Hash.only(to_hash, :fields, :order, :unique, :add_reversed, :reload)
end
to_subquery() click to toggle source

Transform Query into subquery conditions

@return [AndOperation]

a subquery for the Query

@api private

# File lib/dm-core/query.rb, line 655
def to_subquery
  collection = model.all(merge(:fields => model_key))
  Conditions::Operation.new(:and, Conditions::Comparison.new(:in, self_relationship, collection))
end
union(other) click to toggle source

Return the union with another query

@param [Query] other

the other query

@return [Query]

the union of the query and other

@api semipublic

# File lib/dm-core/query.rb, line 428
def union(other)
  return dup if self == other
  set_operation(:union, other)
end
Also aliased as: |, +
unique?() click to toggle source

Indicates if the Query results should be unique

TODO: needs example

@return [Boolean]

true if the results should be unique, false if not

@api semipublic

# File lib/dm-core/query.rb, line 272
def unique?
  @unique
end
update(other) click to toggle source

Updates the Query with another Query or conditions

Pretty unrealistic example:

@example

Journal.all(:limit => 2).query.limit                     # => 2
Journal.all(:limit => 2).query.update(:limit => 3).limit # => 3

@param [Query, Hash] other

other Query or conditions

@return [Query]

self

@api semipublic

# File lib/dm-core/query.rb, line 351
def update(other)
  other_options = if kind_of?(other.class)
    return self if self.eql?(other)
    assert_valid_other(other)
    other.options
  else
    other = other.to_hash
    return self if other.empty?
    other
  end

  @options = @options.merge(other_options).freeze
  assert_valid_options(@options)

  normalize = DataMapper::Ext::Hash.only(other_options, *OPTIONS - [ :conditions ]).map do |attribute, value|
    instance_variable_set("@#{attribute}", DataMapper::Ext.try_dup(value))
    attribute
  end

  merge_conditions([ DataMapper::Ext::Hash.except(other_options, *OPTIONS), other_options[:conditions] ])
  normalize_options(normalize | [ :links, :unique ])

  self
end
valid?() click to toggle source

Indicates if the Query is valid

@return [Boolean]

true if the query is valid

@api semipublic

# File lib/dm-core/query.rb, line 292
def valid?
  conditions.valid?
end
|(other) click to toggle source
Alias for: union

[Validate]

Generated with the Darkfish Rdoc Generator 2.