понедельник, августа 30, 2010

Mysql ERROR 1005 (HY000): Can't create table (errno: 150)

Уже который раз спотыкаюсь об одни и те же грабли, решил записать.

т.е. после создания таблиц:

CREATE TABLE sf_guard_user
(
id BIGINT AUTO_INCREMENT,
first_name VARCHAR(255),
last_name VARCHAR(255),
email_address VARCHAR(255) NOT NULL UNIQUE,
username VARCHAR(128) NOT NULL UNIQUE,
algorithm VARCHAR(128) DEFAULT 'sha1' NOT NULL,
salt VARCHAR(128), password VARCHAR(128),
is_active TINYINT(1) DEFAULT '1',
is_super_admin TINYINT(1) DEFAULT '0',
last_login DATETIME, created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
INDEX is_active_idx_idx (is_active),
PRIMARY KEY(id)
)ENGINE = INNODB;

CREATE TABLE sf_guard_user_profile
(
id BIGINT AUTO_INCREMENT,
user_id BIGINT, first_name VARCHAR(20),
last_name VARCHAR(20),
email VARCHAR(255),
email_hash VARCHAR(255),
INDEX user_id_idx (user_id),
PRIMARY KEY(id)
) ENGINE = INNODB;


я пытаюсь создать ключи:


ALTER TABLE sf_guard_user_profile
ADD CONSTRAINT sf_guard_user_profile_user_id_sf_guard_user_id
FOREIGN KEY (user_id)
REFERENCES sf_guard_user(id)
ON DELETE CASCADE;

и получаю ошибку ERROR 1005 (HY000): Can't create table (errno: 150)
mysql говорит, что не может найти поле на которое ссылаемся

mysql> SHOW ENGINE INNODB STATUS;
...
100830 20:59:41 Error in foreign key constraint of table s1/#sql-477_152:
FOREIGN KEY (user_id) REFERENCES sf_guard_user(id) ON DELETE CASCADE:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
...


mysql это не нравится, отсюда и ошибка, хотя пишет что не может найти поле, а оно есть.
Дело оказывается в том, что в symfony при генерации схемы нет проверки на размерность типов для внешних ключей, т.е. если указать разные размерности для ключевых полей, то будет ошибка, т.е. вместо:

sfGuardUserProfile:
tableName: sf_guard_user_profile
columns:
user_id: integer(4)
first_name: varchar(20)
last_name: varchar(20)
email: varchar(255)
email_hash: varchar(255)
relations:
Users:
class: sfGuardUser
refClass: sfGuardUserGroup
local: group_id
foreign: user_id
foreignAlias: Groups
sfGuardUser:
type: one
foreignType: one
class: sfGuardUser
local: user_id
foreign: id
onDelete: cascade
foreignAlias: Profile

надо :

sfGuardUserProfile:
tableName: sf_guard_user_profile
columns:
user_id: integer
first_name: varchar(20)
last_name: varchar(20)
email: varchar(255)
email_hash: varchar(255)
relations:
Users:
class: sfGuardUser
refClass: sfGuardUserGroup
local: group_id
foreign: user_id
foreignAlias: Groups
sfGuardUser:
type: one
foreignType: one
class: sfGuardUser
local: user_id
foreign: id
onDelete: cascade
foreignAlias: Profile


а именно поле user_id должно быть таким же как в у sfGuardUser