aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/connection_adapters
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters')
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb17
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb85
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb17
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