lib/rom/sql/relation.rb in rom-sql-0.7.0 vs lib/rom/sql/relation.rb in rom-sql-0.8.0

- old
+ new

@@ -1,21 +1,30 @@ require 'rom/sql/header' +require 'rom/sql/types' +require 'rom/sql/schema' + require 'rom/sql/relation/reading' require 'rom/sql/relation/writing' require 'rom/plugins/relation/view' require 'rom/plugins/relation/key_inference' require 'rom/plugins/relation/sql/base_view' require 'rom/plugins/relation/sql/auto_combine' require 'rom/plugins/relation/sql/auto_wrap' +require 'rom/support/deprecations' +require 'rom/support/constants' + module ROM module SQL # Sequel-specific relation extensions # + # @api public class Relation < ROM::Relation + include SQL + adapter :sql use :key_inference use :view use :base_view @@ -23,74 +32,116 @@ use :auto_wrap include Writing include Reading - # @attr_reader [Header] header Internal lazy-initialized header - attr_reader :header - - # Name of the table used in FROM clause - # - # @attr_reader [Symbol] table - attr_reader :table - # Set default dataset for a relation sub-class # # @api private def self.inherited(klass) super klass.class_eval do + schema_dsl SQL::Schema::DSL + schema_inferrer ROM::SQL::Schema::Inferrer + dataset do table = opts[:from].first if db.table_exists?(table) - # quick fix for dbs w/o primary_key inference - # - # TODO: add a way of setting a pk explicitly on a relation - pk = - if db.respond_to?(:primary_key) - Array(db.primary_key(table)) - else - [:id] - end.map { |name| :"#{table}__#{name}" } - - select(*columns).order(*pk) + pk_header = klass.primary_key_header(db, table) + select(*columns).order(*pk_header.qualified) else self end end + + # @!method by_pk(pk) + # Return a relation restricted by its primary key + # @param [Object] pk The primary key value + # @return [SQL::Relation] + # @api public + view(:by_pk, attributes[:base]) do |pk| + where(primary_key => pk) + end end end + # @api private + def self.associations + schema.associations + end + + # @api private + def self.primary_key_header(db, table) + names = + if schema + schema.primary_key_names + elsif db.respond_to?(:primary_key) + Array(db.primary_key(table)) + else + [:id] + end + Header.new(names, table) + end + + # Set primary key + # + # @deprecated + # + # @api public def self.primary_key(value) + Deprecations.announce( + :primary_key, "use schema definition to configure primary key" + ) option :primary_key, reader: true, default: value end - primary_key :id + option :primary_key, reader: true, default: -> rel { + rel.schema? ? rel.schema.primary_key_name : :id + } + # Return table name from relation's sql statement + # + # This value is used by `header` for prefixing column names + # + # @return [Symbol] + # # @api private - def initialize(dataset, registry = {}) - super - @table = dataset.opts[:from].first + def table + @table ||= dataset.opts[:from].first end # Return a header for this relation # # @return [Header] # # @api private def header - @header ||= Header.new(dataset.opts[:select] || dataset.columns, table) + @header ||= Header.new(selected_columns, table) end # Return raw column names # # @return [Array<Symbol>] # # @api private def columns - dataset.columns + @columns ||= dataset.columns + end + + protected + + # Return a list of columns from *the sql select* statement or default to + # dataset columns + # + # This is used to construct relation's header + # + # @return [Array<Symbol>] + # + # @api private + def selected_columns + @selected_columns ||= dataset.opts.fetch(:select, columns) end end end end