Commit 7be1f1c9 authored by mkanat%kerio.com's avatar mkanat%kerio.com

Bug 290405: bz_add_column needs a way to specify an initial value

Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=Tomas.Kopal, a=justdave
parent 6b2e132e
...@@ -331,20 +331,26 @@ sub bz_setup_database { ...@@ -331,20 +331,26 @@ sub bz_setup_database {
##################################################################### #####################################################################
sub bz_add_column { sub bz_add_column {
my ($self, $table, $name, $new_def) = @_; my ($self, $table, $name, $new_def, $init_value) = @_;
# You can't add a NOT NULL column to a table with # You can't add a NOT NULL column to a table with
# no DEFAULT statement. # no DEFAULT statement, unless you have an init_value.
if ($new_def->{NOTNULL} && !exists $new_def->{DEFAULT}) { # SERIAL types are an exception, though, because they can
# auto-populate.
if ( $new_def->{NOTNULL} && !exists $new_def->{DEFAULT}
&& !defined $init_value && $new_def->{TYPE} !~ /SERIAL/)
{
die "Failed adding the column ${table}.${name}:\n You cannot add" die "Failed adding the column ${table}.${name}:\n You cannot add"
. " a NOT NULL column with no default to an existing table.\n"; . " a NOT NULL column with no default to an existing table,\n"
. " unless you specify something for \$init_value."
} }
my $current_def = $self->bz_column_info($table, $name); my $current_def = $self->bz_column_info($table, $name);
if (!$current_def) { if (!$current_def) {
my @statements = $self->_bz_real_schema->get_add_column_ddl( my @statements = $self->_bz_real_schema->get_add_column_ddl(
$table, $name, $new_def); $table, $name, $new_def,
defined $init_value ? $self->quote($init_value) : undef);
print "Adding new column $name to table $table ...\n"; print "Adding new column $name to table $table ...\n";
foreach my $sql (@statements) { foreach my $sql (@statements) {
$self->do($sql); $self->do($sql);
...@@ -898,7 +904,7 @@ Bugzilla::DB - Database access routines, using L<DBI> ...@@ -898,7 +904,7 @@ Bugzilla::DB - Database access routines, using L<DBI>
my @result = $sth->fetchrow_array; my @result = $sth->fetchrow_array;
# Schema Modification # Schema Modification
$dbh->bz_add_column($table, $name, \%definition); $dbh->bz_add_column($table, $name, \%definition, $init_value);
$dbh->bz_add_index($table, $name, $definition); $dbh->bz_add_index($table, $name, $definition);
$dbh->bz_drop_index($table, $name); $dbh->bz_drop_index($table, $name);
$dbh->bz_alter_column($table, $name, \%new_def); $dbh->bz_alter_column($table, $name, \%new_def);
...@@ -1211,7 +1217,7 @@ C<Bugzilla::DB::Schema::ABSTRACT_SCHEMA>. ...@@ -1211,7 +1217,7 @@ C<Bugzilla::DB::Schema::ABSTRACT_SCHEMA>.
=over 4 =over 4
=item C<bz_add_column($table, $name, \%definition)> =item C<bz_add_column($table, $name, \%definition, $init_value)>
Description: Adds a new column to a table in the database. Prints out Description: Adds a new column to a table in the database. Prints out
a brief statement that it did so, to stdout. a brief statement that it did so, to stdout.
...@@ -1221,6 +1227,9 @@ C<Bugzilla::DB::Schema::ABSTRACT_SCHEMA>. ...@@ -1221,6 +1227,9 @@ C<Bugzilla::DB::Schema::ABSTRACT_SCHEMA>.
Params: $table = the table where the column is being added Params: $table = the table where the column is being added
$name = the name of the new column $name = the name of the new column
\%definition = Abstract column definition for the new column \%definition = Abstract column definition for the new column
$init_value = (optional) An initial value to set the column
to. Required if your column is NOT NULL and has
no DEFAULT set.
Returns: nothing Returns: nothing
=item C<bz_add_index($table, $name, $definition)> =item C<bz_add_index($table, $name, $definition)>
......
...@@ -1359,22 +1359,30 @@ sub _get_create_index_ddl { ...@@ -1359,22 +1359,30 @@ sub _get_create_index_ddl {
sub get_add_column_ddl { sub get_add_column_ddl {
=item C<get_add_column_ddl($table, $column, \%definition)> =item C<get_add_column_ddl($table, $column, \%definition, $init_value)>
Description: Generate SQL to add a column to a table. Description: Generate SQL to add a column to a table.
Params: $table - The table containing the column. Params: $table - The table containing the column.
$column - The name of the column being added. $column - The name of the column being added.
\%definition - The new definition for the column, \%definition - The new definition for the column,
in standard C<ABSTRACT_SCHEMA> format. in standard C<ABSTRACT_SCHEMA> format.
$init_value - (optional) An initial value to set
the column to. Should already be SQL-quoted
if necessary.
Returns: An array of SQL statements. Returns: An array of SQL statements.
=cut =cut
my ($self, $table, $column, $definition) = @_; my ($self, $table, $column, $definition, $init_value) = @_;
my @statements;
push(@statements, "ALTER TABLE $table ADD COLUMN $column " .
$self->get_type_ddl($definition));
my $statement = "ALTER TABLE $table ADD COLUMN $column " . # XXX - Note that although this works for MySQL, most databases will fail
$self->get_type_ddl($definition); # before this point, if we haven't set a default.
(push(@statements, "UPDATE $table SET $column = $init_value"))
if defined $init_value;
return ($statement); return (@statements);
} }
sub get_add_index_ddl { sub get_add_index_ddl {
......
...@@ -91,7 +91,7 @@ sub _initialize { ...@@ -91,7 +91,7 @@ sub _initialize {
# Overridden because Pg has such weird ALTER TABLE problems. # Overridden because Pg has such weird ALTER TABLE problems.
sub get_add_column_ddl { sub get_add_column_ddl {
my ($self, $table, $column, $definition) = @_; my ($self, $table, $column, $definition, $init_value) = @_;
my @statements; my @statements;
my $specific = $self->{db_specific}; my $specific = $self->{db_specific};
...@@ -109,13 +109,17 @@ sub get_add_column_ddl { ...@@ -109,13 +109,17 @@ sub get_add_column_ddl {
. " SET DEFAULT $default"); . " SET DEFAULT $default");
} }
if (defined $init_value) {
push(@statements, "UPDATE $table SET $column = $init_value");
}
if ($definition->{NOTNULL}) { if ($definition->{NOTNULL}) {
# Handle rows that were NULL when we added the column. # Handle rows that were NULL when we added the column.
# We *must* have a DEFAULT. This check is usually handled # We *must* have a DEFAULT. This check is usually handled
# at a higher level than this code, but I figure it can't # at a higher level than this code, but I figure it can't
# hurt to have it here. # hurt to have it here.
die "NOT NULL columns must have a DEFAULT" die "NOT NULL columns must have a DEFAULT or an init_value."
unless exists $definition->{DEFAULT}; unless (exists $definition->{DEFAULT} || defined $init_value);
push(@statements, "UPDATE $table SET $column = $default"); push(@statements, "UPDATE $table SET $column = $default");
push(@statements, "ALTER TABLE $table ALTER COLUMN $column " push(@statements, "ALTER TABLE $table ALTER COLUMN $column "
. " SET NOT NULL"); . " SET NOT NULL");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment