0.35 unreleased
- Fix minor breakage (pretty_print) resulting from Jesse's changes.
+ - Update mysql driver to handle BIGSERIAL columns
+ - Update Column.pm, move all mysql and Pg-specific code to DBD driver
+ callbacks
0.34 Sun Aug 19 10:08:51 PDT 2007
- More work on update schema from Slaven Rezic <srezic@cpan.org>,
use DBIx::DBSchema::ColGroup::Unique;
use DBIx::DBSchema::ColGroup::Index;
-$VERSION = "0.35_01";
+$VERSION = "0.35_02";
$VERSION = eval $VERSION; # modperlstyle: convert the string into a number
$DEBUG = 0;
use Carp;
use DBIx::DBSchema::_util qw(_load_driver _dbh);
-$VERSION = '0.09';
+$VERSION = '0.10';
=head1 NAME
my $driver = $dbh ? _load_driver($dbh) : '';
+ ##
+ # type mapping
+ ##
+
my %typemap;
%typemap = eval "\%DBIx::DBSchema::DBD::${driver}::typemap" if $driver;
my $type = defined( $typemap{uc($self->type)} )
? $typemap{uc($self->type)}
: $self->type;
- my $null = $self->null;
+ ##
+ # set default for the callback...
+ ##
my $default;
+ my $orig_default = $self->default;
if ( defined($self->default) && !ref($self->default) && $self->default ne ''
&& ref($dbh)
# false laziness: nicked from FS::Record::_quote
} else {
$default = ref($self->default) ? ${$self->default} : $self->default;
}
+ $self->default($default);
- #this should be a callback into the driver
- if ( $driver eq 'mysql' ) { #yucky mysql hack
- $null ||= "NOT NULL";
- $self->local('AUTO_INCREMENT') if uc($self->type) eq 'SERIAL';
- } elsif ( $driver =~ /^(?:Pg|SQLite)$/ ) { #yucky Pg/SQLite hack
- $null ||= "NOT NULL";
- $null =~ s/^NULL$//;
- }
+ ##
+ # callback into the database-specific driver
+ ##
+
+ my $dbd = "DBIx::DBSchema::DBD::$driver";
+ my $hashref = $dbd->column_callback( $dbh, $self->table_name, $self );
+
+ $self->default($orig_default);
+
+ $type = $hashref->{'effective_type'}
+ if $hashref->{'effective_type'};
+
+ my $null = $self->null;
+
+ #we seem to do this for mysql/Pg/SQLite, i think this should be the default
+ #add something to $hashref if drivers need to overrdide?
+ $null ||= "NOT NULL";
+
+ $null =~ s/^NULL$// unless $hashref->{'explicit_null'};
+
+ $default = $hashref->{'effective_default'}
+ if $hashref->{'effective_default'};
+
+ my $local = $self->local;
+ $local = $hashref->{'effective_local'}
+ if $hashref->{'effective_local'};
+
+ ##
+ # return column line
+ ##
join(' ',
$self->name,
? 'DEFAULT '. $default
: ''
),
- ( ( $driver eq 'mysql' && defined($self->local) )
- ? $self->local
- : ''
- ),
+ ( defined($local) ? $local : ''),
);
}
my $driver = $dbh ? _load_driver($dbh) : '';
- my @after_add = ();
+ my @sql = ();
+ my $table = $self->table_name;
+
+ my $dbd = "DBIx::DBSchema::DBD::$driver";
+ my $hashref = $dbd->add_column_callback( $dbh, $table, $self );
my $real_type = '';
- if ( $driver eq 'Pg' && $self->type eq 'serial' ) {
- $real_type = 'serial';
- $self->type('int');
-
- push @after_add, sub {
- my($table, $column) = @_;
-
- #needs more work for old Pg?
-
- my $pg_server_version = $dbh->{'pg_server_version'};
- unless ( $pg_server_version =~ /\d/ ) {
- warn "WARNING: no pg_server_version! Assuming >= 7.3\n";
- $pg_server_version = 70300;
- }
-
- my $nextval;
- if ( $pg_server_version >= 70300 ) {
- $nextval = "nextval('public.${table}_${column}_seq'::text)";
- } else {
- $nextval = "nextval('${table}_${column}_seq'::text)";
- }
-
- (
- "ALTER TABLE $table ALTER COLUMN $column SET DEFAULT $nextval",
- "CREATE SEQUENCE ${table}_${column}_seq",
- "UPDATE $table SET $column = $nextval WHERE $column IS NULL",
- #"ALTER TABLE $table ALTER $column SET NOT NULL",
- );
-
- };
-
+ if ( $hashref->{'effective_type'} ) {
+ $real_type = $self->type;
+ $self->type($hashref->{'effective_type'});
}
my $real_null = undef;
- if ( $driver eq 'Pg' && ! $self->null ) {
+ if ( exists($hashref->{'effective_null'}) ) {
$real_null = $self->null;
- $self->null('NULL');
-
- my $pg_server_version = $dbh->{'pg_server_version'};
- unless ( $pg_server_version =~ /\d/ ) {
- warn "WARNING: no pg_server_version! Assuming >= 7.3\n";
- $pg_server_version = 70300;
- }
-
- if ( $pg_server_version >= 70300 ) { #this did work on 7.3
- #if ( $pg_server_version > 70400 ) {
-
- push @after_add, sub {
- my($table, $column) = @_;
- "ALTER TABLE $table ALTER $column SET NOT NULL";
- };
-
- } else {
-
- push @after_add, sub {
- my($table, $column) = @_;
- "UPDATE pg_attribute SET attnotnull = TRUE ".
- " WHERE attname = '$column' ".
- " AND attrelid = ( SELECT oid FROM pg_class WHERE relname = '$table' )";
- };
-
- }
-
+ $self->type($hashref->{'effective_type'});
}
- my @r = ();
- my $table = $self->table_name;
- my $column = $self->name;
-
- push @r, "ALTER TABLE $table ADD COLUMN ". $self->line($dbh);
+ push @sql, "ALTER TABLE $table ADD COLUMN ". $self->line($dbh);
- push @r, &{$_}($table, $column) foreach @after_add;
+ push @sql, @{ $hashref->{'sql_after'} } if $hashref->{'sql_after'};
- push @r, "ALTER TABLE $table ADD PRIMARY KEY ( ".
+ push @sql, "ALTER TABLE $table ADD PRIMARY KEY ( ".
$self->table_obj->primary_key. " )"
if $self->name eq $self->table_obj->primary_key;
$self->type($real_type) if $real_type;
$self->null($real_null) if defined $real_null;
- @r;
+ @sql;
}
my $driver = $dbh ? _load_driver($dbh) : '';
- my @r = ();
+ my @sql = ();
+
+ my $dbd = "DBIx::DBSchema::DBD::$driver";
+ my $hashref = $dbd->alter_column_callback( $dbh, $table, $self, $new );
# change the name...
# change the type...
- # change nullability from NOT NULL to NULL
- if ( ! $self->null && $new->null ) {
-
- my $alter = "ALTER TABLE $table ALTER COLUMN $name DROP NOT NULL";
-
- if ( $driver eq 'Pg' ) {
+ if ( $hashref->{'sql_alter_null' } ) {
- my $pg_server_version = $dbh->{'pg_server_version'};
- unless ( $pg_server_version =~ /\d/ ) {
- warn "WARNING: no pg_server_version! Assuming >= 7.3\n";
- $pg_server_version = 70300;
- }
+ push @sql, $hashref->{'sql_alter_null'};
- if ( $pg_server_version < 70300 ) {
- $alter = "UPDATE pg_attribute SET attnotnull = FALSE
- WHERE attname = '$name'
- AND attrelid = ( SELECT oid FROM pg_class
- WHERE relname = '$table'
- )";
- }
+ } else {
+ # change nullability from NOT NULL to NULL
+ if ( ! $self->null && $new->null ) {
+
+ push @sql, "ALTER TABLE $table ALTER COLUMN $name DROP NOT NULL";
+
}
-
- push @r, $alter;
-
- }
-
- # change nullability from NULL to NOT NULL...
- # this one could be more complicated, need to set a DEFAULT value and update
- # the table first...
- if ( $self->null && ! $new->null ) {
-
- my $alter = "ALTER TABLE $table ALTER COLUMN $name SET NOT NULL";
-
- if ( $driver eq 'Pg' ) {
-
- my $pg_server_version = $dbh->{'pg_server_version'};
- unless ( $pg_server_version =~ /\d/ ) {
- warn "WARNING: no pg_server_version! Assuming >= 7.3\n";
- $pg_server_version = 70300;
- }
-
- if ( $pg_server_version < 70300 ) {
- push @r, "UPDATE pg_attribute SET attnotnull = TRUE
- WHERE attname = '$name'
- AND attrelid = ( SELECT oid FROM pg_class
- WHERE relname = '$table'
- )";
- }
-
+
+ # change nullability from NULL to NOT NULL...
+ # this one could be more complicated, need to set a DEFAULT value and update
+ # the table first...
+ if ( $self->null && ! $new->null ) {
+
+ push @sql, "ALTER TABLE $table ALTER COLUMN $name SET NOT NULL";
+
}
- push @r, $alter;
-
}
-
+
# change other stuff...
- @r;
+ @sql;
}
=item sql_drop_column [ DBH ]
=head1 COPYRIGHT
Copyright (c) 2000-2006 Ivan Kohler
+Copyright (c) 2007 Freeside Internet Services, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
use strict;
use vars qw($VERSION);
-$VERSION = '0.04';
+$VERSION = '0.05';
=head1 NAME
sub default_db_catalog { ''; }
-=item default_db_catalog
+=item default_db_schema
Returns the default database schema for the DBI table_info command.
Inheriting from DBIx::DBSchema::DBD will provide the default empty string.
sub default_db_schema { ''; }
+=item column_callback DBH TABLE_NAME COLUMN_OBJ
+
+Optional callback for driver-specific overrides to SQL column definitions.
+
+Should return a hash reference, empty for no action, or with one or more of
+the following keys defined:
+
+effective_type - Optional type override used during column creation.
+
+explicit_null - Set true to have the column definition declare NULL columns explicitly
+
+effective_default - Optional default override used during column creation.
+
+effective_local - Optional local override used during column creation.
+
+
+=cut
+
+sub column_callback { {}; }
+
+=item add_column_callback DBH TABLE_NAME COLUMN_OBJ
+
+Optional callback for additional SQL statments to be called when adding columns
+to an existing table.
+
+Should return a hash reference, empty for no action, or with one or more of
+the following keys defined:
+
+effective_type - Optional type override used during column creation.
+
+effective_null - Optional nullability override used during column creation.
+
+sql_after - Array reference of SQL statements to be executed after the column is added.
+
+=cut
+
+sub add_column_callback { {}; }
+
+=item alter_column_callback DBH TABLE_NAME OLD_COLUMN_OBJ NEW_COLUMN_OBJ
+
+Optional callback for overriding the SQL statments to be called when altering
+columns to an existing table.
+
+Should return a hash reference, empty for no action, or with one or more of
+the following keys defined:
+
+sql_alter_null - Alter SQL statment for changing nullability to be used instead of the default
+
+=cut
+
+sub alter_column_callback { {}; }
+
+=cut
+
=back
=head1 TYPE MAPPING
=head1 COPYRIGHT
Copyright (c) 2000-2005 Ivan Kohler
+Copyright (c) 2007 Freeside Internet Services, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
use DBD::Pg 1.32;
use DBIx::DBSchema::DBD;
-$VERSION = '0.11';
+$VERSION = '0.12';
@ISA = qw(DBIx::DBSchema::DBD);
die "DBD::Pg version 1.32 or 1.41 (or later) required--".
if $DBD::Pg::VERSION != 1.32 && $DBD::Pg::VERSION < 1.41;
%typemap = (
- 'BLOB' => 'BYTEA',
+ 'BLOB' => 'BYTEA',
'LONG VARBINARY' => 'BYTEA',
+ 'TIMESTAMP' => 'TIMESTAMP WITH TIME ZONE',
);
=head1 NAME
$row->{'indisunique'};
}
+sub add_column_callback {
+ my( $proto, $dbh, $table, $column_obj ) = @_;
+ my $name = $column_obj->name;
+
+ my $pg_server_version = $dbh->{'pg_server_version'};
+ my $warning = '';
+ unless ( $pg_server_version =~ /\d/ ) {
+ $warning = "WARNING: no pg_server_version! Assuming >= 7.3\n";
+ $pg_server_version = 70300;
+ }
+
+ my $hashref = { 'sql_after' => [], };
+
+ if ( $column_obj->type =~ /^(\w*)SERIAL$/i ) {
+
+ $hashref->{'effective_type'} = uc($1).'INT';
+
+ #needs more work for old Pg?
+
+ my $nextval;
+ warn $warning if $warning;
+ if ( $pg_server_version >= 70300 ) {
+ $nextval = "nextval('public.${table}_${name}_seq'::text)";
+ } else {
+ $nextval = "nextval('${table}_${name}_seq'::text)";
+ }
+
+ push @{ $hashref->{'sql_after'} },
+ "ALTER TABLE $table ALTER COLUMN $name SET DEFAULT $nextval",
+ "CREATE SEQUENCE ${table}_${name}_seq",
+ "UPDATE $table SET $name = $nextval WHERE $name IS NULL",
+ ;
+
+ }
+
+ if ( ! $column_obj->null ) {
+ $hashref->{'effective_null'} = 'NULL';
+
+ warn $warning if $warning;
+ if ( $pg_server_version >= 70300 ) {
+
+ push @{ $hashref->{'sql_after'} },
+ "ALTER TABLE $table ALTER $name SET NOT NULL";
+
+ } else {
+
+ push @{ $hashref->{'sql_after'} },
+ "UPDATE pg_attribute SET attnotnull = TRUE ".
+ " WHERE attname = '$name' ".
+ " AND attrelid = ( SELECT oid FROM pg_class WHERE relname = '$table' )";
+
+ }
+
+ }
+
+ $hashref;
+
+}
+
+sub alter_column_callback {
+ my( $proto, $dbh, $table, $old_column, $new_column ) = @_;
+ my $name = $old_column->name;
+
+ my $pg_server_version = $dbh->{'pg_server_version'};
+ my $warning = '';
+ unless ( $pg_server_version =~ /\d/ ) {
+ $warning = "WARNING: no pg_server_version! Assuming >= 7.3\n";
+ $pg_server_version = 70300;
+ }
+
+ my $hashref = {};
+
+ # change nullability from NOT NULL to NULL
+ if ( ! $old_column->null && $new_column->null ) {
+
+ warn $warning if $warning;
+ if ( $pg_server_version < 70300 ) {
+ $hashref->{'sql_alter_null'} =
+ "UPDATE pg_attribute SET attnotnull = FALSE
+ WHERE attname = '$name'
+ AND attrelid = ( SELECT oid FROM pg_class
+ WHERE relname = '$table'
+ )";
+ }
+
+ }
+
+ # change nullability from NULL to NOT NULL...
+ # this one could be more complicated, need to set a DEFAULT value and update
+ # the table first...
+ if ( $old_column->null && ! $new_column->null ) {
+
+ warn $warning if $warning;
+ if ( $pg_server_version < 70300 ) {
+ $hashref->{'sql_alter_null'} =
+ "UPDATE pg_attribute SET attnotnull = TRUE
+ WHERE attname = '$name'
+ AND attrelid = ( SELECT oid FROM pg_class
+ WHERE relname = '$table'
+ )";
+ }
+
+ }
+
+ $hashref;
+
+}
+
=head1 AUTHOR
Ivan Kohler <ivan-dbix-dbschema@420.am>
Copyright (c) 2000 Ivan Kohler
Copyright (c) 2000 Mail Abuse Prevention System LLC
+Copyright (c) 2007 Freeside Internet Services, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
use vars qw($VERSION @ISA %typemap);
use DBIx::DBSchema::DBD;
-$VERSION = '0.05';
+$VERSION = '0.06';
@ISA = qw(DBIx::DBSchema::DBD);
%typemap = (
'TIMESTAMP' => 'DATETIME',
'SERIAL' => 'INTEGER',
+ 'BIGSERIAL' => 'BIGINT',
'BOOL' => 'TINYINT',
'LONG VARBINARY' => 'LONGBLOB',
);
( $pkey, \%unique, \%index );
}
+sub column_callback {
+ my( $proto, $dbh, $table, $column_obj ) = @_;
+
+ my $hashref = { 'explicit_null' => 1, };
+
+ $hashref->{'effective_local'} = 'AUTO_INCREMENT'
+ if $column_obj->type =~ /^(\w*)SERIAL$/i;
+
+ if ( $column_obj->default =~ /^(NOW)\(\)$/i
+ && $column_obj->type =~ /^(TIMESTAMP|DATETIME)$/i ) {
+
+ $hashref->{'effective_default'} = 'CURRENT_TIMESTAMP';
+ $hashref->{'effective_type'} = 'TIMESTAMP';
+
+ }
+
+ $hashref;
+
+}
+
=head1 AUTHOR
Ivan Kohler <ivan-dbix-dbschema@420.am>
Copyright (c) 2000 Ivan Kohler
Copyright (c) 2000 Mail Abuse Prevention System LLC
+Copyright (c) 2007 Freeside Internet Services, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.