# xrubocop:disable Metrics/ParameterLists
require_relative "association_loader"
class ::Simple::SQL::Result::Records < ::Simple::SQL::Result
def initialize(records, target_type:, pg_source_oid:) # :nodoc:
expect! records.first => Hash unless records.empty?
super(records)
@hash_records = records
@target_type = target_type
@pg_source_oid = pg_source_oid
@associations = []
materialize
end
# -- preload associations -------------------------------------------------
AssociationLoader = ::Simple::SQL::Result::AssociationLoader
# Preloads an association.
#
# This can now be used as follows:
#
# scope = SQL::Scope.new("SELECT * FROM users")
# results = SQL.all scope, into: :struct
# results.preload(:organization)
#
# The preload method uses foreign key definitions in the database to figure out
# which table to load from.
#
# This method is only available if into: was set in the call to SQL.all.
# It raises an error otherwise.
#
# Parameters:
#
# - association: the name of the association.
# - as: the target name of the association.
# - order_by: if set describes ordering; see Scope#order_by.
# - limit: if set describes limits; see Scope#order_by.
def preload(association, as: nil, order_by: nil, limit: nil)
expect! association => Symbol
expect! as => [nil, Symbol]
# resolve oid into table and schema name.
schema, host_table = ::Simple::SQL.ask <<~SQL, @pg_source_oid
SELECT nspname AS schema, relname AS host_table
FROM pg_class
JOIN pg_namespace ON pg_namespace.oid=pg_class.relnamespace
WHERE pg_class.oid=$1
SQL
AssociationLoader.preload @hash_records, association,
host_table: host_table, schema: schema, as: as,
order_by: order_by, limit: limit
@associations << association
materialize
end
private
# convert the records into the target type.
RowConverter = ::Simple::SQL::Helpers::RowConverter
def materialize
records = @hash_records
records = RowConverter.convert_row(records, associations: @associations, into: @target_type) if @target_type != Hash
replace(records)
end
end