1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
|
module DataObjects
# Abstract base class for adapter-specific Command subclasses
class Command
# The Connection on which the command will be run
attr_reader :connection
# Create a new Command object on the specified connection
def initialize(connection, text)
raise ArgumentError.new("+connection+ must be a DataObjects::Connection") unless DataObjects::Connection === connection
@connection, @text = connection, text
end
# Execute this command and return no dataset
def execute_non_query(*args)
raise NotImplementedError.new
end
# Execute this command and return a DataObjects::Reader for a dataset
def execute_reader(*args)
raise NotImplementedError.new
end
# Assign an array of types for the columns to be returned by this command
def set_types(column_types)
raise NotImplementedError.new
end
# Display the command text
def to_s
@text
end
private
# Escape a string of SQL with a set of arguments.
# The first argument is assumed to be the SQL to escape,
# the remaining arguments (if any) are assumed to be
# values to escape and interpolate.
#
# ==== Examples
# escape_sql("SELECT * FROM zoos")
# # => "SELECT * FROM zoos"
#
# escape_sql("SELECT * FROM zoos WHERE name = ?", "Dallas")
# # => "SELECT * FROM zoos WHERE name = `Dallas`"
#
# escape_sql("SELECT * FROM zoos WHERE name = ? AND acreage > ?", "Dallas", 40)
# # => "SELECT * FROM zoos WHERE name = `Dallas` AND acreage > 40"
#
# ==== Warning
# This method is meant mostly for adapters that don't support
# bind-parameters.
def escape_sql(args)
sql = @text.dup
vars = args.dup
replacements = 0
mismatch = false
sql.gsub!(/'[^']*'|"[^"]*"|`[^`]*`|\?/) do |x|
next x unless x == '?'
replacements += 1
if vars.empty?
mismatch = true
else
var = vars.shift
connection.quote_value(var)
end
end
if !vars.empty? || mismatch
raise ArgumentError, "Binding mismatch: #{args.size} for #{replacements}"
else
sql
end
end
end
end
|