Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
张重言
rails
提交
3e452b12
R
rails
项目概览
张重言
/
rails
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rails
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3e452b12
编写于
5月 10, 2016
作者:
P
Pavel Pravosud
提交者:
Jon McCartie
12月 05, 2016
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make pg adapter use bigserial for pk by default
上级
b92ae610
变更
11
显示空白变更内容
内联
并排
Showing
11 changed file
with
262 addition
and
3 deletion
+262
-3
.gitignore
.gitignore
+0
-1
activerecord/CHANGELOG.md
activerecord/CHANGELOG.md
+4
-0
activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
...tive_record/connection_adapters/abstract_mysql_adapter.rb
+23
-1
activerecord/lib/active_record/errors.rb
activerecord/lib/active_record/errors.rb
+28
-0
activerecord/lib/active_record/migration/compatibility.rb
activerecord/lib/active_record/migration/compatibility.rb
+11
-1
activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb
...ecord/test/cases/adapters/mysql2/legacy_migration_test.rb
+60
-0
activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
...erecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
+13
-0
activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb
...d/test/cases/adapters/postgresql/legacy_migration_test.rb
+54
-0
activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb
...cord/test/cases/adapters/sqlite3/legacy_migration_test.rb
+59
-0
activerecord/test/cases/primary_keys_test.rb
activerecord/test/cases/primary_keys_test.rb
+7
-0
activerecord/test/schema/schema.rb
activerecord/test/schema/schema.rb
+3
-0
未找到文件。
.gitignore
浏览文件 @
3e452b12
...
...
@@ -19,4 +19,3 @@ pkg
/railties/doc
/railties/tmp
/guides/output
/*/.byebug_history
\ No newline at end of file
activerecord/CHANGELOG.md
浏览文件 @
3e452b12
*
PostgreSQL & MySQL: Use big integer as primary key type for new tables
*Jon McCartie*, *Pavel Pravosud*
*
Change the type argument of
`ActiveRecord::Base#attribute`
to be optional.
The default is now
`ActiveRecord::Type::Value.new`
, which provides no type
casting behavior.
...
...
activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
浏览文件 @
3e452b12
...
...
@@ -39,7 +39,7 @@ def arel_visitor # :nodoc:
self
.
emulate_booleans
=
true
NATIVE_DATABASE_TYPES
=
{
primary_key:
"BIGINT(8) UNSIGNED
DEFAULT NULL
auto_increment PRIMARY KEY"
,
primary_key:
"BIGINT(8) UNSIGNED auto_increment PRIMARY KEY"
,
string:
{
name:
"varchar"
,
limit:
255
},
text:
{
name:
"text"
,
limit:
65535
},
integer:
{
name:
"int"
,
limit:
4
},
...
...
@@ -736,6 +736,8 @@ def add_options_for_index_columns(quoted_columns, **options)
ER_NO_REFERENCED_ROW_2
=
1452
ER_DATA_TOO_LONG
=
1406
ER_LOCK_DEADLOCK
=
1213
ER_CANNOT_ADD_FOREIGN
=
1215
ER_CANNOT_CREATE_TABLE
=
1005
def
translate_exception
(
exception
,
message
)
case
error_number
(
exception
)
...
...
@@ -743,6 +745,14 @@ def translate_exception(exception, message)
RecordNotUnique
.
new
(
message
)
when
ER_NO_REFERENCED_ROW_2
InvalidForeignKey
.
new
(
message
)
when
ER_CANNOT_ADD_FOREIGN
mismatched_foreign_key
(
message
)
when
ER_CANNOT_CREATE_TABLE
if
message
.
include?
(
"errno: 150"
)
mismatched_foreign_key
(
message
)
else
super
end
when
ER_DATA_TOO_LONG
ValueTooLong
.
new
(
message
)
when
ER_LOCK_DEADLOCK
...
...
@@ -914,6 +924,18 @@ def create_table_definition(*args) # :nodoc:
MySQL
::
TableDefinition
.
new
(
*
args
)
end
def
mismatched_foreign_key
(
message
)
parts
=
message
.
scan
(
/`(\w+)`[ $)]/
).
flatten
MismatchedForeignKey
.
new
(
self
,
message:
message
,
table:
parts
[
0
],
foreign_key:
parts
[
1
],
target_table:
parts
[
2
],
primary_key:
parts
[
3
],
)
end
def
extract_schema_qualified_name
(
string
)
# :nodoc:
schema
,
name
=
string
.
to_s
.
scan
(
/[^`.\s]+|`[^`]*`/
)
schema
,
name
=
@config
[
:database
],
schema
unless
name
...
...
activerecord/lib/active_record/errors.rb
浏览文件 @
3e452b12
...
...
@@ -123,6 +123,34 @@ class RecordNotUnique < WrappedDatabaseException
class
InvalidForeignKey
<
WrappedDatabaseException
end
# Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.
class
MismatchedForeignKey
<
WrappedDatabaseException
def
initialize
(
adapter
=
nil
,
message:
nil
,
table:
nil
,
foreign_key:
nil
,
target_table:
nil
,
primary_key:
nil
)
@adapter
=
adapter
if
table
msg
=
<<-
EOM
.
strip_heredoc
Column `
#{
foreign_key
}
` on table `
#{
table
}
` has a type of `
#{
column_type
(
table
,
foreign_key
)
}
`.
This does not match column `
#{
primary_key
}
` on `
#{
target_table
}
`, which has type `
#{
column_type
(
target_table
,
primary_key
)
}
`.
To resolve this issue, change the type of the `
#{
foreign_key
}
` column on `
#{
table
}
` to be :integer. (For example `t.integer
#{
foreign_key
}
`).
EOM
else
msg
=
<<-
EOM
There is a mismatch between the foreign key and primary key column types.
Verify that the foreign key column type and the primary key of the associated table match types.
EOM
end
if
message
msg
<<
"
\n
Original message:
#{
message
}
"
end
super
(
msg
)
end
private
def
column_type
(
table
,
column
)
@adapter
.
columns
(
table
).
detect
{
|
c
|
c
.
name
==
column
}.
sql_type
end
end
# Raised when a record cannot be inserted or updated because a value too long for a column type.
class
ValueTooLong
<
StatementInvalid
end
...
...
activerecord/lib/active_record/migration/compatibility.rb
浏览文件 @
3e452b12
...
...
@@ -104,11 +104,21 @@ def index_name_for_remove(table_name, options = {})
class
V5_0
<
V5_1
def
create_table
(
table_name
,
options
=
{})
if
ActiveRecord
::
Base
.
connection
.
adapter_name
==
"PostgreSQL"
connection_name
=
self
.
connection
.
adapter_name
if
connection_name
==
"PostgreSQL"
if
options
[
:id
]
==
:uuid
&&
!
options
[
:default
]
options
[
:default
]
=
"uuid_generate_v4()"
end
end
# Since 5.1 Postgres adapter uses bigserial type for primary
# keys by default and MySQL uses bigint. This compat layer makes old migrations utilize
# serial/int type instead -- the way it used to work before 5.1.
if
options
[
:id
].
blank?
options
[
:id
]
=
:integer
options
[
:auto_increment
]
=
true
end
super
end
end
...
...
activerecord/test/cases/adapters/mysql2/legacy_migration_test.rb
0 → 100644
浏览文件 @
3e452b12
require
"cases/helper"
class
MysqlLegacyMigrationTest
<
ActiveRecord
::
Mysql2TestCase
self
.
use_transactional_tests
=
false
class
GenerateTableWithoutBigint
<
ActiveRecord
::
Migration
[
5.0
]
def
change
create_table
:legacy_integer_pk
do
|
table
|
table
.
string
:foo
end
create_table
:override_pk
,
id: :bigint
do
|
table
|
table
.
string
:bar
end
end
end
def
setup
super
@connection
=
ActiveRecord
::
Base
.
connection
@migration_verbose_old
=
ActiveRecord
::
Migration
.
verbose
ActiveRecord
::
Migration
.
verbose
=
false
migrations
=
[
GenerateTableWithoutBigint
.
new
(
nil
,
1
)]
ActiveRecord
::
Migrator
.
new
(
:up
,
migrations
).
migrate
end
def
teardown
ActiveRecord
::
Migration
.
verbose
=
@migration_verbose_old
@connection
.
drop_table
(
"legacy_integer_pk"
)
@connection
.
drop_table
(
"override_pk"
)
ActiveRecord
::
SchemaMigration
.
delete_all
rescue
nil
super
end
def
test_create_table_uses_integer_as_pkey_by_default
col
=
column
(
:legacy_integer_pk
,
:id
)
assert_equal
"int(11)"
,
sql_type_for
(
col
)
assert
col
.
auto_increment?
end
def
test_create_tables_respects_pk_column_type_override
col
=
column
(
:override_pk
,
:id
)
assert_equal
"bigint(20)"
,
sql_type_for
(
col
)
end
private
def
column
(
table_name
,
column_name
)
ActiveRecord
::
Base
.
connection
.
columns
(
table_name
.
to_s
)
.
detect
{
|
c
|
c
.
name
==
column_name
.
to_s
}
end
def
sql_type_for
(
col
)
col
&&
col
.
sql_type
end
end
activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb
浏览文件 @
3e452b12
...
...
@@ -65,6 +65,19 @@ def order.to_sql
@conn
.
columns_for_distinct
(
"posts.id"
,
[
order
])
end
def
test_errors_for_bigint_fks_on_integer_pk_table
# table old_cars has primary key of integer
error
=
assert_raises
(
ActiveRecord
::
MismatchedForeignKey
)
do
@conn
.
add_reference
:engines
,
:old_car
@conn
.
add_foreign_key
:engines
,
:old_cars
end
assert_match
"Column `old_car_id` on table `engines` has a type of `bigint(20)`"
,
error
.
message
assert_not_nil
error
.
cause
@conn
.
exec_query
(
"ALTER TABLE engines DROP COLUMN old_car_id"
)
end
private
def
with_example_table
(
definition
=
"id int auto_increment primary key, number int, data varchar(255)"
,
&
block
)
...
...
activerecord/test/cases/adapters/postgresql/legacy_migration_test.rb
0 → 100644
浏览文件 @
3e452b12
require
"cases/helper"
class
PostgresqlLegacyMigrationTest
<
ActiveRecord
::
PostgreSQLTestCase
class
GenerateTableWithoutBigserial
<
ActiveRecord
::
Migration
[
5.0
]
def
change
create_table
:legacy_integer_pk
do
|
table
|
table
.
string
:foo
end
create_table
:override_pk
,
id: :bigint
do
|
table
|
table
.
string
:bar
end
end
end
def
setup
super
@migration_verbose_old
=
ActiveRecord
::
Migration
.
verbose
ActiveRecord
::
Migration
.
verbose
=
false
migrations
=
[
GenerateTableWithoutBigserial
.
new
(
nil
,
1
)]
ActiveRecord
::
Migrator
.
new
(
:up
,
migrations
).
migrate
end
def
teardown
ActiveRecord
::
Migration
.
verbose
=
@migration_verbose_old
super
end
def
test_create_table_uses_serial_as_pkey_by_default
col
=
column
(
:legacy_integer_pk
,
:id
)
assert_equal
"integer"
,
sql_type_for
(
col
)
assert
col
.
serial?
end
def
test_create_tables_respects_pk_column_type_override
col
=
column
(
:override_pk
,
:id
)
assert_equal
"bigint"
,
sql_type_for
(
col
)
end
private
def
column
(
table_name
,
column_name
)
ActiveRecord
::
Base
.
connection
.
columns
(
table_name
.
to_s
).
detect
{
|
c
|
c
.
name
==
column_name
.
to_s
}
end
def
sql_type_for
(
col
)
col
&&
col
.
sql_type
end
end
activerecord/test/cases/adapters/sqlite3/legacy_migration_test.rb
0 → 100644
浏览文件 @
3e452b12
require
"cases/helper"
class
SqliteLegacyMigrationTest
<
ActiveRecord
::
SQLite3TestCase
self
.
use_transactional_tests
=
false
class
GenerateTableWithoutBigint
<
ActiveRecord
::
Migration
[
5.0
]
def
change
create_table
:legacy_integer_pk
do
|
table
|
table
.
string
:foo
end
create_table
:override_pk
,
id: :bigint
do
|
table
|
table
.
string
:bar
end
end
end
def
setup
super
@connection
=
ActiveRecord
::
Base
.
connection
@migration_verbose_old
=
ActiveRecord
::
Migration
.
verbose
ActiveRecord
::
Migration
.
verbose
=
false
migrations
=
[
GenerateTableWithoutBigint
.
new
(
nil
,
1
)]
ActiveRecord
::
Migrator
.
new
(
:up
,
migrations
).
migrate
end
def
teardown
ActiveRecord
::
Migration
.
verbose
=
@migration_verbose_old
@connection
.
drop_table
(
"legacy_integer_pk"
)
@connection
.
drop_table
(
"override_pk"
)
ActiveRecord
::
SchemaMigration
.
delete_all
rescue
nil
super
end
def
test_create_table_uses_integer_as_pkey_by_default
col
=
column
(
:legacy_integer_pk
,
:id
)
assert_equal
"INTEGER"
,
sql_type_for
(
col
)
assert
primary_key?
(
:legacy_integer_pk
,
"id"
),
"id is not primary key"
end
private
def
column
(
table_name
,
column_name
)
ActiveRecord
::
Base
.
connection
.
columns
(
table_name
.
to_s
)
.
detect
{
|
c
|
c
.
name
==
column_name
.
to_s
}
end
def
sql_type_for
(
col
)
col
&&
col
.
sql_type
end
def
primary_key?
(
table_name
,
column
)
ActiveRecord
::
Base
.
connection
.
execute
(
"PRAGMA table_info(
#{
table_name
}
)"
).
find
{
|
col
|
col
[
"name"
]
==
column
}[
"pk"
]
==
1
end
end
activerecord/test/cases/primary_keys_test.rb
浏览文件 @
3e452b12
...
...
@@ -361,6 +361,13 @@ class Widget < ActiveRecord::Base
Widget
.
reset_column_information
end
if
current_adapter?
(
:PostgreSQLAdapter
,
:Mysql2Adapter
)
test
"schema dump primary key with bigserial"
do
schema
=
dump_table_schema
"widgets"
assert_match
%r{create_table "widgets", force: :cascade}
,
schema
end
end
test
"primary key column type"
do
column_type
=
Widget
.
type_for_attribute
(
Widget
.
primary_key
)
assert_equal
:integer
,
column_type
.
type
...
...
activerecord/test/schema/schema.rb
浏览文件 @
3e452b12
...
...
@@ -126,6 +126,9 @@
t
.
timestamps
null:
false
end
create_table
:old_cars
,
id: :integer
,
force:
true
do
|
t
|
end
create_table
:carriers
,
force:
true
create_table
:categories
,
force:
true
do
|
t
|
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录