Loading lib/Travelynx/Command/database.pm +62 −59 Original line number Diff line number Diff line Loading @@ -8,35 +8,22 @@ has description => 'Initialize or upgrade database layout'; has usage => sub { shift->extract_usage }; sub get_schema_version { my ($dbh) = @_; # We do not want DBD to print an SQL error if schema_version does not # exist, as this is not an error in this case. Setting $dbh->{PrintError} = # 0 would disable error printing for all subsequent SQL operations, however, # we only want to disable it for this specific query. Hence we use a # prepared statement and only disable error printing only there. my $sth = $dbh->prepare(qq{select version from schema_version}); $sth->{PrintError} = 0; my $success = $sth->execute; if ( not defined $success ) { my ($db) = @_; my $version; eval { $version = $db->select( 'schema_version', ['version'] )->hash->{version}; }; if ($@) { # If it failed, the version table does not exist -> run setup first. return undef; } my $rows = $sth->fetchall_arrayref; if ( @{$rows} == 1 ) { return $rows->[0][0]; } else { printf( "Found multiple schema versions: %s", @{$rows} ); exit(1); } return $version; } sub initialize_db { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ create table schema_version ( version integer primary key Loading Loading @@ -93,8 +80,8 @@ my @migrations = ( # v0 -> v1 sub { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ alter table user_actions add column edited smallint; Loading @@ -113,8 +100,8 @@ my @migrations = ( # v1 -> v2 sub { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ update user_actions set edited = 0; alter table user_actions Loading @@ -129,8 +116,8 @@ my @migrations = ( # reported for routes covering stations without GPS coordinates. Ensure # all caches are rebuilt. sub { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ truncate journey_stats; update schema_version set version = 3; Loading @@ -140,57 +127,73 @@ my @migrations = ( ); sub setup_db { my ($dbh) = @_; $dbh->begin_work; if ( initialize_db($dbh) ) { $dbh->commit; } else { $dbh->rollback; printf( "Database initialization was not successful: %s", $DBI::errstr ); my ($db) = @_; my $tx = $db->begin; eval { initialize_db($db); $tx->commit; }; if ($@) { say "Database initialization failed: $@"; exit(1); } } sub migrate_db { my ($dbh) = @_; $dbh->begin_work; my $schema_version = get_schema_version($dbh); my ($db) = @_; my $tx = $db->begin; my $schema_version = get_schema_version($db); say "Found travelynx schema v${schema_version}"; if ( $schema_version == @migrations ) { say "Database layout is up-to-date"; } eval { for my $i ( $schema_version .. $#migrations ) { printf( "Updating to v%d ...\n", $i + 1 ); if ( not $migrations[$i]($dbh) ) { say "Aborting migration; rollback to v${schema_version}"; $dbh->rollback; $migrations[$i]($db); } }; if ($@) { say STDERR "Migration failed: $@"; say STDERR "Rolling back to v${schema_version}"; exit(1); } if ( get_schema_version($db) == @migrations ) { $tx->commit; } if ( get_schema_version($dbh) == @migrations ) { $dbh->commit; else { printf STDERR ( "Database schema mismatch after migrations: Expected %d, got %d\n", scalar @migrations, get_schema_version($db) ); say STDERR "Rolling back to v${schema_version}"; exit(1); } } sub run { my ( $self, $command ) = @_; my $dbh = $self->app->dbh; my $db = $self->app->pg->db; if ( not defined $dbh ) { printf( "Can't connect to the database: %s\n", $DBI::errstr ); exit(1); } #if ( not defined $dbh ) { # printf( "Can't connect to the database: %s\n", $DBI::errstr ); # exit(1); #} if ( $command eq 'migrate' ) { if ( not defined get_schema_version($dbh) ) { setup_db($dbh); if ( not defined get_schema_version($db) ) { setup_db($db); } migrate_db($dbh); migrate_db($db); } elsif ( $command eq 'has-current-schema' ) { if ( get_schema_version($dbh) == @migrations ) { if ( get_schema_version($db) == @migrations ) { say "yes"; } else { Loading Loading
lib/Travelynx/Command/database.pm +62 −59 Original line number Diff line number Diff line Loading @@ -8,35 +8,22 @@ has description => 'Initialize or upgrade database layout'; has usage => sub { shift->extract_usage }; sub get_schema_version { my ($dbh) = @_; # We do not want DBD to print an SQL error if schema_version does not # exist, as this is not an error in this case. Setting $dbh->{PrintError} = # 0 would disable error printing for all subsequent SQL operations, however, # we only want to disable it for this specific query. Hence we use a # prepared statement and only disable error printing only there. my $sth = $dbh->prepare(qq{select version from schema_version}); $sth->{PrintError} = 0; my $success = $sth->execute; if ( not defined $success ) { my ($db) = @_; my $version; eval { $version = $db->select( 'schema_version', ['version'] )->hash->{version}; }; if ($@) { # If it failed, the version table does not exist -> run setup first. return undef; } my $rows = $sth->fetchall_arrayref; if ( @{$rows} == 1 ) { return $rows->[0][0]; } else { printf( "Found multiple schema versions: %s", @{$rows} ); exit(1); } return $version; } sub initialize_db { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ create table schema_version ( version integer primary key Loading Loading @@ -93,8 +80,8 @@ my @migrations = ( # v0 -> v1 sub { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ alter table user_actions add column edited smallint; Loading @@ -113,8 +100,8 @@ my @migrations = ( # v1 -> v2 sub { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ update user_actions set edited = 0; alter table user_actions Loading @@ -129,8 +116,8 @@ my @migrations = ( # reported for routes covering stations without GPS coordinates. Ensure # all caches are rebuilt. sub { my ($dbh) = @_; return $dbh->do( my ($db) = @_; $db->query( qq{ truncate journey_stats; update schema_version set version = 3; Loading @@ -140,57 +127,73 @@ my @migrations = ( ); sub setup_db { my ($dbh) = @_; $dbh->begin_work; if ( initialize_db($dbh) ) { $dbh->commit; } else { $dbh->rollback; printf( "Database initialization was not successful: %s", $DBI::errstr ); my ($db) = @_; my $tx = $db->begin; eval { initialize_db($db); $tx->commit; }; if ($@) { say "Database initialization failed: $@"; exit(1); } } sub migrate_db { my ($dbh) = @_; $dbh->begin_work; my $schema_version = get_schema_version($dbh); my ($db) = @_; my $tx = $db->begin; my $schema_version = get_schema_version($db); say "Found travelynx schema v${schema_version}"; if ( $schema_version == @migrations ) { say "Database layout is up-to-date"; } eval { for my $i ( $schema_version .. $#migrations ) { printf( "Updating to v%d ...\n", $i + 1 ); if ( not $migrations[$i]($dbh) ) { say "Aborting migration; rollback to v${schema_version}"; $dbh->rollback; $migrations[$i]($db); } }; if ($@) { say STDERR "Migration failed: $@"; say STDERR "Rolling back to v${schema_version}"; exit(1); } if ( get_schema_version($db) == @migrations ) { $tx->commit; } if ( get_schema_version($dbh) == @migrations ) { $dbh->commit; else { printf STDERR ( "Database schema mismatch after migrations: Expected %d, got %d\n", scalar @migrations, get_schema_version($db) ); say STDERR "Rolling back to v${schema_version}"; exit(1); } } sub run { my ( $self, $command ) = @_; my $dbh = $self->app->dbh; my $db = $self->app->pg->db; if ( not defined $dbh ) { printf( "Can't connect to the database: %s\n", $DBI::errstr ); exit(1); } #if ( not defined $dbh ) { # printf( "Can't connect to the database: %s\n", $DBI::errstr ); # exit(1); #} if ( $command eq 'migrate' ) { if ( not defined get_schema_version($dbh) ) { setup_db($dbh); if ( not defined get_schema_version($db) ) { setup_db($db); } migrate_db($dbh); migrate_db($db); } elsif ( $command eq 'has-current-schema' ) { if ( get_schema_version($dbh) == @migrations ) { if ( get_schema_version($db) == @migrations ) { say "yes"; } else { Loading