From: Robert Bohne Date: Thu, 12 Sep 2013 20:23:43 +0000 (+0200) Subject: Added more then one and non integer primary key support X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9cf9f316059793de7a03fcc88bde266c169bb12f;p=dbsrgits%2FSQL-Translator.git Added more then one and non integer primary key support --- diff --git a/lib/SQL/Translator/Generator/DDL/SQLite.pm b/lib/SQL/Translator/Generator/DDL/SQLite.pm index 5a60d51..7d20524 100644 --- a/lib/SQL/Translator/Generator/DDL/SQLite.pm +++ b/lib/SQL/Translator/Generator/DDL/SQLite.pm @@ -10,6 +10,7 @@ engine. I =cut +use Carp; use Moo; has quote_chars => (is=>'ro', default=>sub { +[qw(" ")] } ); @@ -63,30 +64,62 @@ sub _build_unquoted_defaults { sub nullable { () } -sub _ipk { - my ($self, $field) = @_; +sub field_autoinc { + my ($self,$field) = @_; + my $pk = $field->table->primary_key; + my @pk_fields = $pk ? $pk->fields : (); + + if ( $field->is_auto_increment && scalar @pk_fields > 1 ){ + croak sprintf + "SQLite doen't support auto increment with more then one primary key. Problem has occurred by table '%s' and column '%s'", + $field->table->name, + $field->name + ; + } + + ( $_[1]->is_auto_increment ? 'AUTOINCREMENT' : () ) +} - my $pk = $field->table->primary_key; - my @pk_fields = $pk ? $pk->fields : (); +sub primary_key_constraint { + my ($self,$table) = @_; + my $pk = $table->primary_key; + my @pk_fields = $pk ? $pk->fields : (); + return () if (scalar @pk_fields < 2); - $field->is_primary_key && scalar @pk_fields == 1 && - ( $field->data_type =~ /int(eger)?$/i - || - ( $field->data_type =~ /^number?$/i && $field->size !~ /,/ ) ) + return 'PRIMARY KEY (' + . join(', ', map $self->quote($_), @pk_fields) + . ')'; } +sub field_type_and_single_pk { + my ($self, $field) = @_; + my $pk = $field->table->primary_key; + my @pk_fields = $pk ? $pk->fields : (); + my $field_type = $self->field_type($field); + + if ( $field->is_primary_key && scalar @pk_fields == 1){ + # Convert int(xx), number, .. to INTEGER. This is important for backward + # compatibility and conversion from database to database. + if ( $field->data_type =~ /int(eger)?$/i + || ( $field->data_type =~ /^number?$/i && $field->size !~ /,/ ) + ){ + $field_type = 'INTEGER'; + } + + return $field_type . ' PRIMARY KEY'; + } + return $field_type; +} + + sub field { my ($self, $field) = @_; return join ' ', $self->field_comments($field), $self->field_name($field), - ( $self->_ipk($field) - ? $field->is_auto_increment - ? ( 'INTEGER PRIMARY KEY AUTOINCREMENT' ) - : ( 'INTEGER PRIMARY KEY' ) - : ( $self->field_type($field) ) - ), + $self->field_type_and_single_pk($field), + $self->field_autoinc($field), $self->field_nullable($field), $self->field_default($field, { NULL => 1, diff --git a/lib/SQL/Translator/Producer/SQLite.pm b/lib/SQL/Translator/Producer/SQLite.pm index 103c2de..499f4c5 100644 --- a/lib/SQL/Translator/Producer/SQLite.pm +++ b/lib/SQL/Translator/Producer/SQLite.pm @@ -201,27 +201,15 @@ sub create_table } # - # How many fields in PK? - # - my $pk = $table->primary_key; - my @pk_fields = $pk ? $pk->fields : (); - - # # Fields # - my ( @field_defs, $pk_set ); + my ( @field_defs ); for my $field ( @fields ) { push @field_defs, create_field($field); } - if ( - scalar @pk_fields > 1 - || - ( @pk_fields && !grep /INTEGER PRIMARY KEY/, @field_defs ) - ) { - push @field_defs, 'PRIMARY KEY (' . join(', ', map _generator()->quote($_), @pk_fields ) . ')'; - } - + push @field_defs, _generator()->primary_key_constraint($table); + # # Indices # diff --git a/t/56-sqlite-producer.t b/t/56-sqlite-producer.t index 2129c29..8ba09b3 100644 --- a/t/56-sqlite-producer.t +++ b/t/56-sqlite-producer.t @@ -3,6 +3,7 @@ use strict; use Test::More; +use Test::Exception; use Test::SQL::Translator qw(maybe_plan); use SQL::Translator::Schema::View; @@ -200,4 +201,86 @@ $SQL::Translator::Producer::SQLite::NO_QUOTES = 0; is_deeply($result, $expected, 'correctly built table without autoincrement on primary key'); } +{ + # Multi primary key test + my $table = SQL::Translator::Schema::Table->new( + name => 'multi_pk', + ); + $table->add_field( + name => 'id', + data_type => 'integer', + is_nullable => 0, + is_auto_increment => 0, + ); + $table->add_field( + name => 'id2', + data_type => 'integer', + is_nullable => 0, + is_auto_increment => 0, + ); + $table->primary_key('id'); + $table->primary_key('id2'); + my $expected = [ qq]; + my $result = [SQL::Translator::Producer::SQLite::create_table($table, { no_comments => 1 })]; + is_deeply($result, $expected, 'correctly built table with more then one primary key'); +} + +{ + # Multi primary key test + my $table = SQL::Translator::Schema::Table->new( + name => 'text_pk', + ); + $table->add_field( + name => 'id', + data_type => 'text', + is_nullable => 0, + is_auto_increment => 0, + ); + $table->primary_key('id'); + my $expected = [ qq]; + my $result = [SQL::Translator::Producer::SQLite::create_table($table, { no_comments => 1 })]; + is_deeply($result, $expected, 'correctly built table with text primary key'); +} + + +{ + # Multi primary key test + my $table = SQL::Translator::Schema::Table->new( + name => 'multi_pk_with_autoinc', + ); + $table->add_field( + name => 'id', + data_type => 'integer', + is_nullable => 0, + is_auto_increment => 1, + ); + $table->add_field( + name => 'id2', + data_type => 'integer', + is_nullable => 0, + is_auto_increment => 0, + ); + $table->primary_key('id'); + $table->primary_key('id2'); + my $expected = [ qq]; + + throws_ok { + SQL::Translator::Producer::SQLite::create_table( + $table, { no_comments => 1 } + ) + } qr/SQLite doen't support auto increment with more then one primary key. Problem has occurred by table 'multi_pk_with_autoinc' and column 'id'/; + +} + + done_testing;