class Ferret::Expression
Attributes
exemplars[R]
multicolumn[RW]
selectees[R]
stages[R]
type[RW]
Public Class Methods
new()
click to toggle source
Calls superclass method
# File lib/sql-ferret.rb, line 929 def initialize super() @stages = [Ferret::Stage.new(nil, nil, :left)] @selectees = [] @exemplars = [] @multicolumn = false @type = :select # the default return end
Public Instance Methods
assign_stage_qualifiers(ag)
click to toggle source
# File lib/sql-ferret.rb, line 939 def assign_stage_qualifiers ag raise 'type mismatch' \ unless ag.is_a? Ferret::Alias_Generator table_visit_counts = Hash.new 0 # name => count @stages.each_with_index do |stage, i| table_visit_counts[stage.table.name] += 1 end # The tables that we visited more than once need # distinguishing names. @stages.each do |stage| stage.qualifier = if table_visit_counts[stage.table.name] > 1 then ag.create stage.table.name[0] else stage.table.name end end return end
from_clause()
click to toggle source
# File lib/sql-ferret.rb, line 960 def from_clause clause = "from " @stages.each_with_index do |stage, i| # In case of a non-query expression -- a modification --, # the last stage is empty and mustn't be joined. It then # serves only the purpose of holding the last stalk. break if i == @stages.length - 1 and modification? unless i.zero? then clause << " #{stage.join_type} join " end clause << stage.table.name << " as " << stage.qualifier unless i.zero? then clause << " on %s.%s = %s.%s" % [ stage.parent.qualifier, (stage.stalk.haunt || stage.stalk).name, stage.qualifier, stage.stalk.ref.name, ] end end return clause end
modification?()
click to toggle source
# File lib/sql-ferret.rb, line 1046 def modification? case @type when :select, :select_distinct then return false when :update, :insert, :delete then return true else raise 'assertion failed' end end
select()
click to toggle source
Prepare a [[select]] statement as an [[Annotated_SQL_Template]]. If this expression represents a query statement, the result will cover the whole query. If it represents an update statement, the result will cover the subquery that determines key value(s) of records in the last table to update.
# File lib/sql-ferret.rb, line 1008 def select qualifiers_needed = @stages.length != (modification? ? 2 : 1) sql_selectees = @selectees.map do |selectee| (qualifiers_needed ? selectee.stage.qualifier + "." : "") + (selectee.field.haunt || selectee.field).name end.join(', ') outputs = {} @selectees.each do |selectee| outputs[selectee.output_name.to_sym] = selectee.interpretation end sql = "select" sql << " distinct" if @type == :select_distinct sql << " " << sql_selectees << " " << from_clause sql << " " << where_clause unless @exemplars.empty? # Determine the shape of the table shape = 0 shape |= QSF_MULTICOL if @multicolumn # If no [[unique]] exemplar field is specified or if any of # the joins is performed along a ghost field (i.e., # possibly a 1->n reference), our result will have multiple # rows. shape |= QSF_MULTIROW \ unless @exemplars.any?{|ex| ex.column.unique?} and !@stages[1 .. -1].any?{|stage| stage.stalk.ghost?} return Ferret::Annotated_SQL_Template.new(sql, outputs, shape) end
where_clause()
click to toggle source
# File lib/sql-ferret.rb, line 985 def where_clause raise 'assertion failed' if @exemplars.empty? clause = "where " @exemplars.each_with_index do |exemplar, i| clause << " and " unless i.zero? # The qualifier is only necessary if the clause has more # than one stage. if @stages.length > 1 then # In the navigational model, the (primary) filter always # lives in the zeroth stage. clause << @stages[0].qualifier << "." end clause << exemplar.column.name << " [test #{i}]" end return clause end