summaryrefslogtreecommitdiffstats
path: root/vendor/ipl/sql/src/Adapter
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ipl/sql/src/Adapter')
-rw-r--r--vendor/ipl/sql/src/Adapter/BaseAdapter.php120
-rw-r--r--vendor/ipl/sql/src/Adapter/Mssql.php80
-rw-r--r--vendor/ipl/sql/src/Adapter/Mysql.php57
-rw-r--r--vendor/ipl/sql/src/Adapter/Oracle.php39
-rw-r--r--vendor/ipl/sql/src/Adapter/Pgsql.php15
-rw-r--r--vendor/ipl/sql/src/Adapter/Sqlite.php13
6 files changed, 324 insertions, 0 deletions
diff --git a/vendor/ipl/sql/src/Adapter/BaseAdapter.php b/vendor/ipl/sql/src/Adapter/BaseAdapter.php
new file mode 100644
index 0000000..f062f63
--- /dev/null
+++ b/vendor/ipl/sql/src/Adapter/BaseAdapter.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace ipl\Sql\Adapter;
+
+use DateTime;
+use DateTimeZone;
+use ipl\Sql\Config;
+use ipl\Sql\Connection;
+use ipl\Sql\Contract\Adapter;
+use ipl\Sql\QueryBuilder;
+use ipl\Sql\Select;
+use PDO;
+use UnexpectedValueException;
+
+abstract class BaseAdapter implements Adapter
+{
+ /**
+ * Quote character to use for quoting identifiers
+ *
+ * The default quote character is the double quote (") which is used by databases that behave close to ANSI SQL.
+ *
+ * @var array
+ */
+ protected $quoteCharacter = ['"', '"'];
+
+ /** @var string Character to use for escaping quote characters */
+ protected $escapeCharacter = '\\"';
+
+ /** @var array Default PDO connect options */
+ protected $options = [
+ PDO::ATTR_CASE => PDO::CASE_NATURAL,
+ PDO::ATTR_EMULATE_PREPARES => false,
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
+ PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
+ PDO::ATTR_STRINGIFY_FETCHES => false
+ ];
+
+ public function getDsn(Config $config)
+ {
+ $dsn = "{$config->db}:";
+
+ $parts = [];
+
+ foreach (['host', 'dbname', 'port'] as $part) {
+ if (! empty($config->$part)) {
+ $parts[] = "{$part}={$config->$part}";
+ }
+ }
+
+ return $dsn . implode(';', $parts);
+ }
+
+ public function getOptions(Config $config)
+ {
+ if (is_array($config->options)) {
+ return $config->options + $this->options;
+ }
+
+ return $this->options;
+ }
+
+ public function setClientTimezone(Connection $db)
+ {
+ return $this;
+ }
+
+ public function quoteIdentifier($identifiers)
+ {
+ if (is_string($identifiers)) {
+ $identifiers = explode('.', $identifiers);
+ }
+
+ foreach ($identifiers as $i => $identifier) {
+ if ($identifier === '*') {
+ continue;
+ }
+
+ $identifiers[$i] = $this->quoteCharacter[0]
+ . str_replace($this->quoteCharacter[0], $this->escapeCharacter, $identifier)
+ . $this->quoteCharacter[1];
+ }
+
+ return implode('.', $identifiers);
+ }
+
+ public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder)
+ {
+ $queryBuilder->on(QueryBuilder::ON_ASSEMBLE_SELECT, function (Select $select): void {
+ if ($select->hasOrderBy()) {
+ foreach ($select->getOrderBy() as list($_, $direction)) {
+ switch (strtolower($direction ?? '')) {
+ case '':
+ case 'asc':
+ case 'desc':
+ break;
+ default:
+ throw new UnexpectedValueException(
+ sprintf('Invalid direction "%s" in ORDER BY', $direction)
+ );
+ }
+ }
+ }
+ });
+
+ return $this;
+ }
+
+ protected function getTimezoneOffset()
+ {
+ $tz = new DateTimeZone(date_default_timezone_get());
+ $offset = $tz->getOffset(new DateTime());
+ $prefix = $offset >= 0 ? '+' : '-';
+ $offset = abs($offset);
+
+ $hours = (int) floor($offset / 3600);
+ $minutes = (int) floor(($offset % 3600) / 60);
+
+ return sprintf('%s%d:%02d', $prefix, $hours, $minutes);
+ }
+}
diff --git a/vendor/ipl/sql/src/Adapter/Mssql.php b/vendor/ipl/sql/src/Adapter/Mssql.php
new file mode 100644
index 0000000..c9f11ce
--- /dev/null
+++ b/vendor/ipl/sql/src/Adapter/Mssql.php
@@ -0,0 +1,80 @@
+<?php
+
+namespace ipl\Sql\Adapter;
+
+use ipl\Sql\Config;
+use ipl\Sql\QueryBuilder;
+use ipl\Sql\Select;
+use PDO;
+use RuntimeException;
+
+class Mssql extends BaseAdapter
+{
+ protected $quoteCharacter = ['[', ']'];
+
+ protected $escapeCharacter = '[[]';
+
+ public function getDsn(Config $config)
+ {
+ $drivers = array_intersect(['sqlsrv', 'dblib', 'mssql', 'sybase'], PDO::getAvailableDrivers());
+
+ if (empty($drivers)) {
+ throw new RuntimeException('No PDO driver available for connecting to a Microsoft SQL Server');
+ }
+
+ $driver = reset($drivers); // array_intersect preserves keys, so the first may not be indexed at 0
+
+ $isSqlSrv = $driver === 'sqlsrv';
+ if ($isSqlSrv) {
+ $hostOption = 'Server';
+ $dbOption = 'Database';
+ } else {
+ $hostOption = 'host';
+ $dbOption = 'dbname';
+ }
+
+ $dsn = "{$driver}:{$hostOption}={$config->host}";
+
+ if (! empty($config->port)) {
+ if ($isSqlSrv || strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+ $seperator = ',';
+ } else {
+ $seperator = ':';
+ }
+
+ $dsn .= "{$seperator}{$config->port}";
+ }
+
+ $dsn .= ";{$dbOption}={$config->dbname}";
+
+ if (! empty($config->charset) && ! $isSqlSrv) {
+ $dsn .= ";charset={$config->charset}";
+ }
+
+ if (isset($config->useSsl) && $isSqlSrv) {
+ $dsn .= ';Encrypt=' . ($config->useSsl ? 'true' : 'false');
+ }
+
+ if (isset($config->sslDoNotVerifyServerCert) && $isSqlSrv) {
+ $dsn .= ';TrustServerCertificate=' . ($config->sslDoNotVerifyServerCert ? 'true' : 'false');
+ }
+
+ return $dsn;
+ }
+
+ public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder)
+ {
+ parent::registerQueryBuilderCallbacks($queryBuilder);
+
+ $queryBuilder->on(QueryBuilder::ON_ASSEMBLE_SELECT, function (Select $select) {
+ if (
+ ($select->hasLimit() || $select->hasOffset())
+ && ! $select->hasOrderBy()
+ ) {
+ $select->orderBy(1);
+ }
+ });
+
+ return $this;
+ }
+}
diff --git a/vendor/ipl/sql/src/Adapter/Mysql.php b/vendor/ipl/sql/src/Adapter/Mysql.php
new file mode 100644
index 0000000..2421cae
--- /dev/null
+++ b/vendor/ipl/sql/src/Adapter/Mysql.php
@@ -0,0 +1,57 @@
+<?php
+
+namespace ipl\Sql\Adapter;
+
+use ipl\Sql\Config;
+use ipl\Sql\Connection;
+use PDO;
+
+class Mysql extends BaseAdapter
+{
+ protected $quoteCharacter = ['`', '`'];
+
+ protected $escapeCharacter = '``';
+
+ public function setClientTimezone(Connection $db)
+ {
+ $db->exec('SET time_zone = ' . $db->quote($this->getTimezoneOffset()));
+
+ return $this;
+ }
+
+ public function getOptions(Config $config)
+ {
+ $options = parent::getOptions($config);
+
+ if (! empty($config->useSsl)) {
+ if (! empty($config->sslKey)) {
+ $options[PDO::MYSQL_ATTR_SSL_KEY] = $config->sslKey;
+ }
+
+ if (! empty($config->sslCert)) {
+ $options[PDO::MYSQL_ATTR_SSL_CERT] = $config->sslCert;
+ }
+
+ if (! empty($config->sslCa)) {
+ $options[PDO::MYSQL_ATTR_SSL_CA] = $config->sslCa;
+ }
+
+ if (! empty($config->sslCapath)) {
+ $options[PDO::MYSQL_ATTR_SSL_CAPATH] = $config->sslCapath;
+ }
+
+ if (! empty($config->sslCipher)) {
+ $options[PDO::MYSQL_ATTR_SSL_CIPHER] = $config->sslCipher;
+ }
+
+ if (
+ defined('PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')
+ && ! empty($config->sslDoNotVerifyServerCert)
+ ) {
+ $options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
+ }
+ }
+
+ return $options;
+ }
+}
diff --git a/vendor/ipl/sql/src/Adapter/Oracle.php b/vendor/ipl/sql/src/Adapter/Oracle.php
new file mode 100644
index 0000000..de0aee5
--- /dev/null
+++ b/vendor/ipl/sql/src/Adapter/Oracle.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace ipl\Sql\Adapter;
+
+use ipl\Sql\Config;
+use ipl\Sql\Connection;
+
+class Oracle extends BaseAdapter
+{
+ public function getDsn(Config $config)
+ {
+ $dsn = 'oci:dbname=';
+
+ if (! empty($config->host)) {
+ $dsn .= "//{$config->host}";
+
+ if (! empty($config->port)) {
+ $dsn .= ":{$config->port}/";
+ }
+
+ $dsn .= '/';
+ }
+
+ $dsn .= $config->dbname;
+
+ if (! empty($config->charset)) {
+ $dsn .= ";charset={$config->charset}";
+ }
+
+ return $dsn;
+ }
+
+ public function setClientTimezone(Connection $db)
+ {
+ $db->prepexec('ALTER SESSION SET TIME_ZONE = ?', [$this->getTimezoneOffset()]);
+
+ return $this;
+ }
+}
diff --git a/vendor/ipl/sql/src/Adapter/Pgsql.php b/vendor/ipl/sql/src/Adapter/Pgsql.php
new file mode 100644
index 0000000..18bf15d
--- /dev/null
+++ b/vendor/ipl/sql/src/Adapter/Pgsql.php
@@ -0,0 +1,15 @@
+<?php
+
+namespace ipl\Sql\Adapter;
+
+use ipl\Sql\Connection;
+
+class Pgsql extends BaseAdapter
+{
+ public function setClientTimezone(Connection $db)
+ {
+ $db->exec(sprintf('SET TIME ZONE INTERVAL %s HOUR TO MINUTE', $db->quote($this->getTimezoneOffset())));
+
+ return $this;
+ }
+}
diff --git a/vendor/ipl/sql/src/Adapter/Sqlite.php b/vendor/ipl/sql/src/Adapter/Sqlite.php
new file mode 100644
index 0000000..9f4e209
--- /dev/null
+++ b/vendor/ipl/sql/src/Adapter/Sqlite.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace ipl\Sql\Adapter;
+
+use ipl\Sql\Config;
+
+class Sqlite extends BaseAdapter
+{
+ public function getDsn(Config $config)
+ {
+ return "sqlite:{$config->dbname}";
+ }
+}