[Jifty-commit] r955 - in jifty/trunk: . lib lib/Jifty lib/Jifty/Script lib/Jifty/Upgrade

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Fri Apr 28 15:49:54 EDT 2006


Author: alexmv
Date: Fri Apr 28 15:49:53 2006
New Revision: 955

Added:
   jifty/trunk/lib/Jifty/Model/Metadata.pm
   jifty/trunk/lib/Jifty/Upgrade/
   jifty/trunk/lib/Jifty/Upgrade/Internal.pm
Removed:
   jifty/trunk/lib/Jifty/Model/Schema.pm
Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty.pm
   jifty/trunk/lib/Jifty/Everything.pm
   jifty/trunk/lib/Jifty/Handle.pm
   jifty/trunk/lib/Jifty/Script/Schema.pm
   jifty/trunk/lib/Jifty/Upgrade.pm

Log:
 r12682 at zoq-fot-pik:  chmrr | 2006-04-28 15:48:33 -0400
  * _db_version -> _jifty_metadata, jifty schema versioning


Modified: jifty/trunk/lib/Jifty.pm
==============================================================================
--- jifty/trunk/lib/Jifty.pm	(original)
+++ jifty/trunk/lib/Jifty.pm	Fri Apr 28 15:49:53 2006
@@ -5,7 +5,7 @@
 use encoding 'utf8';
 # Work around the fact that Time::Local caches thing on first require
 BEGIN { local $ENV{'TZ'} = "GMT";  require Time::Local;}
-our $VERSION = '0.60321';
+our $VERSION = '0.60427';
 
 =head1 NAME
 

Modified: jifty/trunk/lib/Jifty/Everything.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Everything.pm	(original)
+++ jifty/trunk/lib/Jifty/Everything.pm	Fri Apr 28 15:49:53 2006
@@ -37,8 +37,7 @@
 use Jifty::View::Static::Handler ();
 use Jifty::View::Mason::Handler ();
 
-use Jifty::Model::Schema ();
-
+use Jifty::Model::Metadata ();
 
 
 use Jifty::Request ();

Modified: jifty/trunk/lib/Jifty/Handle.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Handle.pm	(original)
+++ jifty/trunk/lib/Jifty/Handle.pm	Fri Apr 28 15:49:53 2006
@@ -101,18 +101,50 @@
 =cut
 
 sub check_schema_version {
-    my $appv
-        = version->new( Jifty->config->framework('Database')->{'Version'} );
-    require Jifty::Model::Schema;
-    my $dbv = Jifty::Model::Schema->new->in_db;
-    die
-        "Schema has no version in the database; perhaps you need to run this:\n\t bin/jifty schema --setup\n"
-        unless defined $dbv;
-
-    die
-        "Schema version in database ($dbv) doesn't match application schema version ($appv)\n"
-        . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
-        unless $appv == $dbv;
+    require Jifty::Model::Metadata;
+
+    # Application db version check
+    {
+        my $dbv  = Jifty::Model::Metadata->load("application_db_version");
+        my $appv = Jifty->config->framework('Database')->{'Version'};
+
+        # Backwards compatibility -- it used to be in _db_version
+        if ( not defined $dbv ) {
+            my @v;
+            eval {
+                local $SIG{__WARN__} = sub { };
+                @v = Jifty->handle->fetch_result(
+                    "SELECT major, minor, rev FROM _db_version");
+            };
+            $dbv = join( ".", @v ) if @v == 3;
+        }
+
+        die
+            "Application schema has no version in the database; perhaps you need to run this:\n"
+            . "\t bin/jifty schema --setup\n"
+            unless defined $dbv;
+
+        die
+            "Application schema version in database ($dbv) doesn't match application schema version ($appv)\n"
+            . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
+            unless version->new($appv) == version->new($dbv);
+    }
+
+    # Jifty db version check
+    {
+
+        # If we got here, the application had a version (somehow) so
+        # this is an upgrade.  If $dbv is undef, it's because it's
+        # from before when the _jifty_metadata table existed.
+        my $dbv
+            = version->new( Jifty::Model::Metadata->load("jifty_db_version")
+                || '0.60426' );
+        my $appv = version->new($Jifty::VERSION);
+        die
+            "Internal jifty schema version in database ($dbv) doesn't match running jifty version ($appv)\n"
+            . "Please run `bin/jifty schema --setup` to upgrade the database.\n"
+            unless $appv == $dbv;
+    }
 
 }
 

Added: jifty/trunk/lib/Jifty/Model/Metadata.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Model/Metadata.pm	Fri Apr 28 15:49:53 2006
@@ -0,0 +1,94 @@
+use warnings;
+use strict;
+
+=head1 NAME
+
+Jifty::Model::Metadata - Tracks Jifty-related metadata
+
+=head1 SYNOPSIS
+
+  my $app = Jifty->new(config_file => "$ProjectRoot/etc/config.yml");
+  my $application_version = Jifty::Model::Metadata->load("application_db_version");
+
+=head1 DESCRIPTION
+
+Every Jifty application automatically inherits this table, which
+describes information about the Jifty database.  It uses this
+information to smartly upgrade between application versions, as well
+as versions of Jifty itself, for instance.
+
+=cut
+
+package Jifty::Model::Metadata::Schema;
+use Jifty::DBI::Schema;
+
+column key => type is 'text';
+column value => type is 'text';
+
+
+package Jifty::Model::Metadata;
+use version;
+
+use base qw( Jifty::Record );
+
+=head2 table
+
+Schemas are stored in the table C<_jifty_metadata>.
+
+=cut
+
+sub table { '_jifty_metadata' }
+
+=head2 since
+
+The metadata table first appeared in Jifty version 0.60427
+
+=cut
+
+sub since { '0.60427' }
+
+=head2 load KEY
+
+Fetches the given C<KEY> from the metadata store.  Returns undef if
+such a key cannot be found.
+
+=cut
+
+sub load {
+    my $self = shift;
+    $self = $self->new() unless ref $self;
+    return undef unless $self->_handle and $self->_handle->dbh->ping;
+
+    my ($key) = @_;
+    # This may barf all over the place.  That's almost expected in
+    # some circumstances, so we eat all warnings and errors right
+    # here, right now.
+    eval {
+        local $SIG{__WARN__} = sub {};
+        $self->load_by_cols( key => $key );
+    };
+    return undef unless $self->id;
+    return $self->value;
+}
+
+=head2 store KEY => VALUE
+
+Stores the given C<KEY> in the database, overwriting the previous
+value if it existed.
+
+=cut
+
+sub store {
+    my $self = shift;
+    $self = $self->new() unless ref $self;
+
+    my ($key, $value) = @_;
+    $self->load_by_cols( key => $key );
+    if ($self->id) {
+        $self->set_value($value);
+    } else {
+        $self->create( key => $key, value => $value);
+    }
+}
+
+1;

Modified: jifty/trunk/lib/Jifty/Script/Schema.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Script/Schema.pm	(original)
+++ jifty/trunk/lib/Jifty/Script/Schema.pm	Fri Apr 28 15:49:53 2006
@@ -48,7 +48,8 @@
     if ( $self->{create_all_tables} ) {
         $self->create_all_tables();
     } elsif ( $self->{'setup_tables'} ) {
-        $self->upgrade_tables();
+        $self->upgrade_jifty_tables();
+        $self->upgrade_appliction_tables();
     } else {
         print "Done.\n";
     }
@@ -66,7 +67,7 @@
 
     # Import Jifty
     Jifty::Util->require("Jifty");
-    Jifty::Util->require("Jifty::Model::Schema");
+    Jifty::Util->require("Jifty::Model::Metadata");
 }
 
 
@@ -143,7 +144,7 @@
             logger_component => 'SchemaTool',
         );
     };
-    if ( $@ =~ /doesn't match application schema version/i ) {
+    if ( $@ =~ /doesn't match (application schema|running jifty) version/i) {
         # We found an out-of-date DB.  Upgrade it
         $self->{setup_tables} = 1;
     } elsif ( $@ =~ /no version in the database/i ) {
@@ -179,13 +180,14 @@
 sub create_all_tables {
     my $self = shift;
 
-    my $schema = Jifty::Model::Schema->new;
     my $log    = Log::Log4perl->get_logger("SchemaTool");
     $log->info(
         "Generating SQL for application $self->{'_application_class'}...");
 
     my $appv
         = version->new( Jifty->config->framework('Database')->{'Version'} );
+    my $jiftyv
+        = version->new( $Jifty::VERSION || '0.60426' );
 
     for my $model ( __PACKAGE__->models ) {
 
@@ -196,9 +198,9 @@
        #   This *will* try to generate SQL for abstract base classes you might
        #   stick in $AC::Model::.
         next unless $model->isa( 'Jifty::Record' );
-        do { log->info("Skipping $model"); next }
+        do { $log->info("Skipping $model"); next }
             if ( $model->can( 'since' )
-            and $appv < $model->since );
+            and ($model =~ /^Jifty::Model::/ ? $jiftyv : $appv) < $model->since );
 
         $log->info("Using $model");
         my $ret = $self->{'_schema_generator'}->add_model( $model->new );
@@ -219,8 +221,9 @@
             $ret or die "error creating a table: " . $ret->error_message;
         }
 
-        # Update the version in the database
-        $schema->update($appv);
+        # Update the versions in the database
+        Jifty::Model::Metadata->store( application_db_version => $appv);
+        Jifty::Model::Metadata->store( jifty_db_version => $jiftyv);
 
         # Load initial data
         eval {
@@ -235,52 +238,79 @@
         # Commit it all
         Jifty->handle->commit;
     }
-    $log->info("Set up version $appv");
+    $log->info("Set up version $appv, jifty version $jiftyv");
 }
 
 
-=head2 upgrade_tables 
+=head2 upgrade_jifty_tables
 
-Upgrade your app's tables to match your current model.
+Upgrade Jifty's internal tables.
+
+=cut
+
+sub upgrade_jifty_tables {
+    my $self = shift;
+    my $dbv  = version->new( Jifty::Model::Metadata->load( 'jifty_db_version' ) || '0.60426' );
+    my $appv = version->new( $Jifty::VERSION );
+
+    $self->upgrade_tables( "Jifty" => $dbv, $appv, "Jifty::Upgrade::Internal" );
+    Jifty::Model::Metadata->store( jifty_db_version => $appv );
+}
+
+=head2 upgrade_appliction_tables
+
+Upgrade the application's tables.
+
+=cut
+
+sub upgrade_appliction_tables {
+    my $self = shift;
+    my $dbv = version->new( Jifty::Model::Metadata->load( 'application_db_version' ) );
+    my $appv
+        = version->new( Jifty->config->framework('Database')->{'Version'} );
+
+    $self->upgrade_tables( $self->{_application_class} => $dbv, $appv );
+    Jifty::Model::Metadata->store( application_db_version => $appv );
+}
+
+=head2 upgrade_tables BASECLASS, FROM, TO, [UPGRADECLASS]
+
+Given a C<BASECLASS> to upgrade, and two L<version> objects, C<FROM>
+and C<TO>, performs the needed transforms to the database.
+C<UPGRADECLASS>, if not specified, defaults to C<BASECLASS>::Upgrade
 
 =cut
 
 sub upgrade_tables {
     my $self = shift;
+    my ($baseclass, $dbv, $appv, $upgradeclass ) = @_;
+    $upgradeclass ||= $baseclass."::Upgrade";
 
-    my $schema = Jifty::Model::Schema->new;
     my $log    = Log::Log4perl->get_logger("SchemaTool");
     # Find current versions
-    my $dbv = $schema->in_db;
-    my $appv
-        = version->new( Jifty->config->framework('Database')->{'Version'} );
 
     if ( $appv < $dbv ) {
-        print "Version $appv from module older than $dbv in database!\n";
-        exit;
+        print "$baseclass version $appv from module older than $dbv in database!\n";
+        return;
     } elsif ( $appv == $dbv ) {
-
         # Shouldn't happen
-        print "Version $appv up to date.\n";
-        exit;
+        print "$baseclass version $appv up to date.\n";
+        return;
     }
     $log->info(
-        "Gerating SQL to update $self->{'_application_class'} $dbv database to $appv"
+        "Gerating SQL to upgrade $baseclass $dbv database to $appv"
     );
 
-    my %UPGRADES;
-
     # Figure out what versions the upgrade knows about.
+    my %UPGRADES;
     eval {
-        my $upgrader = $self->{'_application_class'} . "::Upgrade";
-        Jifty::Util->require($upgrader);
-
-        $UPGRADES{$_} = [ $upgrader->upgrade_to($_) ]
+        Jifty::Util->require($upgradeclass);
+        $UPGRADES{$_} = [ $upgradeclass->upgrade_to($_) ]
             for grep { $appv >= version->new($_) and $dbv < version->new($_) }
-            $upgrader->versions();
+            $upgradeclass->versions();
     };
 
-    for my $model ( __PACKAGE__->models ) {
+    for my $model ( grep {/^\Q$baseclass\E::Model::/} __PACKAGE__->models ) {
 
         # We don't want to get the Collections, for example.
         do {next} unless $model->isa( 'Jifty::Record' );
@@ -372,7 +402,6 @@
                 }
             }
         }
-        $schema->update($appv);
         $log->info("Upgraded to version $appv");
         Jifty->handle->commit;
     }

Modified: jifty/trunk/lib/Jifty/Upgrade.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Upgrade.pm	(original)
+++ jifty/trunk/lib/Jifty/Upgrade.pm	Fri Apr 28 15:49:53 2006
@@ -28,13 +28,14 @@
 
 =cut
 
-sub since { 
-  my ($version, $sub) = @_;
-  if (exists $UPGRADES{$version}) {
-    $UPGRADES{$version} = sub { $UPGRADES{$version}->(); $sub->(); }
-  } else {
-    $UPGRADES{$version} = $sub;
-  }
+sub since {
+    my ($version, $sub) = @_;
+    my $package = (caller)[0];
+    if (exists $UPGRADES{$package}{$version}) {
+        $UPGRADES{$package}{$version} = sub { $UPGRADES{$package}{$version}->(); $sub->(); }
+    } else {
+        $UPGRADES{$package}{$version} = $sub;
+    }
 }
 
 =head2 versions
@@ -46,7 +47,8 @@
 =cut
 
 sub versions {
-  return sort keys %UPGRADES;
+    my $class = shift;
+    return sort keys %{$UPGRADES{$class} || {}};
 }
 
 =head2 upgrade_to I<VERSION>
@@ -57,9 +59,9 @@
 =cut
 
 sub upgrade_to {
-  my $self = shift;
+  my $class = shift;
   my $version = shift;
-  return $UPGRADES{$version} || sub {};
+  return $UPGRADES{$class}{$version} || sub {};
 }
 
 1;

Added: jifty/trunk/lib/Jifty/Upgrade/Internal.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/lib/Jifty/Upgrade/Internal.pm	Fri Apr 28 15:49:53 2006
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+package Jifty::Upgrade::Internal;
+use Jifty::Upgrade;
+use base qw/Jifty::Upgrade/;
+use Jifty::Model::Metadata;
+
+=head2 Version 0.60427
+
+Version metadata, previously stored in _db_version, get migrated to
+_jifty_metadata, so it could be used to store more than one row
+usefully.
+
+=cut
+
+since '0.60427' => sub {
+    my @v = Jifty->handle->fetch_result("SELECT major, minor, rev FROM _db_version");
+    Jifty->handle->simple_query("DROP TABLE _db_version");
+    Jifty::Model::Metadata->store( application_db_version => version->new(join'.', at v));
+};
+
+1;


More information about the Jifty-commit mailing list