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/connection_pool.rb17
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb16
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb15
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb15
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql/quoting.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb12
14 files changed, 92 insertions, 58 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 9b74c3a10f..dc5b305843 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -849,6 +849,21 @@ module ActiveRecord
remove_connection(spec.name)
owner_to_pool[spec.name] = ConnectionAdapters::ConnectionPool.new(spec)
+
+ message_bus = ActiveSupport::Notifications.instrumenter
+ payload = {
+ connection_id: object_id
+ }
+ if spec
+ payload[:spec_name] = spec.name
+ payload[:config] = spec.config
+ end
+
+ message_bus.instrument('!connection.active_record', payload) do
+ owner_to_pool[spec.name] = ConnectionAdapters::ConnectionPool.new(spec)
+ end
+
+ owner_to_pool[spec.name]
end
# Returns true if there are any active connections among the connection
@@ -881,7 +896,7 @@ module ActiveRecord
# for (not necessarily the current class).
def retrieve_connection(spec_name) #:nodoc:
pool = retrieve_connection_pool(spec_name)
- raise ConnectionNotEstablished, "No connection pool with id '#{spec_name}' found." unless pool
+ raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found." unless pool
conn = pool.connection
raise ConnectionNotEstablished, "No connection for '#{spec_name}' in connection pool" unless conn
conn
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 507a925d32..e667e16964 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb
@@ -10,7 +10,7 @@ module ActiveRecord
def to_sql(arel, binds = [])
if arel.respond_to?(:ast)
collected = visitor.accept(arel.ast, collector)
- collected.compile(binds.dup, self)
+ collected.compile(binds, self)
else
arel
end
@@ -18,11 +18,12 @@ module ActiveRecord
# This is used in the StatementCache object. It returns an object that
# can be used to query the database repeatedly.
- def cacheable_query(arel) # :nodoc:
+ def cacheable_query(klass, arel) # :nodoc:
+ collected = visitor.accept(arel.ast, collector)
if prepared_statements
- ActiveRecord::StatementCache.query visitor, arel.ast
+ klass.query(collected.value)
else
- ActiveRecord::StatementCache.partial_query visitor, arel.ast, collector
+ klass.partial_query(collected.value)
end
end
@@ -315,7 +316,7 @@ module ActiveRecord
end
end
key_list = fixture.keys.map { |name| quote_column_name(name) }
- value_list = prepare_binds_for_database(binds).map do |value|
+ value_list = binds.map(&:value_for_database).map do |value|
begin
quote(value)
rescue TypeError
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 860ef17dca..eda6af08e3 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -112,19 +112,19 @@ module ActiveRecord
end
def quoted_true
- "'t'"
+ "'t'".freeze
end
def unquoted_true
- 't'
+ 't'.freeze
end
def quoted_false
- "'f'"
+ "'f'".freeze
end
def unquoted_false
- 'f'
+ 'f'.freeze
end
# Quote date/time values for use in SQL input. Includes microseconds
@@ -150,12 +150,12 @@ module ActiveRecord
quoted_date(value).sub(/\A2000-01-01 /, '')
end
- def prepare_binds_for_database(binds) # :nodoc:
- binds.map(&:value_for_database)
- end
-
private
+ def type_casted_binds(binds)
+ binds.map { |attr| type_cast(attr.value_for_database) }
+ end
+
def types_which_need_no_typecasting
[nil, Numeric, String]
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index cffd7e8e81..19c265db6e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -129,14 +129,9 @@ module ActiveRecord
# Returns just a table's primary key
def primary_key(table_name)
- pks = primary_keys(table_name)
- warn <<-WARNING.strip_heredoc if pks.count > 1
- WARNING: Rails does not support composite primary key.
-
- #{table_name} has composite primary key. Composite primary key is ignored.
- WARNING
-
- pks.first if pks.one?
+ pk = primary_keys(table_name)
+ pk = pk.first unless pk.size > 1
+ pk
end
# Creates a new table with the name +table_name+. +table_name+ may either
@@ -998,8 +993,8 @@ module ActiveRecord
sm_table = ActiveRecord::Migrator.schema_migrations_table_name
if supports_multi_insert?
- sql = "INSERT INTO #{sm_table} (version) VALUES "
- sql << versions.map {|v| "('#{v}')" }.join(', ')
+ sql = "INSERT INTO #{sm_table} (version) VALUES\n"
+ sql << versions.map {|v| "('#{v}')" }.join(",\n")
sql << ";\n\n"
sql
else
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 5747e4d1ee..0b8bacff4e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -130,7 +130,7 @@ module ActiveRecord
class BindCollector < Arel::Collectors::Bind
def compile(bvs, conn)
- casted_binds = conn.prepare_binds_for_database(bvs)
+ casted_binds = bvs.map(&:value_for_database)
super(casted_binds.map { |value| conn.quote(value) })
end
end
@@ -579,14 +579,15 @@ module ActiveRecord
exception
end
- def log(sql, name = "SQL", binds = [], statement_name = nil)
+ def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil)
@instrumenter.instrument(
"sql.active_record",
- :sql => sql,
- :name => name,
- :connection_id => object_id,
- :statement_name => statement_name,
- :binds => binds) { yield }
+ sql: sql,
+ name: name,
+ binds: binds,
+ type_casted_binds: type_casted_binds,
+ statement_name: statement_name,
+ connection_id: object_id) { yield }
rescue => e
raise translate_exception_class(e, sql)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 3e77b92141..610d78245f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -9,6 +9,7 @@ require 'active_record/connection_adapters/mysql/schema_dumper'
require 'active_record/connection_adapters/mysql/type_metadata'
require 'active_support/core_ext/string/strip'
+require 'active_support/core_ext/regexp'
module ActiveRecord
module ConnectionAdapters
@@ -85,7 +86,7 @@ module ActiveRecord
end
def mariadb? # :nodoc:
- full_version =~ /mariadb/i
+ /mariadb/i.match?(full_version)
end
# Returns true, since this connection adapter supports migrations.
@@ -409,10 +410,13 @@ module ActiveRecord
end
def table_comment(table_name) # :nodoc:
+ schema, name = extract_schema_qualified_name(table_name)
+
select_value(<<-SQL.strip_heredoc, 'SCHEMA')
SELECT table_comment
FROM information_schema.tables
- WHERE table_name=#{quote(table_name)}
+ WHERE table_schema = #{quote(schema)}
+ AND table_name = #{quote(name)}
SQL
end
@@ -543,7 +547,9 @@ module ActiveRecord
end
end
- def table_options(table_name)
+ def table_options(table_name) # :nodoc:
+ table_options = {}
+
create_table_info = create_table_info(table_name)
# strip create_definitions and partition_options
@@ -552,10 +558,14 @@ module ActiveRecord
# strip AUTO_INCREMENT
raw_table_options.sub!(/(ENGINE=\w+)(?: AUTO_INCREMENT=\d+)/, '\1')
+ table_options[:options] = raw_table_options
+
# strip COMMENT
- raw_table_options.sub!(/ COMMENT='.+'/, '')
+ if raw_table_options.sub!(/ COMMENT='.+'/, '')
+ table_options[:comment] = table_comment(table_name)
+ end
- raw_table_options
+ table_options
end
# Maps logical Rails types to MySQL-specific data types.
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb
index 87f0ff7d85..6d1215df2a 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb
@@ -77,9 +77,9 @@ module ActiveRecord
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
end
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
+ type_casted_binds = type_casted_binds(binds)
- log(sql, name, binds) do
+ log(sql, name, binds, type_casted_binds) do
if cache_stmt
cache = @statements[sql] ||= {
stmt: @connection.prepare(sql)
diff --git a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb
index fbab654112..af1db30047 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb
@@ -2,14 +2,14 @@ module ActiveRecord
module ConnectionAdapters
module MySQL
module Quoting # :nodoc:
- QUOTED_TRUE, QUOTED_FALSE = '1', '0'
+ QUOTED_TRUE, QUOTED_FALSE = '1'.freeze, '0'.freeze
def quote_column_name(name)
- @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
+ @quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`".freeze
end
def quote_table_name(name)
- @quoted_table_names[name] ||= super.gsub('.', '`.`')
+ @quoted_table_names[name] ||= super.gsub('.', '`.`').freeze
end
def quoted_true
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
index 6f2e03b370..f5232127c4 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
@@ -124,6 +124,8 @@ module ActiveRecord
pk = primary_key(table_ref) if table_ref
end
+ pk = suppress_composite_primary_key(pk)
+
if pk && use_insert_returning?
sql = "#{sql} RETURNING #{quote_column_name(pk)}"
end
@@ -164,6 +166,12 @@ module ActiveRecord
def exec_rollback_db_transaction
execute "ROLLBACK"
end
+
+ private
+
+ def suppress_composite_primary_key(pk)
+ pk unless pk.is_a?(Array)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index 6414459cd1..9fcf8dbb95 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -28,7 +28,7 @@ module ActiveRecord
# - "schema.name".table_name
# - "schema.name"."table.name"
def quote_table_name(name) # :nodoc:
- @quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted
+ @quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted.freeze
end
# Quotes schema names for use in SQL queries.
@@ -42,7 +42,7 @@ module ActiveRecord
# Quotes column names for use in SQL queries.
def quote_column_name(name) # :nodoc:
- @quoted_column_names[name] ||= PGconn.quote_ident(super)
+ @quoted_column_names[name] ||= PGconn.quote_ident(super).freeze
end
# Quote date/time values for use in SQL input.
@@ -58,7 +58,7 @@ module ActiveRecord
def quote_default_expression(value, column) # :nodoc:
if value.is_a?(Proc)
value.call
- elsif column.type == :uuid && value =~ /\(\)/
+ elsif column.type == :uuid && value.include?('()')
value # Does not quote function default values for UUID columns
elsif column.respond_to?(:array?)
value = type_cast_from_column(column, value)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 45507e206a..4cf6d4b14a 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -238,6 +238,10 @@ module ActiveRecord
PostgreSQLColumn.new(*args)
end
+ def table_options(table_name) # :nodoc:
+ { comment: table_comment(table_name) }
+ end
+
# Returns a comment stored in database for given table
def table_comment(table_name) # :nodoc:
name = Utils.extract_schema_qualified_name(table_name.to_s)
@@ -327,12 +331,12 @@ module ActiveRecord
end
# Returns the sequence name for a table's primary key or some other specified key.
- def default_sequence_name(table_name, pk = nil) #:nodoc:
- result = serial_sequence(table_name, pk || 'id')
+ def default_sequence_name(table_name, pk = 'id') #:nodoc:
+ result = serial_sequence(table_name, pk)
return nil unless result
Utils.extract_schema_qualified_name(result).to_s
rescue ActiveRecord::StatementInvalid
- PostgreSQL::Name.new(nil, "#{table_name}_#{pk || 'id'}_seq").to_s
+ PostgreSQL::Name.new(nil, "#{table_name}_#{pk}_seq").to_s
end
def serial_sequence(table, column)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index ddfc560747..61a980fda9 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -597,15 +597,15 @@ module ActiveRecord
end
def exec_no_cache(sql, name, binds)
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
- log(sql, name, binds) { @connection.async_exec(sql, type_casted_binds) }
+ type_casted_binds = type_casted_binds(binds)
+ log(sql, name, binds, type_casted_binds) { @connection.async_exec(sql, type_casted_binds) }
end
def exec_cache(sql, name, binds)
stmt_key = prepare_statement(sql)
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
+ type_casted_binds = type_casted_binds(binds)
- log(sql, name, binds, stmt_key) do
+ log(sql, name, binds, type_casted_binds, stmt_key) do
@connection.exec_prepared(stmt_key, type_casted_binds)
end
rescue ActiveRecord::StatementInvalid => e
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
index d5a181d3e2..fa20175b0e 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb
@@ -11,7 +11,7 @@ module ActiveRecord
end
def quote_column_name(name)
- @quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}")
+ @quoted_column_names[name] ||= %Q("#{super.gsub('"', '""')}").freeze
end
def quoted_time(value)
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index eb2268157b..41ed784d2e 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -159,7 +159,7 @@ module ActiveRecord
end
# Returns 62. SQLite supports index names up to 64
- # characters. The rest is used by rails internally to perform
+ # characters. The rest is used by Rails internally to perform
# temporary rename operations
def allowed_index_name_length
index_name_length - 2
@@ -188,9 +188,9 @@ module ActiveRecord
end
def exec_query(sql, name = nil, binds = [], prepare: false)
- type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
+ type_casted_binds = type_casted_binds(binds)
- log(sql, name, binds) do
+ log(sql, name, binds, type_casted_binds) do
# Don't cache statements if they are not prepared
unless prepare
stmt = @connection.prepare(sql)
@@ -203,7 +203,6 @@ module ActiveRecord
ensure
stmt.close
end
- stmt = records
else
cache = @statements[sql] ||= {
:stmt => @connection.prepare(sql)
@@ -212,9 +211,10 @@ module ActiveRecord
cols = cache[:cols] ||= stmt.columns
stmt.reset!
stmt.bind_params(type_casted_binds)
+ records = stmt.to_a
end
- ActiveRecord::Result.new(cols, stmt.to_a)
+ ActiveRecord::Result.new(cols, records)
end
end
@@ -548,7 +548,7 @@ module ActiveRecord
columns_string.split(',').each do |column_string|
# This regex will match the column name and collation type and will save
# the value in $1 and $2 respectively.
- collation_hash[$1] = $2 if (COLLATE_REGEX =~ column_string)
+ collation_hash[$1] = $2 if COLLATE_REGEX =~ column_string
end
basic_structure.map! do |column|