Module: Lore::Prepare_Class_Methods

Included in:
Table_Accessor
Defined in:
lib/lore/model/prepare.rb

Overview

Model extension for prepared statements

Constant Summary collapse

@@prepared_statements =
Hash.new

Instance Method Summary collapse

Instance Method Details

#by_id(entity_id) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/lore/model/prepare.rb', line 32

def by_id(entity_id) 
  begin
    return _by_id(entity_id).first
  rescue ::Exception => excep
    if @@prepared_statements[:default_preps] then
      raise excep
    else
      raise ::Exception.new(excep.message + ' (call define_default_preps first?)')
    end
  end
end

#execute_prepared(plan_name, *args) ⇒ Object

}}}



88
89
90
91
# File 'lib/lore/model/prepare.rb', line 88

def execute_prepared(plan_name, *args)
  plan_name = "#{table_name.gsub('.','_')}__#{plan_name.to_s}"
  Table_Select.new(self).select_prepared(plan_name, args)
end

#prepare(plan_name, *args, &block) ⇒ Object

Prepares a query for execution. This offers four advantages:

  • The query doesn’t have to be interpreted by the DB every time

  • The query call is available via direct method call.

  • DB validates against types, thus preventing SQL injection

  • It doesn’t Lore require to compose the query string again. This effects the most significant performance gain (Up to 60% execution time in some benchmarks)

Usage:

Article.prepare(:by_name_and_date, Lore::Type::Integer, Lore::Type::Date) { |a,fields|
  a.where((Article.article_id == fields[0] & 
          (Article.date == fields[1]))
}
Article.by_name_and_date('Merry Christmas', '20081224')

From the PostgreSQL 7.4 Manual:

"In some situations, the query plan produced by for a prepared statement may be 
 inferior to the plan produced if the statement were submitted and executed normally. 
 This is because when the statement is planned and the planner attempts to determine 
 the optimal query plan, the actual values of any parameters specified in the 
 statement are unavailable. PostgreSQL collects statistics on the distribution of 
 data in the table, and can use constant values in a statement to make guesses about 
 the likely result of executing the statement. Since this data is unavailable when 
 planning prepared statements with parameters, the chosen plan may be suboptimal. To 
 examine the query plan PostgreSQL has chosen for a prepared statement, use 
 EXPLAIN EXECUTE. "


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/lore/model/prepare.rb', line 72

def prepare(plan_name, *args, &block)
# {{{
# log('PREPARE: TRYING CLASS METHOD ' << plan_name.to_s)
  if !@@prepared_statements[plan_name] then
    Table_Select.new(self).prepare(plan_name, args, &block)

#   log('PREPARE: CREATE CLASS METHOD ' << plan_name.to_s)
    instance_eval("
    def #{plan_name.to_s}(*args) 
      execute_prepared(:#{plan_name}, args)
    end")
    @@prepared_statements[plan_name] = true
#   log('PREPARE: CREATED CLASS METHOD ' << plan_name.to_s)
  end
end