|
25 | 25 |
|
26 | 26 | define('SCHEMA_VERSION_TABLE_NAME', 'schema_version');
|
27 | 27 |
|
28 |
| -if (isset($argv[1]) && !is_numeric($argv[1])) { |
29 |
| - print |
30 |
| - "USAGE: ./update_schema.php [first_patch_version]\n\n". |
31 |
| - "run './update_schema.php 12' to apply all patches starting from ". |
32 |
| - "version 12.\n". |
33 |
| - "run './update_schema.php' to apply all patches that are new since\n". |
34 |
| - "the last time this script was run\n\n"; |
35 |
| - exit(0); |
| 28 | +$options = getopt('v:u:p:') + array( |
| 29 | + 'v' => null, |
| 30 | + 'u' => null, |
| 31 | + 'p' => null, |
| 32 | +); |
| 33 | + |
| 34 | +if ($options['v'] && !is_numeric($options['v'])) { |
| 35 | + usage(); |
36 | 36 | }
|
37 | 37 |
|
38 | 38 | echo phutil_console_wrap(
|
|
45 | 45 | }
|
46 | 46 |
|
47 | 47 | // Use always the version from the commandline if it is defined
|
48 |
| -$next_version = isset($argv[1]) ? (int)$argv[1] : null; |
49 |
| - |
50 |
| -// Dummy class needed for creating our database |
51 |
| -class DummyUser extends PhabricatorLiskDAO { |
52 |
| - public function getApplicationName() { |
53 |
| - return 'user'; |
54 |
| - } |
| 48 | +$next_version = isset($options['v']) ? (int)$options['v'] : null; |
| 49 | + |
| 50 | +if ($options['u']) { |
| 51 | + $conn_user = $options['u']; |
| 52 | + $conn_pass = $options['p']; |
| 53 | +} else { |
| 54 | + $conn_user = PhabricatorEnv::getEnvConfig('mysql.user'); |
| 55 | + $conn_pass = PhabricatorEnv::getEnvConfig('mysql.pass'); |
55 | 56 | }
|
| 57 | +$conn_host = PhabricatorEnv::getEnvConfig('mysql.host'); |
56 | 58 |
|
57 |
| -// Class needed for setting up the actual SQL connection |
58 |
| -class PhabricatorSchemaVersion extends PhabricatorLiskDAO { |
59 |
| - public function getApplicationName() { |
60 |
| - return 'meta_data'; |
61 |
| - } |
62 |
| -} |
| 59 | +$conn = new AphrontMySQLDatabaseConnection( |
| 60 | + array( |
| 61 | + 'user' => $conn_user, |
| 62 | + 'pass' => $conn_pass, |
| 63 | + 'host' => $conn_host, |
| 64 | + 'database' => null, |
| 65 | + )); |
| 66 | + |
| 67 | +try { |
63 | 68 |
|
64 |
| -// Connect to 'phabricator_user' db first to create our db |
65 |
| -$conn = id(new DummyUser())->establishConnection('w'); |
66 |
| -$create_sql = <<<END |
67 |
| -CREATE DATABASE IF NOT EXISTS `phabricator_meta_data`; |
| 69 | + $create_sql = <<<END |
| 70 | + CREATE DATABASE IF NOT EXISTS `phabricator_meta_data`; |
68 | 71 | END;
|
69 |
| -queryfx($conn, $create_sql); |
| 72 | + queryfx($conn, $create_sql); |
70 | 73 |
|
71 |
| -// 'phabricator_meta_data' database exists, let's connect to it now |
72 |
| -$conn = id(new PhabricatorSchemaVersion())->establishConnection('w'); |
73 |
| -$create_sql = <<<END |
74 |
| -CREATE TABLE IF NOT EXISTS phabricator_meta_data.`schema_version` ( |
75 |
| - `version` INTEGER not null |
76 |
| -); |
| 74 | + $create_sql = <<<END |
| 75 | + CREATE TABLE IF NOT EXISTS phabricator_meta_data.`schema_version` ( |
| 76 | + `version` INTEGER not null |
| 77 | + ); |
77 | 78 | END;
|
78 |
| -queryfx($conn, $create_sql); |
79 |
| - |
80 |
| -// Get the version only if commandline argument wasn't given |
81 |
| -if ($next_version === null) { |
82 |
| - $version = queryfx_one( |
83 |
| - $conn, |
84 |
| - 'SELECT * FROM %T', |
85 |
| - SCHEMA_VERSION_TABLE_NAME); |
86 |
| - |
87 |
| - if (!$version) { |
88 |
| - print "*** No version information in the database ***\n"; |
89 |
| - print "*** Give the first patch version which to ***\n"; |
90 |
| - print "*** apply as the command line argument ***\n"; |
91 |
| - exit(-1); |
| 79 | + queryfx($conn, $create_sql); |
| 80 | + |
| 81 | + // Get the version only if commandline argument wasn't given |
| 82 | + if ($next_version === null) { |
| 83 | + $version = queryfx_one( |
| 84 | + $conn, |
| 85 | + 'SELECT * FROM phabricator_meta_data.%T', |
| 86 | + SCHEMA_VERSION_TABLE_NAME); |
| 87 | + |
| 88 | + if (!$version) { |
| 89 | + print "*** No version information in the database ***\n"; |
| 90 | + print "*** Give the first patch version which to ***\n"; |
| 91 | + print "*** apply as the command line argument ***\n"; |
| 92 | + exit(-1); |
| 93 | + } |
| 94 | + |
| 95 | + $next_version = $version['version'] + 1; |
92 | 96 | }
|
93 | 97 |
|
94 |
| - $next_version = $version['version'] + 1; |
95 |
| -} |
96 |
| - |
97 |
| -// Find the patch files |
98 |
| -$patches_dir = $root.'/resources/sql/patches/'; |
99 |
| -$finder = id(new FileFinder($patches_dir)) |
100 |
| - ->withSuffix('sql'); |
101 |
| -$results = $finder->find(); |
102 |
| - |
103 |
| -$patches = array(); |
104 |
| -foreach ($results as $r) { |
105 |
| - $matches = array(); |
106 |
| - if (preg_match('/(\d+)\..*\.sql$/', $r, $matches)) { |
107 |
| - $patches[] = array('version' => (int)$matches[1], |
108 |
| - 'file' => $r); |
109 |
| - } else { |
110 |
| - print |
111 |
| - "*** WARNING : File {$r} does not follow the normal naming ". |
112 |
| - "convention. ***\n"; |
| 98 | + // Find the patch files |
| 99 | + $patches_dir = $root.'/resources/sql/patches/'; |
| 100 | + $finder = id(new FileFinder($patches_dir)) |
| 101 | + ->withSuffix('sql'); |
| 102 | + $results = $finder->find(); |
| 103 | + |
| 104 | + $patches = array(); |
| 105 | + foreach ($results as $r) { |
| 106 | + $matches = array(); |
| 107 | + if (preg_match('/(\d+)\..*\.sql$/', $r, $matches)) { |
| 108 | + $patches[] = array('version' => (int)$matches[1], |
| 109 | + 'file' => $r); |
| 110 | + } else { |
| 111 | + print |
| 112 | + "*** WARNING : File {$r} does not follow the normal naming ". |
| 113 | + "convention. ***\n"; |
| 114 | + } |
113 | 115 | }
|
114 |
| -} |
115 |
| - |
116 |
| -// Files are in some 'random' order returned by the operating system |
117 |
| -// We need to apply them in proper order |
118 |
| -$patches = isort($patches, 'version'); |
119 | 116 |
|
120 |
| -$patch_applied = false; |
121 |
| -foreach ($patches as $patch) { |
122 |
| - if ($patch['version'] < $next_version) { |
123 |
| - continue; |
| 117 | + // Files are in some 'random' order returned by the operating system |
| 118 | + // We need to apply them in proper order |
| 119 | + $patches = isort($patches, 'version'); |
| 120 | + |
| 121 | + $patch_applied = false; |
| 122 | + foreach ($patches as $patch) { |
| 123 | + if ($patch['version'] < $next_version) { |
| 124 | + continue; |
| 125 | + } |
| 126 | + |
| 127 | + print "Applying patch {$patch['file']}\n"; |
| 128 | + |
| 129 | + $path = Filesystem::resolvePath($patches_dir.$patch['file']); |
| 130 | + |
| 131 | + list($stdout, $stderr) = execx( |
| 132 | + "mysql --user=%s --password=%s --host=%s < %s", |
| 133 | + $conn_user, |
| 134 | + $conn_pass, |
| 135 | + $conn_host, |
| 136 | + $path); |
| 137 | + |
| 138 | + if ($stderr) { |
| 139 | + print $stderr; |
| 140 | + exit(-1); |
| 141 | + } |
| 142 | + |
| 143 | + // Patch was successful, update the db with the latest applied patch version |
| 144 | + // 'DELETE' and 'INSERT' instead of update, because the table might be empty |
| 145 | + queryfx( |
| 146 | + $conn, |
| 147 | + 'DELETE FROM phabricator_meta_data.%T', |
| 148 | + SCHEMA_VERSION_TABLE_NAME); |
| 149 | + queryfx( |
| 150 | + $conn, |
| 151 | + 'INSERT INTO phabricator_meta_data.%T VALUES (%d)', |
| 152 | + SCHEMA_VERSION_TABLE_NAME, |
| 153 | + $patch['version']); |
| 154 | + |
| 155 | + $patch_applied = true; |
124 | 156 | }
|
125 | 157 |
|
126 |
| - print "Applying patch {$patch['file']}\n"; |
127 |
| - |
128 |
| - $path = Filesystem::resolvePath($patches_dir.$patch['file']); |
129 |
| - |
130 |
| - $user = PhabricatorEnv::getEnvConfig('mysql.user'); |
131 |
| - $pass = PhabricatorEnv::getEnvConfig('mysql.pass'); |
132 |
| - $host = PhabricatorEnv::getEnvConfig('mysql.host'); |
133 |
| - |
134 |
| - list($stdout, $stderr) = execx( |
135 |
| - "mysql --user=%s --password=%s --host=%s < %s", |
136 |
| - $user, $pass, $host, $path); |
137 |
| - |
138 |
| - if ($stderr) { |
139 |
| - print $stderr; |
140 |
| - exit(-1); |
| 158 | + if (!$patch_applied) { |
| 159 | + print "Your database is already up-to-date.\n"; |
141 | 160 | }
|
142 | 161 |
|
143 |
| - // Patch was successful, update the db with the latest applied patch version |
144 |
| - // 'DELETE' and 'INSERT' instead of update, because the table might be empty |
145 |
| - queryfx($conn, 'DELETE FROM %T', SCHEMA_VERSION_TABLE_NAME); |
146 |
| - queryfx( |
147 |
| - $conn, |
148 |
| - 'INSERT INTO %T values (%d)', |
149 |
| - SCHEMA_VERSION_TABLE_NAME, |
150 |
| - $patch['version']); |
151 |
| - |
152 |
| - $patch_applied = true; |
| 162 | +} catch (AphrontQueryAccessDeniedException $ex) { |
| 163 | + echo |
| 164 | + "ACCESS DENIED\n". |
| 165 | + "The user '{$conn_user}' does not have sufficient MySQL privileges to\n". |
| 166 | + "execute the schema upgrade. Use the -u and -p flags to run as a user\n". |
| 167 | + "with more privileges (e.g., root).". |
| 168 | + "\n\n". |
| 169 | + "EXCEPTION:\n". |
| 170 | + $ex->getMessage(). |
| 171 | + "\n\n"; |
| 172 | + exit(1); |
153 | 173 | }
|
154 | 174 |
|
155 |
| -if (!$patch_applied) { |
156 |
| - print "Your database is already up-to-date.\n"; |
| 175 | +function usage() { |
| 176 | + echo |
| 177 | + "usage: upgrade_schema.php [-v version] [-u user -p pass]". |
| 178 | + "\n\n". |
| 179 | + "Run 'upgrade_schema.php -v 12' to apply all patches starting from ". |
| 180 | + "version 12.\n". |
| 181 | + "Run 'upgrade_schema.php -u root -p hunter2' to override the configured ". |
| 182 | + "default user.\n"; |
| 183 | + exit(1); |
157 | 184 | }
|
| 185 | + |
0 commit comments