From 924b135d310bdfc67be6cbe1dd2bf44b4a55b943 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 17 Mar 2015 18:29:01 -0700 Subject: [PATCH] Add a `storage renamespace` for mangling SQL dumpfiles into a new namespace Summary: Ref T7149. When users give us dumpfiles for import, they will almost inevitably use the `phabricator` namespace. They need to be renamed to use an instance namespace. We can do this either by: - importing the data first, then renaming; or - renaming first, then importing. This implements the second one, basically `storage renamespace --in dump.sql --from phabricator --to instancename > instance.sql`. Renaming first is a little hackier since we have to `preg_match()` a SQL dump file, but I think it's better overall: - With only one database, it lets you dump/import without downtime. - If you have development stuff in a development environment in the `phabricator` namespace, you don't have to move it aside to do an import. - No possibility that two people doing an import at the same time on the same box will collide with each other. - You can do the rename once and then repeat the import process with the renamed dump more easily. - No tricky stuff with modern Phabricator running against an old dump and the database names not matching up. None of this is super important, but it just makes large dumps a bit easier to work with, and the dumpfile format is regular enough that this seems unlikely to ever really not work. Test Plan: Renamespaced a dump, did a `diff -u`, saw all the relevant parts changed (and only those parts changed). Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7149 Differential Revision: https://secure.phabricator.com/D12105 --- src/__phutil_library_map__.php | 2 + ...orStorageManagementRenamespaceWorkflow.php | 94 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 97c19121e0..b1709eacbd 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2511,6 +2511,7 @@ phutil_register_library_map(array( 'PhabricatorStorageManagementDumpWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementDumpWorkflow.php', 'PhabricatorStorageManagementProbeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementProbeWorkflow.php', 'PhabricatorStorageManagementQuickstartWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementQuickstartWorkflow.php', + 'PhabricatorStorageManagementRenamespaceWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php', 'PhabricatorStorageManagementShellWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementShellWorkflow.php', 'PhabricatorStorageManagementStatusWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementStatusWorkflow.php', 'PhabricatorStorageManagementUpgradeWorkflow' => 'infrastructure/storage/management/workflow/PhabricatorStorageManagementUpgradeWorkflow.php', @@ -5870,6 +5871,7 @@ phutil_register_library_map(array( 'PhabricatorStorageManagementDumpWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementProbeWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementQuickstartWorkflow' => 'PhabricatorStorageManagementWorkflow', + 'PhabricatorStorageManagementRenamespaceWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementShellWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementStatusWorkflow' => 'PhabricatorStorageManagementWorkflow', 'PhabricatorStorageManagementUpgradeWorkflow' => 'PhabricatorStorageManagementWorkflow', diff --git a/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php new file mode 100644 index 0000000000..9de4499b23 --- /dev/null +++ b/src/infrastructure/storage/management/workflow/PhabricatorStorageManagementRenamespaceWorkflow.php @@ -0,0 +1,94 @@ +setName('renamespace') + ->setExamples( + '**renamespace** [__options__] '. + '--in __dump.sql__ --from __old__ --to __new__ > __out.sql__') + ->setSynopsis(pht('Change the database namespace of a .sql dump file.')) + ->setArguments( + array( + array( + 'name' => 'in', + 'param' => 'file', + 'help' => pht('SQL dumpfile to process.'), + ), + array( + 'name' => 'from', + 'param' => 'namespace', + 'help' => pht('Current database namespace used by dumpfile.'), + ), + array( + 'name' => 'to', + 'param' => 'namespace', + 'help' => pht('Desired database namespace for output.'), + ), + )); + } + + public function execute(PhutilArgumentParser $args) { + $console = PhutilConsole::getConsole(); + + $in = $args->getArg('in'); + if (!strlen($in)) { + throw new PhutilArgumentUsageException( + pht('Specify the dumpfile to read with --in.')); + } + + $from = $args->getArg('from'); + if (!strlen($from)) { + throw new PhutilArgumentUsageException( + pht('Specify namespace to rename from with --from.')); + } + + $to = $args->getArg('to'); + if (!strlen($to)) { + throw new PhutilArgumentUsageException( + pht('Specify namespace to rename to with --to.')); + } + + $patterns = array( + 'use' => '@^(USE `)([^_]+)(_.*)$@', + 'create' => '@^(CREATE DATABASE /\*.*?\*/ `)([^_]+)(_.*)$@', + ); + + $found = array_fill_keys(array_keys($patterns), 0); + + $matches = null; + foreach (new LinesOfALargeFile($in) as $line) { + + foreach ($patterns as $key => $pattern) { + if (preg_match($pattern, $line, $matches)) { + $namespace = $matches[2]; + if ($namespace != $from) { + throw new Exception( + pht( + 'Expected namespace "%s", found "%s": %s.', + $from, + $namespace, + $line)); + } + + $line = $matches[1].$to.$matches[3]; + $found[$key]++; + } + } + + echo $line."\n"; + } + + // Give the user a chance to catch things if the results are crazy. + $console->writeErr( + pht( + 'Adjusted **%s** create statements and **%s** use statements.', + new PhutilNumber($found['create']), + new PhutilNumber($found['use']))."\n"); + + return 0; + } + +}