我是否需要为DBIx :: Class belongs_to关系手动创建索引

时间:2011-02-21 22:13:08

标签: mysql perl innodb dbix-class mysql-error-1005

我正在使用DBIx::Class模块来实现我所拥有的应用程序的ORM方法。

我的人际关系有些问题。

我有以下

package MySchema::Result::ClusterIP;
use strict;
use warnings;

use base qw/DBIx::Class::Core/;

our $VERSION = '1.0';

__PACKAGE__->load_components(qw/InflateColumn::Object::Enum Core/);
__PACKAGE__->table('cluster_ip');

__PACKAGE__->add_columns( # Columns here );

__PACKAGE__->set_primary_key('objkey');
__PACKAGE__->belongs_to( 'configuration' => 'MySchema::Result::Configuration', 'config_key');
__PACKAGE__->belongs_to( 'cluster' => 'MySchema::Result::Cluster',
                            { 'foreign.config_key' => 'self.config_key',
                              'foreign.id'         => 'self.cluster_id'
                            }
                        );

以及

package MySchema::Result::Cluster;
use strict;
use warnings;

use base qw/DBIx::Class::Core/;

our $VERSION = '1.0';

__PACKAGE__->load_components(qw/InflateColumn::Object::Enum Core/);
__PACKAGE__->table('cluster');

__PACKAGE__->add_columns(  # Columns here );
__PACKAGE__->set_primary_key('objkey');
__PACKAGE__->belongs_to( 'configuration' => 'MySchema::Result::Configuration', 'config_key');
__PACKAGE__->has_many('cluster_ip'  => 'MySchema::Result::ClusterIP',
                            { 'foreign.config_key' => 'self.config_key',
                              'foreign.cluster_id' => 'self.id'
                            });

还有其他几个模块,但我不相信它们是相关的。

当我尝试部署此架构时,出现以下错误:

DBIx::Class::Schema::deploy(): DBI Exception: DBD::mysql::db do failed: Can't create table 'test.cluster_ip' (errno: 150) [
for Statement "CREATE TABLE `cluster_ip` (
  `objkey` smallint(5) unsigned NOT NULL auto_increment,
  `config_key` smallint(5) unsigned NOT NULL,
  `cluster_id` char(16) NOT NULL,
  INDEX `cluster_ip_idx_config_key_cluster_id` (`config_key`, `cluster_id`),
  INDEX `cluster_ip_idx_config_key` (`config_key`),
  PRIMARY KEY (`objkey`),
  CONSTRAINT `cluster_ip_fk_config_key_cluster_id` FOREIGN KEY (`config_key`, `cluster_id`) REFERENCES `cluster` (`config_key`, `id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `cluster_ip_fk_config_key` FOREIGN KEY (`config_key`) REFERENCES `configuration` (`config_key`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB"] at test_deploy.pl line 18

 (running "CREATE TABLE `cluster_ip` (
  `objkey` smallint(5) unsigned NOT NULL auto_increment,
  `config_key` smallint(5) unsigned NOT NULL,
  `cluster_id` char(16) NOT NULL,
  INDEX `cluster_ip_idx_config_key_cluster_id` (`config_key`, `cluster_id`),
  INDEX `cluster_ip_idx_config_key` (`config_key`),
  PRIMARY KEY (`objkey`),
  CONSTRAINT `cluster_ip_fk_config_key_cluster_id` FOREIGN KEY (`config_key`, `cluster_id`) REFERENC
ES `cluster` (`config_key`, `id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `cluster_ip_fk_config_key` FOREIGN KEY (`config_key`) REFERENCES `configuration` (`conf
ig_key`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB") at test_deploy.pl line 18

据我所知,MySQL正在抱怨FOREIGN KEY约束,特别是config_key表中对idcluster的参考。从我阅读MySQL文档来看,这似乎是一个合理的抱怨,特别是关于this doc page的第三个要点。

这是我的问题。我错过了DBIx::Class模块中的内容吗?我意识到我可以显式创建必要的索引来匹配这个外键约束,但这似乎是重复的工作。我是否应该采取措施使其隐含发生?

2 个答案:

答案 0 :(得分:3)

不确定这里发生了什么,因为SQL::Translator::Producer::MySQL应该在部署的DDL的开头插入SET foreign_key_checks=0,因此不会发生外键错误。我怀疑即使在部署了整个DDL之后某些东西也被破坏了。您可以通过连接到DB并运行以下语句来找出外键错误的确切性质:

SHOW INNODB STATUS;

答案 1 :(得分:0)

我刚刚通过将以下内容添加到导致问题的结果类中来修复了同样的问题:

sub sqlt_deploy_hook {
   my ($self, $sqlt_table) = @_;
   $sqlt_table->add_index(name => 'idx_my_column', fields => ['my_column']);
}