From a0a62f99c687870d538aa39739a15c5460cc3bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=86var=20Arnfj=C3=B6r=C3=B0=20Bjarmason?= Date: Tue, 16 Mar 2010 20:20:45 +0000 Subject: [PATCH] Create the schema with DBIx::Class instead of doing it manually As for the hack here's why: I have this in a Schema::Result::*.pm: sub add_tokenN_id { my ($self, $n) = @_; __PACKAGE__->add_columns( "token${n}_id", { data_type => "INTEGER", default_value => undef, is_foreign_key => 1, is_nullable => 0, size => undef, }, ); __PACKAGE__->belongs_to( "token${n}", "Hailo::Storage::Schema::Result::Token", { id => "token${n}_id" }, {}, ); } If I later do this: for (0 .. $self->order - 1) { Hailo::Storage::Schema::Result::Expr->add_tokenN_id($_); } $schema->deploy; I get this when using the table: DBIx::Class::ResultSet::find(): DBI Exception: DBD::SQLite::db prepare_cached failed: no such column: me.token0_id [for Statement "SELECT me.id FROM expr me WHERE ( ( me.token0_id = ? AND me.token1_id = ? ) )"] at /home/avar/g/hailo/lib/Hailo/Storage/DBD.pm line 449 But if I instead add this right before the add_tokenN_id() definition (so it's called at BEGIN time) everything works, but obviously isn't configurable: add_tokenN_id(undef, 0); add_tokenN_id(undef, 1); Alternatively I could do this as pointed out in #dbix-class: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/0.08/trunk/maint/joint_deps.pl --- lib/Hailo/Storage/DBD.pm | 85 ++----------------------- lib/Hailo/Storage/Schema/Result/Expr.pm | 6 ++ 2 files changed, 10 insertions(+), 81 deletions(-) diff --git a/lib/Hailo/Storage/DBD.pm b/lib/Hailo/Storage/DBD.pm index e1679a6..0b73571 100644 --- a/lib/Hailo/Storage/DBD.pm +++ b/lib/Hailo/Storage/DBD.pm @@ -8,7 +8,6 @@ BEGIN { MooseX::StrictConstructor->import; } use DBI; -use Hailo::Storage::Schema; use List::Util qw; use List::MoreUtils qw; use namespace::clean -except => 'meta'; @@ -58,6 +57,7 @@ has schema => ( sub _build_schema { my ($self) = @_; + require Hailo::Storage::Schema; my $schema = Hailo::Storage::Schema->connect( sub { $self->dbh }, # See http://search.cpan.org/~ribasushi/DBIx-Class-0.08120/lib/DBIx/Class/Storage/DBI.pm#DBIx::Class_specific_connection_attributes @@ -184,15 +184,9 @@ sub stop_learning { sub _create_db { my ($self) = @_; - chomp(my @statements = $self->_table_sql); - - for (0 .. $self->order - 1) { - Hailo::Storage::Schema::Result::Expr->add_tokenN_id($_); - } - - for (@statements) { - $self->dbh->do($_); - } + $ENV{HAILO_STORAGE_SCHEMA_RESULT_EXPR_TOKENN_ORDERS} = $self->order - 1; + require Hailo::Storage::Schema; + $self->schema->deploy; return; } @@ -642,74 +636,3 @@ This program is free software, you can redistribute it and/or modify it under the same terms as Perl itself. =cut - -sub _table_sql { - my ($self) = @_; - my $dbd = $self->dbd; - my @orders = (0 .. $self->order-1); - my $columns = join(', ', map { "token${_}_id" } @orders); - - my $serial = do { - my $txt; - given ($dbd) { - when ('Pg') { $txt = 'SERIAL UNIQUE' } - when ('mysql') { $txt = 'INTEGER PRIMARY KEY AUTO_INCREMENT' } - default { $txt = 'INTEGER PRIMARY KEY AUTOINCREMENT' } - } - $txt; - }; - - my $info = q[ -CREATE TABLE info ( - attribute ] . do { - my $txt; - given ($dbd) { - when ('mysql') { $txt = 'TEXT NOT NULL,' } - default { $txt = 'TEXT NOT NULL PRIMARY KEY,' } - } - $txt; - } . q[ - text TEXT NOT NULL -);]; - my $token = qq[ -CREATE TABLE token ( - id $serial, - spacing INTEGER NOT NULL, - text ] . do { ($dbd eq 'mysql' ? ' VARCHAR(255) ' : ' TEXT ' ) . ' NOT NULL, ' } . q[ - count INTEGER NOT NULL -); -]; - my $expr = qq[ -CREATE TABLE expr ( - id $serial,] . - do { - join(",", map { qq[\n token${_}_id INTEGER NOT NULL REFERENCES token (id)] } @orders) - } . -q[ -);]; - - my $next_token = qq[ -CREATE TABLE next_token ( - id $serial, - expr_id INTEGER NOT NULL REFERENCES expr (id), - token_id INTEGER NOT NULL REFERENCES token (id), - count INTEGER NOT NULL -);]; - my $prev_token = qq[ -CREATE TABLE prev_token ( - id $serial, - expr_id INTEGER NOT NULL REFERENCES expr (id), - token_id INTEGER NOT NULL REFERENCES token (id), - count INTEGER NOT NULL -);]; - my $indexes = qq[CREATE INDEX token_text on token (text);] . -do { - join "", map { qq[CREATE INDEX expr_token${_}_id on expr (token${_}_id);] } @orders -} . -qq[CREATE INDEX expr_token_ids on expr ($columns); -CREATE INDEX next_token_expr_id ON next_token (expr_id); -CREATE INDEX prev_token_expr_id ON prev_token (expr_id); -]; - my $sql = $info . $token . $expr . $next_token . $prev_token . $indexes; - return ($sql =~ /\s*(.*?)\s*;\s*/gs); -} diff --git a/lib/Hailo/Storage/Schema/Result/Expr.pm b/lib/Hailo/Storage/Schema/Result/Expr.pm index e7f866d..fa0eaef 100644 --- a/lib/Hailo/Storage/Schema/Result/Expr.pm +++ b/lib/Hailo/Storage/Schema/Result/Expr.pm @@ -68,6 +68,12 @@ sub add_tokenN_id { ); } +if (my $n = $ENV{HAILO_STORAGE_SCHEMA_RESULT_EXPR_TOKENN_ORDERS}) { + # Work around add_tokenN_id() not working properly after the class + # has been loaded once. + add_tokenN_id(undef, $_) for 0 .. $n; +} + __PACKAGE__->set_primary_key("id"); =head1 RELATIONS