postgresql supports prepare statement deletes

This commit is contained in:
Aaron Patterson 2011-04-28 15:35:19 -07:00
parent 850b3ca477
commit f1df6b2dce
4 changed files with 52 additions and 26 deletions

View File

@ -62,6 +62,13 @@ module ActiveRecord
exec_query(sql, name, binds)
end
# Executes delete +sql+ statement in the context of this connection using
# +binds+ as the bind substitutes. +name+ is the logged along with
# the executed +sql+ statement.
def exec_delete(sql, name, binds)
exec_query(sql, name, binds)
end
# Returns the last auto-generated ID from the affected table.
#
# +id_value+ will be returned unless the value is nil, in
@ -82,8 +89,8 @@ module ActiveRecord
end
# Executes the delete statement and returns the number of rows affected.
def delete(sql, name = nil)
delete_sql(sql, name)
def delete(sql, name = nil, binds = [])
exec_delete(sql, name, binds)
end
# Checks whether there is currently no transaction active. This is done

View File

@ -543,30 +543,26 @@ module ActiveRecord
end
def exec_query(sql, name = 'SQL', binds = [])
return exec_no_cache(sql, name) if binds.empty?
log(sql, name, binds) do
unless @statements.key? sql
nextkey = "a#{@statements.length + 1}"
@connection.prepare nextkey, sql
@statements[sql] = nextkey
end
result = binds.empty? ? exec_no_cache(sql, binds) :
exec_cache(sql, binds)
key = @statements[sql]
# Clear the queue
@connection.get_last_result
@connection.send_query_prepared(key, binds.map { |col, val|
type_cast(val, col)
})
@connection.block
result = @connection.get_last_result
ret = ActiveRecord::Result.new(result.fields, result_as_array(result))
result.clear
return ret
end
end
def exec_delete(sql, name = 'SQL', binds = [])
log(sql, name, binds) do
result = binds.empty? ? exec_no_cache(sql, binds) :
exec_cache(sql, binds)
affected = result.cmd_tuples
result.clear
affected
end
end
def sql_for_insert(sql, pk, id_value, sequence_name, binds)
unless pk
_, table = extract_schema_and_table(sql.split(" ", 4)[2])
@ -980,13 +976,26 @@ module ActiveRecord
end
private
def exec_no_cache(sql, name)
log(sql, name) do
result = @connection.async_exec(sql)
ret = ActiveRecord::Result.new(result.fields, result_as_array(result))
result.clear
ret
def exec_no_cache(sql, binds)
@connection.async_exec(sql)
end
def exec_cache(sql, binds)
unless @statements.key? sql
nextkey = "a#{@statements.length + 1}"
@connection.prepare nextkey, sql
@statements[sql] = nextkey
end
key = @statements[sql]
# Clear the queue
@connection.get_last_result
@connection.send_query_prepared(key, binds.map { |col, val|
type_cast(val, col)
})
@connection.block
@connection.get_last_result
end
# The internal PostgreSQL identifier of the money data type.

View File

@ -77,7 +77,15 @@ module ActiveRecord
def destroy
if persisted?
IdentityMap.remove(self) if IdentityMap.enabled?
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all
pk = self.class.primary_key
column = self.class.columns_hash[pk]
substitute = connection.substitute_at(column, 0)
relation = self.class.unscoped.where(
self.class.arel_table[pk].eq(substitute))
relation.bind_values = [[column, id]]
relation.delete_all
end
@destroyed = true

View File

@ -338,7 +338,9 @@ module ActiveRecord
where(conditions).delete_all
else
statement = arel.compile_delete
affected = @klass.connection.delete statement.to_sql
affected = @klass.connection.delete(
statement.to_sql, 'SQL', bind_values)
reset
affected
end