? includes/table.inc Index: commands/sql/sync.sql.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/drush/commands/sql/sync.sql.inc,v retrieving revision 1.33 diff -u -p -r1.33 sync.sql.inc --- commands/sql/sync.sql.inc 8 Nov 2010 04:48:47 -0000 1.33 +++ commands/sql/sync.sql.inc 9 Nov 2010 06:43:45 -0000 @@ -135,22 +135,22 @@ function drush_sql_sync($source = NULL, drush_sitealias_set_alias_context($destination_settings, 'target-'); // Get the options for the source and target databases - $source_db_url = _drush_sql_get_spec_from_options('source-', FALSE); + $source_db_spec = _drush_sql_get_spec_from_options('source-', FALSE); // The host may have special ssh requirements $source_remote_ssh_options = drush_get_option('source-ssh-options'); // rsync later will also have to know this option $source_rsync_options = array('ssh-options' => $source_remote_ssh_options); - $target_db_url = _drush_sql_get_spec_from_options('target-', FALSE); + $target_db_spec = _drush_sql_get_spec_from_options('target-', FALSE); // The host may have special ssh requirements $target_remote_ssh_options = drush_get_option('target-ssh-options'); // rsync later will also have to know this option $target_rsync_options = array('ssh-options' => $target_remote_ssh_options); - if (empty($source_db_url)) { + if (empty($source_db_spec)) { return drush_set_error('DRUSH_DATABASE_NOT_FOUND', dt('Error: no database record could be found for !source', array('!source' => $source))); } - if (empty($target_db_url)) { + if (empty($target_db_spec)) { return drush_set_error('DRUSH_DATABASE_NOT_FOUND', dt('Error: no database record could be found for !destination', array('!destination' => $destination))); } @@ -158,18 +158,18 @@ function drush_sql_sync($source = NULL, // If the result file is not set, then create a temporary file. // If the remote file is not set, use the same name for the remote // and local files and hope for the best. - $source_dump = drush_sql_dump_file($source_db_url, 'source-'); - $target_dump = drush_sql_dump_file($target_db_url, 'target-'); + $source_dump = drush_sql_dump_file($source_db_spec, 'source-'); + $target_dump = drush_sql_dump_file($target_db_spec, 'target-'); $use_temp_files = drush_get_option('temp'); // Only use one dump file if both the source and the target are on the local machine - if (!isset($source_db_url['remote-host']) && !isset($target_db_url['remote-host'])) { - if ((!$target_db_url['dump-is-temp']) && ($source_db_url['dump-is-temp'])) { + if (!isset($source_db_spec['remote-host']) && !isset($target_db_spec['remote-host'])) { + if ((!$target_db_spec['dump-is-temp']) && ($source_db_spec['dump-is-temp'])) { $source_dump = $target_dump; - $source_db_url['dump-is-temp'] = FALSE; + $source_db_spec['dump-is-temp'] = FALSE; } else { $target_dump = $source_dump; - $target_db_url['dump-is-temp'] = $source_db_url['dump-is-temp']; + $target_db_spec['dump-is-temp'] = $source_db_spec['dump-is-temp']; } $local_file = $source_dump; } @@ -177,19 +177,19 @@ function drush_sql_sync($source = NULL, // If one of the systems is remote, then set the --remove-source-files // rsync option if the source dump file is temporary. This will get // rsync to clean up after us automatically; useful if the source is remote. - if ($source_db_url['dump-is-temp']) { + if ($source_db_spec['dump-is-temp']) { $source_rsync_options['remove-source-files'] = TRUE; } // Set $local_file to whichever side of the operation is local, or make // a temporary file if both source and target are remote. - if (!isset($source_db_url['remote-host'])) { + if (!isset($source_db_spec['remote-host'])) { $local_file = $source_dump; } - elseif (!isset($target_db_url['remote-host'])) { + elseif (!isset($target_db_spec['remote-host'])) { $local_file = $target_dump; } else { - $local_file = drush_tempnam($source_db_url['database'] . ($source_db_url['database'] == $target_db_url['database'] ? '' : '-to-' . $target_db_url['database']) . '.sql.'); + $local_file = drush_tempnam($source_db_spec['database'] . ($source_db_spec['database'] == $target_db_spec['database'] ? '' : '-to-' . $target_db_spec['database']) . '.sql.'); } } @@ -238,7 +238,7 @@ function drush_sql_sync($source = NULL, if (!drush_get_context('DRUSH_SIMULATE')) { // Check to see if we are using a temporary file in a situation // where the user did not specify "--temp". - if (($source_db_url['dump-is-temp'] || $target_db_url['dump-is-temp']) && (!isset($use_temp_files)) && (isset($source_db_url['remote-host']) || isset($target_db_url['remote-host']))) { + if (($source_db_spec['dump-is-temp'] || $target_db_spec['dump-is-temp']) && (!isset($use_temp_files)) && (isset($source_db_spec['remote-host']) || isset($target_db_spec['remote-host']))) { drush_print(dt('WARNING: Using temporary files to store and transfer sql-dump. It is recommended that you specify --source-dump and --target-dump options on the command line, or set \'%dump\' in the path-aliases section of your site alias records. This facilitates fast file transfer via rsync.')); } @@ -266,8 +266,8 @@ function drush_sql_sync($source = NULL, } else { drush_print(); - $txt_source = (isset($source_db_url['remote-host']) ? $source_db_url['remote-host'] . '/' : '') . $source_db_url['database']; - $txt_destination = (isset($target_db_url['remote-host']) ? $target_db_url['remote-host'] . '/' : '') . $target_db_url['database']; + $txt_source = (isset($source_db_spec['remote-host']) ? $source_db_spec['remote-host'] . '/' : '') . $source_db_spec['database']; + $txt_destination = (isset($target_db_spec['remote-host']) ? $target_db_spec['remote-host'] . '/' : '') . $target_db_spec['database']; drush_print(dt("You will destroy data from !target and replace with data from !source.", array('!source' => $txt_source, '!target' => $txt_destination))); } @@ -294,7 +294,7 @@ function drush_sql_sync($source = NULL, } } - if (isset($source_db_url['remote-host'])) { + if (isset($source_db_spec['remote-host'])) { $source_remote_user = drush_get_option('source-remote-user'); if (isset($source_remote_user)) { $source_at ='@'; @@ -308,24 +308,24 @@ function drush_sql_sync($source = NULL, // then first dump to a temporary file and move it to the specified file after // the dump is complete. This will reduce contention during simultaneous dumps // from different users sharing the same dump file. - if (!$source_db_url['dump-is-temp']) { + if (!$source_db_spec['dump-is-temp']) { $source_intermediate = $source_dump . '-' . date("U"); $mv_intermediate = '; mv -f ' . $source_intermediate . ' ' . $source_dump; } drush_set_option('result-file', $source_intermediate); - $dump_exec = drush_sql_build_dump_command($table_selection, $source_db_url) . $mv_intermediate; - if (isset($cache) && !$source_db_url['dump-is-temp']) { + $dump_exec = drush_sql_build_dump_command($table_selection, $source_db_spec) . $mv_intermediate; + if (isset($cache) && !$source_db_spec['dump-is-temp']) { // Inject some bash commands to remotely test the modification date of the target file // if the cache option is set. $dump_exec = 'if [ ! -s ' . $source_dump . ' ] || [ $((`date "+%s"`-`stat --format="%Y" ' . $source_dump . '`)) -gt ' . ($cache * 60 * 60) . ' ] ; then ' . $dump_exec . '; fi'; } - $dump_exec = "ssh $source_remote_ssh_options $source_remote_user$source_at" . $source_db_url['remote-host'] . " " . escapeshellarg($dump_exec); + $dump_exec = "ssh $source_remote_ssh_options $source_remote_user$source_at" . $source_db_spec['remote-host'] . " " . escapeshellarg($dump_exec); } } else { if (!isset($no_dump)) { drush_set_option('result-file', $local_file); - $dump_exec = drush_sql_build_dump_command($table_selection, $source_db_url); + $dump_exec = drush_sql_build_dump_command($table_selection, $source_db_spec); } $no_sync = TRUE; } @@ -340,7 +340,7 @@ function drush_sql_sync($source = NULL, if (!isset($no_sync)) { // If the source file is a temporary file, then we will have rsync // delete it for us (remove-source-files option set above). - drush_core_call_rsync($source_remote_user . $source_at . $source_db_url['remote-host'] . ':' . $source_dump, $local_file, $source_rsync_options); + drush_core_call_rsync($source_remote_user . $source_at . $source_db_spec['remote-host'] . ':' . $source_dump, $local_file, $source_rsync_options); } // We will handle lists of destination sites differently from @@ -359,6 +359,17 @@ function drush_sql_sync($source = NULL, } } else { + // Compose a db connect command that we will use to import our db with + $db_connect = _drush_sql_connect($target_db_spec); + switch (_drush_sql_get_scheme($target_db_spec)) { + case 'mysql': + $db_connect .= ' --silent'; + break; + case 'pgsql': + $db_connect .= ' -q'; + break; + } + // Prior to database import, we will generate a "create database" command // if the '--create-db' option was specified. Note that typically the // web server user will not have permissions to create a database; to specify @@ -367,60 +378,70 @@ function drush_sql_sync($source = NULL, // Under postgres, "alter role username with createdb;" will give create database // permissions to the specified user if said user was not created with this right. $pre_import_commands = ''; - $create_db = drush_get_option('create-db'); - if (isset($create_db)) { - $create_db_target = $target_db_url; - $create_db_target['database'] = ''; + $create_db = drush_get_option('create-db', FALSE); + $drop_tables = drush_get_option('drop', FALSE); + if ($create_db | $drop_tables) { + $su_db_target_spec = $target_db_spec; + $su_db_target_spec['database'] = ''; $db_superuser = drush_get_option(array('db-su', 'target-db-su')); if (isset($db_superuser)) { - $create_db_target['username'] = $db_superuser; + $su_db_target_spec['username'] = $db_superuser; } $db_su_pw = drush_get_option(array('db-su-pw', 'target-db-su-pw')); if (isset($db_su_pw)) { - $create_db_target['password'] = $db_su_pw; - } - $db_su_connect = _drush_sql_connect($create_db_target); - switch (_drush_sql_get_scheme($target_db_url)) { - case 'mysql': - $pre_import_commands = 'echo "DROP DATABASE IF EXISTS ' . $target_db_url['database'] . '; CREATE DATABASE ' . $target_db_url['database'] . '; GRANT ALL PRIVILEGES ON ' . $target_db_url['database'] . '.* TO \'' . $target_db_url['username'] . '\'@\'' . $target_db_url['host'] . '\' IDENTIFIED BY \'' . $target_db_url['password'] . '\';" | ' . $db_su_connect . '; '; - break; - case 'pgsql': - $pre_import_commands = 'echo "drop database if exists ' . $target_db_url['database'] . '; create database ' . $target_db_url['database'] . ';" | ' . $db_su_connect . '; '; - break; + $su_db_target_spec['password'] = $db_su_pw; } - } + $db_su_connect = _drush_sql_connect($su_db_target_spec); - // Generate the import command - $import_command = _drush_sql_connect($target_db_url); - switch (_drush_sql_get_scheme($target_db_url)) { - case 'mysql': - $import_command .= ' --silent'; - break; - case 'pgsql': - $import_command .= ' -q'; - break; + if ($create_db) { + switch (_drush_sql_get_scheme($target_db_spec)) { + case 'mysql': + $pre_import_commands = 'echo "DROP DATABASE IF EXISTS ' . $target_db_spec['database'] . '; CREATE DATABASE ' . $target_db_spec['database'] . '; GRANT ALL PRIVILEGES ON ' . $target_db_spec['database'] . '.* TO \'' . $target_db_spec['username'] . '\'@\'' . $target_db_spec['host'] . '\' IDENTIFIED BY \'' . $target_db_spec['password'] . '\';" | ' . $db_su_connect . '; '; + break; + case 'pgsql': + $pre_import_commands = 'echo "drop database if exists ' . $target_db_spec['database'] . '; create database ' . $target_db_spec['database'] . ';" | ' . $db_su_connect . '; '; + break; + } + } + elseif ($drop_tables) { + switch (_drush_sql_get_scheme($target_db_spec)) { + case 'mysql': + // mysqldump -u[USERNAME] -p[PASSWORD] --add-drop-table --no-data [DATABASE] | grep ^DROP | mysql -u[USERNAME] -p[PASSWORD] [DATABASE] + $pre_import_commands = 'mysqldump ' . str_replace('--database=', ' ', _drush_sql_get_credentials($target_db_spec)) . ' --add-drop-table --no-data | grep -i "^DROP" | ' . $db_connect . '; '; + break; + case 'pgsql': + // To clean the postgres database, we need all of the DROP commands, and also + // all of the ALTER TABLE commands that contain a DROP. + // Using ' | sed -e \'/^CREATE/,$ d\' | ' would be a little safer, since by + // definition all of the commands relating to --clean are emitted before the + // first object is created; however, we use grep instead to avoid a dependency + // on 'sed'. + $pre_import_commands = 'pg_dump ' . str_replace('--dbname=', ' ', _drush_sql_get_credentials($target_db_spec)) . ' --clean --schema-only | grep -i \'^\(DROP\|ALTER TABLE.*DROP\)\' | ' . $db_connect . '; '; + break; + } + } } // If destination is remote, then use rsync to push the database, then use ssh to import the database // If destination is local, then just import the database locally - if (isset($target_db_url['remote-host'])) { + if (isset($target_db_spec['remote-host'])) { $target_remote_user = drush_get_option('target-remote-user'); if (isset($target_remote_user)) { $target_at ='@'; $target_remote_pass = drush_get_option('target-remote-pass') ? ':' . drush_get_option('target-remote-pass') : ''; } - drush_core_call_rsync($local_file, $target_remote_user . $target_at . $target_db_url['remote-host'] . ':' . $target_dump, $target_rsync_options); + drush_core_call_rsync($local_file, $target_remote_user . $target_at . $target_db_spec['remote-host'] . ':' . $target_dump, $target_rsync_options); - $connect_exec = $pre_import_commands . $import_command . ' < ' . $target_dump; - $import_exec = "ssh $target_remote_ssh_options $target_remote_user$target_at" . $target_db_url['remote-host'] . ' ' . escapeshellarg($connect_exec); + $connect_exec = $pre_import_commands . $db_connect . ' < ' . $target_dump; + $import_exec = "ssh $target_remote_ssh_options $target_remote_user$target_at" . $target_db_spec['remote-host'] . ' ' . escapeshellarg($connect_exec); // delete the remote target file if it is a temporary file - if ($target_db_url['dump-is-temp']) { + if ($target_db_spec['dump-is-temp']) { $import_exec .= '; rm -f ' . escapeshellarg($target_dump); } } else { - $import_exec = $pre_import_commands . $import_command . ' < ' . $local_file; + $import_exec = $pre_import_commands . $db_connect . ' < ' . $local_file; } drush_op('system', $import_exec);