mirror of https://github.com/rails/rails
Merge pull request #22642 from seuros/remove-mysql-adapter
Remove legacy mysql adapter
This commit is contained in:
commit
4a58aef7e3
|
@ -18,7 +18,6 @@ env:
|
|||
- "GEM=ap"
|
||||
- "GEM=ac"
|
||||
- "GEM=am,amo,as,av,aj"
|
||||
- "GEM=ar:mysql"
|
||||
- "GEM=ar:mysql2"
|
||||
- "GEM=ar:sqlite3"
|
||||
- "GEM=ar:postgresql"
|
||||
|
@ -29,7 +28,6 @@ rvm:
|
|||
- ruby-head
|
||||
matrix:
|
||||
allow_failures:
|
||||
- env: "GEM=ar:mysql"
|
||||
- rvm: ruby-head
|
||||
fast_finish: true
|
||||
notifications:
|
||||
|
|
1
Gemfile
1
Gemfile
|
@ -94,7 +94,6 @@ platforms :ruby, :mswin, :mswin64, :mingw, :x64_mingw do
|
|||
|
||||
group :db do
|
||||
gem 'pg', '>= 0.18.0'
|
||||
gem 'mysql', '>= 2.9.0'
|
||||
gem 'mysql2', '>= 0.4.0'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -189,8 +189,6 @@ GEM
|
|||
mono_logger (1.1.0)
|
||||
multi_json (1.11.2)
|
||||
mustache (1.0.2)
|
||||
mysql (2.9.1)
|
||||
mysql (2.9.1-x86-mingw32)
|
||||
mysql2 (0.4.2)
|
||||
mysql2 (0.4.2-x64-mingw32)
|
||||
mysql2 (0.4.2-x86-mingw32)
|
||||
|
@ -318,7 +316,6 @@ DEPENDENCIES
|
|||
listen (~> 3.0.5)
|
||||
minitest (< 5.3.4)
|
||||
mocha (~> 0.14)
|
||||
mysql (>= 2.9.0)
|
||||
mysql2 (>= 0.4.0)
|
||||
nokogiri (>= 1.6.7.1)
|
||||
pg (>= 0.18.0)
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
* Extract support for the legacy `mysql` database adapter from core. It will
|
||||
live on in a separate gem for now, but most users should just use `mysql2`.
|
||||
|
||||
*Abdelkader Boudih*
|
||||
|
||||
* ApplicationRecord is a new superclass for all app models, analogous to app
|
||||
controllers subclassing ApplicationController instead of
|
||||
ActionController::Base. This gives apps a single spot to configure app-wide
|
||||
|
|
|
@ -20,7 +20,6 @@ example:
|
|||
|
||||
Simply executing <tt>bundle exec rake test</tt> is equivalent to the following:
|
||||
|
||||
$ bundle exec rake test:mysql
|
||||
$ bundle exec rake test:mysql2
|
||||
$ bundle exec rake test:postgresql
|
||||
$ bundle exec rake test:sqlite3
|
||||
|
|
|
@ -17,14 +17,14 @@ def run_without_aborting(*tasks)
|
|||
abort "Errors running #{errors.join(', ')}" if errors.any?
|
||||
end
|
||||
|
||||
desc 'Run mysql, mysql2, sqlite, and postgresql tests by default'
|
||||
desc 'Run mysql2, sqlite, and postgresql tests by default'
|
||||
task :default => :test
|
||||
|
||||
desc 'Run mysql, mysql2, sqlite, and postgresql tests'
|
||||
desc 'Run mysql2, sqlite, and postgresql tests'
|
||||
task :test do
|
||||
tasks = defined?(JRUBY_VERSION) ?
|
||||
%w(test_jdbcmysql test_jdbcsqlite3 test_jdbcpostgresql) :
|
||||
%w(test_mysql test_mysql2 test_sqlite3 test_postgresql)
|
||||
%w(test_mysql2 test_sqlite3 test_postgresql)
|
||||
run_without_aborting(*tasks)
|
||||
end
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace :test do
|
|||
task :isolated do
|
||||
tasks = defined?(JRUBY_VERSION) ?
|
||||
%w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) :
|
||||
%w(isolated_test_mysql isolated_test_mysql2 isolated_test_sqlite3 isolated_test_postgresql)
|
||||
%w(isolated_test_mysql2 isolated_test_sqlite3 isolated_test_postgresql)
|
||||
run_without_aborting(*tasks)
|
||||
end
|
||||
end
|
||||
|
@ -43,7 +43,7 @@ namespace :db do
|
|||
task :drop => ['db:mysql:drop', 'db:postgresql:drop']
|
||||
end
|
||||
|
||||
%w( mysql mysql2 postgresql sqlite3 sqlite3_mem db2 oracle jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
|
||||
%w( mysql2 postgresql sqlite3 sqlite3_mem db2 oracle jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
|
||||
namespace :test do
|
||||
Rake::TestTask.new(adapter => "#{adapter}:env") { |t|
|
||||
adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
|
||||
|
@ -87,14 +87,14 @@ namespace :db do
|
|||
namespace :mysql do
|
||||
desc 'Build the MySQL test databases'
|
||||
task :build do
|
||||
config = ARTest.config['connections']['mysql']
|
||||
config = ARTest.config['connections']['mysql2']
|
||||
%x( mysql --user=#{config['arunit']['username']} --password=#{config['arunit']['password']} -e "create DATABASE #{config['arunit']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
|
||||
%x( mysql --user=#{config['arunit2']['username']} --password=#{config['arunit2']['password']} -e "create DATABASE #{config['arunit2']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
|
||||
end
|
||||
|
||||
desc 'Drop the MySQL test databases'
|
||||
task :drop do
|
||||
config = ARTest.config['connections']['mysql']
|
||||
config = ARTest.config['connections']['mysql2']
|
||||
%x( mysqladmin --user=#{config['arunit']['username']} --password=#{config['arunit']['password']} -f drop #{config['arunit']['database']} )
|
||||
%x( mysqladmin --user=#{config['arunit2']['username']} --password=#{config['arunit2']['password']} -f drop #{config['arunit2']['database']} )
|
||||
end
|
||||
|
|
|
@ -6,7 +6,7 @@ module Minitest
|
|||
opts.separator ""
|
||||
opts.separator "Active Record options:"
|
||||
opts.on("-a", "--adapter [ADAPTER]",
|
||||
"Run tests using a specific adapter (sqlite3, sqlite3_mem, mysql, mysql2, postgresql)") do |adapter|
|
||||
"Run tests using a specific adapter (sqlite3, sqlite3_mem, mysql2, postgresql)") do |adapter|
|
||||
ENV["ARCONN"] = adapter.strip
|
||||
end
|
||||
|
||||
|
|
|
@ -1101,11 +1101,8 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Type.register(:json, MysqlJson, adapter: :mysql)
|
||||
ActiveRecord::Type.register(:json, MysqlJson, adapter: :mysql2)
|
||||
ActiveRecord::Type.register(:string, MysqlString, adapter: :mysql)
|
||||
ActiveRecord::Type.register(:string, MysqlString, adapter: :mysql2)
|
||||
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql)
|
||||
ActiveRecord::Type.register(:unsigned_integer, Type::UnsignedInteger, adapter: :mysql2)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -175,7 +175,7 @@ module ActiveRecord
|
|||
rescue Gem::LoadError => e
|
||||
raise Gem::LoadError, "Specified '#{spec[:adapter]}' for database adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord)."
|
||||
rescue LoadError => e
|
||||
raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql', 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
|
||||
raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
|
||||
end
|
||||
|
||||
adapter_method = "#{spec[:adapter]}_connection"
|
||||
|
|
|
@ -1,481 +0,0 @@
|
|||
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
||||
require 'active_record/connection_adapters/statement_pool'
|
||||
require 'active_support/core_ext/hash/keys'
|
||||
|
||||
gem 'mysql', '~> 2.9'
|
||||
require 'mysql'
|
||||
|
||||
class Mysql # :nodoc: all
|
||||
class Time
|
||||
# Used for casting DateTime fields to a MySQL friendly Time.
|
||||
# This was documented in 48498da0dfed5239ea1eafb243ce47d7e3ce9e8e
|
||||
def to_date
|
||||
Date.new(year, month, day)
|
||||
end
|
||||
end
|
||||
class Stmt; include Enumerable end
|
||||
class Result; include Enumerable end
|
||||
end
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionHandling # :nodoc:
|
||||
# Establishes a connection to the database that's used by all Active Record objects.
|
||||
def mysql_connection(config)
|
||||
config = config.symbolize_keys
|
||||
host = config[:host]
|
||||
port = config[:port]
|
||||
socket = config[:socket]
|
||||
username = config[:username] ? config[:username].to_s : 'root'
|
||||
password = config[:password].to_s
|
||||
database = config[:database]
|
||||
|
||||
mysql = Mysql.init
|
||||
mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslca] || config[:sslkey]
|
||||
|
||||
default_flags = Mysql.const_defined?(:CLIENT_MULTI_RESULTS) ? Mysql::CLIENT_MULTI_RESULTS : 0
|
||||
default_flags |= Mysql::CLIENT_FOUND_ROWS if Mysql.const_defined?(:CLIENT_FOUND_ROWS)
|
||||
options = [host, username, password, database, port, socket, default_flags]
|
||||
ConnectionAdapters::MysqlAdapter.new(mysql, logger, options, config)
|
||||
rescue Mysql::Error => error
|
||||
if error.message.include?("Unknown database")
|
||||
raise ActiveRecord::NoDatabaseError
|
||||
else
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ConnectionAdapters
|
||||
# The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with
|
||||
# the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/).
|
||||
#
|
||||
# Options:
|
||||
#
|
||||
# * <tt>:host</tt> - Defaults to "localhost".
|
||||
# * <tt>:port</tt> - Defaults to 3306.
|
||||
# * <tt>:socket</tt> - Defaults to "/tmp/mysql.sock".
|
||||
# * <tt>:username</tt> - Defaults to "root"
|
||||
# * <tt>:password</tt> - Defaults to nothing.
|
||||
# * <tt>:database</tt> - The name of the database. No default, must be provided.
|
||||
# * <tt>:encoding</tt> - (Optional) Sets the client encoding by executing "SET NAMES <encoding>" after connection.
|
||||
# * <tt>:reconnect</tt> - Defaults to false (See MySQL documentation: http://dev.mysql.com/doc/refman/5.7/en/auto-reconnect.html).
|
||||
# * <tt>:strict</tt> - Defaults to true. Enable STRICT_ALL_TABLES. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html)
|
||||
# * <tt>:variables</tt> - (Optional) A hash session variables to send as <tt>SET @@SESSION.key = value</tt> on each database connection. Use the value +:default+ to set a variable to its DEFAULT value. (See MySQL documentation: http://dev.mysql.com/doc/refman/5.7/en/set-statement.html).
|
||||
# * <tt>:sslca</tt> - Necessary to use MySQL with an SSL connection.
|
||||
# * <tt>:sslkey</tt> - Necessary to use MySQL with an SSL connection.
|
||||
# * <tt>:sslcert</tt> - Necessary to use MySQL with an SSL connection.
|
||||
# * <tt>:sslcapath</tt> - Necessary to use MySQL with an SSL connection.
|
||||
# * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
|
||||
#
|
||||
class MysqlAdapter < AbstractMysqlAdapter
|
||||
ADAPTER_NAME = 'MySQL'.freeze
|
||||
|
||||
class StatementPool < ConnectionAdapters::StatementPool
|
||||
private
|
||||
|
||||
def dealloc(stmt)
|
||||
stmt[:stmt].close
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(connection, logger, connection_options, config)
|
||||
super
|
||||
@statements = StatementPool.new(self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 }))
|
||||
@client_encoding = nil
|
||||
@connection_options = connection_options
|
||||
connect
|
||||
end
|
||||
|
||||
# Returns true, since this connection adapter supports prepared statement
|
||||
# caching.
|
||||
def supports_statement_cache?
|
||||
true
|
||||
end
|
||||
|
||||
# HELPER METHODS ===========================================
|
||||
|
||||
def each_hash(result) # :nodoc:
|
||||
if block_given?
|
||||
result.each_hash do |row|
|
||||
row.symbolize_keys!
|
||||
yield row
|
||||
end
|
||||
else
|
||||
to_enum(:each_hash, result)
|
||||
end
|
||||
end
|
||||
|
||||
def new_column(field, default, sql_type_metadata = nil, null = true, default_function = nil, collation = nil) # :nodoc:
|
||||
field = set_field_encoding(field)
|
||||
super
|
||||
end
|
||||
|
||||
def error_number(exception) # :nodoc:
|
||||
exception.errno if exception.respond_to?(:errno)
|
||||
end
|
||||
|
||||
# QUOTING ==================================================
|
||||
|
||||
def quote_string(string) #:nodoc:
|
||||
@connection.quote(string)
|
||||
end
|
||||
|
||||
#--
|
||||
# CONNECTION MANAGEMENT ====================================
|
||||
#++
|
||||
|
||||
def active?
|
||||
if @connection.respond_to?(:stat)
|
||||
@connection.stat
|
||||
else
|
||||
@connection.query 'select 1'
|
||||
end
|
||||
|
||||
# mysql-ruby doesn't raise an exception when stat fails.
|
||||
if @connection.respond_to?(:errno)
|
||||
@connection.errno.zero?
|
||||
else
|
||||
true
|
||||
end
|
||||
rescue Mysql::Error
|
||||
false
|
||||
end
|
||||
|
||||
def reconnect!
|
||||
super
|
||||
disconnect!
|
||||
connect
|
||||
end
|
||||
|
||||
# Disconnects from the database if already connected. Otherwise, this
|
||||
# method does nothing.
|
||||
def disconnect!
|
||||
super
|
||||
@connection.close rescue nil
|
||||
end
|
||||
|
||||
def reset!
|
||||
if @connection.respond_to?(:change_user)
|
||||
# See http://bugs.mysql.com/bug.php?id=33540 -- the workaround way to
|
||||
# reset the connection is to change the user to the same user.
|
||||
@connection.change_user(@config[:username], @config[:password], @config[:database])
|
||||
configure_connection
|
||||
end
|
||||
end
|
||||
|
||||
#--
|
||||
# DATABASE STATEMENTS ======================================
|
||||
#++
|
||||
|
||||
def select_all(arel, name = nil, binds = [])
|
||||
if ExplainRegistry.collect? && prepared_statements
|
||||
unprepared_statement { super }
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def select_rows(sql, name = nil, binds = [])
|
||||
@connection.query_with_result = true
|
||||
rows = exec_query(sql, name, binds).rows
|
||||
@connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
|
||||
rows
|
||||
end
|
||||
|
||||
# Clears the prepared statements cache.
|
||||
def clear_cache!
|
||||
super
|
||||
@statements.clear
|
||||
end
|
||||
|
||||
# Taken from here:
|
||||
# https://github.com/tmtm/ruby-mysql/blob/master/lib/mysql/charset.rb
|
||||
# Author: TOMITA Masahiro <tommy@tmtm.org>
|
||||
ENCODINGS = {
|
||||
"armscii8" => nil,
|
||||
"ascii" => Encoding::US_ASCII,
|
||||
"big5" => Encoding::Big5,
|
||||
"binary" => Encoding::ASCII_8BIT,
|
||||
"cp1250" => Encoding::Windows_1250,
|
||||
"cp1251" => Encoding::Windows_1251,
|
||||
"cp1256" => Encoding::Windows_1256,
|
||||
"cp1257" => Encoding::Windows_1257,
|
||||
"cp850" => Encoding::CP850,
|
||||
"cp852" => Encoding::CP852,
|
||||
"cp866" => Encoding::IBM866,
|
||||
"cp932" => Encoding::Windows_31J,
|
||||
"dec8" => nil,
|
||||
"eucjpms" => Encoding::EucJP_ms,
|
||||
"euckr" => Encoding::EUC_KR,
|
||||
"gb2312" => Encoding::EUC_CN,
|
||||
"gbk" => Encoding::GBK,
|
||||
"geostd8" => nil,
|
||||
"greek" => Encoding::ISO_8859_7,
|
||||
"hebrew" => Encoding::ISO_8859_8,
|
||||
"hp8" => nil,
|
||||
"keybcs2" => nil,
|
||||
"koi8r" => Encoding::KOI8_R,
|
||||
"koi8u" => Encoding::KOI8_U,
|
||||
"latin1" => Encoding::ISO_8859_1,
|
||||
"latin2" => Encoding::ISO_8859_2,
|
||||
"latin5" => Encoding::ISO_8859_9,
|
||||
"latin7" => Encoding::ISO_8859_13,
|
||||
"macce" => Encoding::MacCentEuro,
|
||||
"macroman" => Encoding::MacRoman,
|
||||
"sjis" => Encoding::SHIFT_JIS,
|
||||
"swe7" => nil,
|
||||
"tis620" => Encoding::TIS_620,
|
||||
"ucs2" => Encoding::UTF_16BE,
|
||||
"ujis" => Encoding::EucJP_ms,
|
||||
"utf8" => Encoding::UTF_8,
|
||||
"utf8mb4" => Encoding::UTF_8,
|
||||
}
|
||||
|
||||
# Get the client encoding for this database
|
||||
def client_encoding
|
||||
return @client_encoding if @client_encoding
|
||||
|
||||
result = exec_query(
|
||||
"select @@character_set_client",
|
||||
'SCHEMA')
|
||||
@client_encoding = ENCODINGS[result.rows.last.last]
|
||||
end
|
||||
|
||||
def exec_query(sql, name = 'SQL', binds = [], prepare: false)
|
||||
if without_prepared_statement?(binds)
|
||||
result_set, affected_rows = exec_without_stmt(sql, name)
|
||||
else
|
||||
result_set, affected_rows = exec_stmt(sql, name, binds, cache_stmt: prepare)
|
||||
end
|
||||
|
||||
yield affected_rows if block_given?
|
||||
|
||||
result_set
|
||||
end
|
||||
|
||||
def last_inserted_id(result)
|
||||
@connection.insert_id
|
||||
end
|
||||
|
||||
module Fields # :nodoc:
|
||||
class DateTime < Type::DateTime # :nodoc:
|
||||
def cast_value(value)
|
||||
if Mysql::Time === value
|
||||
new_time(
|
||||
value.year,
|
||||
value.month,
|
||||
value.day,
|
||||
value.hour,
|
||||
value.minute,
|
||||
value.second,
|
||||
value.second_part)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Time < Type::Time # :nodoc:
|
||||
def cast_value(value)
|
||||
if Mysql::Time === value
|
||||
new_time(
|
||||
2000,
|
||||
01,
|
||||
01,
|
||||
value.hour,
|
||||
value.minute,
|
||||
value.second,
|
||||
value.second_part)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class << self
|
||||
TYPES = Type::HashLookupTypeMap.new # :nodoc:
|
||||
|
||||
delegate :register_type, :alias_type, to: :TYPES
|
||||
|
||||
def find_type(field)
|
||||
if field.type == Mysql::Field::TYPE_TINY && field.length > 1
|
||||
TYPES.lookup(Mysql::Field::TYPE_LONG)
|
||||
else
|
||||
TYPES.lookup(field.type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
register_type Mysql::Field::TYPE_TINY, Type::Boolean.new
|
||||
register_type Mysql::Field::TYPE_LONG, Type::Integer.new
|
||||
alias_type Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_LONG
|
||||
alias_type Mysql::Field::TYPE_NEWDECIMAL, Mysql::Field::TYPE_LONG
|
||||
|
||||
register_type Mysql::Field::TYPE_DATE, Type::Date.new
|
||||
register_type Mysql::Field::TYPE_DATETIME, Fields::DateTime.new
|
||||
register_type Mysql::Field::TYPE_TIME, Fields::Time.new
|
||||
register_type Mysql::Field::TYPE_FLOAT, Type::Float.new
|
||||
end
|
||||
|
||||
def initialize_type_map(m) # :nodoc:
|
||||
super
|
||||
register_class_with_precision m, %r(datetime)i, Fields::DateTime
|
||||
register_class_with_precision m, %r(time)i, Fields::Time
|
||||
end
|
||||
|
||||
def exec_without_stmt(sql, name = 'SQL') # :nodoc:
|
||||
# Some queries, like SHOW CREATE TABLE don't work through the prepared
|
||||
# statement API. For those queries, we need to use this method. :'(
|
||||
log(sql, name) do
|
||||
result = @connection.query(sql)
|
||||
affected_rows = @connection.affected_rows
|
||||
|
||||
if result
|
||||
types = {}
|
||||
fields = []
|
||||
result.fetch_fields.each { |field|
|
||||
field_name = field.name
|
||||
fields << field_name
|
||||
|
||||
if field.decimals > 0
|
||||
types[field_name] = Type::Decimal.new
|
||||
else
|
||||
types[field_name] = Fields.find_type field
|
||||
end
|
||||
}
|
||||
|
||||
result_set = ActiveRecord::Result.new(fields, result.to_a, types)
|
||||
result.free
|
||||
else
|
||||
result_set = ActiveRecord::Result.new([], [])
|
||||
end
|
||||
|
||||
[result_set, affected_rows]
|
||||
end
|
||||
end
|
||||
|
||||
def execute_and_free(sql, name = nil) # :nodoc:
|
||||
result = execute(sql, name)
|
||||
ret = yield result
|
||||
result.free
|
||||
ret
|
||||
end
|
||||
|
||||
def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
|
||||
super sql, name
|
||||
id_value || @connection.insert_id
|
||||
end
|
||||
alias :create :insert_sql
|
||||
|
||||
def exec_delete(sql, name, binds) # :nodoc:
|
||||
affected_rows = 0
|
||||
|
||||
exec_query(sql, name, binds) do |n|
|
||||
affected_rows = n
|
||||
end
|
||||
|
||||
affected_rows
|
||||
end
|
||||
alias :exec_update :exec_delete
|
||||
|
||||
def begin_db_transaction #:nodoc:
|
||||
exec_query "BEGIN"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def exec_stmt(sql, name, binds, cache_stmt: false)
|
||||
cache = {}
|
||||
type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) }
|
||||
|
||||
log(sql, name, binds) do
|
||||
if !cache_stmt
|
||||
stmt = @connection.prepare(sql)
|
||||
else
|
||||
cache = @statements[sql] ||= {
|
||||
:stmt => @connection.prepare(sql)
|
||||
}
|
||||
stmt = cache[:stmt]
|
||||
end
|
||||
|
||||
begin
|
||||
stmt.execute(*type_casted_binds)
|
||||
rescue Mysql::Error => e
|
||||
# Older versions of MySQL leave the prepared statement in a bad
|
||||
# place when an error occurs. To support older MySQL versions, we
|
||||
# need to close the statement and delete the statement from the
|
||||
# cache.
|
||||
if !cache_stmt
|
||||
stmt.close
|
||||
else
|
||||
@statements.delete sql
|
||||
end
|
||||
raise e
|
||||
end
|
||||
|
||||
cols = nil
|
||||
if metadata = stmt.result_metadata
|
||||
cols = cache[:cols] ||= metadata.fetch_fields.map(&:name)
|
||||
metadata.free
|
||||
end
|
||||
|
||||
result_set = ActiveRecord::Result.new(cols, stmt.to_a) if cols
|
||||
affected_rows = stmt.affected_rows
|
||||
|
||||
stmt.free_result
|
||||
stmt.close if !cache_stmt
|
||||
|
||||
[result_set, affected_rows]
|
||||
end
|
||||
end
|
||||
|
||||
def connect
|
||||
encoding = @config[:encoding]
|
||||
if encoding
|
||||
@connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil
|
||||
end
|
||||
|
||||
if @config[:sslca] || @config[:sslkey]
|
||||
@connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
|
||||
end
|
||||
|
||||
@connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
|
||||
@connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
|
||||
@connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
|
||||
|
||||
@connection.real_connect(*@connection_options)
|
||||
|
||||
# reconnect must be set after real_connect is called, because real_connect sets it to false internally
|
||||
@connection.reconnect = !!@config[:reconnect] if @connection.respond_to?(:reconnect=)
|
||||
|
||||
configure_connection
|
||||
end
|
||||
|
||||
# Many Rails applications monkey-patch a replacement of the configure_connection method
|
||||
# and don't call 'super', so leave this here even though it looks superfluous.
|
||||
def configure_connection
|
||||
super
|
||||
end
|
||||
|
||||
def select(sql, name = nil, binds = [])
|
||||
@connection.query_with_result = true
|
||||
rows = super
|
||||
@connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped
|
||||
rows
|
||||
end
|
||||
|
||||
# Returns the full version of the connected MySQL server.
|
||||
def full_version
|
||||
@full_version ||= @connection.server_info
|
||||
end
|
||||
|
||||
def set_field_encoding(field_name)
|
||||
field_name.force_encoding(client_encoding)
|
||||
if internal_enc = Encoding.default_internal
|
||||
field_name = field_name.encode!(internal_enc)
|
||||
end
|
||||
field_name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -94,8 +94,6 @@ module ActiveRecord
|
|||
ArJdbcMySQL::Error
|
||||
elsif defined?(Mysql2)
|
||||
Mysql2::Error
|
||||
elsif defined?(Mysql)
|
||||
Mysql::Error
|
||||
else
|
||||
StandardError
|
||||
end
|
||||
|
|
|
@ -231,7 +231,6 @@ module ActiveRecord
|
|||
#
|
||||
# The following bundled adapters throw the ActiveRecord::RecordNotUnique exception:
|
||||
#
|
||||
# * ActiveRecord::ConnectionAdapters::MysqlAdapter.
|
||||
# * ActiveRecord::ConnectionAdapters::Mysql2Adapter.
|
||||
# * ActiveRecord::ConnectionAdapters::SQLite3Adapter.
|
||||
# * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.
|
||||
|
|
|
@ -85,7 +85,7 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_charset
|
||||
assert_not_nil @connection.charset
|
||||
assert_not_equal 'character_set_database', @connection.charset
|
||||
|
@ -254,7 +254,7 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :SQLite3Adapter)
|
||||
if current_adapter?(:Mysql2Adapter, :SQLite3Adapter)
|
||||
def test_tables_returning_both_tables_and_views_is_deprecated
|
||||
assert_deprecated { @connection.tables }
|
||||
end
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'support/connection_helper'
|
||||
|
||||
class MysqlActiveSchemaTest < ActiveRecord::MysqlTestCase
|
||||
include ConnectionHelper
|
||||
|
||||
def setup
|
||||
ActiveRecord::Base.connection.singleton_class.class_eval do
|
||||
alias_method :execute_without_stub, :execute
|
||||
def execute(sql, name = nil) return sql end
|
||||
end
|
||||
end
|
||||
|
||||
teardown do
|
||||
reset_connection
|
||||
end
|
||||
|
||||
def test_add_index
|
||||
# add_index calls data_source_exists? and index_name_exists? which can't work since execute is stubbed
|
||||
def (ActiveRecord::Base.connection).data_source_exists?(*); true; end
|
||||
def (ActiveRecord::Base.connection).index_name_exists?(*); false; end
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`) "
|
||||
assert_equal expected, add_index(:people, :last_name, :length => nil)
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`(10)) "
|
||||
assert_equal expected, add_index(:people, :last_name, :length => 10)
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(15)) "
|
||||
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15)
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`) "
|
||||
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15})
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10)) "
|
||||
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15, :first_name => 10})
|
||||
|
||||
%w(SPATIAL FULLTEXT UNIQUE).each do |type|
|
||||
expected = "CREATE #{type} INDEX `index_people_on_last_name` ON `people` (`last_name`) "
|
||||
assert_equal expected, add_index(:people, :last_name, :type => type)
|
||||
end
|
||||
|
||||
%w(btree hash).each do |using|
|
||||
expected = "CREATE INDEX `index_people_on_last_name` USING #{using} ON `people` (`last_name`) "
|
||||
assert_equal expected, add_index(:people, :last_name, :using => using)
|
||||
end
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name` USING btree ON `people` (`last_name`(10)) "
|
||||
assert_equal expected, add_index(:people, :last_name, :length => 10, :using => :btree)
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name` USING btree ON `people` (`last_name`(10)) ALGORITHM = COPY"
|
||||
assert_equal expected, add_index(:people, :last_name, :length => 10, using: :btree, algorithm: :copy)
|
||||
|
||||
assert_raise ArgumentError do
|
||||
add_index(:people, :last_name, algorithm: :coyp)
|
||||
end
|
||||
|
||||
expected = "CREATE INDEX `index_people_on_last_name_and_first_name` USING btree ON `people` (`last_name`(15), `first_name`(15)) "
|
||||
assert_equal expected, add_index(:people, [:last_name, :first_name], :length => 15, :using => :btree)
|
||||
end
|
||||
|
||||
def test_index_in_create
|
||||
def (ActiveRecord::Base.connection).data_source_exists?(*); false; end
|
||||
|
||||
%w(SPATIAL FULLTEXT UNIQUE).each do |type|
|
||||
expected = "CREATE TABLE `people` (#{type} INDEX `index_people_on_last_name` (`last_name`) ) ENGINE=InnoDB"
|
||||
actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t|
|
||||
t.index :last_name, type: type
|
||||
end
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
expected = "CREATE TABLE `people` ( INDEX `index_people_on_last_name` USING btree (`last_name`(10)) ) ENGINE=InnoDB"
|
||||
actual = ActiveRecord::Base.connection.create_table(:people, id: false) do |t|
|
||||
t.index :last_name, length: 10, using: :btree
|
||||
end
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
def test_index_in_bulk_change
|
||||
def (ActiveRecord::Base.connection).data_source_exists?(*); true; end
|
||||
def (ActiveRecord::Base.connection).index_name_exists?(*); false; end
|
||||
|
||||
%w(SPATIAL FULLTEXT UNIQUE).each do |type|
|
||||
expected = "ALTER TABLE `people` ADD #{type} INDEX `index_people_on_last_name` (`last_name`)"
|
||||
actual = ActiveRecord::Base.connection.change_table(:people, bulk: true) do |t|
|
||||
t.index :last_name, type: type
|
||||
end
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
expected = "ALTER TABLE `peaple` ADD INDEX `index_peaple_on_last_name` USING btree (`last_name`(10)), ALGORITHM = COPY"
|
||||
actual = ActiveRecord::Base.connection.change_table(:peaple, bulk: true) do |t|
|
||||
t.index :last_name, length: 10, using: :btree, algorithm: :copy
|
||||
end
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
def test_drop_table
|
||||
assert_equal "DROP TABLE `people`", drop_table(:people)
|
||||
end
|
||||
|
||||
def test_create_mysql_database_with_encoding
|
||||
assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt)
|
||||
assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'})
|
||||
assert_equal "CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`", create_database(:matt_aimonetti, {:charset => :big5, :collation => :big5_chinese_ci})
|
||||
end
|
||||
|
||||
def test_recreate_mysql_database_with_encoding
|
||||
create_database(:luca, {:charset => 'latin1'})
|
||||
assert_equal "CREATE DATABASE `luca` DEFAULT CHARACTER SET `latin1`", recreate_database(:luca, {:charset => 'latin1'})
|
||||
end
|
||||
|
||||
def test_add_column
|
||||
assert_equal "ALTER TABLE `people` ADD `last_name` varchar(255)", add_column(:people, :last_name, :string)
|
||||
end
|
||||
|
||||
def test_add_column_with_limit
|
||||
assert_equal "ALTER TABLE `people` ADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32)
|
||||
end
|
||||
|
||||
def test_drop_table_with_specific_database
|
||||
assert_equal "DROP TABLE `otherdb`.`people`", drop_table('otherdb.people')
|
||||
end
|
||||
|
||||
def test_add_timestamps
|
||||
with_real_execute do
|
||||
begin
|
||||
ActiveRecord::Base.connection.create_table :delete_me
|
||||
ActiveRecord::Base.connection.add_timestamps :delete_me, null: true
|
||||
assert column_present?('delete_me', 'updated_at', 'datetime')
|
||||
assert column_present?('delete_me', 'created_at', 'datetime')
|
||||
ensure
|
||||
ActiveRecord::Base.connection.drop_table :delete_me rescue nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_remove_timestamps
|
||||
with_real_execute do
|
||||
begin
|
||||
ActiveRecord::Base.connection.create_table :delete_me do |t|
|
||||
t.timestamps null: true
|
||||
end
|
||||
ActiveRecord::Base.connection.remove_timestamps :delete_me, { null: true }
|
||||
assert !column_present?('delete_me', 'updated_at', 'datetime')
|
||||
assert !column_present?('delete_me', 'created_at', 'datetime')
|
||||
ensure
|
||||
ActiveRecord::Base.connection.drop_table :delete_me rescue nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_indexes_in_create
|
||||
ActiveRecord::Base.connection.stubs(:data_source_exists?).with(:temp).returns(false)
|
||||
ActiveRecord::Base.connection.stubs(:index_name_exists?).with(:index_temp_on_zip).returns(false)
|
||||
|
||||
expected = "CREATE TEMPORARY TABLE `temp` ( INDEX `index_temp_on_zip` (`zip`) ) ENGINE=InnoDB AS SELECT id, name, zip FROM a_really_complicated_query"
|
||||
actual = ActiveRecord::Base.connection.create_table(:temp, temporary: true, as: "SELECT id, name, zip FROM a_really_complicated_query") do |t|
|
||||
t.index :zip
|
||||
end
|
||||
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
private
|
||||
def with_real_execute
|
||||
ActiveRecord::Base.connection.singleton_class.class_eval do
|
||||
alias_method :execute_with_stub, :execute
|
||||
remove_method :execute
|
||||
alias_method :execute, :execute_without_stub
|
||||
end
|
||||
|
||||
yield
|
||||
ensure
|
||||
ActiveRecord::Base.connection.singleton_class.class_eval do
|
||||
remove_method :execute
|
||||
alias_method :execute, :execute_with_stub
|
||||
end
|
||||
end
|
||||
|
||||
def method_missing(method_symbol, *arguments)
|
||||
ActiveRecord::Base.connection.send(method_symbol, *arguments)
|
||||
end
|
||||
|
||||
def column_present?(table_name, column_name, type)
|
||||
results = ActiveRecord::Base.connection.select_all("SHOW FIELDS FROM #{table_name} LIKE '#{column_name}'")
|
||||
results.first && results.first['Type'] == type
|
||||
end
|
||||
end
|
|
@ -1,54 +0,0 @@
|
|||
require "cases/helper"
|
||||
|
||||
class MysqlCaseSensitivityTest < ActiveRecord::MysqlTestCase
|
||||
class CollationTest < ActiveRecord::Base
|
||||
end
|
||||
|
||||
repair_validations(CollationTest)
|
||||
|
||||
def test_columns_include_collation_different_from_table
|
||||
assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
|
||||
assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
|
||||
end
|
||||
|
||||
def test_case_sensitive
|
||||
assert !CollationTest.columns_hash['string_ci_column'].case_sensitive?
|
||||
assert CollationTest.columns_hash['string_cs_column'].case_sensitive?
|
||||
end
|
||||
|
||||
def test_case_insensitive_comparison_for_ci_column
|
||||
CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => false)
|
||||
CollationTest.create!(:string_ci_column => 'A')
|
||||
invalid = CollationTest.new(:string_ci_column => 'a')
|
||||
queries = assert_sql { invalid.save }
|
||||
ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) }
|
||||
assert_no_match(/lower/i, ci_uniqueness_query)
|
||||
end
|
||||
|
||||
def test_case_insensitive_comparison_for_cs_column
|
||||
CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => false)
|
||||
CollationTest.create!(:string_cs_column => 'A')
|
||||
invalid = CollationTest.new(:string_cs_column => 'a')
|
||||
queries = assert_sql { invalid.save }
|
||||
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
|
||||
assert_match(/lower/i, cs_uniqueness_query)
|
||||
end
|
||||
|
||||
def test_case_sensitive_comparison_for_ci_column
|
||||
CollationTest.validates_uniqueness_of(:string_ci_column, :case_sensitive => true)
|
||||
CollationTest.create!(:string_ci_column => 'A')
|
||||
invalid = CollationTest.new(:string_ci_column => 'A')
|
||||
queries = assert_sql { invalid.save }
|
||||
ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) }
|
||||
assert_match(/binary/i, ci_uniqueness_query)
|
||||
end
|
||||
|
||||
def test_case_sensitive_comparison_for_cs_column
|
||||
CollationTest.validates_uniqueness_of(:string_cs_column, :case_sensitive => true)
|
||||
CollationTest.create!(:string_cs_column => 'A')
|
||||
invalid = CollationTest.new(:string_cs_column => 'A')
|
||||
queries = assert_sql { invalid.save }
|
||||
cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
|
||||
assert_no_match(/binary/i, cs_uniqueness_query)
|
||||
end
|
||||
end
|
|
@ -1,54 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'support/schema_dumping_helper'
|
||||
|
||||
class MysqlCharsetCollationTest < ActiveRecord::MysqlTestCase
|
||||
include SchemaDumpingHelper
|
||||
self.use_transactional_tests = false
|
||||
|
||||
setup do
|
||||
@connection = ActiveRecord::Base.connection
|
||||
@connection.create_table :charset_collations, force: true do |t|
|
||||
t.string :string_ascii_bin, charset: 'ascii', collation: 'ascii_bin'
|
||||
t.text :text_ucs2_unicode_ci, charset: 'ucs2', collation: 'ucs2_unicode_ci'
|
||||
end
|
||||
end
|
||||
|
||||
teardown do
|
||||
@connection.drop_table :charset_collations, if_exists: true
|
||||
end
|
||||
|
||||
test "string column with charset and collation" do
|
||||
column = @connection.columns(:charset_collations).find { |c| c.name == 'string_ascii_bin' }
|
||||
assert_equal :string, column.type
|
||||
assert_equal 'ascii_bin', column.collation
|
||||
end
|
||||
|
||||
test "text column with charset and collation" do
|
||||
column = @connection.columns(:charset_collations).find { |c| c.name == 'text_ucs2_unicode_ci' }
|
||||
assert_equal :text, column.type
|
||||
assert_equal 'ucs2_unicode_ci', column.collation
|
||||
end
|
||||
|
||||
test "add column with charset and collation" do
|
||||
@connection.add_column :charset_collations, :title, :string, charset: 'utf8', collation: 'utf8_bin'
|
||||
|
||||
column = @connection.columns(:charset_collations).find { |c| c.name == 'title' }
|
||||
assert_equal :string, column.type
|
||||
assert_equal 'utf8_bin', column.collation
|
||||
end
|
||||
|
||||
test "change column with charset and collation" do
|
||||
@connection.add_column :charset_collations, :description, :string, charset: 'utf8', collation: 'utf8_unicode_ci'
|
||||
@connection.change_column :charset_collations, :description, :text, charset: 'utf8', collation: 'utf8_general_ci'
|
||||
|
||||
column = @connection.columns(:charset_collations).find { |c| c.name == 'description' }
|
||||
assert_equal :text, column.type
|
||||
assert_equal 'utf8_general_ci', column.collation
|
||||
end
|
||||
|
||||
test "schema dump includes collation" do
|
||||
output = dump_table_schema("charset_collations")
|
||||
assert_match %r{t.string\s+"string_ascii_bin",\s+limit: 255,\s+collation: "ascii_bin"$}, output
|
||||
assert_match %r{t.text\s+"text_ucs2_unicode_ci",\s+limit: 65535,\s+collation: "ucs2_unicode_ci"$}, output
|
||||
end
|
||||
end
|
|
@ -1,210 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'support/connection_helper'
|
||||
require 'support/ddl_helper'
|
||||
|
||||
class MysqlConnectionTest < ActiveRecord::MysqlTestCase
|
||||
include ConnectionHelper
|
||||
include DdlHelper
|
||||
|
||||
class Klass < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def setup
|
||||
super
|
||||
@connection = ActiveRecord::Base.connection
|
||||
end
|
||||
|
||||
def test_mysql_reconnect_attribute_after_connection_with_reconnect_true
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => true}))
|
||||
assert ActiveRecord::Base.connection.raw_connection.reconnect
|
||||
end
|
||||
end
|
||||
|
||||
unless ARTest.connection_config['arunit']['socket']
|
||||
def test_connect_with_url
|
||||
run_without_connection do
|
||||
ar_config = ARTest.connection_config['arunit']
|
||||
|
||||
url = "mysql://#{ar_config["username"]}:#{ar_config["password"]}@localhost/#{ar_config["database"]}"
|
||||
Klass.establish_connection(url)
|
||||
assert_equal ar_config['database'], Klass.connection.current_database
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_reconnect_attribute_after_connection_with_reconnect_false
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => false}))
|
||||
assert !ActiveRecord::Base.connection.raw_connection.reconnect
|
||||
end
|
||||
end
|
||||
|
||||
def test_no_automatic_reconnection_after_timeout
|
||||
assert @connection.active?
|
||||
@connection.update('set @@wait_timeout=1')
|
||||
sleep 2
|
||||
assert !@connection.active?
|
||||
|
||||
# Repair all fixture connections so other tests won't break.
|
||||
@fixture_connections.each(&:verify!)
|
||||
end
|
||||
|
||||
def test_successful_reconnection_after_timeout_with_manual_reconnect
|
||||
assert @connection.active?
|
||||
@connection.update('set @@wait_timeout=1')
|
||||
sleep 2
|
||||
@connection.reconnect!
|
||||
assert @connection.active?
|
||||
end
|
||||
|
||||
def test_successful_reconnection_after_timeout_with_verify
|
||||
assert @connection.active?
|
||||
@connection.update('set @@wait_timeout=1')
|
||||
sleep 2
|
||||
@connection.verify!
|
||||
assert @connection.active?
|
||||
end
|
||||
|
||||
def test_bind_value_substitute
|
||||
bind_param = @connection.substitute_at('foo')
|
||||
assert_equal Arel.sql('?'), bind_param.to_sql
|
||||
end
|
||||
|
||||
def test_exec_no_binds
|
||||
with_example_table do
|
||||
result = @connection.exec_query('SELECT id, data FROM ex')
|
||||
assert_equal 0, result.rows.length
|
||||
assert_equal 2, result.columns.length
|
||||
assert_equal %w{ id data }, result.columns
|
||||
|
||||
@connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")')
|
||||
|
||||
# if there are no bind parameters, it will return a string (due to
|
||||
# the libmysql api)
|
||||
result = @connection.exec_query('SELECT id, data FROM ex')
|
||||
assert_equal 1, result.rows.length
|
||||
assert_equal 2, result.columns.length
|
||||
|
||||
assert_equal [['1', 'foo']], result.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_exec_with_binds
|
||||
with_example_table do
|
||||
@connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")')
|
||||
result = @connection.exec_query(
|
||||
'SELECT id, data FROM ex WHERE id = ?', nil, [ActiveRecord::Relation::QueryAttribute.new("id", 1, ActiveRecord::Type::Value.new)])
|
||||
|
||||
assert_equal 1, result.rows.length
|
||||
assert_equal 2, result.columns.length
|
||||
|
||||
assert_equal [[1, 'foo']], result.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_exec_typecasts_bind_vals
|
||||
with_example_table do
|
||||
@connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")')
|
||||
bind = ActiveRecord::Relation::QueryAttribute.new("id", "1-fuu", ActiveRecord::Type::Integer.new)
|
||||
|
||||
result = @connection.exec_query(
|
||||
'SELECT id, data FROM ex WHERE id = ?', nil, [bind])
|
||||
|
||||
assert_equal 1, result.rows.length
|
||||
assert_equal 2, result.columns.length
|
||||
|
||||
assert_equal [[1, 'foo']], result.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_connection_collation_is_configured
|
||||
assert_equal 'utf8_unicode_ci', @connection.show_variable('collation_connection')
|
||||
assert_equal 'utf8_general_ci', ARUnit2Model.connection.show_variable('collation_connection')
|
||||
end
|
||||
|
||||
def test_mysql_default_in_strict_mode
|
||||
result = @connection.exec_query "SELECT @@SESSION.sql_mode"
|
||||
assert_equal [["STRICT_ALL_TABLES"]], result.rows
|
||||
end
|
||||
|
||||
def test_mysql_strict_mode_disabled
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false}))
|
||||
result = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode"
|
||||
assert_equal [['']], result.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_strict_mode_specified_default
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.merge({strict: :default}))
|
||||
global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode"
|
||||
session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode"
|
||||
assert_equal global_sql_mode.rows, session_sql_mode.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_set_session_variable
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:default_week_format => 3}}))
|
||||
session_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.DEFAULT_WEEK_FORMAT"
|
||||
assert_equal 3, session_mode.rows.first.first.to_i
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_sql_mode_variable_overrides_strict_mode
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.deep_merge(variables: { 'sql_mode' => 'ansi' }))
|
||||
result = ActiveRecord::Base.connection.exec_query 'SELECT @@SESSION.sql_mode'
|
||||
assert_not_equal [['STRICT_ALL_TABLES']], result.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_mysql_set_session_variable_to_default
|
||||
run_without_connection do |orig_connection|
|
||||
ActiveRecord::Base.establish_connection(orig_connection.deep_merge({:variables => {:default_week_format => :default}}))
|
||||
global_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.DEFAULT_WEEK_FORMAT"
|
||||
session_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.DEFAULT_WEEK_FORMAT"
|
||||
assert_equal global_mode.rows, session_mode.rows
|
||||
end
|
||||
end
|
||||
|
||||
def test_get_and_release_advisory_lock
|
||||
lock_name = "test_lock_name"
|
||||
|
||||
got_lock = @connection.get_advisory_lock(lock_name)
|
||||
assert got_lock, "get_advisory_lock should have returned true but it didn't"
|
||||
|
||||
assert_equal test_lock_free(lock_name), false,
|
||||
"expected the test advisory lock to be held but it wasn't"
|
||||
|
||||
released_lock = @connection.release_advisory_lock(lock_name)
|
||||
assert released_lock, "expected release_advisory_lock to return true but it didn't"
|
||||
|
||||
assert test_lock_free(lock_name), 'expected the test lock to be available after releasing'
|
||||
end
|
||||
|
||||
def test_release_non_existent_advisory_lock
|
||||
lock_name = "fake_lock_name"
|
||||
released_non_existent_lock = @connection.release_advisory_lock(lock_name)
|
||||
assert_equal released_non_existent_lock, false,
|
||||
'expected release_advisory_lock to return false when there was no lock to release'
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def test_lock_free(lock_name)
|
||||
@connection.select_value("SELECT IS_FREE_LOCK('#{lock_name}');") == '1'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_example_table(&block)
|
||||
definition ||= <<-SQL
|
||||
`id` int auto_increment PRIMARY KEY,
|
||||
`data` varchar(255)
|
||||
SQL
|
||||
super(@connection, 'ex', definition, &block)
|
||||
end
|
||||
end
|
|
@ -1,49 +0,0 @@
|
|||
require "cases/helper"
|
||||
|
||||
class MysqlConsistencyTest < ActiveRecord::MysqlTestCase
|
||||
self.use_transactional_tests = false
|
||||
|
||||
class Consistency < ActiveRecord::Base
|
||||
self.table_name = "mysql_consistency"
|
||||
end
|
||||
|
||||
setup do
|
||||
@old_emulate_booleans = ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans
|
||||
ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false
|
||||
|
||||
@connection = ActiveRecord::Base.connection
|
||||
@connection.clear_cache!
|
||||
@connection.create_table("mysql_consistency") do |t|
|
||||
t.boolean "a_bool"
|
||||
t.string "a_string"
|
||||
end
|
||||
Consistency.reset_column_information
|
||||
Consistency.create!
|
||||
end
|
||||
|
||||
teardown do
|
||||
ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = @old_emulate_booleans
|
||||
@connection.drop_table "mysql_consistency"
|
||||
end
|
||||
|
||||
test "boolean columns with random value type cast to 0 when emulate_booleans is false" do
|
||||
with_new = Consistency.new
|
||||
with_last = Consistency.last
|
||||
with_new.a_bool = 'wibble'
|
||||
with_last.a_bool = 'wibble'
|
||||
|
||||
assert_equal 0, with_new.a_bool
|
||||
assert_equal 0, with_last.a_bool
|
||||
end
|
||||
|
||||
test "string columns call #to_s" do
|
||||
with_new = Consistency.new
|
||||
with_last = Consistency.last
|
||||
thing = Object.new
|
||||
with_new.a_string = thing
|
||||
with_last.a_string = thing
|
||||
|
||||
assert_equal thing.to_s, with_new.a_string
|
||||
assert_equal thing.to_s, with_last.a_string
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
require "cases/helper"
|
||||
|
||||
class MysqlEnumTest < ActiveRecord::MysqlTestCase
|
||||
class EnumTest < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def test_enum_limit
|
||||
assert_equal 6, EnumTest.columns.first.limit
|
||||
end
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'models/developer'
|
||||
require 'models/computer'
|
||||
|
||||
class MysqlExplainTest < ActiveRecord::MysqlTestCase
|
||||
fixtures :developers
|
||||
|
||||
def test_explain_for_one_query
|
||||
explain = Developer.where(id: 1).explain
|
||||
assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain
|
||||
assert_match %r(developers |.* const), explain
|
||||
end
|
||||
|
||||
def test_explain_with_eager_loading
|
||||
explain = Developer.where(id: 1).includes(:audit_logs).explain
|
||||
assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain
|
||||
assert_match %r(developers |.* const), explain
|
||||
assert_match %(EXPLAIN for: SELECT `audit_logs`.* FROM `audit_logs` WHERE `audit_logs`.`developer_id` = 1), explain
|
||||
assert_match %r(audit_logs |.* ALL), explain
|
||||
end
|
||||
end
|
|
@ -1,119 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'support/ddl_helper'
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class MysqlAdapterTest < ActiveRecord::MysqlTestCase
|
||||
include DdlHelper
|
||||
|
||||
def setup
|
||||
@conn = ActiveRecord::Base.connection
|
||||
end
|
||||
|
||||
def test_bad_connection_mysql
|
||||
assert_raise ActiveRecord::NoDatabaseError do
|
||||
configuration = ActiveRecord::Base.configurations['arunit'].merge(database: 'inexistent_activerecord_unittest')
|
||||
connection = ActiveRecord::Base.mysql_connection(configuration)
|
||||
connection.drop_table 'ex', if_exists: true
|
||||
end
|
||||
end
|
||||
|
||||
def test_valid_column
|
||||
with_example_table do
|
||||
column = @conn.columns('ex').find { |col| col.name == 'id' }
|
||||
assert @conn.valid_type?(column.type)
|
||||
end
|
||||
end
|
||||
|
||||
def test_invalid_column
|
||||
assert_not @conn.valid_type?(:foobar)
|
||||
end
|
||||
|
||||
def test_client_encoding
|
||||
assert_equal Encoding::UTF_8, @conn.client_encoding
|
||||
end
|
||||
|
||||
def test_exec_insert_number
|
||||
with_example_table do
|
||||
insert(@conn, 'number' => 10)
|
||||
|
||||
result = @conn.exec_query('SELECT number FROM ex WHERE number = 10')
|
||||
|
||||
assert_equal 1, result.rows.length
|
||||
# if there are no bind parameters, it will return a string (due to
|
||||
# the libmysql api)
|
||||
assert_equal '10', result.rows.last.last
|
||||
end
|
||||
end
|
||||
|
||||
def test_exec_insert_string
|
||||
with_example_table do
|
||||
str = 'いただきます!'
|
||||
insert(@conn, 'number' => 10, 'data' => str)
|
||||
|
||||
result = @conn.exec_query('SELECT number, data FROM ex WHERE number = 10')
|
||||
|
||||
value = result.rows.last.last
|
||||
|
||||
# FIXME: this should probably be inside the mysql AR adapter?
|
||||
value.force_encoding(@conn.client_encoding)
|
||||
|
||||
# The strings in this file are utf-8, so transcode to utf-8
|
||||
value.encode!(Encoding::UTF_8)
|
||||
|
||||
assert_equal str, value
|
||||
end
|
||||
end
|
||||
|
||||
def test_composite_primary_key
|
||||
with_example_table '`id` INT, `number` INT, foo INT, PRIMARY KEY (`id`, `number`)' do
|
||||
assert_nil @conn.primary_key('ex')
|
||||
end
|
||||
end
|
||||
|
||||
def test_tinyint_integer_typecasting
|
||||
with_example_table '`status` TINYINT(4)' do
|
||||
insert(@conn, { 'status' => 2 }, 'ex')
|
||||
|
||||
result = @conn.exec_query('SELECT status FROM ex')
|
||||
|
||||
assert_equal 2, result.column_types['status'].deserialize(result.last['status'])
|
||||
end
|
||||
end
|
||||
|
||||
def test_supports_extensions
|
||||
assert_not @conn.supports_extensions?, 'does not support extensions'
|
||||
end
|
||||
|
||||
def test_respond_to_enable_extension
|
||||
assert @conn.respond_to?(:enable_extension)
|
||||
end
|
||||
|
||||
def test_respond_to_disable_extension
|
||||
assert @conn.respond_to?(:disable_extension)
|
||||
end
|
||||
|
||||
private
|
||||
def insert(ctx, data, table='ex')
|
||||
binds = data.map { |name, value|
|
||||
Relation::QueryAttribute.new(name, value, Type::Value.new)
|
||||
}
|
||||
columns = binds.map(&:name)
|
||||
|
||||
sql = "INSERT INTO #{table} (#{columns.join(", ")})
|
||||
VALUES (#{(['?'] * columns.length).join(', ')})"
|
||||
|
||||
ctx.exec_insert(sql, 'SQL', binds)
|
||||
end
|
||||
|
||||
def with_example_table(definition = nil, &block)
|
||||
definition ||= <<-SQL
|
||||
`id` int auto_increment PRIMARY KEY,
|
||||
`number` integer,
|
||||
`data` varchar(255)
|
||||
SQL
|
||||
super(@conn, 'ex', definition, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,29 +0,0 @@
|
|||
require "cases/helper"
|
||||
|
||||
class MysqlQuotingTest < ActiveRecord::MysqlTestCase
|
||||
def setup
|
||||
@conn = ActiveRecord::Base.connection
|
||||
end
|
||||
|
||||
def test_type_cast_true
|
||||
assert_equal 1, @conn.type_cast(true)
|
||||
end
|
||||
|
||||
def test_type_cast_false
|
||||
assert_equal 0, @conn.type_cast(false)
|
||||
end
|
||||
|
||||
def test_quoted_date_precision_for_gte_564
|
||||
@conn.stubs(:full_version).returns('5.6.4')
|
||||
@conn.remove_instance_variable(:@version) if @conn.instance_variable_defined?(:@version)
|
||||
t = Time.now.change(usec: 1)
|
||||
assert_match(/\.000001\z/, @conn.quoted_date(t))
|
||||
end
|
||||
|
||||
def test_quoted_date_precision_for_lt_564
|
||||
@conn.stubs(:full_version).returns('5.6.3')
|
||||
@conn.remove_instance_variable(:@version) if @conn.instance_variable_defined?(:@version)
|
||||
t = Time.now.change(usec: 1)
|
||||
assert_no_match(/\.000001\z/, @conn.quoted_date(t))
|
||||
end
|
||||
end
|
|
@ -1,153 +0,0 @@
|
|||
require "cases/helper"
|
||||
|
||||
# a suite of tests to ensure the ConnectionAdapters#MysqlAdapter can handle tables with
|
||||
# reserved word names (ie: group, order, values, etc...)
|
||||
class MysqlReservedWordTest < ActiveRecord::MysqlTestCase
|
||||
class Group < ActiveRecord::Base
|
||||
Group.table_name = 'group'
|
||||
belongs_to :select
|
||||
has_one :values
|
||||
end
|
||||
|
||||
class Select < ActiveRecord::Base
|
||||
Select.table_name = 'select'
|
||||
has_many :groups
|
||||
end
|
||||
|
||||
class Values < ActiveRecord::Base
|
||||
Values.table_name = 'values'
|
||||
end
|
||||
|
||||
class Distinct < ActiveRecord::Base
|
||||
Distinct.table_name = 'distinct'
|
||||
has_and_belongs_to_many :selects
|
||||
has_many :values, :through => :groups
|
||||
end
|
||||
|
||||
def setup
|
||||
@connection = ActiveRecord::Base.connection
|
||||
|
||||
# we call execute directly here (and do similar below) because ActiveRecord::Base#create_table()
|
||||
# will fail with these table names if these test cases fail
|
||||
|
||||
create_tables_directly 'group'=>'id int auto_increment primary key, `order` varchar(255), select_id int',
|
||||
'select'=>'id int auto_increment primary key',
|
||||
'values'=>'id int auto_increment primary key, group_id int',
|
||||
'distinct'=>'id int auto_increment primary key',
|
||||
'distinct_select'=>'distinct_id int, select_id int'
|
||||
end
|
||||
|
||||
teardown do
|
||||
drop_tables_directly ['group', 'select', 'values', 'distinct', 'distinct_select', 'order']
|
||||
end
|
||||
|
||||
# create tables with reserved-word names and columns
|
||||
def test_create_tables
|
||||
assert_nothing_raised {
|
||||
@connection.create_table :order do |t|
|
||||
t.column :group, :string
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
# rename tables with reserved-word names
|
||||
def test_rename_tables
|
||||
assert_nothing_raised { @connection.rename_table(:group, :order) }
|
||||
end
|
||||
|
||||
# alter column with a reserved-word name in a table with a reserved-word name
|
||||
def test_change_columns
|
||||
assert_nothing_raised { @connection.change_column_default(:group, :order, 'whatever') }
|
||||
#the quoting here will reveal any double quoting issues in change_column's interaction with the column method in the adapter
|
||||
assert_nothing_raised { @connection.change_column('group', 'order', :Int, :default => 0) }
|
||||
assert_nothing_raised { @connection.rename_column(:group, :order, :values) }
|
||||
end
|
||||
|
||||
# introspect table with reserved word name
|
||||
def test_introspect
|
||||
assert_nothing_raised { @connection.columns(:group) }
|
||||
assert_nothing_raised { @connection.indexes(:group) }
|
||||
end
|
||||
|
||||
#fixtures
|
||||
self.use_instantiated_fixtures = true
|
||||
self.use_transactional_tests = false
|
||||
|
||||
#activerecord model class with reserved-word table name
|
||||
def test_activerecord_model
|
||||
create_test_fixtures :select, :distinct, :group, :values, :distinct_select
|
||||
x = nil
|
||||
assert_nothing_raised { x = Group.new }
|
||||
x.order = 'x'
|
||||
assert_nothing_raised { x.save }
|
||||
x.order = 'y'
|
||||
assert_nothing_raised { x.save }
|
||||
assert_nothing_raised { Group.find_by_order('y') }
|
||||
assert_nothing_raised { Group.find(1) }
|
||||
Group.find(1)
|
||||
end
|
||||
|
||||
# has_one association with reserved-word table name
|
||||
def test_has_one_associations
|
||||
create_test_fixtures :select, :distinct, :group, :values, :distinct_select
|
||||
v = nil
|
||||
assert_nothing_raised { v = Group.find(1).values }
|
||||
assert_equal 2, v.id
|
||||
end
|
||||
|
||||
# belongs_to association with reserved-word table name
|
||||
def test_belongs_to_associations
|
||||
create_test_fixtures :select, :distinct, :group, :values, :distinct_select
|
||||
gs = nil
|
||||
assert_nothing_raised { gs = Select.find(2).groups }
|
||||
assert_equal gs.length, 2
|
||||
assert(gs.collect(&:id).sort == [2, 3])
|
||||
end
|
||||
|
||||
# has_and_belongs_to_many with reserved-word table name
|
||||
def test_has_and_belongs_to_many
|
||||
create_test_fixtures :select, :distinct, :group, :values, :distinct_select
|
||||
s = nil
|
||||
assert_nothing_raised { s = Distinct.find(1).selects }
|
||||
assert_equal s.length, 2
|
||||
assert(s.collect(&:id).sort == [1, 2])
|
||||
end
|
||||
|
||||
# activerecord model introspection with reserved-word table and column names
|
||||
def test_activerecord_introspection
|
||||
assert_nothing_raised { Group.table_exists? }
|
||||
assert_nothing_raised { Group.columns }
|
||||
end
|
||||
|
||||
# Calculations
|
||||
def test_calculations_work_with_reserved_words
|
||||
assert_nothing_raised { Group.count }
|
||||
end
|
||||
|
||||
def test_associations_work_with_reserved_words
|
||||
assert_nothing_raised { Select.all.merge!(:includes => [:groups]).to_a }
|
||||
end
|
||||
|
||||
#the following functions were added to DRY test cases
|
||||
|
||||
private
|
||||
# custom fixture loader, uses FixtureSet#create_fixtures and appends base_path to the current file's path
|
||||
def create_test_fixtures(*fixture_names)
|
||||
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names)
|
||||
end
|
||||
|
||||
# custom drop table, uses execute on connection to drop a table if it exists. note: escapes table_name
|
||||
def drop_tables_directly(table_names, connection = @connection)
|
||||
table_names.each do |name|
|
||||
connection.drop_table name, if_exists: true
|
||||
end
|
||||
end
|
||||
|
||||
# custom create table, uses execute on connection to create a table, note: escapes table_name, does NOT escape columns
|
||||
def create_tables_directly (tables, connection = @connection)
|
||||
tables.each do |table_name, column_properties|
|
||||
connection.execute("CREATE TABLE `#{table_name}` ( #{column_properties} )")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,94 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'models/post'
|
||||
require 'models/comment'
|
||||
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class MysqlSchemaTest < ActiveRecord::MysqlTestCase
|
||||
fixtures :posts
|
||||
|
||||
def setup
|
||||
@connection = ActiveRecord::Base.connection
|
||||
db = Post.connection_pool.spec.config[:database]
|
||||
table = Post.table_name
|
||||
@db_name = db
|
||||
|
||||
@omgpost = Class.new(ActiveRecord::Base) do
|
||||
self.inheritance_column = :disabled
|
||||
self.table_name = "#{db}.#{table}"
|
||||
def self.name; 'Post'; end
|
||||
end
|
||||
end
|
||||
|
||||
def test_float_limits
|
||||
@connection.create_table :mysql_doubles do |t|
|
||||
t.float :float_no_limit
|
||||
t.float :float_short, limit: 5
|
||||
t.float :float_long, limit: 53
|
||||
|
||||
t.float :float_23, limit: 23
|
||||
t.float :float_24, limit: 24
|
||||
t.float :float_25, limit: 25
|
||||
end
|
||||
|
||||
column_no_limit = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_no_limit' }
|
||||
column_short = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_short' }
|
||||
column_long = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_long' }
|
||||
|
||||
column_23 = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_23' }
|
||||
column_24 = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_24' }
|
||||
column_25 = @connection.columns(:mysql_doubles).find { |c| c.name == 'float_25' }
|
||||
|
||||
# Mysql floats are precision 0..24, Mysql doubles are precision 25..53
|
||||
assert_equal 24, column_no_limit.limit
|
||||
assert_equal 24, column_short.limit
|
||||
assert_equal 53, column_long.limit
|
||||
|
||||
assert_equal 24, column_23.limit
|
||||
assert_equal 24, column_24.limit
|
||||
assert_equal 53, column_25.limit
|
||||
ensure
|
||||
@connection.drop_table "mysql_doubles", if_exists: true
|
||||
end
|
||||
|
||||
def test_schema
|
||||
assert @omgpost.first
|
||||
end
|
||||
|
||||
def test_primary_key
|
||||
assert_equal 'id', @omgpost.primary_key
|
||||
end
|
||||
|
||||
def test_data_source_exists?
|
||||
name = @omgpost.table_name
|
||||
assert @connection.data_source_exists?(name), "#{name} data_source should exist"
|
||||
end
|
||||
|
||||
def test_data_source_exists_wrong_schema
|
||||
assert(!@connection.data_source_exists?("#{@db_name}.zomg"), "data_source should not exist")
|
||||
end
|
||||
|
||||
def test_dump_indexes
|
||||
index_a_name = 'index_key_tests_on_snack'
|
||||
index_b_name = 'index_key_tests_on_pizza'
|
||||
index_c_name = 'index_key_tests_on_awesome'
|
||||
|
||||
table = 'key_tests'
|
||||
|
||||
indexes = @connection.indexes(table).sort_by(&:name)
|
||||
assert_equal 3,indexes.size
|
||||
|
||||
index_a = indexes.select{|i| i.name == index_a_name}[0]
|
||||
index_b = indexes.select{|i| i.name == index_b_name}[0]
|
||||
index_c = indexes.select{|i| i.name == index_c_name}[0]
|
||||
assert_equal :btree, index_a.using
|
||||
assert_nil index_a.type
|
||||
assert_equal :btree, index_b.using
|
||||
assert_nil index_b.type
|
||||
|
||||
assert_nil index_c.using
|
||||
assert_equal :fulltext, index_c.type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'models/topic'
|
||||
require 'models/reply'
|
||||
|
||||
class MysqlStoredProcedureTest < ActiveRecord::MysqlTestCase
|
||||
fixtures :topics
|
||||
|
||||
def setup
|
||||
@connection = ActiveRecord::Base.connection
|
||||
unless ActiveRecord::Base.connection.version >= '5.6.0' || Mysql.const_defined?(:CLIENT_MULTI_RESULTS)
|
||||
skip("no stored procedure support")
|
||||
end
|
||||
end
|
||||
|
||||
# Test that MySQL allows multiple results for stored procedures
|
||||
#
|
||||
# In MySQL 5.6, CLIENT_MULTI_RESULTS is enabled by default.
|
||||
# http://dev.mysql.com/doc/refman/5.6/en/call.html
|
||||
def test_multi_results
|
||||
rows = @connection.select_rows('CALL ten();')
|
||||
assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}"
|
||||
assert @connection.active?, "Bad connection use by 'MysqlAdapter.select_rows'"
|
||||
end
|
||||
|
||||
def test_multi_results_from_find_by_sql
|
||||
topics = Topic.find_by_sql 'CALL topics(3);'
|
||||
assert_equal 3, topics.size
|
||||
assert @connection.active?, "Bad connection use by 'MysqlAdapter.select'"
|
||||
end
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
require "cases/helper"
|
||||
|
||||
class MysqlSqlTypesTest < ActiveRecord::MysqlTestCase
|
||||
def test_binary_types
|
||||
assert_equal 'varbinary(64)', type_to_sql(:binary, 64)
|
||||
assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095)
|
||||
assert_equal 'blob', type_to_sql(:binary, 4096)
|
||||
assert_equal 'blob', type_to_sql(:binary)
|
||||
end
|
||||
|
||||
def type_to_sql(*args)
|
||||
ActiveRecord::Base.connection.type_to_sql(*args)
|
||||
end
|
||||
end
|
|
@ -1,19 +0,0 @@
|
|||
require 'cases/helper'
|
||||
|
||||
class MysqlStatementPoolTest < ActiveRecord::MysqlTestCase
|
||||
if Process.respond_to?(:fork)
|
||||
def test_cache_is_per_pid
|
||||
cache = ActiveRecord::ConnectionAdapters::MysqlAdapter::StatementPool.new(10)
|
||||
cache['foo'] = 'bar'
|
||||
assert_equal 'bar', cache['foo']
|
||||
|
||||
pid = fork {
|
||||
lookup = cache['foo'];
|
||||
exit!(!lookup)
|
||||
}
|
||||
|
||||
Process.waitpid pid
|
||||
assert $?.success?, 'process should exit successfully'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,42 +0,0 @@
|
|||
require "cases/helper"
|
||||
require 'support/schema_dumping_helper'
|
||||
|
||||
class MysqlTableOptionsTest < ActiveRecord::MysqlTestCase
|
||||
include SchemaDumpingHelper
|
||||
|
||||
def setup
|
||||
@connection = ActiveRecord::Base.connection
|
||||
end
|
||||
|
||||
def teardown
|
||||
@connection.drop_table "mysql_table_options", if_exists: true
|
||||
end
|
||||
|
||||
test "table options with ENGINE" do
|
||||
@connection.create_table "mysql_table_options", force: true, options: "ENGINE=MyISAM"
|
||||
output = dump_table_schema("mysql_table_options")
|
||||
options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
|
||||
assert_match %r{ENGINE=MyISAM}, options
|
||||
end
|
||||
|
||||
test "table options with ROW_FORMAT" do
|
||||
@connection.create_table "mysql_table_options", force: true, options: "ROW_FORMAT=REDUNDANT"
|
||||
output = dump_table_schema("mysql_table_options")
|
||||
options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
|
||||
assert_match %r{ROW_FORMAT=REDUNDANT}, options
|
||||
end
|
||||
|
||||
test "table options with CHARSET" do
|
||||
@connection.create_table "mysql_table_options", force: true, options: "CHARSET=utf8mb4"
|
||||
output = dump_table_schema("mysql_table_options")
|
||||
options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
|
||||
assert_match %r{CHARSET=utf8mb4}, options
|
||||
end
|
||||
|
||||
test "table options with COLLATE" do
|
||||
@connection.create_table "mysql_table_options", force: true, options: "COLLATE=utf8mb4_bin"
|
||||
output = dump_table_schema("mysql_table_options")
|
||||
options = %r{create_table "mysql_table_options", force: :cascade, options: "(?<options>.*)"}.match(output)[:options]
|
||||
assert_match %r{COLLATE=utf8mb4_bin}, options
|
||||
end
|
||||
end
|
|
@ -1,65 +0,0 @@
|
|||
require "cases/helper"
|
||||
require "support/schema_dumping_helper"
|
||||
|
||||
class MysqlUnsignedTypeTest < ActiveRecord::MysqlTestCase
|
||||
include SchemaDumpingHelper
|
||||
self.use_transactional_tests = false
|
||||
|
||||
class UnsignedType < ActiveRecord::Base
|
||||
end
|
||||
|
||||
setup do
|
||||
@connection = ActiveRecord::Base.connection
|
||||
@connection.create_table("unsigned_types", force: true) do |t|
|
||||
t.integer :unsigned_integer, unsigned: true
|
||||
t.bigint :unsigned_bigint, unsigned: true
|
||||
t.float :unsigned_float, unsigned: true
|
||||
t.decimal :unsigned_decimal, unsigned: true, precision: 10, scale: 2
|
||||
end
|
||||
end
|
||||
|
||||
teardown do
|
||||
@connection.drop_table "unsigned_types", if_exists: true
|
||||
end
|
||||
|
||||
test "unsigned int max value is in range" do
|
||||
assert expected = UnsignedType.create(unsigned_integer: 4294967295)
|
||||
assert_equal expected, UnsignedType.find_by(unsigned_integer: 4294967295)
|
||||
end
|
||||
|
||||
test "minus value is out of range" do
|
||||
assert_raise(RangeError) do
|
||||
UnsignedType.create(unsigned_integer: -10)
|
||||
end
|
||||
assert_raise(RangeError) do
|
||||
UnsignedType.create(unsigned_bigint: -10)
|
||||
end
|
||||
assert_raise(ActiveRecord::StatementInvalid) do
|
||||
UnsignedType.create(unsigned_float: -10.0)
|
||||
end
|
||||
assert_raise(ActiveRecord::StatementInvalid) do
|
||||
UnsignedType.create(unsigned_decimal: -10.0)
|
||||
end
|
||||
end
|
||||
|
||||
test "schema definition can use unsigned as the type" do
|
||||
@connection.change_table("unsigned_types") do |t|
|
||||
t.unsigned_integer :unsigned_integer_t
|
||||
t.unsigned_bigint :unsigned_bigint_t
|
||||
t.unsigned_float :unsigned_float_t
|
||||
t.unsigned_decimal :unsigned_decimal_t, precision: 10, scale: 2
|
||||
end
|
||||
|
||||
@connection.columns("unsigned_types").select { |c| /^unsigned_/ === c.name }.each do |column|
|
||||
assert column.unsigned?
|
||||
end
|
||||
end
|
||||
|
||||
test "schema dump includes unsigned option" do
|
||||
schema = dump_table_schema "unsigned_types"
|
||||
assert_match %r{t.integer\s+"unsigned_integer",\s+limit: 4,\s+unsigned: true$}, schema
|
||||
assert_match %r{t.integer\s+"unsigned_bigint",\s+limit: 8,\s+unsigned: true$}, schema
|
||||
assert_match %r{t.float\s+"unsigned_float",\s+limit: 24,\s+unsigned: true$}, schema
|
||||
assert_match %r{t.decimal\s+"unsigned_decimal",\s+precision: 10,\s+scale: 2,\s+unsigned: true$}, schema
|
||||
end
|
||||
end
|
|
@ -53,7 +53,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
|
|||
|
||||
def test_belongs_to_with_primary_key_joins_on_correct_column
|
||||
sql = Client.joins(:firm_with_primary_key).to_sql
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
|
||||
assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
|
||||
elsif current_adapter?(:OracleAdapter)
|
||||
|
|
|
@ -175,7 +175,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
|
|||
assert_equal category_attrs , category.attributes_before_type_cast
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_read_attributes_before_type_cast_on_boolean
|
||||
bool = Boolean.create!({ "value" => false })
|
||||
if RUBY_PLATFORM =~ /java/
|
||||
|
|
|
@ -444,7 +444,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|||
Post.reset_table_name
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_update_all_with_order_and_limit
|
||||
assert_equal 1, Topic.limit(1).order('id DESC').update_all(:content => 'bulk updated!')
|
||||
end
|
||||
|
|
|
@ -20,10 +20,6 @@ unless current_adapter?(:DB2Adapter)
|
|||
|
||||
name = binary.name
|
||||
|
||||
# MySQL adapter doesn't properly encode things, so we have to do it
|
||||
if current_adapter?(:MysqlAdapter)
|
||||
name.force_encoding(Encoding::UTF_8)
|
||||
end
|
||||
assert_equal 'いただきます!', name
|
||||
end
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ class CalculationsTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
def test_from_option_with_specified_index
|
||||
if Edge.connection.adapter_name == 'MySQL' or Edge.connection.adapter_name == 'Mysql2'
|
||||
if Edge.connection.adapter_name == 'Mysql2'
|
||||
assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
|
||||
assert_equal Edge.where('sink_id < 5').count(:all),
|
||||
Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
|
||||
|
|
|
@ -38,7 +38,7 @@ module ActiveRecord
|
|||
assert_equal %Q{title varchar(20) DEFAULT 'Hello' NOT NULL}, @viz.accept(column_def)
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_should_set_default_for_mysql_binary_data_types
|
||||
type = SqlTypeMetadata.new(type: :binary, sql_type: "binary(1)")
|
||||
binary_column = AbstractMysqlAdapter::Column.new("title", "a", type)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "cases/helper"
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
module ActiveRecord
|
||||
module ConnectionAdapters
|
||||
class MysqlTypeLookupTest < ActiveRecord::TestCase
|
||||
|
|
|
@ -6,7 +6,7 @@ module ActiveRecord
|
|||
fixtures :people
|
||||
|
||||
def test_custom_lock
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
assert_match 'SHARE MODE', Person.lock('LOCK IN SHARE MODE').to_sql
|
||||
assert_sql(/LOCK IN SHARE MODE/) do
|
||||
Person.all.merge!(:lock => 'LOCK IN SHARE MODE').find(1)
|
||||
|
|
|
@ -4,17 +4,10 @@ require 'models/entrant'
|
|||
|
||||
class DefaultTest < ActiveRecord::TestCase
|
||||
def test_nil_defaults_for_not_null_columns
|
||||
column_defaults =
|
||||
if current_adapter?(:MysqlAdapter) && (Mysql.client_version < 50051 || (50100..50122).include?(Mysql.client_version))
|
||||
{ 'id' => nil, 'name' => '', 'course_id' => nil }
|
||||
else
|
||||
{ 'id' => nil, 'name' => nil, 'course_id' => nil }
|
||||
end
|
||||
|
||||
column_defaults.each do |name, default|
|
||||
%w(id name course_id).each do |name|
|
||||
column = Entrant.columns_hash[name]
|
||||
assert !column.null, "#{name} column should be NOT NULL"
|
||||
assert_equal default, column.default, "#{name} column should be DEFAULT #{default.inspect}"
|
||||
assert_not column.default, "#{name} column should be DEFAULT 'nil'"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -87,7 +80,7 @@ class DefaultStringsTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
class DefaultsTestWithoutTransactionalFixtures < ActiveRecord::TestCase
|
||||
# ActiveRecord::Base#create! (and #save and other related methods) will
|
||||
# open a new transaction. When in transactional tests mode, this will
|
||||
|
|
|
@ -51,7 +51,7 @@ def subsecond_precision_supported?
|
|||
end
|
||||
|
||||
def mysql_enforcing_gtid_consistency?
|
||||
current_adapter?(:MysqlAdapter, :Mysql2Adapter) && 'ON' == ActiveRecord::Base.connection.show_variable('enforce_gtid_consistency')
|
||||
current_adapter?(:Mysql2Adapter) && 'ON' == ActiveRecord::Base.connection.show_variable('enforce_gtid_consistency')
|
||||
end
|
||||
|
||||
def supports_savepoints?
|
||||
|
|
|
@ -9,7 +9,7 @@ class TestAdapterWithInvalidConnection < ActiveRecord::TestCase
|
|||
def setup
|
||||
# Can't just use current adapter; sqlite3 will create a database
|
||||
# file on the fly.
|
||||
Bird.establish_connection adapter: 'mysql', database: 'i_do_not_exist'
|
||||
Bird.establish_connection adapter: 'mysql2', database: 'i_do_not_exist'
|
||||
end
|
||||
|
||||
teardown do
|
||||
|
|
|
@ -354,7 +354,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
# MySQL 5.7 and Oracle do not allow to create duplicate indexes on the same columns
|
||||
unless current_adapter?(:MysqlAdapter, :Mysql2Adapter, :OracleAdapter)
|
||||
unless current_adapter?(:Mysql2Adapter, :OracleAdapter)
|
||||
def test_migrate_revert_add_index_with_name
|
||||
RevertNamedIndexMigration1.new.migrate(:up)
|
||||
RevertNamedIndexMigration2.new.migrate(:up)
|
||||
|
|
|
@ -50,7 +50,7 @@ module ActiveRecord
|
|||
|
||||
def test_create_table_with_defaults
|
||||
# MySQL doesn't allow defaults on TEXT or BLOB columns.
|
||||
mysql = current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
mysql = current_adapter?(:Mysql2Adapter)
|
||||
|
||||
connection.create_table :testings do |t|
|
||||
t.column :one, :string, :default => "hello"
|
||||
|
@ -141,7 +141,7 @@ module ActiveRecord
|
|||
assert_equal 'smallint', one.sql_type
|
||||
assert_equal 'integer', four.sql_type
|
||||
assert_equal 'bigint', eight.sql_type
|
||||
elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
elsif current_adapter?(:Mysql2Adapter)
|
||||
assert_match 'int(11)', default.sql_type
|
||||
assert_match 'tinyint', one.sql_type
|
||||
assert_match 'int', four.sql_type
|
||||
|
@ -442,7 +442,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def test_create_table_with_force_cascade_drops_dependent_objects
|
||||
skip "MySQL > 5.5 does not drop dependent objects with DROP TABLE CASCADE" if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
skip "MySQL > 5.5 does not drop dependent objects with DROP TABLE CASCADE" if current_adapter?(:Mysql2Adapter)
|
||||
# can't re-create table referenced by foreign key
|
||||
assert_raises(ActiveRecord::StatementInvalid) do
|
||||
@connection.create_table :trains, force: true
|
||||
|
|
|
@ -37,13 +37,13 @@ module ActiveRecord
|
|||
|
||||
def test_add_column_without_limit
|
||||
# TODO: limit: nil should work with all adapters.
|
||||
skip "MySQL wrongly enforces a limit of 255" if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
skip "MySQL wrongly enforces a limit of 255" if current_adapter?(:Mysql2Adapter)
|
||||
add_column :test_models, :description, :string, limit: nil
|
||||
TestModel.reset_column_information
|
||||
assert_nil TestModel.columns_hash["description"].limit
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_unabstracted_database_dependent_types
|
||||
add_column :test_models, :intelligence_quotient, :tinyint
|
||||
TestModel.reset_column_information
|
||||
|
@ -171,7 +171,7 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
||||
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
def test_out_of_range_limit_should_raise
|
||||
assert_raise(ActiveRecordError) { add_column :test_models, :integer_too_big, :integer, :limit => 10 }
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ module ActiveRecord
|
|||
ActiveRecord::Base.primary_key_prefix_type = nil
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_column_positioning
|
||||
assert_equal %w(first second third), conn.columns(:testings).map(&:name)
|
||||
end
|
||||
|
|
|
@ -62,7 +62,7 @@ module ActiveRecord
|
|||
assert_equal '70000', default_after
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_mysql_rename_column_preserves_auto_increment
|
||||
rename_column "test_models", "id", "id_test"
|
||||
assert connection.columns("test_models").find { |c| c.name == "id_test" }.auto_increment?
|
||||
|
|
|
@ -99,7 +99,7 @@ module ActiveRecord
|
|||
assert_equal 1, foreign_keys.size
|
||||
|
||||
fk = foreign_keys.first
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
# ON DELETE RESTRICT is the default on MySQL
|
||||
assert_equal nil, fk.on_delete
|
||||
else
|
||||
|
|
|
@ -176,7 +176,7 @@ module ActiveRecord
|
|||
connection.remove_index("testings", :name => "named_admin")
|
||||
|
||||
# Selected adapters support index sort order
|
||||
if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
||||
if current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
||||
connection.add_index("testings", ["last_name"], :order => {:last_name => :desc})
|
||||
connection.remove_index("testings", ["last_name"])
|
||||
connection.add_index("testings", ["last_name", "first_name"], :order => {:last_name => :desc})
|
||||
|
|
|
@ -500,7 +500,7 @@ class MigrationTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
||||
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
def test_out_of_range_limit_should_raise
|
||||
Person.connection.drop_table :test_limits rescue nil
|
||||
e = assert_raise(ActiveRecord::ActiveRecordError, "integer limit didn't raise") do
|
||||
|
|
|
@ -268,7 +268,7 @@ class CompositePrimaryKeyTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
|
||||
self.use_transactional_tests = false
|
||||
|
||||
|
@ -308,7 +308,7 @@ if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter)
|
||||
class PrimaryKeyBigSerialTest < ActiveRecord::TestCase
|
||||
include SchemaDumpingHelper
|
||||
|
||||
|
@ -351,7 +351,7 @@ if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter, :Mysql2Adapter)
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
test "primary key column type with options" do
|
||||
@connection.create_table(:widgets, id: :primary_key, limit: 8, unsigned: true, force: true)
|
||||
column = @connection.columns(:widgets).find { |c| c.name == 'id' }
|
||||
|
|
|
@ -117,7 +117,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|||
|
||||
assert_match %r{c_int_4.*}, output
|
||||
assert_no_match %r{c_int_4.*limit:}, output
|
||||
elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
elsif current_adapter?(:Mysql2Adapter)
|
||||
assert_match %r{c_int_without_limit.*limit: 4}, output
|
||||
|
||||
assert_match %r{c_int_1.*limit: 1}, output
|
||||
|
@ -169,7 +169,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|||
|
||||
def test_schema_dumps_index_columns_in_right_order
|
||||
index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_index/).first.strip
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
||||
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index", using: :btree', index_definition
|
||||
else
|
||||
assert_equal 't.index ["firm_id", "type", "rating"], name: "company_index"', index_definition
|
||||
|
@ -180,7 +180,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|||
index_definition = standard_dump.split(/\n/).grep(/t\.index.*company_partial_index/).first.strip
|
||||
if current_adapter?(:PostgreSQLAdapter)
|
||||
assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
|
||||
elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
elsif current_adapter?(:Mysql2Adapter)
|
||||
assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
|
||||
elsif current_adapter?(:SQLite3Adapter) && ActiveRecord::Base.connection.supports_partial_index?
|
||||
assert_equal 't.index ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
|
||||
|
@ -201,7 +201,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|||
assert_match %r{t\.boolean\s+"has_fun",.+default: false}, output
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
def test_schema_dump_should_add_default_value_for_mysql_text_field
|
||||
output = standard_dump
|
||||
assert_match %r{t\.text\s+"body",\s+limit: 65535,\s+null: false$}, output
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
require 'cases/helper'
|
||||
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
|
||||
if current_adapter?(:Mysql2Adapter)
|
||||
module ActiveRecord
|
||||
class MysqlDBCreateTest < ActiveRecord::TestCase
|
||||
def setup
|
||||
@connection = stub(:create_database => true)
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'my-app-db'
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ module ActiveRecord
|
|||
|
||||
def test_establishes_connection_without_database
|
||||
ActiveRecord::Base.expects(:establish_connection).
|
||||
with('adapter' => 'mysql', 'database' => nil)
|
||||
with('adapter' => 'mysql2', 'database' => nil)
|
||||
|
||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||
end
|
||||
|
@ -65,7 +65,7 @@ module ActiveRecord
|
|||
@connection = stub("Connection", create_database: true)
|
||||
@error = Mysql::Error.new "Invalid permissions"
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'my-app-db',
|
||||
'username' => 'pat',
|
||||
'password' => 'wossname'
|
||||
|
@ -92,7 +92,7 @@ module ActiveRecord
|
|||
def test_connection_established_as_root
|
||||
assert_permissions_granted_for "pat"
|
||||
ActiveRecord::Base.expects(:establish_connection).with(
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => nil,
|
||||
'username' => 'root',
|
||||
'password' => 'secret'
|
||||
|
@ -124,7 +124,7 @@ module ActiveRecord
|
|||
assert_permissions_granted_for "pat"
|
||||
ActiveRecord::Base.expects(:establish_connection).returns do
|
||||
ActiveRecord::Base.expects(:establish_connection).with(
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'my-app-db',
|
||||
'username' => 'pat',
|
||||
'password' => 'secret'
|
||||
|
@ -157,7 +157,7 @@ module ActiveRecord
|
|||
def setup
|
||||
@connection = stub(:drop_database => true)
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'my-app-db'
|
||||
}
|
||||
|
||||
|
@ -182,7 +182,7 @@ module ActiveRecord
|
|||
def setup
|
||||
@connection = stub(:recreate_database => true)
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'test-db'
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ module ActiveRecord
|
|||
def setup
|
||||
@connection = stub(:create_database => true)
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'my-app-db'
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ module ActiveRecord
|
|||
def setup
|
||||
@connection = stub(:create_database => true)
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'my-app-db'
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ module ActiveRecord
|
|||
class MySQLStructureDumpTest < ActiveRecord::TestCase
|
||||
def setup
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'test-db'
|
||||
}
|
||||
end
|
||||
|
@ -297,7 +297,7 @@ module ActiveRecord
|
|||
class MySQLStructureLoadTest < ActiveRecord::TestCase
|
||||
def setup
|
||||
@configuration = {
|
||||
'adapter' => 'mysql',
|
||||
'adapter' => 'mysql2',
|
||||
'database' => 'test-db'
|
||||
}
|
||||
end
|
||||
|
|
|
@ -77,12 +77,6 @@ module ActiveRecord
|
|||
end
|
||||
end
|
||||
|
||||
class MysqlTestCase < TestCase
|
||||
def self.run(*args)
|
||||
super if current_adapter?(:MysqlAdapter)
|
||||
end
|
||||
end
|
||||
|
||||
class SQLite3TestCase < TestCase
|
||||
def self.run(*args)
|
||||
super if current_adapter?(:SQLite3Adapter)
|
||||
|
|
|
@ -150,7 +150,7 @@ class ViewWithoutPrimaryKeyTest < ActiveRecord::TestCase
|
|||
end
|
||||
|
||||
# sqlite dose not support CREATE, INSERT, and DELETE for VIEW
|
||||
if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
|
||||
if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)
|
||||
class UpdateableViewTest < ActiveRecord::TestCase
|
||||
self.use_transactional_tests = false
|
||||
fixtures :books
|
||||
|
@ -196,7 +196,7 @@ class UpdateableViewTest < ActiveRecord::TestCase
|
|||
end
|
||||
end
|
||||
end
|
||||
end # end fo `if current_adapter?(:MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)`
|
||||
end # end fo `if current_adapter?(:Mysql2Adapter, :PostgreSQLAdapter)`
|
||||
end # end fo `if ActiveRecord::Base.connection.supports_views?`
|
||||
|
||||
if ActiveRecord::Base.connection.respond_to?(:supports_materialized_views?) &&
|
||||
|
|
|
@ -51,15 +51,6 @@ connections:
|
|||
password: arunit
|
||||
database: arunit2
|
||||
|
||||
mysql:
|
||||
arunit:
|
||||
username: rails
|
||||
encoding: utf8
|
||||
collation: utf8_unicode_ci
|
||||
arunit2:
|
||||
username: rails
|
||||
encoding: utf8
|
||||
|
||||
mysql2:
|
||||
arunit:
|
||||
username: rails
|
||||
|
|
|
@ -113,19 +113,19 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
def test_mysql
|
||||
start(adapter: 'mysql', database: 'db')
|
||||
start(adapter: 'mysql2', database: 'db')
|
||||
assert !aborted
|
||||
assert_equal [%w[mysql mysql5], 'db'], dbconsole.find_cmd_and_exec_args
|
||||
end
|
||||
|
||||
def test_mysql_full
|
||||
start(adapter: 'mysql', database: 'db', host: 'locahost', port: 1234, socket: 'socket', username: 'user', password: 'qwerty', encoding: 'UTF-8')
|
||||
start(adapter: 'mysql2', database: 'db', host: 'locahost', port: 1234, socket: 'socket', username: 'user', password: 'qwerty', encoding: 'UTF-8')
|
||||
assert !aborted
|
||||
assert_equal [%w[mysql mysql5], '--host=locahost', '--port=1234', '--socket=socket', '--user=user', '--default-character-set=UTF-8', '-p', 'db'], dbconsole.find_cmd_and_exec_args
|
||||
end
|
||||
|
||||
def test_mysql_include_password
|
||||
start({adapter: 'mysql', database: 'db', username: 'user', password: 'qwerty'}, ['-p'])
|
||||
start({adapter: 'mysql2', database: 'db', username: 'user', password: 'qwerty'}, ['-p'])
|
||||
assert !aborted
|
||||
assert_equal [%w[mysql mysql5], '--user=user', '--password=qwerty', 'db'], dbconsole.find_cmd_and_exec_args
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue