diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 5949985e4d..75b4c1e653 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -220,11 +220,19 @@ module ActiveRecord @local_tz = nil @table_alias_length = nil @postgresql_version = nil + @statements = Hash.new { |h,k| h[k] = "a#{h.length + 1}" } connect @local_tz = execute('SHOW TIME ZONE').first["TimeZone"] end + def clear_cache! + @statements.each_value do |value| + exec "DEALLOCATE #{value}" + end + @statements.clear + end + # Is this connection alive and ready for queries? def active? if @connection.respond_to?(:status) @@ -250,8 +258,14 @@ module ActiveRecord end end + def reset! + clear_cache! + super + end + # Close the connection. def disconnect! + clear_cache! @connection.close rescue nil end @@ -501,6 +515,30 @@ module ActiveRecord end end + def exec(sql, name = 'SQL', binds = []) + return async_exec(sql, name, binds) if @async + + log(sql, name) do + end + end + + def async_exec(sql, name, binds) + log(sql, name) do + unless @statements.key? sql + @connection.prepare @statements[sql], sql + end + + key = @statements[sql] + + # Clear the queue + @connection.get_last_result + @connection.send_query_prepared(key, []) + @connection.block + result = @connection.get_last_result + ActiveRecord::Result.new(result.fields, result_as_array(result)) + end + end + # Executes an UPDATE query and returns the number of affected tuples. def update_sql(sql, name = nil) super.cmd_tuples diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index 7b72151b57..a61482256a 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -5,6 +5,8 @@ module ActiveRecord class PostgreSQLAdapterTest < ActiveRecord::TestCase def setup @connection = ActiveRecord::Base.connection + @connection.exec('drop table if exists ex') + @connection.exec('create table ex(id serial primary key, data character varying(255))') end def test_table_alias_length @@ -12,6 +14,21 @@ module ActiveRecord @connection.table_alias_length end end + + def test_exec_no_binds + result = @connection.exec('SELECT id, data FROM ex') + assert_equal 0, result.rows.length + assert_equal 2, result.columns.length + assert_equal %w{ id data }, result.columns + + string = @connection.quote('foo') + @connection.exec("INSERT INTO ex (id, data) VALUES (1, #{string})") + result = @connection.exec('SELECT id, data FROM ex') + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [['1', 'foo']], result.rows + end end end end