Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Icinga PHP Library - SQL abstraction layer

![Build Status](https://github.com/Icinga/ipl-sql/workflows/PHP%20Tests/badge.svg?branch=main)

The package `ipl\Sql` provides a [database connection
abstraction](#sql-connection) and an [SQL query abstraction layer](#sql-queries)
for building SQL queries via an OOP API.
Expand Down
3 changes: 0 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ parameters:
paths:
- src

scanDirectories:
- vendor

universalObjectCratesClasses: # to ignore magic property errors
- ipl\Sql\Config

Expand Down
18 changes: 9 additions & 9 deletions src/Adapter/BaseAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ abstract class BaseAdapter implements Adapter
*
* @var array
*/
protected $quoteCharacter = ['"', '"'];
protected array $quoteCharacter = ['"', '"'];

/** @var string Character to use for escaping quote characters */
protected $escapeCharacter = '\\"';
protected string $escapeCharacter = '\\"';

/** @var array Default PDO connect options */
protected $options = [
protected array $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)
public function getDsn(Config $config): string
{
$dsn = "{$config->db}:";

Expand All @@ -50,7 +50,7 @@ public function getDsn(Config $config)
return $dsn . implode(';', $parts);
}

public function getOptions(Config $config)
public function getOptions(Config $config): array
{
if (is_array($config->options)) {
return $config->options + $this->options;
Expand All @@ -59,12 +59,12 @@ public function getOptions(Config $config)
return $this->options;
}

public function setClientTimezone(Connection $db)
public function setClientTimezone(Connection $db): static
{
return $this;
}

public function quoteIdentifier($identifiers)
public function quoteIdentifier(array|string $identifiers): string
{
if (is_string($identifiers)) {
$identifiers = explode('.', $identifiers);
Expand All @@ -83,7 +83,7 @@ public function quoteIdentifier($identifiers)
return implode('.', $identifiers);
}

public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder)
public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static
{
$queryBuilder->on(QueryBuilder::ON_ASSEMBLE_SELECT, function (Select $select): void {
if ($select->hasOrderBy()) {
Expand All @@ -105,7 +105,7 @@ public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder)
return $this;
}

protected function getTimezoneOffset()
protected function getTimezoneOffset(): string
{
$tz = new DateTimeZone(date_default_timezone_get());
$offset = $tz->getOffset(new DateTime());
Expand Down
8 changes: 4 additions & 4 deletions src/Adapter/Mssql.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

class Mssql extends BaseAdapter
{
protected $quoteCharacter = ['[', ']'];
protected array $quoteCharacter = ['[', ']'];

protected $escapeCharacter = '[[]';
protected string $escapeCharacter = '[[]';

public function getDsn(Config $config)
public function getDsn(Config $config): string
{
$drivers = array_intersect(['sqlsrv', 'dblib', 'mssql', 'sybase'], PDO::getAvailableDrivers());

Expand Down Expand Up @@ -62,7 +62,7 @@ public function getDsn(Config $config)
return $dsn;
}

public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder)
public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static
{
parent::registerQueryBuilderCallbacks($queryBuilder);

Expand Down
30 changes: 18 additions & 12 deletions src/Adapter/Mysql.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,57 @@

use ipl\Sql\Config;
use ipl\Sql\Connection;
use PDO;

class Mysql extends BaseAdapter
{
protected $quoteCharacter = ['`', '`'];
protected array $quoteCharacter = ['`', '`'];

protected $escapeCharacter = '``';
protected string $escapeCharacter = '``';

public function setClientTimezone(Connection $db)
public function setClientTimezone(Connection $db): static
{
$db->exec('SET time_zone = ' . $db->quote($this->getTimezoneOffset()));

return $this;
}

public function getOptions(Config $config)
public function getOptions(Config $config): array
{
$options = parent::getOptions($config);
// In PHP 8.5+, driver-specific constants of the PDO class are deprecated,
// but the replacements are only available since php 8.4
if (version_compare(PHP_VERSION, '8.4.0', '<')) {
$mysqlConstantPrefix = 'PDO::MYSQL_ATTR_';
} else {
$mysqlConstantPrefix = 'Pdo\Mysql::ATTR_';
}

if (! empty($config->useSsl)) {
if (! empty($config->sslKey)) {
$options[PDO::MYSQL_ATTR_SSL_KEY] = $config->sslKey;
$options[constant($mysqlConstantPrefix . 'SSL_KEY')] = $config->sslKey;
}

if (! empty($config->sslCert)) {
$options[PDO::MYSQL_ATTR_SSL_CERT] = $config->sslCert;
$options[constant($mysqlConstantPrefix . 'SSL_CERT')] = $config->sslCert;
}

if (! empty($config->sslCa)) {
$options[PDO::MYSQL_ATTR_SSL_CA] = $config->sslCa;
$options[constant($mysqlConstantPrefix . 'SSL_CA')] = $config->sslCa;
}

if (! empty($config->sslCapath)) {
$options[PDO::MYSQL_ATTR_SSL_CAPATH] = $config->sslCapath;
$options[constant($mysqlConstantPrefix . 'SSL_CAPATH')] = $config->sslCapath;
}

if (! empty($config->sslCipher)) {
$options[PDO::MYSQL_ATTR_SSL_CIPHER] = $config->sslCipher;
$options[constant($mysqlConstantPrefix . 'SSL_CIPHER')] = $config->sslCipher;
}

if (
defined('PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT')
defined($mysqlConstantPrefix . 'SSL_VERIFY_SERVER_CERT')
&& ! empty($config->sslDoNotVerifyServerCert)
) {
$options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
$options[constant($mysqlConstantPrefix . 'SSL_VERIFY_SERVER_CERT')] = false;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Adapter/Oracle.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

class Oracle extends BaseAdapter
{
public function getDsn(Config $config)
public function getDsn(Config $config): string
{
$dsn = 'oci:dbname=';

Expand All @@ -30,7 +30,7 @@ public function getDsn(Config $config)
return $dsn;
}

public function setClientTimezone(Connection $db)
public function setClientTimezone(Connection $db): static
{
$db->prepexec('ALTER SESSION SET TIME_ZONE = ?', [$this->getTimezoneOffset()]);

Expand Down
2 changes: 1 addition & 1 deletion src/Adapter/Pgsql.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class Pgsql extends BaseAdapter
{
public function setClientTimezone(Connection $db)
public function setClientTimezone(Connection $db): static
{
$db->exec(sprintf('SET TIME ZONE INTERVAL %s HOUR TO MINUTE', $db->quote($this->getTimezoneOffset())));

Expand Down
2 changes: 1 addition & 1 deletion src/Adapter/Sqlite.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class Sqlite extends BaseAdapter
{
public function getDsn(Config $config)
public function getDsn(Config $config): string
{
return "sqlite:{$config->dbname}";
}
Expand Down
10 changes: 5 additions & 5 deletions src/CommonTableExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ trait CommonTableExpression
*
* @var array[]
*/
protected $with = [];
protected array $with = [];

public function getWith()
public function getWith(): array
{
return $this->with;
}

public function with(Select $query, $alias, $recursive = false)
public function with(Select $query, string $alias, bool $recursive = false): static
{
$this->with[] = [$query, $alias, $recursive];

return $this;
}

public function resetWith()
public function resetWith(): static
{
$this->with = [];

Expand All @@ -43,7 +43,7 @@ public function resetWith()
*
* Shall be called by using classes in their __clone()
*/
protected function cloneCte()
protected function cloneCte(): void
{
foreach ($this->with as &$cte) {
$cte[0] = clone $cte[0];
Expand Down
6 changes: 3 additions & 3 deletions src/CommonTableExpressionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface CommonTableExpressionInterface
*
* @return array[]
*/
public function getWith();
public function getWith(): array;

/**
* Add a CTE
Expand All @@ -28,12 +28,12 @@ public function getWith();
*
* @return $this
*/
public function with(Select $query, $alias, $recursive = false);
public function with(Select $query, string $alias, bool $recursive = false): static;

/**
* Reset all CTEs
*
* @return $this
*/
public function resetWith();
public function resetWith(): static;
}
4 changes: 2 additions & 2 deletions src/Compat/FilterProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

class FilterProcessor
{
public static function assembleFilter(Filter\Rule $filter, $level = 0)
public static function assembleFilter(Filter\Rule $filter, int $level = 0): ?array
{
$condition = null;

Expand Down Expand Up @@ -60,7 +60,7 @@ public static function assembleFilter(Filter\Rule $filter, $level = 0)
return $condition;
}

public static function assemblePredicate(Filter\Condition $filter)
public static function assemblePredicate(Filter\Condition $filter): array
{
$column = $filter->getColumn();
$expression = $filter->getValue();
Expand Down
45 changes: 16 additions & 29 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,31 @@

namespace ipl\Sql;

use InvalidArgumentException;
use ipl\Stdlib\Str;
use OutOfRangeException;

use function ipl\Stdlib\get_php_type;

/**
* SQL connection configuration
*/
class Config
{
/** @var string Type of the DBMS */
public $db;
/** @var ?string Type of the DBMS */
public ?string $db = null;

/** @var string Database host */
public $host;
/** @var ?string Database host */
public ?string $host = null;

/** @var int Database port */
public $port;
/** @var string|int|null Database port */
public string|int|null $port = null;

/** @var string Database name */
public $dbname;
/** @var ?string Database name */
public ?string $dbname = null;

/** @var string Username to use for authentication */
public $username;
/** @var ?string Username to use for authentication */
public ?string $username = null;

/** @var string Password to use for authentication */
public $password;
/** @var ?string Password to use for authentication */
public ?string $password = null;

/**
* Character set for the connection
Expand All @@ -38,7 +35,7 @@ class Config
*
* @var string
*/
public $charset;
public string $charset = '';

/**
* PDO connect options
Expand All @@ -48,30 +45,20 @@ class Config
*
* @var array
*/
public $options;
public array $options = [];

/** @var array Extra settings e.g. for SQL SSL connections */
protected $extraSettings = [];
protected array $extraSettings = [];

/**
* Create a new SQL connection configuration from the given configuration key-value pairs
*
* Keys will be converted to camelCase, e.g. use_ssl → useSsl.
*
* @param iterable $config Configuration key-value pairs
*
* @throws InvalidArgumentException If $config is not iterable
*/
public function __construct($config)
public function __construct(iterable $config)
{
if (! is_iterable($config)) {
throw new InvalidArgumentException(sprintf(
'%s expects parameter one to be iterable, got %s instead',
__METHOD__,
get_php_type($config)
));
}

foreach ($config as $key => $value) {
$key = Str::camel($key);
$this->$key = $value;
Expand Down
Loading