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

Revert "Add prepared statements support for Mysql2Adapter" #22420

Merged
merged 1 commit into from
Nov 26, 2015
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
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ platforms :ruby do
group :db do
gem 'pg', '>= 0.18.0'
gem 'mysql', '>= 2.9.0'
gem 'mysql2', '>= 0.4.2'
gem 'mysql2', '>= 0.4.0'
end
end

Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ GEM
multi_json (1.11.2)
mustache (1.0.2)
mysql (2.9.1)
mysql2 (0.4.2)
mysql2 (0.4.1)
nokogiri (1.6.7.rc3)
mini_portile (~> 0.7.0.rc4)
pg (0.18.3)
Expand Down Expand Up @@ -347,7 +347,7 @@ DEPENDENCIES
minitest (< 5.3.4)
mocha (~> 0.14)
mysql (>= 2.9.0)
mysql2 (>= 0.4.2)
mysql2 (>= 0.4.0)
nokogiri (>= 1.6.7.rc3)
pg (>= 0.18.0)
psych (~> 2.0)
Expand Down
4 changes: 0 additions & 4 deletions activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
* Add prepared statements support for `Mysql2Adapter`.

*Ryuta Kamizono*

* Add schema dumping support for PostgreSQL geometric data types.

*Ryuta Kamizono*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
require 'active_record/connection_adapters/mysql/schema_creation'
require 'active_record/connection_adapters/mysql/schema_definitions'
require 'active_record/connection_adapters/mysql/schema_dumper'
require 'active_record/connection_adapters/statement_pool'

require 'active_support/core_ext/string/strip'

Expand Down Expand Up @@ -142,22 +141,13 @@ def attributes_for_hash
INDEX_TYPES = [:fulltext, :spatial]
INDEX_USINGS = [:btree, :hash]

class StatementPool < ConnectionAdapters::StatementPool
private

def dealloc(stmt)
stmt[:stmt].close
end
end

# FIXME: Make the first parameter more similar for the two adapters
def initialize(connection, logger, connection_options, config)
super(connection, logger)
@connection_options, @config = connection_options, config
@quoted_column_names, @quoted_table_names = {}, {}

@visitor = Arel::Visitors::MySQL.new self
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))

if self.class.type_cast_config_to_boolean(config.fetch(:prepared_statements) { true })
@prepared_statements = true
Expand Down Expand Up @@ -194,12 +184,6 @@ def supports_bulk_alter? #:nodoc:
true
end

# Returns true, since this connection adapter supports prepared statement
# caching.
def supports_statement_cache?
true
end

# Technically MySQL allows to create indexes with the sort order syntax
# but at the moment (5.5) it doesn't yet implement them
def supports_index_sort_order?
Expand Down Expand Up @@ -407,20 +391,9 @@ def build_footer(nrows, elapsed)
end
end

def select_all(arel, name = nil, binds = [])
rows = if ExplainRegistry.collect? && prepared_statements
unprepared_statement { super }
else
super
end
@connection.next_result while @connection.more_results?
rows
end

# Clears the prepared statements cache.
def clear_cache!
super
reload_type_map
@statements.clear
end

# Executes the SQL statement in the context of this connection.
Expand All @@ -431,26 +404,11 @@ def execute(sql, name = nil)
# MysqlAdapter has to free a result after using it, so we use this method to write
# stuff in an abstract way without concerning ourselves about whether it needs to be
# explicitly freed or not.
def execute_and_free(sql, name = nil) # :nodoc:
def execute_and_free(sql, name = nil) #:nodoc:
yield execute(sql, name)
end

def exec_delete(sql, name, binds) # :nodoc:
if without_prepared_statement?(binds)
execute_and_free(sql, name) { @connection.affected_rows }
else
exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
end
end
alias :exec_update :exec_delete

def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) # :nodoc:
super
id_value || last_inserted_id
end
alias :create :insert_sql

def update_sql(sql, name = nil) # :nodoc:
def update_sql(sql, name = nil) #:nodoc:
super
@connection.affected_rows
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require 'active_record/connection_adapters/abstract_mysql_adapter'

gem 'mysql2', '>= 0.4.2', '< 0.5'
gem 'mysql2', '>= 0.3.18', '< 0.5'
require 'mysql2'

module ActiveRecord
Expand Down Expand Up @@ -33,6 +33,7 @@ class Mysql2Adapter < AbstractMysqlAdapter

def initialize(connection, logger, connection_options, config)
super
@prepared_statements = false
configure_connection
end

Expand Down Expand Up @@ -125,13 +126,9 @@ def disconnect!
# Returns an array of arrays containing the field values.
# Order is the same as that returned by +columns+.
def select_rows(sql, name = nil, binds = [])
rows = if without_prepared_statement?(binds)
execute_and_free(sql, name) { |result| result.to_a }
else
exec_stmt_and_free(sql, name, binds) { |stmt, result| result.to_a }
end
result = execute(sql, name)
@connection.next_result while @connection.more_results?
rows
result.to_a
end

# Executes the SQL statement in the context of this connection.
Expand All @@ -146,59 +143,35 @@ def execute(sql, name = nil)
end

def exec_query(sql, name = 'SQL', binds = [], prepare: false)
if without_prepared_statement?(binds)
execute_and_free(sql, name) do |result|
ActiveRecord::Result.new(result.fields, result.to_a) if result
end
else
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |stmt, result|
ActiveRecord::Result.new(result.fields, result.to_a) if result
end
end
end

def last_inserted_id(result = nil)
@connection.last_id
result = execute(sql, name)
@connection.next_result while @connection.more_results?
ActiveRecord::Result.new(result.fields, result.to_a)
end

private
alias exec_without_stmt exec_query

def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
if @connection
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
# made since we established the connection
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
end

type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
super
id_value || @connection.last_id
end
alias :create :insert_sql

log(sql, name, binds) do
if !cache_stmt
stmt = @connection.prepare(sql)
else
cache = @statements[sql] ||= {
stmt: @connection.prepare(sql)
}
stmt = cache[:stmt]
end
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
execute to_sql(sql, binds), name
end

begin
result = stmt.execute(*type_casted_binds)
rescue Mysql2::Error => e
if !cache_stmt
stmt.close
else
@statements.delete(sql)
end
raise e
end
def exec_delete(sql, name, binds)
execute to_sql(sql, binds), name
@connection.affected_rows
end
alias :exec_update :exec_delete

ret = yield stmt, result
stmt.close if !cache_stmt
ret
end
def last_inserted_id(result)
@connection.last_id
end

private

def connect
@connection = Mysql2::Client.new(@config)
configure_connection
Expand Down