1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-19 16:58:48 +02:00

Schema upgrade script.

Summary:
Created a script the runs all the necessary patches for db schema.
Stores information in the db about the latest patch that was applied.

Test Plan:
Created two test files '024.test.sql' and '023.test.sql' in this order.
'023' creates a database and '024' creates a table in this db. First ran
'./upgrade_schema.php 23' and made sure that patches were applied in order.
Then ran './upgrade_schema.php' to make sure db was up-to-date. Checked
manually from the db that the database and table exists.

Reviewed By: epriestley
Reviewers: epriestley
CC: jungejason, epriestley, tuomaspelkonen
Differential Revision: 115
This commit is contained in:
tuomaspelkonen 2011-04-07 16:55:32 -07:00
parent 540c2ec3df
commit 4f6bac95e9

142
scripts/sql/upgrade_schema.php Executable file
View file

@ -0,0 +1,142 @@
#!/usr/bin/env php
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
require_once $root.'/scripts/__init_env__.php';
const TABLE_NAME = 'schema_version';
if (isset($argv[1]) && !is_numeric($argv[1])) {
print
"USAGE: ./update_schema.php [first_patch_version]\n\n".
"run './update_schema.php 12' to apply all patches starting from ".
"version 12.\n".
"run './update_schema.php' to apply all patches that are new since\n".
"the last time this script was run\n\n";
exit(0);
}
// Use always the version from the commandline if it is defined
$next_version = isset($argv[1]) ? (int)$argv[1] : null;
// Dummy class needed for creating our database
class DummyUser extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'user';
}
}
// Class needed for setting up the actual SQL connection
class PhabricatorSchemaVersion extends PhabricatorLiskDAO {
public function getApplicationName() {
return 'meta_data';
}
}
// Connect to 'phabricator_user' db first to create our db
$conn = id(new DummyUser())->establishConnection('w');
$create_sql = <<<END
CREATE DATABASE IF NOT EXISTS `phabricator_meta_data`;
END;
queryfx($conn, $create_sql);
// 'phabricator_meta_data' database exists, let's connect to it now
$conn = id(new PhabricatorSchemaVersion())->establishConnection('w');
$create_sql = <<<END
CREATE TABLE IF NOT EXISTS phabricator_meta_data.`schema_version` (
`version` INTEGER not null
);
END;
queryfx($conn, $create_sql);
// Get the version only if commandline argument wasn't given
if ($next_version === null) {
$version = queryfx_one(
$conn,
'SELECT * FROM %T',
TABLE_NAME);
if (!$version) {
print "*** No version information in the database ***\n";
print "*** Give the first patch version which to ***\n";
print "*** apply as the command line argument ***\n";
exit(-1);
}
$next_version = $version['version'] + 1;
}
// Find the patch files
$patches_dir = $root.'/resources/sql/patches/';
$finder = id(new FileFinder($patches_dir))
->withSuffix('sql');
$results = $finder->find();
$patches = array();
foreach ($results as $r) {
$matches = array();
if (preg_match('/(\d+)\..*\.sql$/', $r, $matches)) {
$patches[] = array('version' => (int)$matches[1],
'file' => $r);
} else {
print
"*** WARNING : File {$r} does not follow the normal naming ".
"convention. ***\n";
}
}
// Files are in some 'random' order returned by the operating system
// We need to apply them in proper order
$patches = isort($patches, 'version');
$patch_applied = false;
foreach ($patches as $patch) {
if ($patch['version'] < $next_version) {
continue;
}
print "Applying patch {$patch['file']}\n";
$path = Filesystem::resolvePath($patches_dir.$patch['file']);
$user = PhabricatorEnv::getEnvConfig('mysql.user');
$pass = PhabricatorEnv::getEnvConfig('mysql.pass');
$host = PhabricatorEnv::getEnvConfig('mysql.host');
list($stdout, $stderr) = execx(
"mysql --user=%s --password=%s --host=%s < %s",
$user, $pass, $host, $path);
if ($stderr) {
print $stderr;
exit(-1);
}
// Patch was successful, update the db with the latest applied patch version
// 'DELETE' and 'INSERT' instead of update, because the table might be empty
queryfx($conn, 'DELETE FROM %T', TABLE_NAME);
queryfx($conn, 'INSERT INTO %T values (%d)', TABLE_NAME, $patch['version']);
$patch_applied = true;
}
if (!$patch_applied) {
print "Your database is already up-to-date\n";
}