+=item quoted_default DATABASE_HANDLE
+
+Returns this column's default value quoted for the database.
+
+=cut
+
+sub quoted_default {
+ my($self, $dbh) = @_;
+ my $driver = $dbh ? _load_driver($dbh) : '';
+
+ return ${$self->default} if ref($self->default);
+
+ my $dbd = "DBIx::DBSchema::DBD::$driver";
+
+ return $dbh->quote($self->default)
+ if defined($self->default)
+ && $self->default ne ''
+ && ref($dbh)
+ && $dbd->column_value_needs_quoting($self);
+
+ return $self->default;
+
+}
+
+=item sql_add_column [ DBH ]
+
+Returns SQL to add this column to an existing table. (To create a new table,
+see L<DBIx::DBSchema::Table/sql_create_table> instead.)
+
+NOTE: This interface has changed in 0.41
+
+Returns two listrefs. The first is a list of column alteration SQL fragments
+for an ALTER TABLE statement. The second is a list of full SQL statements that
+should be run after the ALTER TABLE statement.
+
+The data source can be specified by passing an open DBI database handle, or by
+passing the DBI data source name, username and password.
+
+Although the username and password are optional, it is best to call this method
+with a database handle or data source including a valid username and password -
+a DBI connection will be opened and the quoting and type mapping will be more
+reliable.
+
+If passed a DBI data source (or handle) such as `DBI:Pg:dbname=database', will
+use PostgreSQL-specific syntax. Non-standard syntax for other engines (if
+applicable) may also be supported in the future.
+
+=cut
+
+sub sql_add_column {
+ my($self, $dbh) = ( shift, _dbh(@_) );
+
+ die "$self: this column is not assigned to a table"
+ unless $self->table_name;
+
+ my $driver = $dbh ? _load_driver($dbh) : '';
+
+ my @alter_table = ();
+ 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 ( $hashref->{'effective_type'} ) {
+ $real_type = $self->type;
+ $self->type($hashref->{'effective_type'});
+ }
+
+ my $real_null = undef;
+ if ( exists($hashref->{'effective_null'}) ) {
+ $real_null = $self->null;
+ $self->null($hashref->{'effective_null'});
+ }
+
+ push @alter_table, "ADD COLUMN ". $self->line($dbh);
+
+ push @sql, @{ $hashref->{'sql_after'} } if $hashref->{'sql_after'};
+
+ 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;
+
+ (\@alter_table, \@sql);
+
+}
+
+=item sql_alter_column PROTOTYPE_COLUMN [ DATABASE_HANDLE | DATA_SOURCE [ USERNAME PASSWORD [ ATTR ] ] ]
+
+Returns SQL to alter this column so that it is identical to the provided
+prototype column, also a DBIx::DBSchema::Column object.
+
+NOTE: This interface has changed in 0.41
+
+Returns two listrefs. The first is a list of column alteration SQL fragments
+for an ALTER TABLE statement. The second is a list of full SQL statements that
+should be run after the ALTER TABLE statement.
+
+Optionally, the data source can be specified by passing an open DBI database
+handle, or by passing the DBI data source name, username and password.
+
+If passed a DBI data source (or handle) such as `DBI:Pg:dbname=database', will
+use PostgreSQL-specific syntax. Non-standard syntax for other engines (if
+applicable) may also be supported in the future.
+
+If not passed a data source (or handle), or if there is no driver for the
+specified database, will attempt to use generic SQL syntax.
+
+=cut
+
+sub sql_alter_column {
+ my($self, $opt, $new, $dbh) = ( shift, _parse_opt(\@_), shift, _dbh(@_) );
+
+ my $table = $self->table_name;
+ die "$self: this column is not assigned to a table"
+ unless $table;
+
+ my $name = $self->name;
+
+ my $driver = $dbh ? _load_driver($dbh) : '';
+
+ my @alter_table = ();
+ my @sql = ();
+
+ my $dbd = "DBIx::DBSchema::DBD::$driver";
+ my $hashref = $dbd->alter_column_callback( $dbh, $table, $self, $new );
+
+ if ( $hashref->{'sql_alter'} ) {
+
+ push @sql, $hashref->{'sql_alter'};
+
+ } else {
+
+ # change the name...
+ # not yet implemented. how do we tell which old column it was?
+
+ # change the type...
+ if ( $hashref->{'sql_alter_type'} ) {
+ push @alter_table, $hashref->{'sql_alter_type'};
+ }
+
+ # change nullability...
+
+ if ( $hashref->{'sql_alter_null'} ) {
+
+ push @sql, $hashref->{'sql_alter_null'};
+
+ } else {
+
+ # change nullability from NOT NULL to NULL
+ if ( ! $self->null && $new->null ) {
+
+ push @alter_table, "ALTER COLUMN $name DROP NOT NULL";
+
+ }
+
+ # 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 @alter_table, "ALTER COLUMN $name SET NOT NULL";
+
+ }
+
+ }
+
+ # change default
+ my $old_default = $self->quoted_default($dbh);
+ my $new_default = $new->quoted_default($dbh);
+ if ( $old_default ne $new_default
+ && ( uc($old_default) ne 'NOW()' || uc($new_default) ne 'NOW()' )
+ )
+ {
+
+ #warn "old default: $old_default / new default: $new_default\n";
+
+ my $alter = "ALTER COLUMN $name";
+
+ if ( $new_default ne '' ) {
+ #warn "changing from $old_default to $new_default\n";
+ push @alter_table, "$alter SET DEFAULT $new_default";
+ } elsif ( $old_default !~ /^nextval/i ) { #Pg-specific :(
+ push @alter_table, "$alter DROP DEFAULT";
+
+ push @sql, "UPDATE TABLE $table SET $name = NULL WHERE $name = ''"
+ if $opt->{'nullify_default'} && $old_default eq "''" && $new->null;
+ }
+
+ }
+
+ # change other stuff... (what next?)
+
+ }
+
+ (\@alter_table, \@sql);
+
+}
+
+=item sql_drop_column [ DBH ]
+
+Returns SQL to drop this column from an existing table.
+
+NOTE: This interface has changed in 0.41
+
+Returns a list of column alteration SQL fragments for an ALTER TABLE statement.
+
+The optional database handle or DBI data source/username/password is not yet
+used.
+
+=cut
+
+sub sql_drop_column {
+ my( $self, $dbh ) = ( shift, _dbh(@_) );
+
+ my $table = $self->table_name;
+ my $name = $self->name;
+
+ ("DROP COLUMN $name"); # XXX what about indexes???
+}
+