app/fetchers/base_list_fetcher.rb
require 'models/helpers/relational_operators'
module VCAP::CloudController
class BaseListFetcher
class << self
def filter(message, dataset, klass)
dataset = advanced_filtering(message, dataset, klass)
dataset = dataset.where("#{klass.table_name}__guid": message.guids) if message.requested?(:guids)
dataset
end
def advanced_filtering(message, dataset, klass)
advanced_filters = {}
advanced_filters['created_at'] = message.created_ats if message.requested?(:created_ats)
advanced_filters['updated_at'] = message.updated_ats if message.requested?(:updated_ats)
advanced_filters.each do |filter, values|
if values.is_a?(Hash)
values.map do |operator, given_timestamp|
if operator == RelationalOperators::LESS_THAN_COMPARATOR
normalized_timestamp = Time.parse(given_timestamp).utc
dataset = dataset.where(Sequel.qualify(klass.table_name, filter) < normalized_timestamp)
elsif operator == RelationalOperators::LESS_THAN_OR_EQUAL_COMPARATOR
normalized_timestamp = (Time.parse(given_timestamp).utc + 0.999999).utc
dataset = dataset.where(Sequel.qualify(klass.table_name, filter) <= normalized_timestamp)
elsif operator == RelationalOperators::GREATER_THAN_COMPARATOR
normalized_timestamp = (Time.parse(given_timestamp).utc + 0.999999).utc
dataset = dataset.where(Sequel.qualify(klass.table_name, filter) > normalized_timestamp)
elsif operator == RelationalOperators::GREATER_THAN_OR_EQUAL_COMPARATOR
normalized_timestamp = Time.parse(given_timestamp).utc
dataset = dataset.where(Sequel.qualify(klass.table_name, filter) >= normalized_timestamp)
end
end
else
# Gotcha: unlike the other relational operators, which are hashes such as
# { lt: '2020-06-30T12:34:56Z' }, the equals operator is simply an array, e.g.
# [ '2020-06-30T12:34:56Z' ].
# Gotcha: the equals operator returns all resources occurring within
# the span of the second (e.g. "12:34:56.00-12:34:56.9999999"), for databases store
# timestamps in sub-second accuracy (PostgreSQL stores in microseconds, for example)
bounds_expressions = values.map do |timestamp|
lower_bound = Time.parse(timestamp).utc
upper_bound = Time.at(lower_bound + 0.999999).utc
(Sequel.qualify(klass.table_name, filter) <= upper_bound) &
(Sequel.qualify(klass.table_name, filter) >= lower_bound)
end
dataset = dataset.where(Sequel.|(*bounds_expressions))
end
end
dataset
end
end
end
end