Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5-1-stable: Don't cache queries for schema statements #29875

Merged
merged 1 commit into from
Jul 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ def select_one(arel, name = nil, binds = [])

# Returns a single value from a record
def select_value(arel, name = nil, binds = [])
if result = select_rows(arel, name, binds).first
result.first
end
single_value_from_rows(select_rows(arel, name, binds))
end

# Returns an array of the values of the first column in a select:
Expand All @@ -68,6 +66,18 @@ def select_rows(arel, name = nil, binds = [])
select_all(arel, name, binds).rows
end

def query_value(sql, name = nil) # :nodoc:
single_value_from_rows(query(sql, name))
end

def query_values(sql, name = nil) # :nodoc:
query(sql, name).map(&:first)
end

def query(sql, name = nil) # :nodoc:
exec_query(sql, name).rows
end

# Executes the SQL statement in the context of this connection and returns
# the raw result from the connection adapter.
# Note: depending on your database connector, the result returned by this
Expand Down Expand Up @@ -370,7 +380,11 @@ def sql_for_insert(sql, pk, id_value, sequence_name, binds)
end

def last_inserted_id(result)
row = result.rows.first
single_value_from_rows(result.rows)
end

def single_value_from_rows(rows)
row = rows.first
row && row.first
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def table_alias_for(table_name)
# Returns the relation names useable to back Active Record models.
# For most adapters this means all #tables and #views.
def data_sources
select_values(data_source_sql, "SCHEMA")
query_values(data_source_sql, "SCHEMA")
rescue NotImplementedError
tables | views
end
Expand All @@ -41,37 +41,37 @@ def data_sources
# data_source_exists?(:ebooks)
#
def data_source_exists?(name)
select_values(data_source_sql(name), "SCHEMA").any? if name.present?
query_values(data_source_sql(name), "SCHEMA").any? if name.present?
rescue NotImplementedError
data_sources.include?(name.to_s)
end

# Returns an array of table names defined in the database.
def tables
select_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
end

# Checks to see if the table +table_name+ exists on the database.
#
# table_exists?(:developers)
#
def table_exists?(table_name)
select_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
rescue NotImplementedError
tables.include?(table_name.to_s)
end

# Returns an array of view names defined in the database.
def views
select_values(data_source_sql(type: "VIEW"), "SCHEMA")
query_values(data_source_sql(type: "VIEW"), "SCHEMA")
end

# Checks to see if the view +view_name+ exists on the database.
#
# view_exists?(:ebooks)
#
def view_exists?(view_name)
select_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
rescue NotImplementedError
views.include?(view_name.to_s)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ def supports_advisory_locks?
end

def get_advisory_lock(lock_name, timeout = 0) # :nodoc:
select_value("SELECT GET_LOCK(#{quote(lock_name)}, #{timeout})") == 1
query_value("SELECT GET_LOCK(#{quote(lock_name)}, #{timeout})") == 1
end

def release_advisory_lock(lock_name) # :nodoc:
select_value("SELECT RELEASE_LOCK(#{quote(lock_name)})") == 1
query_value("SELECT RELEASE_LOCK(#{quote(lock_name)})") == 1
end

def native_database_types
Expand Down Expand Up @@ -176,7 +176,7 @@ def error_number(exception) # :nodoc:
# REFERENTIAL INTEGRITY ====================================

def disable_referential_integrity #:nodoc:
old = select_value("SELECT @@FOREIGN_KEY_CHECKS")
old = query_value("SELECT @@FOREIGN_KEY_CHECKS")

begin
update("SET FOREIGN_KEY_CHECKS = 0")
Expand Down Expand Up @@ -291,7 +291,7 @@ def drop_database(name) #:nodoc:
end

def current_database
select_value "SELECT DATABASE() as db"
query_value("SELECT database()", "SCHEMA")
end

# Returns the database character set.
Expand Down Expand Up @@ -351,7 +351,7 @@ def new_column_from_field(table_name, field) # :nodoc:
def table_comment(table_name) # :nodoc:
scope = quoted_scope(table_name)

select_value(<<-SQL.strip_heredoc, "SCHEMA")
query_value(<<-SQL.strip_heredoc, "SCHEMA")
SELECT table_comment
FROM information_schema.tables
WHERE table_schema = #{scope[:schema]}
Expand Down Expand Up @@ -457,7 +457,7 @@ def foreign_keys(table_name)

scope = quoted_scope(table_name)

fk_info = select_all(<<-SQL.strip_heredoc, "SCHEMA")
fk_info = exec_query(<<-SQL.strip_heredoc, "SCHEMA")
SELECT fk.referenced_table_name AS 'to_table',
fk.referenced_column_name AS 'primary_key',
fk.column_name AS 'column',
Expand Down Expand Up @@ -534,7 +534,7 @@ def type_to_sql(type, limit: nil, precision: nil, scale: nil, unsigned: nil, **)

# SHOW VARIABLES LIKE 'name'
def show_variable(name)
select_value("SELECT @@#{name}", "SCHEMA")
query_value("SELECT @@#{name}", "SCHEMA")
rescue ActiveRecord::StatementInvalid
nil
end
Expand All @@ -544,7 +544,7 @@ def primary_keys(table_name) # :nodoc:

scope = quoted_scope(table_name)

select_values(<<-SQL.strip_heredoc, "SCHEMA")
query_values(<<-SQL.strip_heredoc, "SCHEMA")
SELECT column_name
FROM information_schema.key_column_usage
WHERE constraint_name = 'PRIMARY'
Expand Down Expand Up @@ -745,7 +745,7 @@ def rename_column_sql(table_name, column_name, new_column_name)
auto_increment: column.auto_increment?
}

current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'", "SCHEMA")["Type"]
current_type = exec_query("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE #{quote(column_name)}", "SCHEMA").first["Type"]
td = create_table_definition(table_name)
cd = td.new_column_definition(new_column_name, current_type, options)
schema_creation.accept(ChangeColumnDefinition.new(cd, column.name))
Expand Down Expand Up @@ -864,7 +864,7 @@ def extract_foreign_key_action(specifier) # :nodoc:
end

def create_table_info(table_name) # :nodoc:
select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"]
exec_query("SHOW CREATE TABLE #{quote_table_name(table_name)}", "SCHEMA").first["Create Table"]
end

def create_table_definition(*args) # :nodoc:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ def select_all(arel, name = nil, binds = [], preparable: nil) # :nodoc:
result
end

def query(sql, name = nil) # :nodoc:
execute(sql, name).to_a
end

# Executes the SQL statement in the context of this connection.
def execute(sql, name = nil)
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def schema_precision(column)
def schema_collation(column)
if column.collation && table_name = column.table_name
@table_collation_cache ||= {}
@table_collation_cache[table_name] ||= select_one("SHOW TABLE STATUS LIKE '#{table_name}'")["Collation"]
@table_collation_cache[table_name] ||= exec_query("SHOW TABLE STATUS LIKE #{quote(table_name)}", "SCHEMA").first["Collation"]
column.collation.inspect if column.collation != @table_collation_cache[table_name]
end
end
Expand All @@ -64,7 +64,7 @@ def extract_expression_for_virtual_column(column)
" WHERE table_schema = #{scope[:schema]}" \
" AND table_name = #{scope[:name]}" \
" AND column_name = #{quote(column.name)}"
select_value(sql, "SCHEMA").inspect
query_value(sql, "SCHEMA").inspect
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ def lookup_cast_type_from_column(column) # :nodoc:
end

private
def lookup_cast_type(sql_type)
super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i)
end

def _quote(value)
case value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def drop_table(table_name, options = {}) # :nodoc:

# Returns true if schema exists.
def schema_exists?(name)
select_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = #{quote(name)}", "SCHEMA").to_i > 0
query_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = #{quote(name)}", "SCHEMA").to_i > 0
end

# Verifies existence of an index with a given name.
Expand All @@ -73,7 +73,7 @@ def index_name_exists?(table_name, index_name, default = nil)
table = quoted_scope(table_name)
index = quoted_scope(index_name)

select_value(<<-SQL, "SCHEMA").to_i > 0
query_value(<<-SQL, "SCHEMA").to_i > 0
SELECT COUNT(*)
FROM pg_class t
INNER JOIN pg_index d ON t.oid = d.indrelid
Expand Down Expand Up @@ -173,7 +173,7 @@ def table_options(table_name) # :nodoc:
def table_comment(table_name) # :nodoc:
scope = quoted_scope(table_name, type: "BASE TABLE")
if scope[:name]
select_value(<<-SQL.strip_heredoc, "SCHEMA")
query_value(<<-SQL.strip_heredoc, "SCHEMA")
SELECT pg_catalog.obj_description(c.oid, 'pg_class')
FROM pg_catalog.pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
Expand All @@ -186,32 +186,32 @@ def table_comment(table_name) # :nodoc:

# Returns the current database name.
def current_database
select_value("SELECT current_database()", "SCHEMA")
query_value("SELECT current_database()", "SCHEMA")
end

# Returns the current schema name.
def current_schema
select_value("SELECT current_schema", "SCHEMA")
query_value("SELECT current_schema", "SCHEMA")
end

# Returns the current database encoding format.
def encoding
select_value("SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname LIKE '#{current_database}'", "SCHEMA")
query_value("SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = current_database()", "SCHEMA")
end

# Returns the current database collation.
def collation
select_value("SELECT datcollate FROM pg_database WHERE datname LIKE '#{current_database}'", "SCHEMA")
query_value("SELECT datcollate FROM pg_database WHERE datname = current_database()", "SCHEMA")
end

# Returns the current database ctype.
def ctype
select_value("SELECT datctype FROM pg_database WHERE datname LIKE '#{current_database}'", "SCHEMA")
query_value("SELECT datctype FROM pg_database WHERE datname = current_database()", "SCHEMA")
end

# Returns an array of schema names.
def schema_names
select_values(<<-SQL, "SCHEMA")
query_values(<<-SQL, "SCHEMA")
SELECT nspname
FROM pg_namespace
WHERE nspname !~ '^pg_.*'
Expand Down Expand Up @@ -244,12 +244,12 @@ def schema_search_path=(schema_csv)

# Returns the active schema search path.
def schema_search_path
@schema_search_path ||= select_value("SHOW search_path", "SCHEMA")
@schema_search_path ||= query_value("SHOW search_path", "SCHEMA")
end

# Returns the current client message level.
def client_min_messages
select_value("SHOW client_min_messages", "SCHEMA")
query_value("SHOW client_min_messages", "SCHEMA")
end

# Set the client message level.
Expand All @@ -267,7 +267,7 @@ def default_sequence_name(table_name, pk = "id") #:nodoc:
end

def serial_sequence(table, column)
select_value("SELECT pg_get_serial_sequence('#{table}', '#{column}')", "SCHEMA")
query_value("SELECT pg_get_serial_sequence(#{quote(table)}, #{quote(column)})", "SCHEMA")
end

# Sets the sequence of a table's primary key to the specified value.
Expand All @@ -278,7 +278,7 @@ def set_pk_sequence!(table, value) #:nodoc:
if sequence
quoted_sequence = quote_table_name(sequence)

select_value("SELECT setval('#{quoted_sequence}', #{value})", "SCHEMA")
query_value("SELECT setval(#{quote(quoted_sequence)}, #{value})", "SCHEMA")
else
@logger.warn "#{table} has primary key #{pk} with no default sequence." if @logger
end
Expand All @@ -300,18 +300,16 @@ def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc:

if pk && sequence
quoted_sequence = quote_table_name(sequence)
max_pk = select_value("select MAX(#{quote_column_name pk}) from #{quote_table_name(table)}")
max_pk = query_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}", "SCHEMA")
if max_pk.nil?
if postgresql_version >= 100000
minvalue = select_value("SELECT seqmin from pg_sequence where seqrelid = '#{quoted_sequence}'::regclass")
minvalue = query_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass", "SCHEMA")
else
minvalue = select_value("SELECT min_value FROM #{quoted_sequence}")
minvalue = query_value("SELECT min_value FROM #{quoted_sequence}", "SCHEMA")
end
end

select_value(<<-end_sql, "SCHEMA")
SELECT setval('#{quoted_sequence}', #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false})
end_sql
query_value("SELECT setval(#{quote(quoted_sequence)}, #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false})", "SCHEMA")
end
end

Expand Down Expand Up @@ -370,7 +368,7 @@ def pk_and_sequence_for(table) #:nodoc:
end

def primary_keys(table_name) # :nodoc:
select_values(<<-SQL.strip_heredoc, "SCHEMA")
query_values(<<-SQL.strip_heredoc, "SCHEMA")
SELECT a.attname
FROM (
SELECT indrelid, indkey, generate_subscripts(indkey, 1) idx
Expand Down Expand Up @@ -520,7 +518,7 @@ def rename_index(table_name, old_name, new_name)

def foreign_keys(table_name)
scope = quoted_scope(table_name)
fk_info = select_all(<<-SQL.strip_heredoc, "SCHEMA")
fk_info = exec_query(<<-SQL.strip_heredoc, "SCHEMA")
SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete
FROM pg_constraint c
JOIN pg_class t1 ON c.conrelid = t1.oid
Expand Down