Class DataMapper::Adapters::Sql::Commands::LoadCommand
In: lib/data_mapper/adapters/sql/commands/load_command.rb
lib/data_mapper/adapters/sql/commands/load_command.rb
Parent: Object

Methods

Classes and Modules

Class DataMapper::Adapters::Sql::Commands::LoadCommand::ConditionsError
Class DataMapper::Adapters::Sql::Commands::LoadCommand::Loader

Attributes

conditions  [R] 
conditions  [R] 
database_context  [R] 
database_context  [R] 
options  [R] 
options  [R] 

Public Class methods

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 131
131:           def initialize(adapter, database_context, primary_class, options = {})
132:             @adapter, @database_context, @primary_class = adapter, database_context, primary_class
133:             
134:             # BEGIN: Partion out the options hash into general options,
135:             # and conditions.
136:             standard_find_options = @adapter.class::FIND_OPTIONS
137:             conditions_hash = {}
138:             @options = {}
139:             
140:             options.each do |key,value|
141:               if standard_find_options.include?(key) && key != :conditions
142:                 @options[key] = value
143:               else
144:                 conditions_hash[key] = value
145:               end
146:             end
147:             # END
148:             
149:             @order = @options[:order]
150:             @limit = @options[:limit]
151:             @offset = @options[:offset]
152:             @reload = @options[:reload]
153:             @instance_id = conditions_hash[:id]
154:             @conditions = parse_conditions(conditions_hash)
155:             @loaders = Hash.new { |h,k| h[k] = Loader.new(self, k) }
156:           end

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 131
131:           def initialize(adapter, database_context, primary_class, options = {})
132:             @adapter, @database_context, @primary_class = adapter, database_context, primary_class
133:             
134:             # BEGIN: Partion out the options hash into general options,
135:             # and conditions.
136:             standard_find_options = @adapter.class::FIND_OPTIONS
137:             conditions_hash = {}
138:             @options = {}
139:             
140:             options.each do |key,value|
141:               if standard_find_options.include?(key) && key != :conditions
142:                 @options[key] = value
143:               else
144:                 conditions_hash[key] = value
145:               end
146:             end
147:             # END
148:             
149:             @order = @options[:order]
150:             @limit = @options[:limit]
151:             @offset = @options[:offset]
152:             @reload = @options[:reload]
153:             @instance_id = conditions_hash[:id]
154:             @conditions = parse_conditions(conditions_hash)
155:             @loaders = Hash.new { |h,k| h[k] = Loader.new(self, k) }
156:           end

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 322
322:             def self.qualify_columns?
323:               @qualify_columns
324:             end

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 322
322:             def self.qualify_columns?
323:               @qualify_columns
324:             end

Public Instance methods

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 197
197:           def call
198:             
199:             # Check to see if the query is for a specific id and return if found
200:             #
201:             # NOTE: If the :id option is an Array:
202:             # We could search for loaded instance ids and reject from
203:             # the Array for already loaded instances, but working under the
204:             # assumption that we'll probably have to issue a query to find
205:             # at-least some of the instances we're looking for, it's faster to
206:             # just skip that and go straight for the query.
207:             unless reload? || @instance_id.blank? || @instance_id.is_a?(Array)
208:               # If the id is for only a single record, attempt to find it.
209:               if instance = @database_context.identity_map.get(@primary_class, @instance_id)
210:                 return [instance]
211:               end
212:             end
213:             
214:             results = []
215:             
216:             # Execute the statement and load the objects.
217:             @adapter.connection do |db|
218:               sql, *parameters = to_parameterized_sql
219:               command = db.create_command(sql)
220:               command.execute_reader(*parameters) do |reader|
221:                 if @options.has_key?(:intercept_load)
222:                   load(reader, &@options[:intercept_load])
223:                 else
224:                   load(reader)
225:                 end
226:               end
227:             end
228:             
229:             results += @loaders[@primary_class].loaded_set
230:             
231:             return results
232:           end

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 197
197:           def call
198:             
199:             # Check to see if the query is for a specific id and return if found
200:             #
201:             # NOTE: If the :id option is an Array:
202:             # We could search for loaded instance ids and reject from
203:             # the Array for already loaded instances, but working under the
204:             # assumption that we'll probably have to issue a query to find
205:             # at-least some of the instances we're looking for, it's faster to
206:             # just skip that and go straight for the query.
207:             unless reload? || @instance_id.blank? || @instance_id.is_a?(Array)
208:               # If the id is for only a single record, attempt to find it.
209:               if instance = @database_context.identity_map.get(@primary_class, @instance_id)
210:                 return [instance]
211:               end
212:             end
213:             
214:             results = []
215:             
216:             # Execute the statement and load the objects.
217:             @adapter.connection do |db|
218:               sql, *parameters = to_parameterized_sql
219:               command = db.create_command(sql)
220:               command.execute_reader(*parameters) do |reader|
221:                 if @options.has_key?(:intercept_load)
222:                   load(reader, &@options[:intercept_load])
223:                 else
224:                   load(reader)
225:                 end
226:               end
227:             end
228:             
229:             results += @loaders[@primary_class].loaded_set
230:             
231:             return results
232:           end

Access the Conditions instance

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 173
173:           def conditions
174:             @conditions
175:           end

Access the Conditions instance

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 173
173:           def conditions
174:             @conditions
175:           end

Are any conditions present?

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 256
256:           def conditions_empty?
257:             @conditions.empty?
258:           end

Are any conditions present?

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 256
256:           def conditions_empty?
257:             @conditions.empty?
258:           end

expression_to_sql takes a set of arguments, and turns them into a an Array of generated SQL, followed by optional Values to interpolate as SQL-Parameters.

Parameters: clause The name of the column as a Symbol, a raw-SQL String, a Mappings::Column instance, or a Symbol::Operator. value The Value for the condition. collector An Array representing all conditions that is appended to by expression_to_sql

Returns: Undefined Output. The work performed is added to the collector argument. Example:

  conditions = []
  expression_to_sql(:name, 'Bob', conditions)
  => +undefined return value+
  conditions.inspect
  => ["name = ?", 'Bob']

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 344
344:           def expression_to_sql(clause, value, collector)
345:             qualify_columns = qualify_columns?
346: 
347:             case clause
348:             when Symbol::Operator then
349:               operator = case clause.type
350:               when :gt then '>'
351:               when :gte then '>='
352:               when :lt then '<'
353:               when :lte then '<='
354:               when :not then inequality_operator(value)
355:               when :eql then equality_operator(value)
356:               when :like then equality_operator(value, 'LIKE')
357:               when :in then equality_operator(value)
358:               else raise ArgumentError.new('Operator type not supported')
359:               end
360:               collector << ["#{primary_class_table[clause].to_sql(qualify_columns)} #{operator} ?", value]
361:             when Symbol then
362:               collector << ["#{primary_class_table[clause].to_sql(qualify_columns)} #{equality_operator(value)} ?", value]
363:             when String then
364:               collector << [clause, *value]
365:             when Mappings::Column then
366:               collector << ["#{clause.to_sql(qualify_columns)} #{equality_operator(value)} ?", value]
367:             else raise "CAN HAS CRASH? #{clause.inspect}"
368:             end
369:           rescue => e
370:             if e.is_a?(ConditionsError)
371:               raise e
372:             else
373:               raise ConditionsError.new(clause, value, e)
374:             end
375:           end

expression_to_sql takes a set of arguments, and turns them into a an Array of generated SQL, followed by optional Values to interpolate as SQL-Parameters.

Parameters: clause The name of the column as a Symbol, a raw-SQL String, a Mappings::Column instance, or a Symbol::Operator. value The Value for the condition. collector An Array representing all conditions that is appended to by expression_to_sql

Returns: Undefined Output. The work performed is added to the collector argument. Example:

  conditions = []
  expression_to_sql(:name, 'Bob', conditions)
  => +undefined return value+
  conditions.inspect
  => ["name = ?", 'Bob']

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 344
344:           def expression_to_sql(clause, value, collector)
345:             qualify_columns = qualify_columns?
346: 
347:             case clause
348:             when Symbol::Operator then
349:               operator = case clause.type
350:               when :gt then '>'
351:               when :gte then '>='
352:               when :lt then '<'
353:               when :lte then '<='
354:               when :not then inequality_operator(value)
355:               when :eql then equality_operator(value)
356:               when :like then equality_operator(value, 'LIKE')
357:               when :in then equality_operator(value)
358:               else raise ArgumentError.new('Operator type not supported')
359:               end
360:               collector << ["#{primary_class_table[clause].to_sql(qualify_columns)} #{operator} ?", value]
361:             when Symbol then
362:               collector << ["#{primary_class_table[clause].to_sql(qualify_columns)} #{equality_operator(value)} ?", value]
363:             when String then
364:               collector << [clause, *value]
365:             when Mappings::Column then
366:               collector << ["#{clause.to_sql(qualify_columns)} #{equality_operator(value)} ?", value]
367:             else raise "CAN HAS CRASH? #{clause.inspect}"
368:             end
369:           rescue => e
370:             if e.is_a?(ConditionsError)
371:               raise e
372:             else
373:               raise ConditionsError.new(clause, value, e)
374:             end
375:           end

Display an overview of load options at a glance.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 159
159:           def inspect
160:             "#<\#{self.class.name}:0x%x\n@database=\#{@adapter.name}\n@reload=\#{@reload.inspect}\n@order=\#{@order.inspect}\n@limit=\#{@limit.inspect}\n@offset=\#{@offset.inspect}\n@options=\#{@options.inspect}>\n".compress_lines % (object_id * 2)
161:           end

Display an overview of load options at a glance.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 159
159:           def inspect
160:             "#<\#{self.class.name}:0x%x\n@database=\#{@adapter.name}\n@reload=\#{@reload.inspect}\n@order=\#{@order.inspect}\n@limit=\#{@limit.inspect}\n@offset=\#{@offset.inspect}\n@options=\#{@options.inspect}>\n".compress_lines % (object_id * 2)
161:           end

Determine if there is a limitation on the number of instances returned in the results. If nil, no limit is set. Can be used in conjunction with offset for paging through a set of results.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 187
187:           def limit
188:             @limit
189:           end

Determine if there is a limitation on the number of instances returned in the results. If nil, no limit is set. Can be used in conjunction with offset for paging through a set of results.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 187
187:           def limit
188:             @limit
189:           end

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 234
234:           def load(reader)          
235:             # The following blocks are identical aside from the yield.
236:             # It's written this way to avoid a conditional within each
237:             # iterator, and to take advantage of the performance of
238:             # yield vs. Proc#call.
239:             if block_given?
240:               reader.each do
241:                 @loaders.each_pair do |klass,loader|
242:                   row = reader.current_row
243:                   yield(loader.materialize(row), @columns, row)
244:                 end
245:               end
246:             else
247:               reader.each do
248:                 @loaders.each_pair do |klass,loader|
249:                   loader.materialize(reader.current_row)
250:                 end
251:               end
252:             end
253:           end

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 234
234:           def load(reader)          
235:             # The following blocks are identical aside from the yield.
236:             # It's written this way to avoid a conditional within each
237:             # iterator, and to take advantage of the performance of
238:             # yield vs. Proc#call.
239:             if block_given?
240:               reader.each do
241:                 @loaders.each_pair do |klass,loader|
242:                   row = reader.current_row
243:                   yield(loader.materialize(row), @columns, row)
244:                 end
245:               end
246:             else
247:               reader.each do
248:                 @loaders.each_pair do |klass,loader|
249:                   loader.materialize(reader.current_row)
250:                 end
251:               end
252:             end
253:           end

Used in conjunction with limit to page through a set of results.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 193
193:           def offset
194:             @offset
195:           end

Used in conjunction with limit to page through a set of results.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 193
193:           def offset
194:             @offset
195:           end

If more than one table is involved in the query, the column definitions should be qualified by the table name. ie: people.name This method determines wether that needs to happen or not. Note: After the first call, the calculations are avoided by overwriting this method with a simple getter.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 320
320:           def qualify_columns?
321:             @qualify_columns = !(included_associations.empty? && shallow_included_associations.empty?)
322:             def self.qualify_columns?
323:               @qualify_columns
324:             end
325:             @qualify_columns
326:           end

If more than one table is involved in the query, the column definitions should be qualified by the table name. ie: people.name This method determines wether that needs to happen or not. Note: After the first call, the calculations are avoided by overwriting this method with a simple getter.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 320
320:           def qualify_columns?
321:             @qualify_columns = !(included_associations.empty? && shallow_included_associations.empty?)
322:             def self.qualify_columns?
323:               @qualify_columns
324:             end
325:             @qualify_columns
326:           end

If true then force the command to reload any objects already existing in the IdentityMap when executing.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 179
179:           def reload?
180:             @reload
181:           end

If true then force the command to reload any objects already existing in the IdentityMap when executing.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 179
179:           def reload?
180:             @reload
181:           end

Generate a select statement based on the initialization arguments.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 262
262:           def to_parameterized_sql
263:             parameters = []
264:             
265:             sql = 'SELECT ' << columns_for_select.join(', ')
266:             sql << ' FROM ' << from_table_name            
267:             
268:             included_associations.each do |association|
269:               sql << ' ' << association.to_sql
270:             end
271:             
272:             shallow_included_associations.each do |association|
273:               sql << ' ' << association.to_shallow_sql
274:             end
275:             
276:             unless conditions_empty?
277:               sql << ' WHERE ('
278:               
279:               last_index = @conditions.size
280:               current_index = 0
281:               
282:               @conditions.each do |condition|
283:                 case condition
284:                 when String then sql << condition
285:                 when Array then
286:                     sql << condition.shift
287:                     parameters += condition
288:                 else
289:                   raise "Unable to parse condition: #{condition.inspect}" if condition
290:                 end
291:                 
292:                 if (current_index += 1) == last_index
293:                   sql << ')'
294:                 else
295:                   sql << ') AND ('
296:                 end
297:               end
298:             end # unless conditions_empty?
299:             
300:             unless @order.nil?
301:               sql << ' ORDER BY ' << @order.to_s
302:             end
303:         
304:             unless @limit.nil?
305:               sql << ' LIMIT ' << @limit.to_s
306:             end
307:             
308:             unless @offset.nil?
309:               sql << ' OFFSET ' << @offset.to_s
310:             end
311:             
312:             parameters.unshift(sql)
313:           end

Generate a select statement based on the initialization arguments.

[Source]

     # File lib/data_mapper/adapters/sql/commands/load_command.rb, line 262
262:           def to_parameterized_sql
263:             parameters = []
264:             
265:             sql = 'SELECT ' << columns_for_select.join(', ')
266:             sql << ' FROM ' << from_table_name            
267:             
268:             included_associations.each do |association|
269:               sql << ' ' << association.to_sql
270:             end
271:             
272:             shallow_included_associations.each do |association|
273:               sql << ' ' << association.to_shallow_sql
274:             end
275:             
276:             unless conditions_empty?
277:               sql << ' WHERE ('
278:               
279:               last_index = @conditions.size
280:               current_index = 0
281:               
282:               @conditions.each do |condition|
283:                 case condition
284:                 when String then sql << condition
285:                 when Array then
286:                     sql << condition.shift
287:                     parameters += condition
288:                 else
289:                   raise "Unable to parse condition: #{condition.inspect}" if condition
290:                 end
291:                 
292:                 if (current_index += 1) == last_index
293:                   sql << ')'
294:                 else
295:                   sql << ') AND ('
296:                 end
297:               end
298:             end # unless conditions_empty?
299:             
300:             unless @order.nil?
301:               sql << ' ORDER BY ' << @order.to_s
302:             end
303:         
304:             unless @limit.nil?
305:               sql << ' LIMIT ' << @limit.to_s
306:             end
307:             
308:             unless @offset.nil?
309:               sql << ' OFFSET ' << @offset.to_s
310:             end
311:             
312:             parameters.unshift(sql)
313:           end

[Validate]