diff --git a/src/Sql/SqlBase.php b/src/Sql/SqlBase.php index 4efa8269bd..b8d66d607b 100644 --- a/src/Sql/SqlBase.php +++ b/src/Sql/SqlBase.php @@ -119,14 +119,29 @@ public static function create(array $options = []): ?SqlBase public static function getInstance($db_spec, $options): ?self { $driver = $db_spec['driver']; + // Drush ships drivers for core database types, and modules/libraries + // may define additional Drush DB drivers in this namespace. $class_name = !empty($driver) ? 'Drush\Sql\Sql' . ucfirst($driver) : null; - if ($class_name && class_exists($class_name)) { + try { + if (!$class_name || !class_exists($class_name)) { + // Handle custom database drivers which extend a defined driver. + $driver_class = $db_spec['namespace'] . '\\Connection'; + if (!class_exists($driver_class)) { + throw new \InvalidArgumentException(); + } + $connection = (new \ReflectionClass($driver_class))->newInstanceWithoutConstructor(); + // This will only work if the method is basically static, as most + // will be...but we can't truly instantiate the Connection class + // here without also calling with a "real" PDO connection. + $class_name = 'Drush\Sql\Sql' . ucfirst($connection->databaseType()); + } $instance = method_exists($class_name, 'make') ? $class_name::make($db_spec, $options) : new $class_name($db_spec, $options); - // Inject config - $instance->setConfig(Drush::config()); - return $instance; + } catch (\Throwable) { + return null; } - return null; + // Inject config + $instance->setConfig(Drush::config()); + return $instance; } /*