From: <pau...@us...> - 2008-06-24 15:52:26
|
Revision: 1006 http://everydevel.svn.sourceforge.net/everydevel/?rev=1006&view=rev Author: paul_the_nomad Date: 2008-06-24 08:52:14 -0700 (Tue, 24 Jun 2008) Log Message: ----------- FIXES: NodeBase.pm/DB.pm - loadNodetypeModules had a hard to reproduce bug. This was caused by loading a nodetype module before the nodetype module itself was loaded. The bug would only appear when the DB backend returned nodetype names (fetched by fetch_all_nodetype_names) in an order that put the nodetype nodetype after other nodetypes. Because nodetype has the lowest node_id 'ORDER BY node_id' fixes this. Pg.pm - postgresql SQL assumes that anything quoted in double quotes is a column name. Literal values should use single quotes. Additional type checking added in addFieldToTable so that if we pass an empty string as a default it is changed to '0' for default. Build.PL - Test suite uses features only available in File::Temp 0.18 and later. Modified Paths: -------------- trunk/ebase/Build.PL trunk/ebase/lib/Everything/DB/Pg.pm trunk/ebase/lib/Everything/DB/Test/Pg.pm trunk/ebase/lib/Everything/DB.pm trunk/ebase/lib/Everything/NodeBase.pm trunk/ebase/lib/Everything/Test/DB.pm Modified: trunk/ebase/Build.PL =================================================================== --- trunk/ebase/Build.PL 2008-06-23 08:30:43 UTC (rev 1005) +++ trunk/ebase/Build.PL 2008-06-24 15:52:14 UTC (rev 1006) @@ -51,6 +51,7 @@ 'Test::Simple' => 0.47, 'Template' => 0, 'Proc::ProcessTable' => 0, + 'File::Temp' => 0.18, }, scripts => [ File::Spec->catfile( 'bin', 'nbmasta' ) ], test_files => join( ' ', @test_files ), Modified: trunk/ebase/lib/Everything/DB/Pg.pm =================================================================== --- trunk/ebase/lib/Everything/DB/Pg.pm 2008-06-23 08:30:43 UTC (rev 1005) +++ trunk/ebase/lib/Everything/DB/Pg.pm 2008-06-24 15:52:14 UTC (rev 1006) @@ -246,61 +246,52 @@ # Returns # 1 if successful, 0 if failure. # -sub addFieldToTable -{ - my ( $this, $table, $fieldname, $type, $primary, $default ) = @_; - my $sql; +sub addFieldToTable { + my ( $this, $table, $fieldname, $type, $primary, $default ) = @_; + my $sql; - return 0 if ( ( $table eq "" ) || ( $fieldname eq "" ) || ( $type eq "" ) ); + return 0 if ( ( $table eq "" ) || ( $fieldname eq "" ) || ( $type eq "" ) ); - if ( not defined $default ) - { - if ( $type =~ /^int/i ) - { - $default = 0; - } - else - { - $default = ""; - } - } - elsif ( $type =~ /^text/i ) - { + if ( ( ( not defined($default) ) || ( $default eq '' ) ) + && ( $type =~ /^int/i || $type =~ /(?:big)|(?:small)int/i ) ) + { + $default = 0; + } - # Text blobs cannot have default strings. They need to be empty. - $default = ""; - } + elsif ( ( not defined($default) ) && $type =~ /^text/i ) { - $sql = "alter table \"$table\" add $fieldname $type"; - $sql .= " default \"$default\" not null"; + # Text blobs cannot have default strings. They need to be empty. + $default = ""; + } - $this->{dbh}->do($sql); + $sql = "alter table \"$table\" add $fieldname $type"; + $sql .= " default '$default' not null"; - if ($primary) - { + $this->{dbh}->do($sql); - # This requires a little bit of work. We need to figure out what - # primary keys already exist, drop them, and then add them all - # back in with the new key. - my @fields = $this->getFieldsHash($table); - my @prikeys; - my $primaries; - my $field; + if ($primary) { - foreach $field (@fields) - { - push @prikeys, $$field{Field} if ( $$field{Key} eq "PRI" ); - } + # This requires a little bit of work. We need to figure out what + # primary keys already exist, drop them, and then add them all + # back in with the new key. + my @fields = $this->getFieldsHash($table); + my @prikeys; + my $primaries; + my $field; - $this->{dbh}->do("alter table \"$table\" drop primary key") - if ( @prikeys > 0 ); + foreach $field (@fields) { + push @prikeys, $$field{Field} if ( $$field{Key} eq "PRI" ); + } - push @prikeys, $fieldname; # add the new field to the primaries - $primaries = join ',', @prikeys; - $this->{dbh}->do("alter table \"$table\" add primary key($primaries)"); - } + $this->{dbh}->do("alter table \"$table\" drop primary key") + if ( @prikeys > 0 ); - return 1; + push @prikeys, $fieldname; # add the new field to the primaries + $primaries = join ',', @prikeys; + $this->{dbh}->do("alter table \"$table\" add primary key($primaries)"); + } + + return 1; } ############################################################################# Modified: trunk/ebase/lib/Everything/DB/Test/Pg.pm =================================================================== --- trunk/ebase/lib/Everything/DB/Test/Pg.pm 2008-06-23 08:30:43 UTC (rev 1005) +++ trunk/ebase/lib/Everything/DB/Test/Pg.pm 2008-06-24 15:52:14 UTC (rev 1006) @@ -37,7 +37,7 @@ sub test_fetch_all_nodetype_names : Test(+0) { my $self = shift; - $self->add_expected_sql('SELECT title FROM "node" WHERE type_nodetype=1 '); + $self->add_expected_sql('SELECT title FROM "node" WHERE type_nodetype=1 ORDER BY node_id'); $self->SUPER; } @@ -274,7 +274,7 @@ } -sub test_add_field_to_table : Test(22) { +sub test_add_field_to_table : Test(25) { my $self = shift; $self->{instance}->{dbh} ->set_always( 'prepare_cached', $self->{instance}->{dbh} ); @@ -307,22 +307,42 @@ ); like( $args->[1], - qr/default "" not null/, + qr/default '' not null/, '... with a blank default for text fields' ); + $self->{instance}->addFieldToTable( 't', 'f', 'int', 0 ); ( $method, $args ) = $self->{instance}->{dbh}->next_call(); like( $args->[1], - qr/default "0" not null/, + qr/default '0' not null/, '... a zero default for int fields' ); $self->{instance}->{dbh}->clear; + + $self->{instance}->addFieldToTable( 't', 'f', 'bigint', 0 ); + ( $method, $args ) = $self->{instance}->{dbh}->next_call(); + like( + $args->[1], + qr/default '0' not null/, + '... a zero default for bigint fields' + ); + $self->{instance}->{dbh}->clear; + + $self->{instance}->addFieldToTable( 't', 'f', 'smallint', 0 ); + ( $method, $args ) = $self->{instance}->{dbh}->next_call(); + like( + $args->[1], + qr/default '0' not null/, + '... a zero default for smallint fields' + ); + $self->{instance}->{dbh}->clear; + $self->{instance}->addFieldToTable( 't', 'f', 'something else', 0 ); ( $method, $args ) = $self->{instance}->{dbh}->next_call(); like( $args->[1], - qr/default "" not null/, + qr/default '' not null/, '... a blank default for all other fields' ); @@ -333,10 +353,21 @@ ( $method, $args ) = $self->{instance}->{dbh}->next_call(); like( $args->[1], - qr/default "default" not null/, + qr/default 'default' not null/, '... and the given default, if given' ); + $self->{instance}->{dbh}->clear; + $self->{instance}->{dbh}->set_series( 'fetchrow_hashref', @$fields ); + $self->{instance} + ->addFieldToTable( 't', 'f', 'smallint', 0, '' ); + ( $method, $args ) = $self->{instance}->{dbh}->next_call(); + like( + $args->[1], + qr/default '0' not null/, + '... default moved to 0 if empty string and type is int.' + ); + $self->{instance}->{dbh}->clear(); $self->{instance} ->addFieldToTable( 't', 'f', 'something else', 1, 'default' ); @@ -344,7 +375,7 @@ is( $method, 'do', '... for table' ); is( $args->[1], - 'alter table "t" add f something else default "default" not null', + q|alter table "t" add f something else default 'default' not null|, '... makes some sql to amend a table.' ); Modified: trunk/ebase/lib/Everything/DB.pm =================================================================== --- trunk/ebase/lib/Everything/DB.pm 2008-06-23 08:30:43 UTC (rev 1005) +++ trunk/ebase/lib/Everything/DB.pm 2008-06-24 15:52:14 UTC (rev 1006) @@ -25,15 +25,17 @@ =head2 C<fetch_all_nodetype_names()> -This method returns a list of the names of all nodetypes in the system. +This method returns a list of the names of all nodetypes in the system. Takes an optional argument, which is text passed to sqlSelectMany. =cut sub fetch_all_nodetype_names { - my $self = shift; - my $csr = $self->sqlSelectMany( 'title', 'node', 'type_nodetype=1' ); + my ( $self, $order_by ) = @_; + $order_by ||= 'ORDER BY node_id'; + my $csr = $self->sqlSelectMany( 'title', 'node', 'type_nodetype=1', $order_by ); + return unless $csr; my @modules; Modified: trunk/ebase/lib/Everything/NodeBase.pm =================================================================== --- trunk/ebase/lib/Everything/NodeBase.pm 2008-06-23 08:30:43 UTC (rev 1005) +++ trunk/ebase/lib/Everything/NodeBase.pm 2008-06-24 15:52:14 UTC (rev 1006) @@ -165,7 +165,7 @@ my %modules; - for my $nodetype ( $self->{storage}->fetch_all_nodetype_names() ) + for my $nodetype ( $self->{storage}->fetch_all_nodetype_names( 'ORDER BY node_id' ) ) { my $module = "Everything::Node::$nodetype"; if ($self->loadNodetypeModule( $module ) ){ Modified: trunk/ebase/lib/Everything/Test/DB.pm =================================================================== --- trunk/ebase/lib/Everything/Test/DB.pm 2008-06-23 08:30:43 UTC (rev 1005) +++ trunk/ebase/lib/Everything/Test/DB.pm 2008-06-24 15:52:14 UTC (rev 1006) @@ -258,7 +258,7 @@ my $self = shift; $self->{instance}->{dbh}->clear; - $self->add_expected_sql('SELECT title FROM node WHERE type_nodetype=1 ') unless $self->isset_expected_sql; + $self->add_expected_sql('SELECT title FROM node WHERE type_nodetype=1 ORDER BY node_id') unless $self->isset_expected_sql; { my @a = @lists; $self->{instance}->{dbh}->mock( 'fetchrow_array', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |