diff --git a/commands/sql/sql.drush.inc b/commands/sql/sql.drush.inc deleted file mode 100644 index 8811a329d0..0000000000 --- a/commands/sql/sql.drush.inc +++ /dev/null @@ -1,59 +0,0 @@ -get_db_spec()) { - return drush_sql_get_class($db_spec); - } - } - } - - throw new \Drush\Sql\SqlException('Unable to find a matching SQL Class. Drush cannot find your database connection details.'); -} - -/** - * Wrapper for drush_get_class; instantiates a Drupal version-specific instance - * of SqlVersion class. - * - * @return Drush\Sql\SqlVersion - */ -function drush_sql_get_version() { - return drush_get_class('Drush\Sql\Sql', array(), array(drush_drupal_major_version())) ?: NULL; -} diff --git a/includes/drush.inc b/includes/drush.inc index 3ac2c21107..aaf0a49d65 100644 --- a/includes/drush.inc +++ b/includes/drush.inc @@ -1413,7 +1413,7 @@ function drush_print_timers() { } /** - * Turn drupal_set_message errors into drush_log errors + * Turn drupal_set_message() errors into drush_log errors */ function _drush_log_drupal_messages() { if (function_exists('drupal_get_messages')) { diff --git a/includes/filesystem.inc b/includes/filesystem.inc index 14bf055c1c..72b644fda3 100644 --- a/includes/filesystem.inc +++ b/includes/filesystem.inc @@ -4,6 +4,7 @@ * @file * Filesystem utilities. */ +use Drush\Sql\SqlBase; use Webmozart\PathUtil\Path; /** @@ -576,8 +577,8 @@ function drush_preflight_backup_dir($subdir = NULL) { // Try to use db name as subdir if none was provided. if (empty($subdir)) { $subdir = 'unknown'; - if ($sql = drush_sql_get_class()) { - $db_spec = $sql->db_spec(); + if ($sql = SqlBase::create()) { + $db_spec = $sql->getDbSpec(); $subdir = $db_spec['database']; } } diff --git a/lib/Drush.php b/lib/Drush.php index c31df76265..97df329a7b 100644 --- a/lib/Drush.php +++ b/lib/Drush.php @@ -6,6 +6,7 @@ */ use League\Container\ContainerInterface; +use Psr\Log\LoggerInterface; use SebastianBergmann\Version; /** diff --git a/lib/Drush/Boot/DrupalBoot.php b/lib/Drush/Boot/DrupalBoot.php index fdc9016f4d..26086c4189 100644 --- a/lib/Drush/Boot/DrupalBoot.php +++ b/lib/Drush/Boot/DrupalBoot.php @@ -3,6 +3,7 @@ namespace Drush\Boot; use Drush\Log\LogLevel; +use Drush\Sql\SqlBase; use Psr\Log\LoggerInterface; use Drupal\user\Entity\User; @@ -476,17 +477,17 @@ function bootstrap_drupal_database_validate() { // Drupal requires PDO, and Drush requires php 5.6+ which ships with PDO // but PHP may be compiled with --disable-pdo. if (!class_exists('\PDO')) { - drush_log(dt('PDO support is required.'), LogLevel::BOOTSTRAP); + $this->logger->log(LogLevel::BOOTSTRAP, dt('PDO support is required.')); return FALSE; } try { - $sql = drush_sql_get_class(); + $sql = SqlBase::create(); if (!$sql->query('SELECT 1;')) { return drush_bootstrap_error('DRUSH_DRUPAL_DB_ERROR'); } } catch (\Exception $e) { - drush_log(dt('Unable to validate DB c: @e', array('@e' => $e->getMessage())), 'debug'); + $this->logger->log(LogLevel::DEBUG, dt('Unable to validate DB: @e', array('@e' => $e->getMessage()))); return FALSE; } return TRUE; @@ -518,8 +519,8 @@ function bootstrap_drupal_database_validate() { */ function bootstrap_drupal_database_has_table($required_tables) { try { - $sql = drush_sql_get_class(); - $spec = $sql->db_spec(); + $sql = SqlBase::create(); + $spec = $sql->getDbSpec(); $prefix = isset($spec['prefix']) ? $spec['prefix'] : NULL; if (!is_array($prefix)) { $prefix = array('default' => $prefix); diff --git a/lib/Drush/Commands/OptionsCommands.php b/lib/Drush/Commands/OptionsCommands.php index 0ddc2bca0e..daf544ed3f 100644 --- a/lib/Drush/Commands/OptionsCommands.php +++ b/lib/Drush/Commands/OptionsCommands.php @@ -33,7 +33,7 @@ public function optionsetSsh() {} * @option db-url A Drupal 6 style database URL. * @option target The name of a target within the specified database connection. Defaults to default */ - public function optionsetSql() {} + public function optionsetSql($options = ['database' => 'default', 'target' => 'default']) {} /** * @hook option @optionset_table_selection diff --git a/lib/Drush/Commands/core/SiteInstallCommands.php b/lib/Drush/Commands/core/SiteInstallCommands.php index ab97ad29ca..a5cd49c813 100644 --- a/lib/Drush/Commands/core/SiteInstallCommands.php +++ b/lib/Drush/Commands/core/SiteInstallCommands.php @@ -5,6 +5,7 @@ use Drush\Commands\DrushCommands; use Drush\Log\LogLevel; use Drupal\Core\Config\FileStorage; +use Drush\Sql\SqlBase; class SiteInstallCommands extends DrushCommands { @@ -62,8 +63,8 @@ public function install($profile, $additional = NULL, $options = ['db-url' => NU $class_loader = drush_drupal_load_autoloader(DRUPAL_ROOT); $profile = $this->determineProfile($profile, $options, $class_loader); - $sql = drush_sql_get_class(); - $db_spec = $sql->db_spec(); + $sql = SqlBase::create($options); + $db_spec = $sql->getDbSpec(); $account_pass = $options['account-pass'] ?: drush_generate_password(); $settings = array( @@ -190,8 +191,8 @@ public function validate(CommandData $commandData) { } } - $sql = drush_sql_get_class(); - if (!$sql->db_spec()) { + $sql = SqlBase::create($commandData->input()->getOptions()); + if (!$sql->getDbSpec()) { throw new \Exception(dt('Could not determine database connection parameters. Pass --db-url option.')); } } @@ -203,8 +204,8 @@ public function validate(CommandData $commandData) { * */ public function pre(CommandData $commandData) { - $sql = drush_sql_get_class(); - $db_spec = $sql->db_spec(); + $sql = SqlBase::create($commandData->input()->getOptions()); + $db_spec = $sql->getDbSpec(); // Make sure URI is set so we get back a proper $alias_record. Needed for quick-drupal. _drush_bootstrap_selected_uri(); @@ -227,7 +228,7 @@ public function pre(CommandData $commandData) { if ($sitesfile_write) { $msg[] = dt('create a @sitesfile file', array('@sitesfile' => $sitesfile)); } - if ($sql->db_exists()) { + if ($sql->dbExists()) { $msg[] = dt("DROP all tables in your '@db' database.", array('@db' => $db_spec['database'])); } else { @@ -266,7 +267,7 @@ public function pre(CommandData $commandData) { define('MAINTENANCE_MODE', 'install'); drush_bootstrap(DRUSH_BOOTSTRAP_DRUPAL_SITE); - if (!$sql->drop_or_create()) { + if (!$sql->dropOrCreate()) { throw new \Exception(dt('Failed to create database: @error', array('@error' => implode(drush_shell_exec_output())))); } } diff --git a/lib/Drush/Commands/core/StatusCommands.php b/lib/Drush/Commands/core/StatusCommands.php index ede8dc63e5..a1039de63d 100644 --- a/lib/Drush/Commands/core/StatusCommands.php +++ b/lib/Drush/Commands/core/StatusCommands.php @@ -5,6 +5,7 @@ use Consolidation\AnnotatedCommand\AnnotationData; use Consolidation\OutputFormatters\StructuredData\PropertyList; use Drush\Commands\DrushCommands; +use Drush\Sql\SqlBase; use Symfony\Component\Console\Input\InputInterface; use Consolidation\OutputFormatters\StructuredData\AssociativeList; @@ -83,8 +84,8 @@ public static function getPropertyList($options) { if ($site_root = drush_get_context('DRUSH_DRUPAL_SITE_ROOT')) { $status_table['uri'] = drush_get_context('DRUSH_URI'); try { - $sql = drush_sql_get_class(); - $db_spec = $sql->db_spec(); + $sql = SqlBase::create($options); + $db_spec = $sql->getDbSpec(); $status_table['db-driver'] = $db_spec['driver']; if (!empty($db_spec['unix_socket'])) { $status_table['db-socket'] = $db_spec['unix_socket']; diff --git a/lib/Drush/Commands/sql/SanitizeUserTableCommands.php b/lib/Drush/Commands/sql/SanitizeUserTableCommands.php index 769c99f285..0f089cf45c 100644 --- a/lib/Drush/Commands/sql/SanitizeUserTableCommands.php +++ b/lib/Drush/Commands/sql/SanitizeUserTableCommands.php @@ -4,6 +4,7 @@ use Consolidation\AnnotatedCommand\CommandData; use Drupal\Core\Database\Database; use Drush\Commands\DrushCommands; +use Drush\Sql\SqlBase; use Symfony\Component\Console\Input\InputInterface; /** @@ -39,7 +40,7 @@ public function sanitize($result, CommandData $commandData) { if ($this->isEnabled($options['sanitize-email'])) { if (strpos($options['sanitize-email'], '%') !== FALSE) { // We need a different sanitization query for MSSQL, Postgres and Mysql. - $sql = drush_sql_get_class(); + $sql = SqlBase::create($commandData->input()->getOptions()); $db_driver = $sql->scheme(); if ($db_driver == 'pgsql') { $email_map = array('%uid' => "' || uid || '", '%mail' => "' || replace(mail, '@', '_') || '", '%name' => "' || replace(name, ' ', '_') || '"); diff --git a/lib/Drush/Commands/sql/SqlCommands.php b/lib/Drush/Commands/sql/SqlCommands.php index a2bdddccf3..f7c8f49cc9 100644 --- a/lib/Drush/Commands/sql/SqlCommands.php +++ b/lib/Drush/Commands/sql/SqlCommands.php @@ -3,6 +3,7 @@ use Drupal\Core\Database\Database; use Drush\Commands\DrushCommands; +use Drush\Sql\SqlBase; class SqlCommands extends DrushCommands { @@ -16,7 +17,7 @@ class SqlCommands extends DrushCommands { * @hidden */ public function conf($options = ['format' => 'yaml', 'all' => FALSE, 'show-passwords' => FALSE]) { - drush_bootstrap_max(DRUSH_BOOTSTRAP_DRUPAL_CONFIGURATION); + $this->further($options); if ($options['all']) { $return = Database::getAllConnectionInfo(); foreach ($return as $key1 => $value) { @@ -28,8 +29,8 @@ public function conf($options = ['format' => 'yaml', 'all' => FALSE, 'show-passw } } else { - $sql = drush_sql_get_class(); - $return = $sql->db_spec(); + $sql = SqlBase::create($options); + $return = $sql->getDbSpec(); if (!$options['show-passwords']) { unset($return['password']); } @@ -50,7 +51,7 @@ public function conf($options = ['format' => 'yaml', 'all' => FALSE, 'show-passw */ public function connect($options = ['extra' => '']) { $this->further($options); - $sql = drush_sql_get_class(); + $sql = SqlBase::create($options); return $sql->connect(FALSE); } @@ -68,10 +69,10 @@ public function connect($options = ['extra' => '']) { * @usage drush sql-create --db-su=root --db-su-pw=rootpassword --db-url="mysql://drupal_db_user:drupal_db_password@127.0.0.1/drupal_db" * Create the database as specified in the db-url option. */ - public function create() { + public function create($options = []) { $this->further($options); - $sql = drush_sql_get_class(); - $db_spec = $sql->db_spec(); + $sql = SqlBase::create($options); + $db_spec = $sql->getDbSpec(); // Prompt for confirmation. if (!drush_get_context('DRUSH_SIMULATE')) { // @todo odd - maybe for sql-sync. @@ -94,10 +95,10 @@ public function create() { * @optionset_sql * @topics docs-policy */ - public function drop() { + public function drop($options = []) { $this->further($options); - $sql = drush_sql_get_class(); - $db_spec = $sql->db_spec(); + $sql = SqlBase::create($options); + $db_spec = $sql->getDbSpec(); if (!drush_confirm(dt('Do you really want to drop all tables in the database !db?', array('!db' => $db_spec['database'])))) { return drush_user_abort(); } @@ -118,9 +119,9 @@ public function drop() { * Open a SQL CLI and skip reading table information. * @remote-tty */ - public function cli() { + public function cli($options = []) { $this->further($options); - $sql = drush_sql_get_class(); + $sql = SqlBase::create($options); drush_shell_proc_open($sql->connect()); } @@ -134,8 +135,6 @@ public function cli() { * @option file Path to a file containing the SQL to be run. Gzip files are accepted. * @option extra Add custom options to the connect string (e.g. --extra=--skip-column-names) * @option db-prefix Enable replacement of braces in your query. - * @option db-spec A database specification. Only used with --backend calls. - * @hidden-option db-spec * @validate-file-exists file * @aliases sqlq * @usage drush sql-query "SELECT * FROM users WHERE uid=1" @@ -148,7 +147,7 @@ public function cli() { * Alternate way to import sql statements from a file. * */ - public function query($query = '', $options = ['result-file' => NULL, 'file' => NULL, 'extra' => NULL, 'db-prefix' => NULL, 'db-spec' => NULL]) { + public function query($query = '', $options = ['result-file' => NULL, 'file' => NULL, 'extra' => NULL, 'db-prefix' => NULL]) { $this->further($options); $filename = $options['file']; // Enable prefix processing when db-prefix option is used. @@ -164,7 +163,7 @@ public function query($query = '', $options = ['result-file' => NULL, 'file' => } } else { - $sql = drush_sql_get_class($options['db-spec']); + $sql = SqlBase::create($options); $result = $sql->query($query, $filename, $options['result-file']); if (!$result) { throw new \Exception(dt('Query failed.')); @@ -197,7 +196,7 @@ public function query($query = '', $options = ['result-file' => NULL, 'file' => */ public function dump($options = ['result-file' => NULL, 'create-db' => NULL, 'data-only' => NULL, 'ordered-dump' => NULL, 'gzip' => NULL, 'extra' => NULL, 'extra-dump' => NULL]) { $this->further($options); - $sql = drush_sql_get_class(); + $sql = SqlBase::create($options); return $sql->dump($options); } diff --git a/lib/Drush/Sql/Sql7.php b/lib/Drush/Sql/Sql7.php deleted file mode 100644 index d19801912e..0000000000 --- a/lib/Drush/Sql/Sql7.php +++ /dev/null @@ -1,20 +0,0 @@ -db_spec = $db_spec; + public function __construct($db_spec, $options) { + $this->dbSpec = $db_spec; + $this->options = $options; + } + + /** + * Get a driver specific instance of this class. + * + * @param $options + * An options array as handed to a command callback. + * @return SqlBase + */ + public static function create($options = []) { + // Set defaults in the unfortunate event that caller doesn't provide values. + $options += [ + 'database' => 'default', + 'target' => 'default', + 'db-url' => NULL, + 'databases' => NULL, + 'db-prefix' => NULL, + ]; + $database = $options['database']; + $target = $options['target']; + + if ($url = $options['db-url']) { + $url = is_array($url) ? $url[$database] : $url; + $db_spec = drush_convert_db_from_db_url($url); + $db_spec['db_prefix'] = $options['db-prefix']; + return self::getInstance($db_spec, $options); + } + elseif (($databases = $options['databases']) && (array_key_exists($database, $databases)) && (array_key_exists($target, $databases[$database]))) { + // @todo 'databases' option is not declared anywhere? + $db_spec = $databases[$database][$target]; + return self::getInstance($db_spec, $options); + } + elseif ($info = Database::getConnectionInfo($database)) { + $db_spec = $info[$target]; + return self::getInstance($db_spec, $options); + } + else { + throw new \Exception(dt('Unable to load Drupal settings. Check your --root, --uri, etc.')); + } + } + + public static function getInstance($db_spec, $options) { + $driver = $db_spec['driver']; + $class_name = 'Drush\Sql\Sql'. ucfirst($driver); + return new $class_name($db_spec, $options); } /* * Get the current $db_spec. */ - public function db_spec() { - return $this->db_spec; + public function getDbSpec() { + return $this->dbSpec; + } + + /** + * Set the current db spec. + * + * @param array $dbSpec + */ + public function setDbSpec($dbSpec) { + $this->dbSpec = $dbSpec; } /** @@ -48,21 +107,18 @@ public function command() {} * @return string */ public function connect($hide_password = TRUE) { - return trim($this->command() . ' ' . $this->creds($hide_password) . ' ' . drush_get_option('extra', $this->query_extra)); + return trim($this->command() . ' ' . $this->creds($hide_password) . ' ' . $this->getOption('extra', $this->queryExtra)); } /* * Execute a SQL dump and return the path to the resulting dump file. - * - * @param array @options - * The options array as passed to the Annotated Command. */ - public function dump($options) { + public function dump() { /** @var string|bool $file Path where dump file should be stored. If TRUE, generate a path based on usual backup directory and current date.*/ - $file = isset($options['result-file']) ? $options['result-file'] : NULL; + $file = $this->getOption('result-file'); $file_suffix = ''; - $table_selection = $this->getExpandedTableSelection($options); + $table_selection = $this->getExpandedTableSelection($this->getOptions()); $file = $this->dumpFile($file); $cmd = $this->dumpCmd($table_selection, $options); // Gzip the output from dump command(s) if requested. @@ -92,13 +148,11 @@ public function dump($options) { * * @param array $table_selection * Supported keys: 'skip', 'structure', 'tables'. - * @param array $options - * An options array as passed by an Annotated Command. * @return string * One or more mysqldump/pg_dump/sqlite3/etc statements that are ready for executing. * If multiple statements are needed, enclose in parenthesis. */ - public function dumpCmd($table_selection, $options) {} + public function dumpCmd($table_selection) {} /* * Generate a path to an output file for a SQL dump when needed. @@ -108,7 +162,7 @@ public function dumpCmd($table_selection, $options) {} * Otherwise, just return the path that was provided. */ public function dumpFile($file) { - $database = $this->db_spec['database']; + $database = $this->dbSpec['database']; // $file is passed in to us usually via --result-file. If the user // has set $options['result-file'] = TRUE, then we @@ -132,8 +186,7 @@ public function dumpFile($file) { /** * Execute a SQL query. * - * Note: This is an API function. Try to avoid using drush_get_option() and instead - * pass params in. If you don't want to query results to print during --debug then + * If you don't want to query results to print during --debug then * provide a $result_file whose value can be drush_bit_bucket(). * * @param string $query @@ -143,7 +196,7 @@ public function dumpFile($file) { * @param string $result_file * A path to save query results to. Can be drush_bit_bucket() if desired. * - * @return + * @return boolean * TRUE on success, FALSE on failure */ public function query($query, $input_file = NULL, $result_file = '') { @@ -159,8 +212,8 @@ public function query($query, $input_file = NULL, $result_file = '') { // Save $query to a tmp file if needed. We will redirect it in. if (!$input_file) { - $query = $this->query_prefix($query); - $query = $this->query_format($query); + $query = $this->queryPrefix($query); + $query = $this->queryFormat($query); $input_file = drush_save_data_to_temp_file($query); } @@ -168,8 +221,8 @@ public function query($query, $input_file = NULL, $result_file = '') { $this->command(), $this->creds(), $this->silent(), // This removes column header and various helpful things in mysql. - drush_get_option('extra', $this->query_extra), - $this->query_file, + $this->getOption('extra', $this->queryExtra), + $this->queryFile, drush_escapeshellarg($input_file), ); $exec = implode(' ', $parts); @@ -187,7 +240,7 @@ public function query($query, $input_file = NULL, $result_file = '') { $success = drush_shell_exec($exec); - if ($success && drush_get_option('file-delete')) { + if ($success && $this->getOption('file-delete')) { drush_op('drush_delete_dir', $input_file); } @@ -200,24 +253,19 @@ public function query($query, $input_file = NULL, $result_file = '') { public function silent() {} - public function query_prefix($query) { + public function queryPrefix($query) { // Inject table prefixes as needed. if (drush_has_boostrapped(DRUSH_BOOTSTRAP_DRUPAL_DATABASE)) { // Enable prefix processing which can be dangerous so off by default. See http://drupal.org/node/1219850. - if (drush_get_option('db-prefix')) { - if (drush_drupal_major_version() >= 7) { - $query = \Database::getConnection()->prefixTables($query); - } - else { - $query = db_prefix_tables($query); - } + if ($this->getOption('db-prefix')) { + $query = \Database::getConnection()->prefixTables($query); } } return $query; } - public function query_format($query) { + public function queryFormat($query) { return $query; } @@ -246,8 +294,9 @@ public function drop($tables) { * @param boolean $quoted * Quote the database name. Mysql uses backticks to quote which can cause problems * in a Windows shell. Set TRUE if the CREATE is not running on the bash command line. + * @return string */ - public function createdb_sql($dbname, $quoted = FALSE) {} + public function createdbSql($dbname, $quoted = FALSE) {} /** * Create a new database. @@ -259,8 +308,8 @@ public function createdb_sql($dbname, $quoted = FALSE) {} * True if successful, FALSE otherwise. */ public function createdb($quoted = FALSE) { - $dbname = $this->db_spec['database']; - $sql = $this->createdb_sql($dbname, $quoted); + $dbname = $this->getDbSpec()['database']; + $sql = $this->createdbSql($dbname, $quoted); // Adjust connection to allow for superuser creds if provided. $this->su(); return $this->query($sql); @@ -272,8 +321,8 @@ public function createdb($quoted = FALSE) { * return boolean * TRUE or FALSE depending on success. */ - public function drop_or_create() { - if ($this->db_exists()) { + public function dropOrCreate() { + if ($this->dbExists()) { return $this->drop($this->listTables()); } else { @@ -286,7 +335,7 @@ public function drop_or_create() { * * @return bool */ - public function db_exists() {} + public function dbExists() {} public function delete() {} @@ -305,7 +354,7 @@ public function creds($hide_password = TRUE) {} * @return string */ public function scheme() { - return $this->db_spec['driver']; + return $this->dbSpec['driver']; } /** @@ -322,7 +371,7 @@ public function listTables() {} * @return string * A bash fragment. */ - public function params_to_options($parameters) { + public function paramsToOptions($parameters) { // Turn each parameter into a valid parameter string. $parameter_strings = array(); foreach ($parameters as $key => $value) { @@ -344,22 +393,34 @@ public function params_to_options($parameters) { * @return null */ public function su() { - $create_db_target = $this->db_spec; + $create_db_target = $this->getDbSpec(); $create_db_target['database'] = ''; - $db_superuser = drush_get_option('db-su'); - if (isset($db_superuser)) { + $db_superuser = $this->getOption('db-su'); + if (!empty($db_superuser)) { $create_db_target['username'] = $db_superuser; } - $db_su_pw = drush_get_option('db-su-pw'); + $db_su_pw = $this->getOption('db-su-pw'); // If --db-su-pw is not provided and --db-su is, default to empty password. // This way db cli command will take password from .my.cnf or .pgpass. if (!empty($db_su_pw)) { $create_db_target['password'] = $db_su_pw; } - elseif (isset($db_superuser)) { + elseif (!empty($db_superuser)) { unset($create_db_target['password']); } - $this->db_spec = $create_db_target; + $this->setDbSpec($create_db_target); + } + + /** + * @return array + */ + public function getOptions() { + return $this->options; + } + + public function getOption($name, $default = NULL) { + $options = $this->getOptions(); + return array_key_exists($name, $options) ? $options[$name] : $default; } } diff --git a/lib/Drush/Sql/Sqlmysql.php b/lib/Drush/Sql/SqlMysql.php similarity index 61% rename from lib/Drush/Sql/Sqlmysql.php rename to lib/Drush/Sql/SqlMysql.php index 302d25b472..e6bf78ba1c 100644 --- a/lib/Drush/Sql/Sqlmysql.php +++ b/lib/Drush/Sql/SqlMysql.php @@ -4,20 +4,21 @@ use PDO; -class Sqlmysql extends SqlBase { +class SqlMysql extends SqlBase { public function command() { return 'mysql'; } public function creds($hide_password = TRUE) { + $dbSpec = $this->getDbSpec(); if ($hide_password) { // EMPTY password is not the same as NO password, and is valid. $contents = <<db_spec['username']; + $parameters['user'] = $dbSpec['username']; // EMPTY password is not the same as NO password, and is valid. - if (isset($this->db_spec['password'])) { - $parameters['password'] = $this->db_spec['password']; + if (isset($dbSpec['password'])) { + $parameters['password'] = $dbSpec['password']; } } - // Some drush commands (e.g. site-install) want to connect to the + // Some Drush commands (e.g. site-install) want to connect to the // server, but not the database. Connect to the built-in database. - $parameters['database'] = empty($this->db_spec['database']) ? 'information_schema' : $this->db_spec['database']; + $parameters['database'] = empty($dbSpec['database']) ? 'information_schema' : $dbSpec['database']; // Default to unix socket if configured. - if (!empty($this->db_spec['unix_socket'])) { - $parameters['socket'] = $this->db_spec['unix_socket']; + if (!empty($dbSpec['unix_socket'])) { + $parameters['socket'] = $dbSpec['unix_socket']; } // EMPTY host is not the same as NO host, and is valid (see unix_socket). - elseif (isset($this->db_spec['host'])) { - $parameters['host'] = $this->db_spec['host']; + elseif (isset($dbSpec['host'])) { + $parameters['host'] = $dbSpec['host']; } - if (!empty($this->db_spec['port'])) { - $parameters['port'] = $this->db_spec['port']; + if (!empty($dbSpec['port'])) { + $parameters['port'] = $dbSpec['port']; } - if (!empty($this->db_spec['pdo']['unix_socket'])) { - $parameters['socket'] = $this->db_spec['pdo']['unix_socket']; + if (!empty($dbSpec['pdo']['unix_socket'])) { + $parameters['socket'] = $dbSpec['pdo']['unix_socket']; } - if (!empty($this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CA])) { - $parameters['ssl-ca'] = $this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CA]; + if (!empty($dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CA])) { + $parameters['ssl-ca'] = $dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CA]; } - if (!empty($this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CAPATH])) { - $parameters['ssl-capath'] = $this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CAPATH]; + if (!empty($dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CAPATH])) { + $parameters['ssl-capath'] = $dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CAPATH]; } - if (!empty($this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CERT])) { - $parameters['ssl-cert'] = $this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CERT]; + if (!empty($dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CERT])) { + $parameters['ssl-cert'] = $dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CERT]; } - if (!empty($this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CIPHER])) { - $parameters['ssl-cipher'] = $this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_CIPHER]; + if (!empty($dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CIPHER])) { + $parameters['ssl-cipher'] = $dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_CIPHER]; } - if (!empty($this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_KEY])) { - $parameters['ssl-key'] = $this->db_spec['pdo'][PDO::MYSQL_ATTR_SSL_KEY]; + if (!empty($dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_KEY])) { + $parameters['ssl-key'] = $dbSpec['pdo'][PDO::MYSQL_ATTR_SSL_KEY]; } - return $this->params_to_options($parameters); + return $this->paramsToOptions($parameters); } public function silent() { return '--silent'; } - public function createdb_sql($dbname, $quoted = FALSE) { + public function createdbSql($dbname, $quoted = FALSE) { + $dbSpec = $this->getDbSpec(); if ($quoted) { $dbname = '`' . $dbname . '`'; } @@ -92,15 +94,18 @@ public function createdb_sql($dbname, $quoted = FALSE) { // localhost is special and only allows local Unix socket file connections. // - If the database is on a remote server, create a wilcard user with %. // We can't easily know what IP adderss or hostname would represent our server. - $domain = ($this->db_spec['host'] == 'localhost') ? 'localhost' : '%'; - $sql[] = sprintf('GRANT ALL PRIVILEGES ON %s.* TO \'%s\'@\'%s\'', $dbname, $this->db_spec['username'], $domain); - $sql[] = sprintf("IDENTIFIED BY '%s';", $this->db_spec['password']); + $domain = ($dbSpec['host'] == 'localhost') ? 'localhost' : '%'; + $sql[] = sprintf('GRANT ALL PRIVILEGES ON %s.* TO \'%s\'@\'%s\'', $dbname, $dbSpec['username'], $domain); + $sql[] = sprintf("IDENTIFIED BY '%s';", $dbSpec['password']); $sql[] = 'FLUSH PRIVILEGES;'; } return implode(' ', $sql); } - public function db_exists() { + /** + * @inheritdoc + */ + public function dbExists() { $current = drush_get_context('DRUSH_SIMULATE'); drush_set_context('DRUSH_SIMULATE', FALSE); // Suppress output. We only care about return value. @@ -118,7 +123,8 @@ public function listTables() { return $tables; } - public function dumpCmd($table_selection, $options) { + public function dumpCmd($table_selection) { + $dbSpec = $this->getDbSpec(); $parens = FALSE; $skip_tables = $table_selection['skip']; $structure_tables = $table_selection['structure']; @@ -126,11 +132,9 @@ public function dumpCmd($table_selection, $options) { $ignores = array(); $skip_tables = array_merge($structure_tables, $skip_tables); - $data_only = $options['data-only']; + $data_only = $this->getOption('data-only'); // The ordered-dump option is only supported by MySQL for now. - // @todo add documention once a hook for drush_get_option_help() is available. - // @see drush_get_option_help() in drush.inc - $ordered_dump = $options['ordered-dump']; + $ordered_dump = $this->getOption('ordered-dump'); $exec = 'mysqldump '; // mysqldump wants 'databasename' instead of 'database=databasename' for no good reason. @@ -146,7 +150,7 @@ public function dumpCmd($table_selection, $options) { if (isset($ordered_dump)) { $extra .= ' --skip-extended-insert --order-by-primary'; } - if ($option = $options['extra-dump'] ?: $this->query_extra) { + if ($option = $this->getOption('extra-dump', $this->queryExtra)) { $extra .= " $option"; } $exec .= $extra; @@ -157,7 +161,7 @@ public function dumpCmd($table_selection, $options) { else { // Append the ignore-table options. foreach ($skip_tables as $table) { - $ignores[] = '--ignore-table=' . $this->db_spec['database'] . '.' . $table; + $ignores[] = '--ignore-table=' . $dbSpec['database'] . '.' . $table; $parens = TRUE; } $exec .= ' '. implode(' ', $ignores); diff --git a/lib/Drush/Sql/Sqloracle.php b/lib/Drush/Sql/SqlOracle.php similarity index 77% rename from lib/Drush/Sql/Sqloracle.php rename to lib/Drush/Sql/SqlOracle.php index 3d0cfb7291..67f16437f7 100644 --- a/lib/Drush/Sql/Sqloracle.php +++ b/lib/Drush/Sql/SqlOracle.php @@ -4,10 +4,10 @@ use Drush\Log\LogLevel; -class Sqloracle extends SqlBase { +class SqlOracle extends SqlBase { // The way you pass a sql file when issueing a query. - public $query_file = '@'; + public $queryFile = '@'; public function command() { // use rlwrap if available for readline support @@ -22,15 +22,15 @@ public function command() { } public function creds() { - return ' ' . $this->db_spec['username'] . '/' . $this->db_spec['password'] . ($this->db_spec['host'] == 'USETNS' ? '@' . $this->db_spec['database'] : '@//' . $this->db_spec['host'] . ':' . ($db_spec['port'] ? $db_spec['port'] : '1521') . '/' . $this->db_spec['database']); + return ' ' . $this->dbSpec['username'] . '/' . $this->dbSpec['password'] . ($this->dbSpec['host'] == 'USETNS' ? '@' . $this->dbSpec['database'] : '@//' . $this->dbSpec['host'] . ':' . ($db_spec['port'] ? $db_spec['port'] : '1521') . '/' . $this->dbSpec['database']); } - public function createdb_sql($dbname) { + public function createdbSql($dbname) { return drush_log("Unable to generate CREATE DATABASE sql for $dbname", LogLevel::ERROR); } // @todo $suffix = '.sql'; - public function query_format($query) { + public function queryFormat($query) { // remove trailing semicolon from query if we have it $query = preg_replace('/\;$/', '', $query); @@ -71,20 +71,20 @@ public function listTables() { // @todo $file is no longer provided. We are supposed to return bash that can be piped to gzip. // Probably Oracle needs to override dump() entirely - http://stackoverflow.com/questions/2236615/oracle-can-imp-exp-go-to-stdin-stdout. - public function dumpCmd($table_selection, $options) { - $create_db = $options['create-db']; + public function dumpCmd($table_selection) { + $create_db = $this->getOption('create-db'); $exec = 'exp ' . $this->creds(); // Change variable '$file' by reference in order to get drush_log() to report. if (!$file) { - $file = $this->db_spec['username'] . '.dmp'; + $file = $this->dbSpec['username'] . '.dmp'; } $exec .= ' file=' . $file; if (!empty($tables)) { $exec .= ' tables="(' . implode(',', $tables) . ')"'; } - $exec .= ' owner=' . $this->db_spec['username']; - if ($option = $options['extra-dump'] ?: $this->query_extra) { + $exec .= ' owner=' . $this->dbSpec['username']; + if ($option = $this->getOption('extra-dump', $this->queryExtra)) { $exec .= " $option"; } return array($exec, $file); diff --git a/lib/Drush/Sql/Sqlpgsql.php b/lib/Drush/Sql/SqlPgsql.php similarity index 70% rename from lib/Drush/Sql/Sqlpgsql.php rename to lib/Drush/Sql/SqlPgsql.php index 434f1f234e..c40673501c 100644 --- a/lib/Drush/Sql/Sqlpgsql.php +++ b/lib/Drush/Sql/SqlPgsql.php @@ -4,23 +4,24 @@ define('PSQL_SHOW_TABLES', "SELECT tablename FROM pg_tables WHERE schemaname='public';"); -class Sqlpgsql extends SqlBase { +class SqlPgsql extends SqlBase { - public $query_extra = "--no-align --field-separator=\"\t\" --pset tuples_only=on"; + public $queryExtra = "--no-align --field-separator=\"\t\" --pset tuples_only=on"; - public $query_file = "--file"; + public $queryFile = "--file"; private $password_file = NULL; - private function password_file() { - if (!isset($password_file) && isset($this->db_spec['password'])) { + private function createPasswordFile() { + $dbSpec = $this->getDbSpec(); + if (!isset($this->getPasswordFile()) && isset($dbSpec['password'])) { $pgpass_parts = array( - empty($this->db_spec['host']) ? 'localhost' : $this->db_spec['host'], - empty($this->db_spec['port']) ? '5432' : $this->db_spec['port'], + empty($dbSpec['host']) ? 'localhost' : $dbSpec['host'], + empty($Spec['port']) ? '5432' : $dbSpec['port'], // Database '*', - $this->db_spec['username'], - $this->db_spec['password'] + $dbSpec['username'], + $dbSpec['password'] ); // Escape colon and backslash characters in entries. // @see http://www.postgresql.org/docs/9.1/static/libpq-pgpass.html @@ -38,7 +39,7 @@ private function password_file() { public function command() { $environment = ""; - $pw_file = $this->password_file(); + $pw_file = $this->createPasswordFile(); if (isset($pw_file)) { $environment = "PGPASSFILE={$pw_file} "; } @@ -50,24 +51,25 @@ public function command() { * Not used in postgres. Use .pgpass file instead. See http://drupal.org/node/438828. */ public function creds($hide_password = TRUE) { + $dbSpec = $this->getDbSpec(); // Some drush commands (e.g. site-install) want to connect to the // server, but not the database. Connect to the built-in database. - $parameters['dbname'] = empty($this->db_spec['database']) ? 'template1' : $this->db_spec['database']; + $parameters['dbname'] = empty($dbSpec['database']) ? 'template1' : $dbSpec['database']; // Host and port are optional but have defaults. - $parameters['host'] = empty($this->db_spec['host']) ? 'localhost' : $this->db_spec['host']; - $parameters['port'] = empty($this->db_spec['port']) ? '5432' : $this->db_spec['port']; + $parameters['host'] = empty($dbSpec['host']) ? 'localhost' : $['host']; + $parameters['port'] = empty($dbSpec['port']) ? '5432' : $dbSpec['port']; // Username is required. - $parameters['username'] = $this->db_spec['username']; + $parameters['username'] = $dbSpec['username']; // Don't set the password. // @see http://drupal.org/node/438828 - return $this->params_to_options($parameters); + return $this->paramsToOptions($parameters); } - public function createdb_sql($dbname, $quoted = FALSE) { + public function createdbSql($dbname, $quoted = FALSE) { if ($quoted) { $dbname = '`' . $dbname . '`'; } @@ -76,19 +78,20 @@ public function createdb_sql($dbname, $quoted = FALSE) { return implode(' ', $sql); } - public function db_exists() { - $database = $this->db_spec['database']; + public function dbExists() { + $dbSpec = $this->getDbSpec(); + $database = $dbSpec['database']; // Get a new class instance that has no 'database'. - $db_spec_no_db = $this->db_spec; + $db_spec_no_db = $dbSpec; unset($db_spec_no_db['database']); - $sql_no_db = drush_sql_get_class($db_spec_no_db); + $sql_no_db = new SqlPgsql($db_spec_no_db, $this->.$this->getOptions()); $query = "SELECT 1 AS result FROM pg_database WHERE datname='$database'"; drush_shell_exec($sql_no_db->connect() . ' -t -c %s', $query); $output = drush_shell_exec_output(); return (bool)$output[0]; } - public function query_format($query) { + public function queryFormat($query) { if (strtolower($query) == 'show tables;') { return PSQL_SHOW_TABLES; } @@ -104,7 +107,7 @@ public function listTables() { return array(); } - public function dumpCmd($table_selection, $options) { + public function dumpCmd($table_selection) { $parens = FALSE; $skip_tables = $table_selection['skip']; $structure_tables = $table_selection['structure']; @@ -112,16 +115,16 @@ public function dumpCmd($table_selection, $options) { $ignores = array(); $skip_tables = array_merge($structure_tables, $skip_tables); - $data_only = $options['data-only']; + $data_only = $this->getOption('data-only'); - $create_db = $options['create-db']; + $create_db = $this->getOption(['create-db'); $exec = 'pg_dump '; // Unlike psql, pg_dump does not take a '--dbname=' before the database name. $extra = str_replace('--dbname=', ' ', $this->creds()); if (isset($data_only)) { $extra .= ' --data-only'; } - if ($option = $options['extra-dump'] ?: $this->query_extra) { + if ($option = $this->getOption('extra-dump', $this->queryExtra) { $extra .= " $option"; } $exec .= $extra; @@ -150,4 +153,11 @@ public function dumpCmd($table_selection, $options) { } return $parens ? "($exec)" : $exec; } + + /** + * @return string|null + */ + public function getPasswordFile() { + return $this->password_file; + } } diff --git a/lib/Drush/Sql/Sqlsqlite.php b/lib/Drush/Sql/SqlSqlite.php similarity index 87% rename from lib/Drush/Sql/Sqlsqlite.php rename to lib/Drush/Sql/SqlSqlite.php index ac0c454ba3..6fb37adc9b 100644 --- a/lib/Drush/Sql/Sqlsqlite.php +++ b/lib/Drush/Sql/SqlSqlite.php @@ -4,7 +4,7 @@ use Drush\Log\LogLevel; -class Sqlsqlite extends SqlBase { +class SqlSqlite extends SqlBase { public function command() { return 'sqlite3'; } @@ -13,10 +13,10 @@ public function creds($hide_password = TRUE) { // SQLite doesn't do user management, instead relying on the filesystem // for that. So the only info we really need is the path to the database // file, and not as a "--key=value" parameter. - return ' ' . $this->db_spec['database']; + return ' ' . $this->getDbSpec()['database']; } - public function createdb_sql($dbname, $quoted = false) { + public function createdbSql($dbname, $quoted = false) { return ''; } @@ -28,7 +28,7 @@ public function createdb_sql($dbname, $quoted = false) { * in a Windows shell. Set TRUE if the CREATE is not running on the bash command line. */ public function createdb($quoted = FALSE) { - $file = $this->db_spec['database']; + $file = $this->getDbSpec()['database']; if (file_exists($file)) { drush_log("SQLITE: Deleting existing database '$file'", LogLevel::DEBUG); drush_delete_dir($file, TRUE); @@ -47,8 +47,8 @@ public function createdb($quoted = FALSE) { } } - public function db_exists() { - return file_exists($this->db_spec['database']); + public function dbExists() { + return file_exists($this->getDbSpec()['database']); } public function listTables() { @@ -81,7 +81,7 @@ public function drop($tables) { return $this->query($sql); } - public function dumpCmd($table_selection, $options) { + public function dumpCmd($table_selection) { // Dumping is usually not necessary in SQLite, since all database data // is stored in a single file which can be copied just // like any other file. But it still has a use in migration purposes and @@ -91,7 +91,7 @@ public function dumpCmd($table_selection, $options) { // Postgres or MySQL equivalents. We may be able to fake some in the // future, but for now, let's just support simple dumps. $exec .= ' ".dump"'; - if ($option = $options['extra-dump'] ?: $this->query_extra) { + if ($option = $this->.$this->getOption('extra-dump', $this->queryExtra)) { $exec .= " $option"; } return $exec; diff --git a/lib/Drush/Sql/Sqlsqlsrv.php b/lib/Drush/Sql/SqlSqlsrv.php similarity index 56% rename from lib/Drush/Sql/Sqlsqlsrv.php rename to lib/Drush/Sql/SqlSqlsrv.php index c98f6cf99e..35167d8f4c 100644 --- a/lib/Drush/Sql/Sqlsqlsrv.php +++ b/lib/Drush/Sql/SqlSqlsrv.php @@ -2,10 +2,10 @@ namespace Drush\Sql; -class Sqlsqlsrv extends SqlBase { +class SqlSqlsrv extends SqlBase { // The way you pass a sql file when issueing a query. - public $query_file = '-h -1 -i'; + public $queryFile = '-h -1 -i'; public function command() { return 'sqlcmd'; @@ -14,24 +14,26 @@ public function command() { public function creds() { // Some drush commands (e.g. site-install) want to connect to the // server, but not the database. Connect to the built-in database. - $database = empty($this->db_spec['database']) ? 'master' : $this->db_spec['database']; + $dbSpec = $this->getDbSpec(); + $database = empty($dbSpec['database']) ? 'master' : $dbSpec['database']; // Host and port are optional but have defaults. - $host = empty($this->db_spec['host']) ? '.\SQLEXPRESS' : $this->db_spec['host']; - if ($this->db_spec['username'] == '') { + $host = empty($dbSpec['host']) ? '.\SQLEXPRESS' : $dbSpec['host']; + if ($dbSpec['username'] == '') { return ' -S ' . $host . ' -d ' . $database; } else { - return ' -S ' . $host . ' -d ' . $database . ' -U ' . $this->db_spec['username'] . ' -P ' . $this->db_spec['password']; + return ' -S ' . $host . ' -d ' . $database . ' -U ' . $dbSpec['username'] . ' -P ' . $dbSpec['password']; } } - public function db_exists() { + public function dbExists() { // TODO: untested, but the gist is here. - $database = $this->db_spec['database']; + $dbSpec = $this->getDbSpec(); + $database = $dbSpec['database']; // Get a new class instance that has no 'database'. - $db_spec_no_db = $this->db_spec; + $db_spec_no_db = $dbSpec; unset($db_spec_no_db['database']); - $sql_no_db = drush_sql_get_class($db_spec_no_db); + $sql_no_db = new SqlSqlsrv($db_spec_no_db, $this->getOptions()); $query = "if db_id('$database') IS NOT NULL print 1"; drush_shell_exec($sql_no_db->connect() . ' -Q %s', $query); $output = drush_shell_exec_output(); @@ -50,12 +52,13 @@ public function listTables() { // @todo $file is no longer provided. We are supposed to return bash that can be piped to gzip. // Probably sqlsrv needs to override dump() entirely. - public function dumpCmd($table_selection, $options) { + public function dumpCmd($table_selection) { + $dbSpec = $this->getDbSpec(); if (!$file) { - $file = $this->db_spec['database'] . '_' . date('Ymd_His') . '.bak'; + $file = $dbSpec['database'] . '_' . date('Ymd_His') . '.bak'; } - $exec = "sqlcmd -U \"" . $this->db_spec['username'] . "\" -P \"" . $this->db_spec['password'] . "\" -S \"" . $this->db_spec['host'] . "\" -Q \"BACKUP DATABASE [" . $this->db_spec['database'] . "] TO DISK='" . $file . "'\""; - if ($option = $options['extra-dump'] :? $this->query_extra) { + $exec = "sqlcmd -U \"" . $dbSpec['username'] . "\" -P \"" . $dbSpec['password'] . "\" -S \"" . $dbSpec['host'] . "\" -Q \"BACKUP DATABASE [" . $dbSpec['database'] . "] TO DISK='" . $file . "'\""; + if ($option = $this->getOption('extra-dump', $this->queryExtra)) { $exec .= " $option"; } return array($exec, $file); diff --git a/lib/Drush/Sql/SqlVersion.php b/lib/Drush/Sql/SqlVersion.php deleted file mode 100644 index dcdaf4a2f8..0000000000 --- a/lib/Drush/Sql/SqlVersion.php +++ /dev/null @@ -1,15 +0,0 @@ -