Changeset 2881

Show
Ignore:
Timestamp:
08/01/08 21:38:08 (4 months ago)
Author:
mpaschal
Message:

Treat multi-column primary keys correctly when generating table SQL on core databases
BugzID: 80847

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/release-42/lib/MT/ObjectDriver/DDL.pm

    r2187 r2881  
    2828sub create_sequence {} 
    2929sub drop_sequence {} 
    30 sub unique_constraint_sql { '' } 
     30 
     31sub unique_constraint_sql { 
     32    my $ddl = shift; 
     33    my ($class) = @_; 
     34 
     35    my $pk = $class->properties->{primary_key}; 
     36    return q{} if !ref $pk || 'ARRAY' ne ref $pk; 
     37 
     38    my $driver = $class->driver; 
     39    my $dbd = $driver->dbd; 
     40    my $table = $class->table_name; 
     41 
     42    my @key_fields = map { $dbd->db_column_name($table, $_) } @$pk; 
     43    return ', PRIMARY KEY (' . join(q{, }, @key_fields) . ')'; 
     44
    3145 
    3246sub table_exists { 
     
    258272    my @stmts; 
    259273    if ($indexes) { 
    260         # FIXME: Handle possible future primary key tuple case 
    261274        my $pk = $props->{primary_key}; 
     275        undef $pk if ref $pk;  # ignore complex key 
    262276        foreach my $name (keys %$indexes) { 
    263277            next if $pk && $name eq $pk; 
     
    283297    my $pk = $props->{primary_key}; 
    284298    if (!ref $indexes->{$name}) { 
    285         if (!($pk && $name eq $pk)) { 
     299        if (!$pk || ref $pk || $name ne $pk) { 
    286300            push @stmts, "CREATE INDEX ${table_name}_$name ON $table_name (${field_prefix}_$name)"; 
    287301        } 
     
    362376        $default = ' DEFAULT ' . $value; 
    363377    } 
    364     my $key = ''; 
    365     $key = ' PRIMARY KEY' if $def->{key}; 
     378    my $key = !$def->{key}                          ? q{} 
     379            : ref $class->properties->{primary_key} ? q{} 
     380            :                                         ' PRIMARY KEY' 
     381            ; 
    366382    return $field_prefix . '_' . $name . ' ' . $type . $nullable . $default . $key; 
    367383} 
     
    430446=head1 NAME 
    431447 
    432 MT::ObjectDriver::DDL 
    433  
    434 =head1 DESCRIPTION 
     448MT::ObjectDriver::DDL - Data Definition Language driver 
    435449 
    436450=head1 SYNOPSIS 
     
    443457    my @ddl = $ddl->as_ddl; 
    444458 
     459=head1 DESCRIPTION 
     460 
     461The Data Definition Language (DDL) drivers provide compatible SQL for creating 
     462and changing the database tables that contain Movable Type's data. The DDL 
     463drivers are mainly used by MT::Upgrade, the automatic upgrader. 
     464 
    445465=head1 METHODS 
    446466 
     467=head2 $ddl->column_defs($class) 
     468 
     469Returns a description of the current column definitions in the table holding 
     470records for C<$class>, an C<MT::Object> subclass. These descriptions are 
     471comparable to the results of C<MT::Object::column_defs()>; that is, the 
     472description for a class is a hashref containing a column definition for each 
     473column of the class, keyed on the name of the column. Each column definition is 
     474itself a hashref with the possible keys: 
     475 
     476=over 4 
     477 
     478=item * C<type> 
     479 
     480The type of data contained in the column. See C<db2type()> for the possible 
     481values of this member. 
     482 
     483=item * C<auto> 
     484 
     485If true, indicates the column is an auto-increment column (that is, a column 
     486automatically filled by the database when no value is provided for new 
     487records). 
     488 
     489=item * C<key> 
     490 
     491If true, indicates the column is or is part of the table's primary key. The 
     492combined value of all key columns in a record must be unique, and should 
     493constitute the identity of the record. 
     494 
     495=item * C<size> 
     496 
     497For string columns, the maximum possible length of values in the column. 
     498 
     499=item * C<not_null> 
     500 
     501If true, indicates the column is not allowed to contain a C<NULL> value. 
     502 
     503=item * C<default> 
     504 
     505The default value used if a record is sent to be saved with no value for that 
     506column. 
     507 
     508=back 
     509 
     510If the table does not exist, no value is returned. 
     511 
     512Subclasses B<must> themselves implement C<column_defs()>. No default 
     513implementation is provided. 
     514 
     515=head2 $ddl->index_defs($class) 
     516 
     517Returns a description of all the index definitions for the table storing 
     518records for C<$class>, an C<MT::Object> subclass. These descriptions are 
     519hashrefs containing individual index definitions, keyed on the names of the 
     520indexes. 
     521 
     522Each index definition is either C<1>, meaning the index is on the single column 
     523named the same as the index, or a hashref with the possible keys: 
     524 
     525=over 4 
     526 
     527=item * C<columns> 
     528 
     529An arrayref listing the columns that compose the index. 
     530 
     531=item * C<unique> 
     532 
     533If true, indicates a record's values for the indexes are required to be unique 
     534across the table. 
     535 
     536=back 
     537 
     538If no indexes exist for the table, either no value or an empty hashref is 
     539returned. 
     540 
     541=head2 $ddl->table_exists($class) 
     542 
     543Returns whether the table for C<$class>, an C<MT::Object> subclass, exists in 
     544the database. 
     545 
     546=head2 $ddl->unique_constraint_sql($class) 
     547 
     548Returns the SQL describing the uniqueness constraints specified in the 
     549properties of C<$class>, an C<MT::Object> subclass, suitable for insertion at 
     550the end of a C<CREATE TABLE> statement. 
     551 
     552The default implementation returns a standard multi-column C<PRIMARY KEY> 
     553declaration if the primary key of C<$class> is multiple columns, or the empty 
     554string otherwise. 
     555 
     556=head2 $ddl->can_add_column() 
     557 
     558Returns whether the database can add columns to a table that already exists. 
     559 
     560The default implementation returns false. Subclasses should override this 
     561method to return true if they implement C<add_column_sql()>. 
     562 
     563=head2 $ddl->can_drop_column() 
     564 
     565Returns whether the database can drop (remove) columns from a table that 
     566already exists. 
     567 
     568The default implementation returns false. Subclasses should override this 
     569method to return true if they implement C<drop_column_sql()>. 
     570 
     571=head2 $ddl->can_alter_column() 
     572 
     573Returns whether the database can change the definition of a column that already 
     574exists. 
     575 
     576The default implementation returns false. Subclasses should override this 
     577method to return true if they implement C<alter_column_sql()>. 
     578 
     579=head2 $ddl->can_add_constraint() 
     580 
     581Returns whether the database can add a constraint on the table that already 
     582exists. 
     583 
     584The default implementation returns B<true>. Subclasses should override this 
     585method to return B<false> if the database does not support the C<ALTER TABLE 
     586... ADD CONSTRAINT> statement. 
     587 
     588=head2 $ddl->fix_class() 
     589 
     590=head2 $ddl->insert_from_sql() 
     591 
     592=head2 $ddl->drop_table_sql() 
     593 
     594=head2 $ddl->drop_index_sql() 
     595 
     596=head2 $ddl->create_table_sql() 
     597 
     598=head2 $ddl->create_table_as_sql() 
     599 
     600=head2 $ddl->index_table_sql() 
     601 
     602=head2 $ddl->index_column_sql() 
     603 
     604=head2 $ddl->add_column_sql() 
     605 
     606=head2 $ddl->alter_column_sql() 
     607 
     608=head2 $ddl->drop_column_sql() 
     609 
     610=head2 $ddl->column_sql() 
     611 
     612=head2 $ddl->cast_column_sql() 
     613 
     614=head2 $ddl->db2type() 
     615 
     616=head2 $ddl->type2db() 
     617 
     618TODO 
     619 
    447620=head2 $ddl->add_column() 
    448621 
     622=head2 $ddl->alter_column() 
     623 
     624=head2 $ddl->drop_column() 
     625 
     626=head2 $ddl->index_column() 
     627 
     628B<Deprecated.> These methods return the results of the corresponding C<_sql> 
     629methods. 
     630 
    449631=head2 $ddl->create_table() 
    450632 
    451633=head2 $ddl->drop_table() 
    452634 
    453 =head2 $ddl->drop_column() 
    454  
    455 =head2 $ddl->create_index() 
    456  
    457 =head2 $ddl->drop_index() 
     635=head2 $ddl->index_table() 
     636 
     637=head2 $ddl->create_sequence() 
     638 
     639=head2 $ddl->drop_sequence() 
     640 
     641B<Deprecated.> These methods return no value. 
    458642 
    459643=head1 AUTHOR & COPYRIGHT 
  • branches/release-42/lib/MT/ObjectDriver/DDL/SQLite.pm

    r2705 r2881  
    101101    $sth->execute or return undef; 
    102102    my $defs = {}; 
     103    my @pks; 
    103104    while (my $row = $sth->fetchrow_hashref) { 
    104105        my $colname = lc $row->{name}; 
     
    109110        } 
    110111        $defs->{$colname}{type} = $coltype; 
     112        # TODO: isn't key for pks, not foreign keys? 
    111113        if ($colname =~ m/_id$/) { 
    112114            $defs->{$colname}{key} = 1; 
    113115        } 
    114         if ( ($coltype eq 'integer') && $row->{pk} ) { 
    115             # with sqlite, integer primary keys auto increment. always. 
     116        if ($row->{pk}) { 
    116117            $defs->{$colname}{key} = 1; 
    117             $defs->{$colname}{auto} = 1
     118            push @pks, $colname
    118119        } 
    119120        $defs->{$colname}{not_null} = 1 
     
    124125    $sth->finish; 
    125126    return undef unless %$defs; 
     127 
     128    if (@pks && 1 == scalar @pks) { 
     129        my ($colname) = @pks; 
     130        if ($defs->{$colname}{type} eq 'integer') { 
     131            # with sqlite, simple integer primary keys auto increment. always. 
     132            $defs->{$colname}{auto} = 1; 
     133        } 
     134    } 
     135 
    126136    return $defs; 
    127137} 
     
    173183    my ($class) = @_; 
    174184 
    175     my $table_name = $class->table_name; 
    176     my $props = $class->properties; 
     185    my $table_name   = $class->table_name; 
     186    my $props        = $class->properties; 
    177187    my $field_prefix = $class->datasource; 
    178     my $indexes = $props->{indexes}; 
     188    my $indexes      = $props->{indexes}; 
     189    my $pk           = $props->{primary_key}; 
    179190 
    180191    my @stmts; 
    181192    if ($indexes) { 
    182         # FIXME: Handle possible future primary key tuple case 
    183         my $pk = $props->{primary_key}; 
    184193        foreach my $name (keys %$indexes) { 
    185194            next if $pk && $name eq $pk; 
     
    199208        } 
    200209    } 
     210    if ($pk && 'ARRAY' eq ref $pk) { 
     211        my @columns = map { join q{_}, $field_prefix, $_ } @$pk; 
     212        my $columns = join q{, }, @columns; 
     213        push @stmts, "PRIMARY KEY ($columns)"; 
     214    } 
    201215    if (@stmts) { 
    202216        return ',' . join("\n", @stmts); 
  • branches/release-42/lib/MT/ObjectDriver/DDL/mysql.pm

    r1927 r2881  
    9797        $defs->{$colname}{type} = $coltype; 
    9898        $defs->{$colname}{auto} = ($row->{Extra} =~ m/auto_increment/i) ? 1 : 0; 
     99        $defs->{$colname}{key}  = $row->{Key} eq 'PRI' ? 1 : 0; 
    99100        if (($coltype eq 'string') && $size) { 
    100101            $defs->{$colname}{size} = $size;