mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
parent
249e943a0d
commit
af9878d640
13 changed files with 90 additions and 101 deletions
|
@ -125,7 +125,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
||||||
)
|
)
|
||||||
|
|
||||||
{Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
|
{Learn more}[link:classes/ActiveRecord/Base.html] and read about the built-in support for
|
||||||
MySQL[link:classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html],
|
MySQL[link:classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html],
|
||||||
PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
PostgreSQL[link:classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html], and
|
||||||
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
|
||||||
|
|
||||||
|
|
|
@ -208,7 +208,7 @@ module ActiveRecord
|
||||||
# * You are joining an existing open transaction
|
# * You are joining an existing open transaction
|
||||||
# * You are creating a nested (savepoint) transaction
|
# * You are creating a nested (savepoint) transaction
|
||||||
#
|
#
|
||||||
# The mysql, mysql2 and postgresql adapters support setting the transaction
|
# The mysql2 and postgresql adapters support setting the transaction
|
||||||
# isolation level. However, support is disabled for MySQL versions below 5,
|
# isolation level. However, support is disabled for MySQL versions below 5,
|
||||||
# because they are affected by a bug[http://bugs.mysql.com/bug.php?id=39170]
|
# because they are affected by a bug[http://bugs.mysql.com/bug.php?id=39170]
|
||||||
# which means the isolation level gets persisted outside the transaction.
|
# which means the isolation level gets persisted outside the transaction.
|
||||||
|
|
|
@ -376,7 +376,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
# Provides access to the underlying database driver for this adapter. For
|
# Provides access to the underlying database driver for this adapter. For
|
||||||
# example, this method returns a Mysql object in case of MysqlAdapter,
|
# example, this method returns a Mysql2::Client object in case of Mysql2Adapter,
|
||||||
# and a PGconn object in case of PostgreSQLAdapter.
|
# and a PGconn object in case of PostgreSQLAdapter.
|
||||||
#
|
#
|
||||||
# This is useful for when you need to call a proprietary method such as
|
# This is useful for when you need to call a proprietary method such as
|
||||||
|
|
|
@ -107,11 +107,10 @@ module ActiveRecord
|
||||||
##
|
##
|
||||||
# :singleton-method:
|
# :singleton-method:
|
||||||
# By default, the Mysql2Adapter will consider all columns of type <tt>tinyint(1)</tt>
|
# By default, the Mysql2Adapter will consider all columns of type <tt>tinyint(1)</tt>
|
||||||
# as boolean. If you wish to disable this emulation (which was the default
|
# as boolean. If you wish to disable this emulation you can add the following line
|
||||||
# behavior in versions 0.13.1 and earlier) you can add the following line
|
|
||||||
# to your application.rb file:
|
# to your application.rb file:
|
||||||
#
|
#
|
||||||
# ActiveRecord::ConnectionAdapters::Mysql[2]Adapter.emulate_booleans = false
|
# ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
|
||||||
class_attribute :emulate_booleans
|
class_attribute :emulate_booleans
|
||||||
self.emulate_booleans = true
|
self.emulate_booleans = true
|
||||||
|
|
||||||
|
@ -400,10 +399,10 @@ module ActiveRecord
|
||||||
log(sql, name) { @connection.query(sql) }
|
log(sql, name) { @connection.query(sql) }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Mysql2Adapter has to free a result after using it, so we use this method to write
|
# Mysql2Adapter doesn't have to free a result after using it, but we use this method
|
||||||
# stuff in an abstract way without concerning ourselves about whether it needs to be
|
# to write stuff in an abstract way without concerning ourselves about whether it
|
||||||
# explicitly freed or not.
|
# 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)
|
yield execute(sql, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ module ActiveRecord
|
||||||
# example for regular databases (MySQL, PostgreSQL, etc):
|
# example for regular databases (MySQL, PostgreSQL, etc):
|
||||||
#
|
#
|
||||||
# ActiveRecord::Base.establish_connection(
|
# ActiveRecord::Base.establish_connection(
|
||||||
# adapter: "mysql",
|
# adapter: "mysql2",
|
||||||
# host: "localhost",
|
# host: "localhost",
|
||||||
# username: "myuser",
|
# username: "myuser",
|
||||||
# password: "mypass",
|
# password: "mypass",
|
||||||
|
|
|
@ -272,7 +272,7 @@ module ActiveRecord
|
||||||
# * You are joining an existing open transaction
|
# * You are joining an existing open transaction
|
||||||
# * You are creating a nested (savepoint) transaction
|
# * You are creating a nested (savepoint) transaction
|
||||||
#
|
#
|
||||||
# The mysql, mysql2 and postgresql adapters support setting the transaction isolation level.
|
# The mysql2 and postgresql adapters support setting the transaction isolation level.
|
||||||
class TransactionIsolationError < ActiveRecordError
|
class TransactionIsolationError < ActiveRecordError
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -68,9 +68,6 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase
|
||||||
assert_equal 'utf8_general_ci', ARUnit2Model.connection.show_variable('collation_connection')
|
assert_equal 'utf8_general_ci', ARUnit2Model.connection.show_variable('collation_connection')
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Below is a straight up copy/paste from mysql/connection_test.rb
|
|
||||||
# I'm not sure what the correct way is to share these tests between
|
|
||||||
# adapters in minitest.
|
|
||||||
def test_mysql_default_in_strict_mode
|
def test_mysql_default_in_strict_mode
|
||||||
result = @connection.exec_query "SELECT @@SESSION.sql_mode"
|
result = @connection.exec_query "SELECT @@SESSION.sql_mode"
|
||||||
assert_equal [["STRICT_ALL_TABLES"]], result.rows
|
assert_equal [["STRICT_ALL_TABLES"]], result.rows
|
||||||
|
@ -83,7 +80,7 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase
|
||||||
assert_equal [['']], result.rows
|
assert_equal [['']], result.rows
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_passing_arbitary_flags_to_adapter
|
def test_passing_arbitary_flags_to_adapter
|
||||||
run_without_connection do |orig_connection|
|
run_without_connection do |orig_connection|
|
||||||
ActiveRecord::Base.establish_connection(orig_connection.merge({flags: Mysql2::Client::COMPRESS}))
|
ActiveRecord::Base.establish_connection(orig_connection.merge({flags: Mysql2::Client::COMPRESS}))
|
||||||
|
|
|
@ -82,7 +82,6 @@ class BasicsTest < ActiveRecord::TestCase
|
||||||
classname = conn.class.name[/[^:]*$/]
|
classname = conn.class.name[/[^:]*$/]
|
||||||
badchar = {
|
badchar = {
|
||||||
'SQLite3Adapter' => '"',
|
'SQLite3Adapter' => '"',
|
||||||
'MysqlAdapter' => '`',
|
|
||||||
'Mysql2Adapter' => '`',
|
'Mysql2Adapter' => '`',
|
||||||
'PostgreSQLAdapter' => '"',
|
'PostgreSQLAdapter' => '"',
|
||||||
'OracleAdapter' => '"',
|
'OracleAdapter' => '"',
|
||||||
|
|
|
@ -545,8 +545,8 @@ class CalculationsTest < ActiveRecord::TestCase
|
||||||
assert_equal 7, Company.includes(:contracts).sum(:developer_id)
|
assert_equal 7, Company.includes(:contracts).sum(:developer_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_from_option_with_specified_index
|
if current_adapter?(:Mysql2Adapter)
|
||||||
if Edge.connection.adapter_name == 'Mysql2'
|
def test_from_option_with_specified_index
|
||||||
assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
|
assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
|
||||||
assert_equal Edge.where('sink_id < 5').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)
|
Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
|
||||||
|
|
|
@ -63,8 +63,6 @@ module ActiveRecord
|
||||||
# Do a manual insertion
|
# Do a manual insertion
|
||||||
if current_adapter?(:OracleAdapter)
|
if current_adapter?(:OracleAdapter)
|
||||||
connection.execute "insert into test_models (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
|
connection.execute "insert into test_models (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
|
||||||
elsif current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003 #before MySQL 5.0.3 decimals stored as strings
|
|
||||||
connection.execute "insert into test_models (wealth) values ('12345678901234567890.0123456789')"
|
|
||||||
elsif current_adapter?(:PostgreSQLAdapter)
|
elsif current_adapter?(:PostgreSQLAdapter)
|
||||||
connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)"
|
connection.execute "insert into test_models (wealth) values (12345678901234567890.0123456789)"
|
||||||
else
|
else
|
||||||
|
|
|
@ -12,7 +12,6 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
ADAPTERS_TASKS = {
|
ADAPTERS_TASKS = {
|
||||||
mysql: :mysql_tasks,
|
|
||||||
mysql2: :mysql_tasks,
|
mysql2: :mysql_tasks,
|
||||||
postgresql: :postgresql_tasks,
|
postgresql: :postgresql_tasks,
|
||||||
sqlite3: :sqlite_tasks
|
sqlite3: :sqlite_tasks
|
||||||
|
|
|
@ -59,97 +59,94 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_adapter?(:MysqlAdapter)
|
class MysqlDBCreateAsRootTest < ActiveRecord::TestCase
|
||||||
class MysqlDBCreateAsRootTest < ActiveRecord::TestCase
|
def setup
|
||||||
def setup
|
@connection = stub("Connection", create_database: true)
|
||||||
@connection = stub("Connection", create_database: true)
|
@error = Mysql2::Error.new("Invalid permissions")
|
||||||
@error = Mysql::Error.new "Invalid permissions"
|
@configuration = {
|
||||||
@configuration = {
|
'adapter' => 'mysql2',
|
||||||
|
'database' => 'my-app-db',
|
||||||
|
'username' => 'pat',
|
||||||
|
'password' => 'wossname'
|
||||||
|
}
|
||||||
|
|
||||||
|
$stdin.stubs(:gets).returns("secret\n")
|
||||||
|
$stdout.stubs(:print).returns(nil)
|
||||||
|
@error.stubs(:errno).returns(1045)
|
||||||
|
ActiveRecord::Base.stubs(:connection).returns(@connection)
|
||||||
|
ActiveRecord::Base.stubs(:establish_connection).
|
||||||
|
raises(@error).
|
||||||
|
then.returns(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_root_password_is_requested
|
||||||
|
assert_permissions_granted_for("pat")
|
||||||
|
$stdin.expects(:gets).returns("secret\n")
|
||||||
|
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_connection_established_as_root
|
||||||
|
assert_permissions_granted_for("pat")
|
||||||
|
ActiveRecord::Base.expects(:establish_connection).with(
|
||||||
|
'adapter' => 'mysql2',
|
||||||
|
'database' => nil,
|
||||||
|
'username' => 'root',
|
||||||
|
'password' => 'secret'
|
||||||
|
)
|
||||||
|
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_database_created_by_root
|
||||||
|
assert_permissions_granted_for("pat")
|
||||||
|
@connection.expects(:create_database).
|
||||||
|
with('my-app-db', {})
|
||||||
|
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_grant_privileges_for_normal_user
|
||||||
|
assert_permissions_granted_for("pat")
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_do_not_grant_privileges_for_root_user
|
||||||
|
@configuration['username'] = 'root'
|
||||||
|
@configuration['password'] = ''
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_connection_established_as_normal_user
|
||||||
|
assert_permissions_granted_for("pat")
|
||||||
|
ActiveRecord::Base.expects(:establish_connection).returns do
|
||||||
|
ActiveRecord::Base.expects(:establish_connection).with(
|
||||||
'adapter' => 'mysql2',
|
'adapter' => 'mysql2',
|
||||||
'database' => 'my-app-db',
|
'database' => 'my-app-db',
|
||||||
'username' => 'pat',
|
'username' => 'pat',
|
||||||
'password' => 'wossname'
|
|
||||||
}
|
|
||||||
|
|
||||||
$stdin.stubs(:gets).returns("secret\n")
|
|
||||||
$stdout.stubs(:print).returns(nil)
|
|
||||||
@error.stubs(:errno).returns(1045)
|
|
||||||
ActiveRecord::Base.stubs(:connection).returns(@connection)
|
|
||||||
ActiveRecord::Base.stubs(:establish_connection).
|
|
||||||
raises(@error).
|
|
||||||
then.returns(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
if defined?(::Mysql)
|
|
||||||
def test_root_password_is_requested
|
|
||||||
assert_permissions_granted_for "pat"
|
|
||||||
$stdin.expects(:gets).returns("secret\n")
|
|
||||||
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_connection_established_as_root
|
|
||||||
assert_permissions_granted_for "pat"
|
|
||||||
ActiveRecord::Base.expects(:establish_connection).with(
|
|
||||||
'adapter' => 'mysql2',
|
|
||||||
'database' => nil,
|
|
||||||
'username' => 'root',
|
|
||||||
'password' => 'secret'
|
'password' => 'secret'
|
||||||
)
|
)
|
||||||
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
raise @error
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_database_created_by_root
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
assert_permissions_granted_for "pat"
|
end
|
||||||
@connection.expects(:create_database).
|
|
||||||
with('my-app-db', {})
|
|
||||||
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
def test_sends_output_to_stderr_when_other_errors
|
||||||
end
|
@error.stubs(:errno).returns(42)
|
||||||
|
|
||||||
def test_grant_privileges_for_normal_user
|
$stderr.expects(:puts).at_least_once.returns(nil)
|
||||||
assert_permissions_granted_for "pat"
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_do_not_grant_privileges_for_root_user
|
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
||||||
@configuration['username'] = 'root'
|
end
|
||||||
@configuration['password'] = ''
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_connection_established_as_normal_user
|
private
|
||||||
assert_permissions_granted_for "pat"
|
|
||||||
ActiveRecord::Base.expects(:establish_connection).returns do
|
|
||||||
ActiveRecord::Base.expects(:establish_connection).with(
|
|
||||||
'adapter' => 'mysql2',
|
|
||||||
'database' => 'my-app-db',
|
|
||||||
'username' => 'pat',
|
|
||||||
'password' => 'secret'
|
|
||||||
)
|
|
||||||
|
|
||||||
raise @error
|
def assert_permissions_granted_for(db_user)
|
||||||
end
|
db_name = @configuration['database']
|
||||||
|
db_password = @configuration['password']
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
@connection.expects(:execute).with("GRANT ALL PRIVILEGES ON #{db_name}.* TO '#{db_user}'@'localhost' IDENTIFIED BY '#{db_password}' WITH GRANT OPTION;")
|
||||||
end
|
|
||||||
|
|
||||||
def test_sends_output_to_stderr_when_other_errors
|
|
||||||
@error.stubs(:errno).returns(42)
|
|
||||||
|
|
||||||
$stderr.expects(:puts).at_least_once.returns(nil)
|
|
||||||
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create @configuration
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def assert_permissions_granted_for(db_user)
|
|
||||||
db_name = @configuration['database']
|
|
||||||
db_password = @configuration['password']
|
|
||||||
@connection.expects(:execute).with("GRANT ALL PRIVILEGES ON #{db_name}.* TO '#{db_user}'@'localhost' IDENTIFIED BY '#{db_password}' WITH GRANT OPTION;")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -319,7 +319,7 @@ All these configuration options are delegated to the `I18n` library.
|
||||||
|
|
||||||
The MySQL adapter adds one additional configuration option:
|
The MySQL adapter adds one additional configuration option:
|
||||||
|
|
||||||
* `ActiveRecord::ConnectionAdapters::Mysql[2]Adapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns in a MySQL database to be booleans and is true by default.
|
* `ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns in a MySQL database to be booleans and is true by default.
|
||||||
|
|
||||||
The schema dumper adds one additional configuration option:
|
The schema dumper adds one additional configuration option:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue