Show
Ignore:
Timestamp:
05/12/08 23:21:43 (6 months ago)
Author:
bchoate
Message:

Backport of SQLite fixes for upgrading metadata column to narrow tables. BugId:79719,79720

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/release-37/lib/MT/Upgrade.pm

    r2293 r2311  
    888888        }, 
    889889 
    890         # Helper upgrade routine for core_upgrade_meta 
     890        # Helper upgrade routines for core_upgrade_meta 
    891891        # and possibly other object types that require 
    892892        # this migration; version_limit is unspecified, so 
    893         # this can only be invoked if another upgrade 
    894         # operation utilizes it
     893        # these can only be invoked if another upgrade 
     894        # operation utilizes them
    895895        'core_upgrade_meta_for_table' => { 
    896             priority => 3.3
     896            priority => 1.5
    897897            code => \&core_upgrade_meta_for_table, 
     898        }, 
     899        'core_drop_meta_for_table' => { 
     900            priority => 3.4, 
     901            code => \&core_drop_meta_for_table, 
    898902        }, 
    899903        'core_replace_file_template_format' => { 
     
    925929        next TYPE if !$class->has_meta();  # nothing to upgrade 
    926930 
    927         next TYPE if $added_step{$class->datasource};  # already got that one 
    928  
     931        my $t = $type; 
    929932        my $class_type = $class->properties->{class_type}; 
    930933        if ($class_type && $class_type ne $class->datasource) { 
     934            $t = $class_type; 
    931935            if (my $super_class = MT->model($class->datasource)) { 
    932936                $class = $super_class 
     
    935939            # If there's no appropriate superclass, go to update with the class 
    936940            # we have, not the class we want. 
    937         } 
    938  
    939         my %step_param = ( type => $type ); 
    940         $step_param{plugindata} = 1 if $type eq 'category'; 
     941            next TYPE if $added_step{$type};  # already got that one 
     942        } 
     943        else { 
     944            next TYPE if $added_step{$class->datasource};  # already got that one 
     945        } 
     946 
     947        my %step_param = ( type => $t ); 
     948        $step_param{plugindata} = 1 
     949            if ( $class eq 'MT::Category' ) || ( $class eq 'MT::Folder' ); 
    941950        $step_param{meta_column} = $class->properties->{meta_column} 
    942951            if $class->properties->{meta_column}; 
    943952        $self->add_step('core_upgrade_meta_for_table', %step_param); 
    944         $added_step{$class->datasource} = 1; 
     953        $added_step{$class} = 1; 
    945954    } 
    946955    return 0; 
     
    10171026    my $pid = join q{:}, $param{step} . "_type", $class; 
    10181027 
    1019     my $msg = MT->translate("Upgrading metadata storage for [_1]", $class->class_label_plural); 
    1020  
    1021     my $driver = $class->dbi_driver; 
     1028    my $db_class = $class; 
     1029    my $class_type = $class->properties->{class_type}; 
     1030    if ($class_type && $class_type ne $class->datasource) { 
     1031        if (my $super_class = MT->model($class->datasource)) { 
     1032            $db_class = $super_class 
     1033                if $super_class->datasource eq $class->datasource; 
     1034        } 
     1035        # If there's no appropriate superclass, go to update with the class 
     1036        # we have, not the class we want. 
     1037    } 
     1038 
     1039    my $driver = $db_class->dbi_driver; 
    10221040    my $dbh = $driver->rw_handle; 
    10231041    my $dbd = $driver->dbd; 
     
    10291047 
    10301048    my $ddl = $driver->dbd->ddl_class; 
    1031     my $db_defs = $ddl->column_defs($class); 
     1049    my $db_defs = $ddl->column_defs($db_class); 
    10321050    return 0 unless $db_defs && exists($db_defs->{$meta_col}); 
    10331051 
     
    10461064    $sth->execute 
    10471065        or return $self->error($dbh->errstr || $DBI::errstr); 
     1066 
     1067    my $msg = $self->translate_escape("Upgrading metadata storage for [_1]", $class->class_label_plural); 
    10481068 
    10491069    if (!$offset) { 
     
    10701090            if ($metadataref) { 
    10711091                my $metadata = $$metadataref; 
    1072                 my $obj = $class->load($id); 
     1092                my $obj = $class->load( { id => $id }, { no_class => 1, fetchonly => [ 'id', ( $class_type ? ( $class->properties->{class_column} ) : () ) ] }); 
    10731093                if ($obj) { 
    10741094                    my $changed = 0; 
     
    10841104                            foreach my $cfname (keys %$cfdata) { 
    10851105                                my $cfvalue = $cfdata->{$cfname}; 
     1106                                my $cftype = $type; 
     1107                                if ($class_type) { 
     1108                                    $cftype = $obj->class_type; 
     1109                                } 
     1110 
    10861111                                # make sure CustomFields::Field exists 
    1087                                 my $fld = $fields{$cfname} ||= $cfclass->load({ basename => $cfname, obj_type => $type }); 
     1112                                my $fld = $fields{$cfname}{$cftype} ||= $cfclass->load({ basename => $cfname, obj_type => $cftype }); 
    10881113                                next unless $fld; 
    10891114 
     
    11211146    } else { 
    11221147        # done, so lets drop that meta column, what say you? 
    1123         $sql = $dbd->ddl_class->drop_column_sql($class, $param{meta_column} || 'meta'); 
    1124         $dbh->do($sql); 
     1148        if ($dbd->ddl_class->can_drop_column) { 
     1149            # if the driver cannot drop a column, it is likely 
     1150            # to get dropped as the table is updated for other 
     1151            # new columns anyway. 
     1152            $sql = $dbd->ddl_class->drop_column_sql($class, 
     1153                $param{meta_column} || 'meta'); 
     1154            $self->add_step('core_drop_meta_for_table', class => $db_class, sql => $sql); 
     1155        } 
    11251156        $self->progress($msg . ' (100%)', $pid); 
    11261157        $offset = 0;  # done! 
    11271158    } 
    11281159    return $offset; 
     1160} 
     1161 
     1162sub core_drop_meta_for_table { 
     1163    my $self = shift; 
     1164    my (%param) = @_; 
     1165    my $class = $param{class}; 
     1166    my $sql = $param{sql}; 
     1167 
     1168    eval "require $class;"; 
     1169    my $driver = $class->dbi_driver; 
     1170    my $dbh = $driver->rw_handle; 
     1171    $dbh->do($sql); 
     1172 
     1173    return 0; 
    11291174} 
    11301175 
     
    15861631 
    15871632    my $class = MT->model($type); 
     1633 
     1634    # handle schema updates for meta table 
     1635    if ($class->meta_pkg) { 
     1636        $self->check_type($type . ':meta'); 
     1637    } 
     1638 
    15881639    if (my $result = $self->type_diff($type)) { 
    15891640        if ($result->{fix}) { 
     
    15991650                if $result->{index}; 
    16001651        } 
    1601     } 
    1602  
    1603     # handle schema updates for meta table 
    1604     if ($class->meta_pkg) { 
    1605         $self->check_type($type . ':meta'); 
    16061652    } 
    16071653 
     
    21132159# if they require processing that will take time to complete. 
    21142160 
    2115 sub pre_upgrade_class { 1 } 
    2116 sub post_upgrade_class { 1 } 
     2161sub pre_upgrade_class { 
     2162#     my $self = shift; 
     2163#     my ($class) = @_; 
     2164#  
     2165#     # Special case for handling upgrade process for old "meta" column 
     2166#     # storage to new narrow tables; some database drivers cannot 
     2167#     # add new columns without recreating the table, so it's necessary 
     2168#     # to add a fake 'meta' column to classes that declare meta support 
     2169#     # so they upgrade properly. 
     2170#     if (MT->config->SchemaVersion < 4.0057) { 
     2171#         # The mt_category table did not have a 'meta' column and is 
     2172#         # upgraded in a different way, so do not include it in this 
     2173#         # case. 
     2174#         if (($class ne 'MT::Category') && ($class ne 'MT::Folder')) { 
     2175#             unless ($class->driver->dbd->ddl_class->can_add_column) { 
     2176#                 if ($class->can('has_meta') && $class->has_meta) { 
     2177# $self->progress("Triggering special handling for class $class"); 
     2178#                     my $props = $class->properties; 
     2179#                     my $defs = $class->column_defs; 
     2180#                     my $col = $props->{meta_column} ||= 'meta'; 
     2181#                     $defs->{$col} = { type => 'blob' }; 
     2182#                     push @{$props->{columns}}, $col; 
     2183#                 } 
     2184#             } 
     2185#         } 
     2186#     } 
     2187 
     2188    return 1; 
     2189
     2190 
     2191sub post_upgrade_class { 
     2192    my $self = shift; 
     2193    my ($class) = @_; 
     2194 
     2195    # Special case for handling upgrade process for old "meta" column 
     2196    # storage to new narrow tables; some database drivers cannot 
     2197    # add new columns without recreating the table, so it's necessary 
     2198    # to prioritize migration of meta column data before the schema 
     2199    # for that class is updated and the meta column winds up getting 
     2200    # dropped as a result. 
     2201    if (MT->config->SchemaVersion < 4.0057) { 
     2202        return 1 unless $class =~ m/::Meta$/; 
     2203 
     2204        my $pc = $class; 
     2205        $pc =~ s/::Meta$//; 
     2206 
     2207        my $type = $pc->datasource; 
     2208        # 'page' instead of 'entry', for instance 
     2209        $type = $pc->class_type || $type if $pc->can('class_type'); 
     2210 
     2211        my %step_param = ( type => $type ); 
     2212        $step_param{plugindata} = 1 if $type eq 'category'; 
     2213        $step_param{meta_column} = $pc->properties->{meta_column} 
     2214            if $pc->properties->{meta_column}; 
     2215        $self->add_step('core_upgrade_meta_for_table', %step_param); 
     2216    } 
     2217 
     2218    return 1; 
     2219
     2220 
    21172221sub pre_alter_column { 1 } 
    21182222sub post_alter_column { 1 }