diff options
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters')
5 files changed, 70 insertions, 64 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 6d9b5c7b32..70da9d5f1e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -55,6 +55,13 @@ module ActiveRecord def exec_query(sql, name = 'SQL', binds = []) end + # Executes insert +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_insert(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 @@ -280,10 +287,6 @@ module ActiveRecord execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert' end - def null_insert_value - Arel.sql 'DEFAULT' - end - def empty_insert_statement_value "VALUES(DEFAULT)" end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index d24cce0a3c..468a2b106b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -223,7 +223,9 @@ module ActiveRecord rescue Exception => e message = "#{e.class.name}: #{e.message}: #{sql}" @logger.debug message if @logger - raise translate_exception(e, message) + exception = translate_exception(e, message) + exception.set_backtrace e.backtrace + raise exception end def translate_exception(e, message) diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index c2e75acb9a..2c05ff21f9 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -208,16 +208,18 @@ module ActiveRecord true end - # Returns +true+ when the connection adapter supports prepared statement - # caching, otherwise returns +false+ + # Returns +true+, since this connection adapter supports prepared statement + # caching. def supports_statement_cache? true end + # Returns true. def supports_migrations? #:nodoc: true end + # Returns true. def supports_primary_key? #:nodoc: true end @@ -308,6 +310,8 @@ module ActiveRecord connect end + # Disconnects from the database if already connected. Otherwise, this + # method does nothing. def disconnect! @connection.close rescue nil end @@ -330,6 +334,7 @@ module ActiveRecord rows end + # Clears the prepared statements cache. def clear_cache! @statements.values.each do |cache| cache[:stmt].close @@ -427,10 +432,6 @@ module ActiveRecord end end - def exec_insert(sql, name, binds) - exec_query(sql, name, binds) - end - def last_inserted_id(result) @connection.insert_id end @@ -558,6 +559,10 @@ module ActiveRecord end end + # Drops a MySQL database. + # + # Example: + # drop_database 'sebastian_development' def drop_database(name) #:nodoc: execute "DROP DATABASE IF EXISTS `#{name}`" end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 4e6d9ae087..0c2afc180b 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -1,6 +1,9 @@ require 'active_record/connection_adapters/abstract_adapter' require 'active_support/core_ext/kernel/requires' require 'active_support/core_ext/object/blank' + +# Make sure we're using pg high enough for PGResult#values +gem 'pg', '~> 0.11' require 'pg' module ActiveRecord @@ -220,8 +223,8 @@ module ActiveRecord ADAPTER_NAME end - # Returns +true+ when the connection adapter supports prepared statement - # caching, otherwise returns +false+ + # Returns +true+, since this connection adapter supports prepared statement + # caching. def supports_statement_cache? true end @@ -246,6 +249,7 @@ module ActiveRecord @local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"] end + # Clears the prepared statements cache. def clear_cache! @statements.each_value do |value| @connection.query "DEALLOCATE #{value}" @@ -284,7 +288,8 @@ module ActiveRecord super end - # Close the connection. + # Disconnects from the database if already connected. Otherwise, this + # method does nothing. def disconnect! clear_cache! @connection.close rescue nil @@ -469,42 +474,43 @@ module ActiveRecord # create a 2D array representing the result set def result_as_array(res) #:nodoc: # check if we have any binary column and if they need escaping - unescape_col = [] - res.nfields.times do |j| - unescape_col << res.ftype(j) + ftypes = Array.new(res.nfields) do |i| + [i, res.ftype(i)] end - ary = [] - res.ntuples.times do |i| - ary << [] - res.nfields.times do |j| - data = res.getvalue(i,j) - case unescape_col[j] - - # unescape string passed BYTEA field (OID == 17) - when BYTEA_COLUMN_TYPE_OID - data = unescape_bytea(data) if String === data - - # If this is a money type column and there are any currency symbols, - # then strip them off. Indeed it would be prettier to do this in - # PostgreSQLColumn.string_to_decimal but would break form input - # fields that call value_before_type_cast. - when MONEY_COLUMN_TYPE_OID - # Because money output is formatted according to the locale, there are two - # cases to consider (note the decimal separators): - # (1) $12,345,678.12 - # (2) $12.345.678,12 - case data - when /^-?\D+[\d,]+\.\d{2}$/ # (1) - data.gsub!(/[^-\d.]/, '') - when /^-?\D+[\d.]+,\d{2}$/ # (2) - data.gsub!(/[^-\d,]/, '').sub!(/,/, '.') - end + rows = res.values + return rows unless ftypes.any? { |_, x| + x == BYTEA_COLUMN_TYPE_OID || x == MONEY_COLUMN_TYPE_OID + } + + typehash = ftypes.group_by { |_, type| type } + binaries = typehash[BYTEA_COLUMN_TYPE_OID] || [] + monies = typehash[MONEY_COLUMN_TYPE_OID] || [] + + rows.each do |row| + # unescape string passed BYTEA field (OID == 17) + binaries.each do |index, _| + row[index] = unescape_bytea(row[index]) + end + + # If this is a money type column and there are any currency symbols, + # then strip them off. Indeed it would be prettier to do this in + # PostgreSQLColumn.string_to_decimal but would break form input + # fields that call value_before_type_cast. + monies.each do |index, _| + data = row[index] + # Because money output is formatted according to the locale, there are two + # cases to consider (note the decimal separators): + # (1) $12,345,678.12 + # (2) $12.345.678,12 + case data + when /^-?\D+[\d,]+\.\d{2}$/ # (1) + data.gsub!(/[^-\d.]/, '') + when /^-?\D+[\d.]+,\d{2}$/ # (2) + data.gsub!(/[^-\d,]/, '').sub!(/,/, '.') end - ary[i] << data end end - return ary end @@ -561,10 +567,6 @@ module ActiveRecord end end - def exec_insert(sql, name, binds) - exec_query(sql, name, binds) - end - def sql_for_insert(sql, pk, id_value, sequence_name, binds) unless pk _, table = extract_schema_and_table(sql.split(" ", 4)[2]) @@ -650,7 +652,7 @@ module ActiveRecord execute "CREATE DATABASE #{quote_table_name(name)}#{option_string}" end - # Drops a PostgreSQL database + # Drops a PostgreSQL database. # # Example: # drop_database 'matt_development' @@ -942,10 +944,7 @@ module ActiveRecord order_columns.delete_if { |c| c.blank? } order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" } - # Return a DISTINCT ON() clause that's distinct on the columns we want but includes - # all the required columns for the ORDER BY to work properly. - sql = "DISTINCT #{columns}, " - sql << order_columns * ', ' + "DISTINCT #{columns}, #{order_columns * ', '}" end protected diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 9e7f874f4b..ed5006dcec 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -66,16 +66,18 @@ module ActiveRecord sqlite_version >= '3.6.8' end - # Returns +true+ when the connection adapter supports prepared statement - # caching, otherwise returns +false+ + # Returns true, since this connection adapter supports prepared statement + # caching. def supports_statement_cache? true end + # Returns true. def supports_migrations? #:nodoc: true end + # Returns true. def supports_primary_key? #:nodoc: true end @@ -88,12 +90,15 @@ module ActiveRecord sqlite_version >= '3.1.6' end + # Disconnects from the database if already connected. Otherwise, this + # method does nothing. def disconnect! super clear_cache! @connection.close rescue nil end + # Clears the prepared statements cache. def clear_cache! @statements.clear end @@ -173,10 +178,6 @@ module ActiveRecord end end - def exec_insert(sql, name, binds) - exec_query(sql, name, binds) - end - def last_inserted_id(result) @connection.last_insert_row_id end @@ -345,10 +346,6 @@ module ActiveRecord alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s}) end - def null_insert_value - Arel.sql 'NULL' - end - def empty_insert_statement_value "VALUES(NULL)" end |