Skip to content

Commit

Permalink
Merge pull request #4 from prajapati-kaushik/0000-charset-pass-as-que…
Browse files Browse the repository at this point in the history
…rystring-and-support

perf: support charset pass as query string #0000
  • Loading branch information
joostfaassen committed Nov 9, 2023
2 parents 7542de5 + bc87ecd commit 1044dff
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 41 deletions.
50 changes: 39 additions & 11 deletions src/Config.php
Expand Up @@ -2,8 +2,6 @@

namespace Connector;

use RuntimeException;

class Config
{
protected $name;
Expand All @@ -17,6 +15,7 @@ class Config
protected $properties = []; // arbitrary database properties such as name, description, tier, etc
protected $arguments = []; // DSN arguments
protected $fileName;
protected $queries = [];

public function getName()
{
Expand All @@ -26,6 +25,7 @@ public function getName()
public function setName($name)
{
$this->name = $name;

return $this;
}

Expand All @@ -37,6 +37,7 @@ public function getPort()
public function setPort($port)
{
$this->port = $port;

return $this;
}

Expand All @@ -48,6 +49,7 @@ public function getServer()
public function setServer($server)
{
$this->server = $server;

return $this;
}

Expand All @@ -59,10 +61,10 @@ public function getCluster()
public function setCluster($cluster)
{
$this->cluster = $cluster;

return $this;
}


public function getAddress()
{
return $this->address;
Expand All @@ -71,10 +73,10 @@ public function getAddress()
public function setAddress($address)
{
$this->address = $address;

return $this;
}


public function getPassword()
{
return $this->password;
Expand All @@ -83,6 +85,7 @@ public function getPassword()
public function setPassword($password)
{
$this->password = $password;

return $this;
}

Expand All @@ -94,6 +97,7 @@ public function getUsername()
public function setUsername($username)
{
$this->username = $username;

return $this;
}

Expand All @@ -110,6 +114,7 @@ public function setDriver($driver)
$this->port = 3306;
break;
}

return $this;
}

Expand All @@ -128,6 +133,7 @@ public function setFileName($fileName)
public function setProperty($key, $value)
{
$this->properties[$key] = $value;

return $this;
}

Expand All @@ -136,12 +142,14 @@ public function getProperty($key)
if (!isset($this->properties[$key])) {
return null;
}

return $this->properties[$key];
}

public function setArgument($key, $value)
{
$this->arguments[$key] = $value;

return $this;
}

Expand All @@ -150,6 +158,7 @@ public function getArgument($key)
if (!isset($this->arguments[$key])) {
return null;
}

return $this->arguments[$key];
}

Expand All @@ -161,33 +170,52 @@ public function getArguments()
public function validate()
{
if (!$this->getName()) {
throw new RuntimeException("Missing name");
throw new \RuntimeException('Missing name');
}
switch ($this->getDriver()) {
case 'mysql':
case 'pgsql':
if (!$this->getUsername()) {
throw new RuntimeException("Missing username");
throw new \RuntimeException('Missing username');
}
if (!$this->getUsername()) {
throw new RuntimeException("Missing password");
throw new \RuntimeException('Missing password');
}
if (!$this->getAddress()) {
throw new RuntimeException("Missing address");
throw new \RuntimeException('Missing address');
}
if (!$this->getPort()) {
throw new RuntimeException("Missing port");
throw new \RuntimeException('Missing port');
}
break;
case 'sqlite':
break;
case 'sqlsrv':
if (!$this->getAddress()) {
throw new RuntimeException("Missing address");
throw new \RuntimeException('Missing address');
}
break;
default:
throw new RuntimeException("Unsupported driver: " . $this->getDriver());
throw new \RuntimeException('Unsupported driver: '.$this->getDriver());
}
}

/**
* @param [array] $array
*/
public function setQueries($array = []): self
{
$this->queries = $array;

return $this;
}

public function getQuery($key)
{
if (!isset($this->queries[$key])) {
return null;
}

return $this->queries[$key];
}
}
69 changes: 39 additions & 30 deletions src/Connector.php
Expand Up @@ -3,12 +3,11 @@
namespace Connector;

use Connector\Backend\BackendInterface;
use PDO;
use RuntimeException;

class Connector
{
protected $backends = [];

public function registerBackend(BackendInterface $backend)
{
$this->backends[] = $backend;
Expand All @@ -26,22 +25,28 @@ public function getConfig($dsn)
$arguments = parse_url($dsn, PHP_URL_QUERY);
parse_str($arguments, $arguments); // parse ?x=y&a=b format into k/v array

foreach ($arguments as $k=>$v) {
foreach ($arguments as $k => $v) {
$config->setArgument($k, $v);
}

if ($port) {
$config->setPort($port);
}
$urlPath = parse_url($dsn, PHP_URL_PATH);
if (parse_url($dsn, PHP_URL_SCHEME) == 'sqlite') {
if ('sqlite' == parse_url($dsn, PHP_URL_SCHEME)) {
$i = pathinfo($urlPath);
$config->setName($i['filename']);
$config->setFileName($urlPath);
} else {
$config->setName(substr($urlPath, 1));
}

// query pramater
parse_str(parse_url($dsn, PHP_URL_QUERY), $params);
if ($params) {
$config->setQueries($params);
}

// TODO: support further resolving cluster/server settings
// from backends based on address/host/server?
return $config;
Expand All @@ -54,24 +59,25 @@ public function getConfig($dsn)
$this->loadKeys($config, $dsnKeys);

if ($config->getCluster()) {
$clusterKeys = $backend->getKeys('clusters/' . $config->getCluster());
$clusterKeys = $backend->getKeys('clusters/'.$config->getCluster());
if ($clusterKeys) {
$this->loadKeys($config, $clusterKeys);
}
}

if ($config->getServer()) {
$serverKeys = $backend->getKeys('servers/' . $config->getServer());
$serverKeys = $backend->getKeys('servers/'.$config->getServer());
if ($serverKeys) {
$this->loadKeys($config, $serverKeys);
} else {
$config->setAddress($config->getServer());
}
}

return $config;
}
}
throw new RuntimeException("Can't resolve DSN `" . $dsn . '`');
throw new \RuntimeException("Can't resolve DSN `".$dsn.'`');
}

public function getPdoDsn(Config $config, $mode = 'db')
Expand All @@ -81,71 +87,72 @@ public function getPdoDsn(Config $config, $mode = 'db')
case 'server':
break;
default:
throw new RuntimeException("Invalid mode: " . $mode);
throw new \RuntimeException('Invalid mode: '.$mode);
}
$pdoDsn = $config->getDriver() . ':';
$pdoDsn = $config->getDriver().':';
switch ($config->getDriver()) {
case 'pgsql':
case 'mysql':
$pdoDsn .= 'host=' . $config->getAddress() . ';';
$pdoDsn .= 'host='.$config->getAddress().';';
if ($config->getPort()) {
$pdoDsn .= 'port=' . $config->getPort() . ';';
$pdoDsn .= 'port='.$config->getPort().';';
}
if ($mode=='db') {
$pdoDsn .= 'dbname=' . $config->getName() . ';';
if ('db' == $mode) {
$pdoDsn .= 'dbname='.$config->getName().';';
}
$pdoDsn .= 'charset=utf8;';
$pdoDsn .= 'charset='.($config->getQuery('charset') ? $config->getQuery('charset') : 'utf8;');
break;
case 'sqlite':
$pdoDsn .= $config->getFileName();
break;
case 'sqlsrv':
$pdoDsn .= 'Server=' . $config->getAddress() . ';Database=' . $config->getName();
foreach ($config->getArguments() as $k=>$v) {
$pdoDsn .= ';' . $k . '=' . $v;
$pdoDsn .= 'Server='.$config->getAddress().';Database='.$config->getName();
foreach ($config->getArguments() as $k => $v) {
$pdoDsn .= ';'.$k.'='.$v;
}
break;
default:
throw new RuntimeException("Unsupported driver: " . $config->getDriver());
throw new \RuntimeException('Unsupported driver: '.$config->getDriver());
}

return $pdoDsn;
}

public function create(Config $config)
{
if ($this->exists($config)) {
throw new RuntimeException("Database already exists");
throw new \RuntimeException('Database already exists');
}
// TODO: validate dbname?
switch ($config->getDriver()) {
case 'mysql':
$pdo = $this->getPdo($config, 'server');
$stmt = $pdo->prepare(
"CREATE DATABASE " . $config->getName()
'CREATE DATABASE '.$config->getName()
);
$stmt->execute();
break;
default:
throw new RuntimeException("Unsupported driver: " . $config->getDriver());
throw new \RuntimeException('Unsupported driver: '.$config->getDriver());
}
}

public function drop(Config $config)
{
if (!$this->exists($config)) {
throw new RuntimeException("Database does not exists");
throw new \RuntimeException('Database does not exists');
}
// TODO: validate dbname?
switch ($config->getDriver()) {
case 'mysql':
$pdo = $this->getPdo($config, 'server');
$stmt = $pdo->prepare(
"DROP DATABASE " . $config->getName()
'DROP DATABASE '.$config->getName()
);
$stmt->execute();
break;
default:
throw new RuntimeException("Unsupported driver: " . $config->getDriver());
throw new \RuntimeException('Unsupported driver: '.$config->getDriver());
}
}

Expand All @@ -155,20 +162,21 @@ public function exists(Config $config)
case 'mysql':
$pdo = $this->getPdo($config, 'server');
$stmt = $pdo->prepare(
"SELECT COUNT(*) AS c FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = :dbname"
'SELECT COUNT(*) AS c FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = :dbname'
);
$stmt->execute(
[
':dbname' => $config->getName()
':dbname' => $config->getName(),
]
);

return (bool) $stmt->fetchColumn();
case 'sqlite':
return $this->getPdo($config, 'server');
break;
default:
throw new RuntimeException("Unsupported driver");
throw new \RuntimeException('Unsupported driver');
}
}

Expand All @@ -177,7 +185,7 @@ public function getPdo(Config $config, $mode = 'db')
$pdoDsn = $this->getPdoDsn($config, $mode);
$config->validate(); // throws if invalid

return new PDO($pdoDsn, $config->getUsername(), $config->getPassword());
return new \PDO($pdoDsn, $config->getUsername(), $config->getPassword());
}

public function loadKeys(Config $config, $keys)
Expand All @@ -186,13 +194,14 @@ public function loadKeys(Config $config, $keys)
return;
}
foreach ($keys as $key => $value) {
$methodName = 'set' . ucfirst($key);
$methodName = 'set'.ucfirst($key);
if (method_exists($config, $methodName)) {
$config->$methodName($value);
} else {
$config->setProperty($key, $value);
}
}

return $config;
}
}

0 comments on commit 1044dff

Please sign in to comment.