diff --git a/composer.json b/composer.json index 2dd665d..3bfeaa5 100644 --- a/composer.json +++ b/composer.json @@ -8,10 +8,10 @@ "require": { "php": ">=8.2", "ext-pdo": "*", - "ipl/stdlib": ">=0.12.0" + "ipl/stdlib": "dev-modernize-code" }, "require-dev": { - "ipl/stdlib": "dev-main" + "ipl/stdlib": "dev-modernize-code" }, "autoload": { "files": [ diff --git a/src/Adapter/BaseAdapter.php b/src/Adapter/BaseAdapter.php index f062f63..6426d5c 100644 --- a/src/Adapter/BaseAdapter.php +++ b/src/Adapter/BaseAdapter.php @@ -21,13 +21,13 @@ 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, @@ -35,7 +35,7 @@ abstract class BaseAdapter implements Adapter PDO::ATTR_STRINGIFY_FETCHES => false ]; - public function getDsn(Config $config) + public function getDsn(Config $config): string { $dsn = "{$config->db}:"; @@ -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; @@ -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(string|array $identifiers): string { if (is_string($identifiers)) { $identifiers = explode('.', $identifiers); @@ -83,11 +83,11 @@ 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()) { - foreach ($select->getOrderBy() as list($_, $direction)) { + foreach ($select->getOrderBy() as [$_, $direction]) { switch (strtolower($direction ?? '')) { case '': case 'asc': @@ -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()); diff --git a/src/Adapter/Mssql.php b/src/Adapter/Mssql.php index c9f11ce..55d6c95 100644 --- a/src/Adapter/Mssql.php +++ b/src/Adapter/Mssql.php @@ -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()); @@ -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); diff --git a/src/Adapter/Mysql.php b/src/Adapter/Mysql.php index 52c8c0c..df3471c 100644 --- a/src/Adapter/Mysql.php +++ b/src/Adapter/Mysql.php @@ -8,18 +8,18 @@ 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); diff --git a/src/Adapter/Oracle.php b/src/Adapter/Oracle.php index de0aee5..a6c5aa0 100644 --- a/src/Adapter/Oracle.php +++ b/src/Adapter/Oracle.php @@ -7,7 +7,7 @@ class Oracle extends BaseAdapter { - public function getDsn(Config $config) + public function getDsn(Config $config): string { $dsn = 'oci:dbname='; @@ -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()]); diff --git a/src/Adapter/Pgsql.php b/src/Adapter/Pgsql.php index 18bf15d..871d059 100644 --- a/src/Adapter/Pgsql.php +++ b/src/Adapter/Pgsql.php @@ -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()))); diff --git a/src/Adapter/Sqlite.php b/src/Adapter/Sqlite.php index 9f4e209..e040b6f 100644 --- a/src/Adapter/Sqlite.php +++ b/src/Adapter/Sqlite.php @@ -6,7 +6,7 @@ class Sqlite extends BaseAdapter { - public function getDsn(Config $config) + public function getDsn(Config $config): string { return "sqlite:{$config->dbname}"; } diff --git a/src/CommonTableExpression.php b/src/CommonTableExpression.php index 596ec39..5877fbf 100644 --- a/src/CommonTableExpression.php +++ b/src/CommonTableExpression.php @@ -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 = []; @@ -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]; diff --git a/src/CommonTableExpressionInterface.php b/src/CommonTableExpressionInterface.php index 7e93bc8..22facc5 100644 --- a/src/CommonTableExpressionInterface.php +++ b/src/CommonTableExpressionInterface.php @@ -17,23 +17,23 @@ interface CommonTableExpressionInterface * * @return array[] */ - public function getWith(); + public function getWith(): array; /** * Add a CTE * * @param Select $query * @param string $alias - * @param bool $recursive + * @param bool $recursive * * @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; } diff --git a/src/Compat/FilterProcessor.php b/src/Compat/FilterProcessor.php index 1ed1c3d..457b712 100644 --- a/src/Compat/FilterProcessor.php +++ b/src/Compat/FilterProcessor.php @@ -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; @@ -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(); diff --git a/src/Config.php b/src/Config.php index 5fa103e..f03bddc 100644 --- a/src/Config.php +++ b/src/Config.php @@ -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 @@ -38,7 +35,7 @@ class Config * * @var string */ - public $charset; + public string $charset = ''; /** * PDO connect options @@ -48,10 +45,10 @@ 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 @@ -59,19 +56,9 @@ class Config * 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; @@ -83,7 +70,7 @@ public function __isset(string $name): bool return isset($this->extraSettings[$name]); } - public function __get(string $name) + public function __get(string $name): mixed { if (array_key_exists($name, $this->extraSettings)) { return $this->extraSettings[$name]; diff --git a/src/Connection.php b/src/Connection.php index 5c29713..f7106d4 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -4,6 +4,7 @@ use BadMethodCallException; use Exception; +use Generator; use InvalidArgumentException; use ipl\Sql\Contract\Adapter; use ipl\Sql\Contract\Quoter; @@ -11,6 +12,7 @@ use LogicException; use PDO; use PDOStatement; +use Throwable; /** * Connection to a SQL database using the native PDO for database access @@ -20,16 +22,16 @@ class Connection implements Quoter use Plugins; /** @var Config */ - protected $config; + protected Config $config; /** @var ?PDO */ - protected $pdo; + protected ?PDO $pdo = null; - /** @var QueryBuilder */ - protected $queryBuilder; + /** @var ?QueryBuilder */ + protected ?QueryBuilder $queryBuilder = null; /** @var Adapter */ - protected $adapter; + protected Adapter $adapter; /** * Create a new database connection using the given config for initialising the options for the connection @@ -40,7 +42,7 @@ class Connection implements Quoter * * @throws InvalidArgumentException If there's no adapter for the given database available */ - public function __construct($config) + public function __construct(Config|iterable $config) { $config = $config instanceof Config ? $config : new Config($config); @@ -61,15 +63,15 @@ public function __construct($config) /** * Proxy PDO method calls * - * @param string $name The name of the PDO method to call - * @param array $arguments Arguments for the method to call + * @param string $name The name of the PDO method to call + * @param array $arguments Arguments for the method to call * * @return mixed * * @throws BadMethodCallException If the called method does not exist * */ - public function __call($name, array $arguments) + public function __call(string $name, array $arguments): mixed { $this->connect(); @@ -88,7 +90,7 @@ public function __call($name, array $arguments) * * If you have to adjust the connection after construction, override this method. */ - public function init() + public function init(): void { } @@ -97,7 +99,7 @@ public function init() * * @return Adapter */ - public function getAdapter() + public function getAdapter(): Adapter { return $this->adapter; } @@ -107,7 +109,7 @@ public function getAdapter() * * @return Config */ - public function getConfig() + public function getConfig(): Config { return $this->config; } @@ -117,7 +119,7 @@ public function getConfig() * * @return QueryBuilder */ - public function getQueryBuilder() + public function getQueryBuilder(): QueryBuilder { if ($this->queryBuilder === null) { $this->queryBuilder = new QueryBuilder($this->adapter); @@ -134,7 +136,7 @@ public function getQueryBuilder() * * @return PDO */ - protected function createPdoAdapter() + protected function createPdoAdapter(): PDO { $adapter = $this->getAdapter(); @@ -153,7 +155,7 @@ protected function createPdoAdapter() * * @return $this */ - public function connect() + public function connect(): static { if ($this->pdo !== null) { return $this; @@ -175,7 +177,7 @@ public function connect() * * @return $this */ - public function disconnect() + public function disconnect(): static { $this->pdo = null; @@ -189,11 +191,11 @@ public function disconnect() * * @return bool */ - public function ping($reconnect = true) + public function ping(bool $reconnect = true): bool { try { $this->query('SELECT 1')->closeCursor(); - } catch (Exception $e) { + } catch (Throwable) { if (! $reconnect) { return false; } @@ -209,12 +211,12 @@ public function ping($reconnect = true) /** * Fetch and return all result rows as sequential array * - * @param Select|string $stmt The SQL statement to prepare and execute. - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute. + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchAll($stmt, ?array $values = null) + public function fetchAll(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(); @@ -223,12 +225,12 @@ public function fetchAll($stmt, ?array $values = null) /** * Fetch and return the first column of all result rows as sequential array * - * @param Select|string $stmt The SQL statement to prepare and execute. - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute. + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchCol($stmt, ?array $values = null) + public function fetchCol(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_COLUMN, 0); @@ -237,12 +239,12 @@ public function fetchCol($stmt, ?array $values = null) /** * Fetch and return the first row of the result rows * - * @param Select|string $stmt The SQL statement to prepare and execute. - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute. + * @param ?array $values Values to bind to the statement * - * @return array + * @return mixed */ - public function fetchOne($stmt, ?array $values = null) + public function fetchOne(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetch(); @@ -251,7 +253,7 @@ public function fetchOne($stmt, ?array $values = null) /** * Alias of {@link fetchOne()} */ - public function fetchRow($stmt, ?array $values = null) + public function fetchRow(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetch(); @@ -262,12 +264,12 @@ public function fetchRow($stmt, ?array $values = null) * * First column is the key and the second column is the value. * - * @param Select|string $stmt The SQL statement to prepare and execute. - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute. + * @param ?array $values Values to bind to the statement * * @return array */ - public function fetchPairs($stmt, ?array $values = null) + public function fetchPairs(Select|string $stmt, ?array $values = null): array { return $this->prepexec($stmt, $values) ->fetchAll(PDO::FETCH_KEY_PAIR); @@ -276,12 +278,12 @@ public function fetchPairs($stmt, ?array $values = null) /** * Fetch and return the first column of the first result row * - * @param Select|string $stmt The SQL statement to prepare and execute. - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute. + * @param ?array $values Values to bind to the statement * - * @return string + * @return mixed */ - public function fetchScalar($stmt, ?array $values = null) + public function fetchScalar(Select|string $stmt, ?array $values = null): mixed { return $this->prepexec($stmt, $values) ->fetchColumn(0); @@ -292,12 +294,12 @@ public function fetchScalar($stmt, ?array $values = null) * * `Connection::yieldAll(Select|string $stmt [[, array $values], int $fetchMode [, mixed ...$fetchModeOptions]])` * - * @param Select|string $stmt The SQL statement to prepare and execute. - * @param mixed ...$args Values to bind to the statement, fetch mode for the statement, fetch mode options + * @param Select|string $stmt The SQL statement to prepare and execute. + * @param mixed ...$args Values to bind to the statement, fetch mode for the statement, fetch mode options * - * @return \Generator + * @return Generator */ - public function yieldAll($stmt, ...$args) + public function yieldAll(Select|string $stmt, ...$args): Generator { $values = null; @@ -342,12 +344,12 @@ public function yieldAll($stmt, ...$args) /** * Yield the first column of each result row * - * @param Select|string $stmt The SQL statement to prepare and execute - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute + * @param ?array $values Values to bind to the statement * - * @return \Generator + * @return Generator */ - public function yieldCol($stmt, ?array $values = null) + public function yieldCol(Select|string $stmt, ?array $values = null): Generator { $sth = $this->prepexec($stmt, $values); @@ -361,19 +363,19 @@ public function yieldCol($stmt, ?array $values = null) /** * Yield key-value pairs with the first column as key and the second column as value for each result row * - * @param Select|string $stmt The SQL statement to prepare and execute - * @param ?array $values Values to bind to the statement + * @param Select|string $stmt The SQL statement to prepare and execute + * @param ?array $values Values to bind to the statement * - * @return \Generator + * @return Generator */ - public function yieldPairs($stmt, ?array $values = null) + public function yieldPairs(Select|string $stmt, ?array $values = null): Generator { $sth = $this->prepexec($stmt, $values); $sth->setFetchMode(PDO::FETCH_NUM); foreach ($sth as $row) { - list($key, $value) = $row; + [$key, $value] = $row; yield $key => $value; } @@ -394,7 +396,7 @@ public function prepexec($stmt, $values = null) } if (is_object($stmt)) { - list($stmt, $values) = $this->getQueryBuilder()->assemble($stmt); + [$stmt, $values] = $this->getQueryBuilder()->assemble($stmt); } $this->connect(); @@ -412,9 +414,9 @@ public function prepexec($stmt, $values = null) * * @return PDOStatement */ - public function select(Select $select) + public function select(Select $select): PDOStatement { - list($stmt, $values) = $this->getQueryBuilder()->assembleSelect($select); + [$stmt, $values] = $this->getQueryBuilder()->assembleSelect($select); return $this->prepexec($stmt, $values); } @@ -422,15 +424,13 @@ public function select(Select $select) /** * Insert a table row with the specified data * - * @param string $table The table to insert data into. The table specification must be in - * one of the following formats: 'table' or 'schema.table' - * @param iterable $data Row data in terms of column-value pairs + * @param string $table The table to insert data into. The table specification must be in one of the following + * formats: 'table' or 'schema.table' + * @param iterable $data Row data in terms of column-value pairs * * @return PDOStatement - * - * @throws InvalidArgumentException If data type is invalid */ - public function insert($table, $data) + public function insert(string $table, iterable $data): PDOStatement { $insert = (new Insert()) ->into($table) @@ -461,20 +461,20 @@ public function lastInsertId(?string $name = null): false|string /** * Update table rows with the specified data, optionally based on a given condition * - * @param string|array $table The table to update. The table specification must be in one of - * the following formats: - * 'table', 'table alias', ['alias' => 'table'] - * @param iterable $data The columns to update in terms of column-value pairs - * @param mixed $condition The WHERE condition - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|array $table The table to update. The table specification must be in one of the following formats: + * 'table', 'table alias', ['alias' => 'table'] + * @param iterable $data The columns to update in terms of column-value pairs + * @param string|array|null $condition The WHERE condition + * @param string $operator The operator to combine multiple conditions with, if the condition is in the array format * * @return PDOStatement - * - * @throws InvalidArgumentException If data type is invalid */ - public function update($table, $data, $condition = null, $operator = Sql::ALL) - { + public function update( + string|array $table, + iterable $data, + string|array|null $condition = null, + string $operator = Sql::ALL + ): PDOStatement { $update = (new Update()) ->table($table) ->set($data); @@ -489,16 +489,18 @@ public function update($table, $data, $condition = null, $operator = Sql::ALL) /** * Delete table rows, optionally based on a given condition * - * @param string|array $table The table to delete data from. The table specification must be in one of the - * following formats: 'table', 'table alias', ['alias' => 'table'] - * @param mixed $condition The WHERE condition - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|array $table The table to delete data from. The table specification must be in one of the following + * formats: 'table', 'table alias', ['alias' => 'table'] + * @param string|array|null $condition The WHERE condition + * @param string $operator The operator to combine multiple conditions with, if the condition is in the array format * * @return PDOStatement */ - public function delete($table, $condition = null, $operator = Sql::ALL) - { + public function delete( + string|array $table, + string|array|null $condition = null, + string $operator = Sql::ALL + ): PDOStatement { $delete = (new Delete()) ->from($table); @@ -514,7 +516,7 @@ public function delete($table, $condition = null, $operator = Sql::ALL) * * @return bool Whether the transaction was started successfully */ - public function beginTransaction() + public function beginTransaction(): bool { $this->connect(); @@ -526,7 +528,7 @@ public function beginTransaction() * * @return bool Whether the transaction was committed successfully */ - public function commitTransaction() + public function commitTransaction(): bool { return $this->pdo->commit(); } @@ -536,7 +538,7 @@ public function commitTransaction() * * @return bool Whether the transaction was rolled back successfully */ - public function rollBackTransaction() + public function rollBackTransaction(): bool { return $this->pdo->rollBack(); } @@ -545,13 +547,13 @@ public function rollBackTransaction() * Run the given callback in a transaction * * @param callable $callback The callback to run in a transaction. - * This connection instance is passed as parameter to the callback + * This connection instance is passed as parameter to the callback * - * @return mixed The return value of the callback + * @return mixed The return value of the callback * - * @throws Exception If an error occurs when running the callback + * @throws Exception If an error occurs when running the callback */ - public function transaction(callable $callback) + public function transaction(callable $callback): mixed { $this->beginTransaction(); @@ -567,8 +569,8 @@ public function transaction(callable $callback) return $result; } - public function quoteIdentifier($identifier) + public function quoteIdentifier(string|array $identifiers): string { - return $this->getAdapter()->quoteIdentifier($identifier); + return $this->getAdapter()->quoteIdentifier($identifiers); } } diff --git a/src/Contract/Adapter.php b/src/Contract/Adapter.php index 6142626..4be8ea7 100644 --- a/src/Contract/Adapter.php +++ b/src/Contract/Adapter.php @@ -15,7 +15,7 @@ interface Adapter extends Quoter * * @return string */ - public function getDsn(Config $config); + public function getDsn(Config $config): string; /** * Get the PDO connect options based on the specified connection configuration @@ -24,7 +24,7 @@ public function getDsn(Config $config); * * @return array */ - public function getOptions(Config $config); + public function getOptions(Config $config): array; /** * Set the client time zone @@ -33,7 +33,7 @@ public function getOptions(Config $config); * * @return $this */ - public function setClientTimezone(Connection $db); + public function setClientTimezone(Connection $db): static; /** * Register callbacks for query builder events @@ -42,5 +42,5 @@ public function setClientTimezone(Connection $db); * * @return $this */ - public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder); + public function registerQueryBuilderCallbacks(QueryBuilder $queryBuilder): static; } diff --git a/src/Contract/Quoter.php b/src/Contract/Quoter.php index 79c4c78..1e0f6f3 100644 --- a/src/Contract/Quoter.php +++ b/src/Contract/Quoter.php @@ -17,5 +17,5 @@ interface Quoter * * @return string */ - public function quoteIdentifier($identifiers); + public function quoteIdentifier(string|array $identifiers): string; } diff --git a/src/Cursor.php b/src/Cursor.php index 85c5b1c..680e67d 100644 --- a/src/Cursor.php +++ b/src/Cursor.php @@ -12,19 +12,19 @@ class Cursor implements IteratorAggregate, Paginatable { /** @var Connection */ - protected $db; + protected Connection $db; /** @var Select */ - protected $select; + protected Select $select; /** @var array */ - protected $fetchModeAndArgs = []; + protected array $fetchModeAndArgs = []; /** * Create a new cursor for the given connection and query * * @param Connection $db - * @param Select $select + * @param Select $select */ public function __construct(Connection $db, Select $select) { @@ -37,7 +37,7 @@ public function __construct(Connection $db, Select $select) * * @return array */ - public function getFetchMode() + public function getFetchMode(): array { return $this->fetchModeAndArgs; } @@ -45,13 +45,13 @@ public function getFetchMode() /** * Set the fetch mode * - * @param int $fetchMode Fetch mode as one of the PDO fetch mode constants. - * Please see {@link https://www.php.net/manual/en/pdostatement.setfetchmode} for details - * @param mixed ...$args Fetch mode arguments + * @param int $fetchMode Fetch mode as one of the PDO fetch mode constants. + * Please see {@link https://www.php.net/manual/en/pdostatement.setfetchmode} for details + * @param mixed ...$args Fetch mode arguments * * @return $this */ - public function setFetchMode($fetchMode, ...$args) + public function setFetchMode(int $fetchMode, ...$args): static { array_unshift($args, $fetchMode); @@ -65,34 +65,34 @@ public function getIterator(): Traversable return $this->db->yieldAll($this->select, ...$this->getFetchMode()); } - public function hasLimit() + public function hasLimit(): bool { return $this->select->hasLimit(); } - public function getLimit() + public function getLimit(): ?int { return $this->select->getLimit(); } - public function limit($limit) + public function limit(?int $limit): static { $this->select->limit($limit); return $this; } - public function hasOffset() + public function hasOffset(): bool { return $this->select->hasOffset(); } - public function getOffset() + public function getOffset(): ?int { return $this->select->getOffset(); } - public function offset($offset) + public function offset(?int $offset): static { $this->select->offset($offset); diff --git a/src/Delete.php b/src/Delete.php index 53736b8..232cf84 100644 --- a/src/Delete.php +++ b/src/Delete.php @@ -10,15 +10,15 @@ class Delete implements CommonTableExpressionInterface, WhereInterface use CommonTableExpression; use Where; - /** @var array|null The FROM part of the DELETE query */ - protected $from; + /** @var ?array The FROM part of the DELETE query */ + protected ?array $from = null; /** * Get the FROM part of the DELETE query * - * @return array|null + * @return ?array */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -32,12 +32,12 @@ public function getFrom() * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|array $table The table to delete data from. The table specification must be in one of the - * following formats: 'table', 'table alias', ['alias' => 'table'] + * @param string|array $table The table to delete data from. The table specification must be in one of the following + * formats: 'table', 'table alias', ['alias' => 'table'] * * @return $this */ - public function from($table) + public function from(string|array $table): static { $this->from = ! is_array($table) ? [$table] : $table; diff --git a/src/Expression.php b/src/Expression.php index 0f544b1..6edb266 100644 --- a/src/Expression.php +++ b/src/Expression.php @@ -8,13 +8,13 @@ class Expression implements ExpressionInterface { /** @var string The statement of the expression */ - protected $statement; + protected string $statement; - /** @var array The columns used by the expression */ - protected $columns; + /** @var ?array The columns used by the expression */ + protected ?array $columns; /** @var array The values for the expression */ - protected $values; + protected array $values; /** * Create a new database expression @@ -23,31 +23,31 @@ class Expression implements ExpressionInterface * @param ?array $columns The columns used by the expression * @param mixed ...$values The values for the expression */ - public function __construct($statement, ?array $columns = null, ...$values) + public function __construct(string $statement, ?array $columns = null, ...$values) { $this->statement = $statement; $this->columns = $columns; $this->values = $values; } - public function getStatement() + public function getStatement(): string { return $this->statement; } - public function getColumns() + public function getColumns(): array { return $this->columns ?: []; } - public function setColumns(array $columns) + public function setColumns(array $columns): static { $this->columns = $columns; return $this; } - public function getValues() + public function getValues(): array { return $this->values; } diff --git a/src/ExpressionInterface.php b/src/ExpressionInterface.php index 9ebe5ee..9c994d6 100644 --- a/src/ExpressionInterface.php +++ b/src/ExpressionInterface.php @@ -12,14 +12,14 @@ interface ExpressionInterface * * @return string */ - public function getStatement(); + public function getStatement(): string; /** * Get the columns used by the expression * * @return array */ - public function getColumns(); + public function getColumns(): array; /** * Set the columns to use by the expression @@ -28,12 +28,12 @@ public function getColumns(); * * @return $this */ - public function setColumns(array $columns); + public function setColumns(array $columns): static; /** * Get the values for the expression * * @return array */ - public function getValues(); + public function getValues(): array; } diff --git a/src/Filter/In.php b/src/Filter/In.php index c126af6..fea2c91 100644 --- a/src/Filter/In.php +++ b/src/Filter/In.php @@ -7,18 +7,14 @@ class In extends Filter\Condition { - use InAndNotInUtils; - /** * Create a new sql IN condition * - * @param string[]|string $column + * @param string|string[] $column * @param Select $select */ - public function __construct($column, Select $select) + public function __construct(string|array $column, Select $select) { - $this - ->setColumn($column) - ->setValue($select); + parent::__construct($column, $select); } } diff --git a/src/Filter/InAndNotInUtils.php b/src/Filter/InAndNotInUtils.php deleted file mode 100644 index 6f26de1..0000000 --- a/src/Filter/InAndNotInUtils.php +++ /dev/null @@ -1,62 +0,0 @@ -column; - } - - /** - * Set the columns of this condition - * - * @param string[]|string $column - * - * @return $this - */ - public function setColumn($column): self - { - $this->column = $column; - - return $this; - } - - /** - * Get the value of this condition - * - * @return Select - */ - public function getValue(): Select - { - return $this->value; - } - - /** - * Set the value of this condition - * - * @param Select $value - * - * @return $this - */ - public function setValue($value): self - { - $this->value = $value; - - return $this; - } -} diff --git a/src/Filter/NotIn.php b/src/Filter/NotIn.php index cdf6241..3339f15 100644 --- a/src/Filter/NotIn.php +++ b/src/Filter/NotIn.php @@ -7,18 +7,14 @@ class NotIn extends Filter\Condition { - use InAndNotInUtils; - /** * Create a new sql NOT IN condition * - * @param string[]|string $column + * @param string|string[] $column * @param Select $select */ - public function __construct($column, Select $select) + public function __construct(string|array $column, Select $select) { - $this - ->setColumn($column) - ->setValue($select); + parent::__construct($column, $select); } } diff --git a/src/Insert.php b/src/Insert.php index 738a842..669d724 100644 --- a/src/Insert.php +++ b/src/Insert.php @@ -2,8 +2,6 @@ namespace ipl\Sql; -use InvalidArgumentException; - use function ipl\Stdlib\arrayval; /** @@ -13,24 +11,24 @@ class Insert implements CommonTableExpressionInterface { use CommonTableExpression; - /** @var string|null The table for the INSERT INTO query */ - protected $into; + /** @var ?string The table for the INSERT INTO query */ + protected ?string $into = null; - /** @var array|null The columns for which the query provides values */ - protected $columns; + /** @var ?array The columns for which the query provides values */ + protected ?array $columns = null; - /** @var array|null The values to insert */ - protected $values; + /** @var ?array $values The values to insert */ + protected ?array $values = null; - /** @var Select|null The select query for INSERT INTO ... SELECT queries */ - protected $select; + /** @var ?Select The select query for INSERT INTO ... SELECT queries */ + protected ?Select $select = null; /** * Get the table for the INSERT INTo query * - * @return string|null + * @return ?string */ - public function getInto() + public function getInto(): ?string { return $this->into; } @@ -45,11 +43,11 @@ public function getInto() * {@link Connection::quoteIdentifier()} as well. * * @param string $table The table to insert data into. The table specification must be in one of the following - * formats: 'table' or 'schema.table' + * formats: 'table' or 'schema.table' * * @return $this */ - public function into($table) + public function into(string $table): static { $this->into = $table; @@ -61,7 +59,7 @@ public function into($table) * * @return array */ - public function getColumns() + public function getColumns(): array { if (! empty($this->columns)) { return array_keys($this->columns); @@ -90,7 +88,7 @@ public function getColumns() * * @return $this */ - public function columns(array $columns) + public function columns(array $columns): static { $this->columns = array_flip($columns); @@ -102,7 +100,7 @@ public function columns(array $columns) * * @return array */ - public function getValues() + public function getValues(): array { return array_values($this->values ?: []); } @@ -118,10 +116,8 @@ public function getValues() * @param iterable $values List of values or associative set of column-value pairs * * @return $this - * - * @throws InvalidArgumentException If values type is invalid */ - public function values($values) + public function values(iterable $values): static { $this->values = arrayval($values); @@ -135,7 +131,7 @@ public function values($values) * * @return $this */ - public function select(Select $select) + public function select(Select $select): static { $this->select = $select; @@ -145,9 +141,9 @@ public function select(Select $select) /** * Get the select query for the INSERT INTO ... SELECT statement * - * @return Select|null + * @return ?Select */ - public function getSelect() + public function getSelect(): ?Select { return $this->select; } diff --git a/src/LimitOffset.php b/src/LimitOffset.php index 99c30a2..254314b 100644 --- a/src/LimitOffset.php +++ b/src/LimitOffset.php @@ -12,75 +12,61 @@ trait LimitOffset * * If unset or lower than 0, no limit will be applied. * - * @var int|null + * @var ?int */ - protected $limit; + protected ?int $limit = null; /** * Offset from where to start the result set * * If unset or lower than 0, the result set will start from the beginning. * - * @var int|null + * @var ?int */ - protected $offset; + protected ?int $offset = null; - public function hasLimit() + public function hasLimit(): bool { return $this->limit !== null; } - public function getLimit() + public function getLimit(): ?int { return $this->limit; } - public function limit($limit) + public function limit(?int $limit): static { - if ($limit !== null) { - $limit = (int) $limit; - if ($limit < 0) { - $limit = null; - } - } - - $this->limit = $limit; + $this->limit = $limit < 0 ? null : $limit; return $this; } - public function resetLimit() + public function resetLimit(): static { $this->limit = null; return $this; } - public function hasOffset() + public function hasOffset(): bool { return $this->offset !== null; } - public function getOffset() + public function getOffset(): ?int { return $this->offset; } - public function offset($offset) + public function offset(?int $offset): static { - if ($offset !== null) { - $offset = (int) $offset; - if ($offset <= 0) { - $offset = null; - } - } - - $this->offset = $offset; + $this->offset = $offset <= 0 ? null : $offset; return $this; } - public function resetOffset() + public function resetOffset(): static { $this->offset = null; diff --git a/src/LimitOffsetInterface.php b/src/LimitOffsetInterface.php index 94628c4..d27720c 100644 --- a/src/LimitOffsetInterface.php +++ b/src/LimitOffsetInterface.php @@ -12,60 +12,59 @@ interface LimitOffsetInterface * * @return bool */ - public function hasLimit(); + public function hasLimit(): bool; /** * Get the limit * - * @return int|null + * @return ?int */ - public function getLimit(); + public function getLimit(): ?int; /** * Set the limit * - * @param int|null $limit Maximum number of items to return. - * If you want to disable the limit, use null or a negative value + * @param ?int $limit Maximum number of items to return. To disable the limit, use null or a negative value * * @return $this */ - public function limit($limit); + public function limit(?int $limit): static; /** * Reset the limit * * @return $this */ - public function resetLimit(); + public function resetLimit(): static; /** * Get whether an offset is configured * * @return bool */ - public function hasOffset(); + public function hasOffset(): bool; /** * Get the offset * - * @return int|null + * @return ?int */ - public function getOffset(); + public function getOffset(): ?int; /** * Set the offset * - * @param int|null $offset Start result set after this many rows. - * If you want to disable the offset, use null, 0, or a negative value + * @param ?int $offset Start result set after this many rows. If you want to disable the offset, use null, 0, or + * a negative value * * @return $this */ - public function offset($offset); + public function offset(?int $offset): static; /** * Reset the offset * * @return $this */ - public function resetOffset(); + public function resetOffset(): static; } diff --git a/src/OrderBy.php b/src/OrderBy.php index a19d7c5..2129787 100644 --- a/src/OrderBy.php +++ b/src/OrderBy.php @@ -8,20 +8,22 @@ trait OrderBy { /** @var ?array ORDER BY part of the query */ - protected $orderBy; + protected ?array $orderBy = null; - public function hasOrderBy() + public function hasOrderBy(): bool { return $this->orderBy !== null; } - public function getOrderBy() + public function getOrderBy(): ?array { return $this->orderBy; } - public function orderBy($orderBy, $direction = null) - { + public function orderBy( + int|string|ExpressionInterface|Select|array $orderBy, + int|string|null $direction = null + ): static { if (! is_array($orderBy)) { $orderBy = [$orderBy]; } @@ -33,7 +35,7 @@ public function orderBy($orderBy, $direction = null) } if (is_array($column) && count($column) === 2) { - list($column, $dir) = $column; + [$column, $dir] = $column; } if ($dir === SORT_ASC) { @@ -48,7 +50,7 @@ public function orderBy($orderBy, $direction = null) return $this; } - public function resetOrderBy() + public function resetOrderBy(): static { $this->orderBy = null; @@ -60,7 +62,7 @@ public function resetOrderBy() * * Shall be called by using classes in their __clone() */ - protected function cloneOrderBy() + protected function cloneOrderBy(): void { if ($this->orderBy !== null) { foreach ($this->orderBy as &$orderBy) { diff --git a/src/OrderByInterface.php b/src/OrderByInterface.php index 0ee0dda..4243172 100644 --- a/src/OrderByInterface.php +++ b/src/OrderByInterface.php @@ -8,18 +8,18 @@ interface OrderByInterface { /** - * Get whether a ORDER BY part is configured + * Get whether an ORDER BY part is configured * * @return bool */ - public function hasOrderBy(); + public function hasOrderBy(): bool; /** * Get the ORDER BY part of the query * - * @return array|null + * @return ?array */ - public function getOrderBy(); + public function getOrderBy(): ?array; /** * Set the ORDER BY part of the query - either plain columns or expressions or scalar subqueries @@ -28,24 +28,27 @@ public function getOrderBy(); * appends the specified ORDER BY part to an already existing one. * * This method does NOT quote the columns you specify for the ORDER BY. - * If you allow user input here, you must protected yourself against SQL injection using + * If you allow user input here, you must protect yourself against SQL injection using * {@link Connection::quoteIdentifier()} for the field names passed to this method. * If you are using special field names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|int|array $orderBy The ORDER BY part. The items can be in any format of the following: - * ['column', 'column' => 'DESC', 'column' => SORT_DESC, ['column', 'DESC']] - * @param string|int $direction The default direction. Can be any of the following: - * 'ASC', 'DESC', SORT_ASC, SORT_DESC + * @param int|string|ExpressionInterface|Select|array $orderBy The ORDER BY part. The array type supports the + * following format: ['column', 'column' => 'DESC', 'column' => SORT_DESC, ['column', 'DESC']] + * @param int|string|null $direction The default direction. Can be any of the following: + * 'ASC', 'DESC', SORT_ASC, SORT_DESC * * @return $this */ - public function orderBy($orderBy, $direction = null); + public function orderBy( + int|string|ExpressionInterface|Select|array $orderBy, + int|string|null $direction = null + ): static; /** * Reset the ORDER BY part of the query * * @return $this */ - public function resetOrderBy(); + public function resetOrderBy(): static; } diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index f65c68c..e799681 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -2,13 +2,10 @@ namespace ipl\Sql; -use InvalidArgumentException; use ipl\Sql\Adapter\Mssql; use ipl\Sql\Contract\Adapter; use ipl\Stdlib\Events; -use function ipl\Stdlib\get_php_type; - class QueryBuilder { use Events; @@ -141,9 +138,9 @@ class QueryBuilder public const ON_DELETE_ASSEMBLED = 'deleteAssembled'; /** @var Adapter */ - protected $adapter; + protected Adapter $adapter; - protected $separator = " "; + protected string $separator = " "; /** * Create a new query builder for the specified database adapter @@ -163,26 +160,15 @@ public function __construct(Adapter $adapter) * @param Delete|Insert|Select|Update $stmt * * @return array - * - * @throw InvalidArgumentException If statement type is invalid */ - public function assemble($stmt) + public function assemble(Delete|Insert|Select|Update $stmt): array { - switch (true) { - case $stmt instanceof Delete: - return $this->assembleDelete($stmt); - case $stmt instanceof Insert: - return $this->assembleInsert($stmt); - case $stmt instanceof Select: - return $this->assembleSelect($stmt); - case $stmt instanceof Update: - return $this->assembleUpdate($stmt); - default: - throw new InvalidArgumentException(sprintf( - __METHOD__ . ' expects instances of Delete, Insert, Select or Update. Got %s instead.', - get_php_type($stmt) - )); - } + return match (true) { + $stmt instanceof Delete => $this->assembleDelete($stmt), + $stmt instanceof Insert => $this->assembleInsert($stmt), + $stmt instanceof Select => $this->assembleSelect($stmt), + $stmt instanceof Update => $this->assembleUpdate($stmt) + }; } /** @@ -192,7 +178,7 @@ public function assemble($stmt) * * @return array */ - public function assembleDelete(Delete $delete) + public function assembleDelete(Delete $delete): array { $values = []; @@ -218,7 +204,7 @@ public function assembleDelete(Delete $delete) * * @return array */ - public function assembleInsert(Insert $insert) + public function assembleInsert(Insert $insert): array { $values = []; @@ -249,7 +235,7 @@ public function assembleInsert(Insert $insert) * * @return array */ - public function assembleSelect(Select $select, array &$values = []) + public function assembleSelect(Select $select, array &$values = []): array { $select = clone $select; @@ -271,7 +257,7 @@ public function assembleSelect(Select $select, array &$values = []) $unions = $this->buildUnions($select->getUnion(), $values); if ($unions) { - list($unionKeywords, $selects) = $unions; + [$unionKeywords, $selects] = $unions; if ($sql) { $sql = "($sql)"; @@ -307,7 +293,7 @@ public function assembleSelect(Select $select, array &$values = []) * * @return array */ - public function assembleUpdate(Update $update) + public function assembleUpdate(Update $update): array { $values = []; @@ -335,7 +321,7 @@ public function assembleUpdate(Update $update) * * @return string The WITH part of a query */ - public function buildWith(array $with, array &$values) + public function buildWith(array $with, array &$values): string { if (empty($with)) { return ''; @@ -345,8 +331,8 @@ public function buildWith(array $with, array &$values) $hasRecursive = false; foreach ($with as $cte) { - list($query, $alias, $recursive) = $cte; - list($cteSql, $cteValues) = $this->assembleSelect($query); + [$query, $alias, $recursive] = $cte; + [$cteSql, $cteValues] = $this->assembleSelect($query); $ctes[] = "$alias AS ($cteSql)"; @@ -364,7 +350,7 @@ public function buildWith(array $with, array &$values) * * @return string The DELETE FROM part of a query */ - public function buildDeleteFrom(?array $from = null) + public function buildDeleteFrom(?array $from = null): string { if ($from === null) { return ''; @@ -393,7 +379,7 @@ public function buildDeleteFrom(?array $from = null) * * @return array */ - public function unpackCondition($expression, array $values) + public function unpackCondition(string $expression, array $values): array { $placeholders = preg_match_all('/(\?)/', $expression, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); @@ -440,7 +426,7 @@ public function unpackCondition($expression, array $values) * * @return string */ - public function buildCondition(array $condition, array &$values) + public function buildCondition(array $condition, array &$values): string { $sql = []; @@ -453,7 +439,7 @@ public function buildCondition(array $condition, array &$values) // Operator format $sql[] = $this->buildCondition($value, $values); } else { - list($unpackedExpression, $unpackedValues) = $this->unpackCondition($expression, $value); + [$unpackedExpression, $unpackedValues] = $this->unpackCondition($expression, $value); $sql[] = $unpackedExpression; $values = array_merge($values, $unpackedValues); } @@ -491,7 +477,7 @@ public function buildCondition(array $condition, array &$values) * * @return string The WHERE part of the query */ - public function buildWhere(?array $where = null, array &$values = []) + public function buildWhere(?array $where = null, array &$values = []): string { if ($where === null) { return ''; @@ -507,7 +493,7 @@ public function buildWhere(?array $where = null, array &$values = []) * * @return string The INSERT INTO part of a INSERT INTO ... statement */ - public function buildInsertInto($into) + public function buildInsertInto(?string $into): string { if (empty($into)) { return ''; @@ -525,7 +511,7 @@ public function buildInsertInto($into) * * @return string The columns and SELECT part of the INSERT INTO ... SELECT statement */ - public function buildInsertIntoSelect(array $columns, Select $select, array &$values) + public function buildInsertIntoSelect(array $columns, Select $select, array &$values): string { $sql = [ '(' . implode(',', $columns) . ')', @@ -544,7 +530,7 @@ public function buildInsertIntoSelect(array $columns, Select $select, array &$va * * @return string The columns and values part of a INSERT INTO ... statement */ - public function buildInsertColumnsAndValues(array $columns, array $insertValues, array &$values) + public function buildInsertColumnsAndValues(array $columns, array $insertValues, array &$values): string { $sql = ['(' . implode(',', $columns) . ')']; @@ -570,12 +556,12 @@ public function buildInsertColumnsAndValues(array $columns, array $insertValues, * Build the SELECT part of a query * * @param array $columns - * @param bool $distinct + * @param bool $distinct * @param array $values * * @return string The SELECT part of the query */ - public function buildSelect(array $columns, $distinct, array &$values) + public function buildSelect(array $columns, bool $distinct, array &$values): string { if (empty($columns)) { return ''; @@ -614,7 +600,7 @@ public function buildSelect(array $columns, $distinct, array &$values) * * @return string The FROM part of the query */ - public function buildFrom(?array $from = null, array &$values = []) + public function buildFrom(?array $from = null, array &$values = []): string { if ($from === null) { return ''; @@ -640,12 +626,13 @@ public function buildFrom(?array $from = null, array &$values = []) /** * Build the JOIN part(s) of a query * - * @param array $joins + * @param ?array $joins + * * @oaram array $values * * @return string The JOIN part(s) of the query */ - public function buildJoin($joins, array &$values) + public function buildJoin(?array $joins, array &$values): string { if ($joins === null) { return ''; @@ -653,7 +640,7 @@ public function buildJoin($joins, array &$values) $sql = []; foreach ($joins as $join) { - list($joinType, $table, $condition) = $join; + [$joinType, $table, $condition] = $join; if (is_array($table)) { $tableName = null; @@ -691,7 +678,7 @@ public function buildJoin($joins, array &$values) * * @return string The GROUP BY part of the query */ - public function buildGroupBy(?array $groupBy = null, array &$values = []) + public function buildGroupBy(?array $groupBy = null, array &$values = []): string { if ($groupBy === null) { return ''; @@ -716,7 +703,7 @@ public function buildGroupBy(?array $groupBy = null, array &$values = []) * * @return string The HAVING part of the query */ - public function buildHaving(?array $having = null, array &$values = []) + public function buildHaving(?array $having = null, array &$values = []): string { if ($having === null) { return ''; @@ -733,7 +720,7 @@ public function buildHaving(?array $having = null, array &$values = []) * * @return string The ORDER BY part of the query */ - public function buildOrderBy(?array $orderBy = null, array &$values = []) + public function buildOrderBy(?array $orderBy = null, array &$values = []): string { if ($orderBy === null) { return ''; @@ -742,7 +729,7 @@ public function buildOrderBy(?array $orderBy = null, array &$values = []) $sql = []; foreach ($orderBy as $column) { - list($column, $direction) = $column; + [$column, $direction] = $column; if ($column instanceof ExpressionInterface) { $column = $this->buildExpression($column, $values); @@ -763,12 +750,12 @@ public function buildOrderBy(?array $orderBy = null, array &$values = []) /** * Build the LIMIT and OFFSET part of a query * - * @param int $limit - * @param int $offset + * @param ?int $limit + * @param ?int $offset * * @return string The LIMIT and OFFSET part of the query */ - public function buildLimitOffset($limit = null, $offset = null) + public function buildLimitOffset(?int $limit = null, ?int $offset = null): string { $sql = []; @@ -801,9 +788,9 @@ public function buildLimitOffset($limit = null, $offset = null) * @param ?array $unions * @param array $values * - * @return array|null The UNION parts of the query + * @return ?array The UNION parts of the query */ - public function buildUnions(?array $unions = null, array &$values = []) + public function buildUnions(?array $unions = null, array &$values = []): ?array { if ($unions === null) { return null; @@ -813,10 +800,10 @@ public function buildUnions(?array $unions = null, array &$values = []) $selects = []; foreach ($unions as $union) { - list($select, $all) = $union; + [$select, $all] = $union; if ($select instanceof Select) { - list($select, $values) = $this->assembleSelect($select, $values); + [$select, $values] = $this->assembleSelect($select, $values); } $unionKeywords[] = ($all ? 'UNION ALL' : 'UNION'); @@ -833,7 +820,7 @@ public function buildUnions(?array $unions = null, array &$values = []) * * @return string The UPDATE {table} part of the query */ - public function buildUpdateTable(?array $updateTable = null) + public function buildUpdateTable(?array $updateTable = null): string { if ($updateTable === null) { return ''; @@ -862,7 +849,7 @@ public function buildUpdateTable(?array $updateTable = null) * * @return string The SET part of a UPDATE query */ - public function buildUpdateSet(?array $set = null, array &$values = []) + public function buildUpdateSet(?array $set = null, array &$values = []): string { if (empty($set)) { return ''; @@ -892,7 +879,7 @@ public function buildUpdateSet(?array $set = null, array &$values = []) * * @return string The expression's statement */ - public function buildExpression(ExpressionInterface $expression, array &$values = []) + public function buildExpression(ExpressionInterface $expression, array &$values = []): string { $stmt = $expression->getStatement(); $columns = $expression->getColumns(); diff --git a/src/Select.php b/src/Select.php index f56a131..e4a9040 100644 --- a/src/Select.php +++ b/src/Select.php @@ -13,13 +13,13 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or use Where; /** @var bool Whether the query is DISTINCT */ - protected $distinct = false; + protected bool $distinct = false; - /** @var array|null The columns for the SELECT query */ - protected $columns; + /** @var ?array The columns for the SELECT query */ + protected ?array $columns = null; - /** @var array|null FROM part of the query, i.e. the table names to select data from */ - protected $from; + /** @var ?array FROM part of the query, i.e. the table names to select data from */ + protected ?array $from = null; /** * The tables to JOIN @@ -31,13 +31,13 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or * * @var ?array */ - protected $join; + protected ?array $join = null; - /** @var array|null The columns for the GROUP BY part of the query */ - protected $groupBy; + /** @var ?array The columns for the GROUP BY part of the query */ + protected ?array $groupBy = null; - /** @var array|null Internal representation for the HAVING part of the query */ - protected $having; + /** @var ?array Internal representation for the HAVING part of the query */ + protected ?array $having = null; /** * The queries to UNION @@ -49,14 +49,14 @@ class Select implements CommonTableExpressionInterface, LimitOffsetInterface, Or * * @var ?array */ - protected $union; + protected ?array $union = null; /** * Get whether to SELECT DISTINCT * * @return bool */ - public function getDistinct() + public function getDistinct(): bool { return $this->distinct; } @@ -68,7 +68,7 @@ public function getDistinct() * * @return $this */ - public function distinct($distinct = true) + public function distinct(bool $distinct = true): static { $this->distinct = $distinct; @@ -80,7 +80,7 @@ public function distinct($distinct = true) * * @return array */ - public function getColumns() + public function getColumns(): array { return $this->columns ?: []; } @@ -96,13 +96,12 @@ public function getColumns() * If you are using special column names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|ExpressionInterface|Select|array $columns The column(s) to add to the SELECT. - * The items can be any mix of the following: 'column', - * 'column as alias', ['alias' => 'column'] + * @param string|ExpressionInterface|self|array $columns The column(s) to add to the SELECT. + * The items can be any mix of the following: 'column', 'column as alias', ['alias' => 'column'] * * @return $this */ - public function columns($columns) + public function columns(string|ExpressionInterface|self|array $columns): static { if (! is_array($columns)) { $columns = [$columns]; @@ -116,9 +115,9 @@ public function columns($columns) /** * Get the FROM part of the query * - * @return array|null + * @return ?array */ - public function getFrom() + public function getFrom(): ?array { return $this->from; } @@ -129,17 +128,17 @@ public function getFrom() * Multiple calls to this method will not overwrite the previous set FROM part but append the tables to the FROM. * * Note that this method does NOT quote the tables you specify for the FROM. - * If you allow user input here, you must protected yourself against SQL injection using + * If you allow user input here, you must protect yourself against SQL injection using * {@link Connection::quoteIdentifier()} for the table names passed to this method. * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|Select|array $tables The table(s) to add to the FROM part. The items can be any mix of the - * following: ['table', 'table alias', 'alias' => 'table'] + * @param string|self|array $tables The table(s) to add to the FROM part. The items can be any mix of the + * following: ['table', 'table alias', 'alias' => 'table'] * * @return $this */ - public function from($tables) + public function from(string|self|array $tables): static { if (! is_array($tables)) { $tables = [$tables]; @@ -153,29 +152,30 @@ public function from($tables) /** * Get the JOIN part(s) of the query * - * @return array|null + * @return ?array */ - public function getJoin() + public function getJoin(): ?array { return $this->join; } /** - * Add a INNER JOIN part to the query + * Add an INNER JOIN part to the query * - * @param string|Select|array $table The table to be joined, can be any of the following: - * 'table' 'table alias' ['alias' => 'table'] - * @param string|ExpressionInterface|Select|array $condition The join condition, i.e. the ON part of the JOIN. - * Please see {@link WhereInterface::where()} - * for the supported formats and - * restrictions regarding quoting of the field names. - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|self|array $table The table to be joined, can be any of the following: + * 'table' 'table alias' ['alias' => 'table'] + * @param string|ExpressionInterface|self|array $condition The join condition, i.e. the ON part of the JOIN. + * Please see {@link WhereInterface::where()} for the supported formats and restrictions regarding quoting of the + * field names. + * @param string $operator The operator to combine multiple conditions with, if the condition is in the array format * * @return $this */ - public function join($table, $condition, $operator = Sql::ALL) - { + public function join( + string|self|array $table, + string|ExpressionInterface|self|array $condition, + string $operator = Sql::ALL + ): static { $this->join[] = ['INNER', $table, $this->buildCondition($condition, $operator)]; return $this; @@ -184,19 +184,20 @@ public function join($table, $condition, $operator = Sql::ALL) /** * Add a LEFT JOIN part to the query * - * @param string|Select|array $table The table to be joined, can be any of the following: - * 'table' 'table alias' ['alias' => 'table'] - * @param string|ExpressionInterface|Select|array $condition The join condition, i.e. the ON part of the JOIN. - * Please see {@link WhereInterface::where()} - * for the supported formats and - * restrictions regarding quoting of the field names. - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|self|array $table The table to be joined, can be any of the following: + * 'table' 'table alias' ['alias' => 'table'] + * @param string|ExpressionInterface|self|array $condition The join condition, i.e. the ON part of the JOIN. + * Please see {@link WhereInterface::where()} for the supported formats and restrictions regarding quoting of the + * field names. + * @param string $operator The operator to combine multiple conditions with, if the condition is in the array format * * @return $this */ - public function joinLeft($table, $condition, $operator = Sql::ALL) - { + public function joinLeft( + string|self|array $table, + string|ExpressionInterface|self|array $condition, + string $operator = Sql::ALL + ): static { $this->join[] = ['LEFT', $table, $this->buildCondition($condition, $operator)]; return $this; @@ -205,19 +206,20 @@ public function joinLeft($table, $condition, $operator = Sql::ALL) /** * Add a RIGHT JOIN part to the query * - * @param string|Select|array $table The table to be joined, can be any of the following: - * 'table' 'table alias' ['alias' => 'table'] - * @param string|ExpressionInterface|Select|array $condition The join condition, i.e. the ON part of the JOIN. - * Please see {@link WhereInterface::where()} - * for the supported formats and - * restrictions regarding quoting of the field names. - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|self|array $table The table to be joined, can be any of the following: + * 'table' 'table alias' ['alias' => 'table'] + * @param string|ExpressionInterface|self|array $condition The join condition, i.e. the ON part of the JOIN. + * Please see {@link WhereInterface::where()} for the supported formats and restrictions regarding quoting of the + * field names. + * @param string $operator The operator to combine multiple conditions with, if the condition is in the array format * * @return $this */ - public function joinRight($table, $condition, $operator = Sql::ALL) - { + public function joinRight( + string|self|array $table, + string|ExpressionInterface|self|array $condition, + string $operator = Sql::ALL + ): static { $this->join[] = ['RIGHT', $table, $this->buildCondition($condition, $operator)]; return $this; @@ -226,9 +228,9 @@ public function joinRight($table, $condition, $operator = Sql::ALL) /** * Get the GROUP BY part of the query * - * @return array|null + * @return ?array */ - public function getGroupBy() + public function getGroupBy(): ?array { return $this->groupBy; } @@ -237,7 +239,7 @@ public function getGroupBy() * Add a GROUP BY part to the query - either plain columns or expressions or scalar subqueries * * This method does NOT quote the columns you specify for the GROUP BY. - * If you allow user input here, you must protected yourself against SQL injection using + * If you allow user input here, you must protect yourself against SQL injection using * {@link Connection::quoteIdentifier()} for the field names passed to this method. * If you are using special field names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. @@ -245,14 +247,14 @@ public function getGroupBy() * Note that this method does not override an already set GROUP BY part. Instead, multiple calls to this function * add the specified GROUP BY part. * - * @param string|ExpressionInterface|Select|array $groupBy + * @param string|ExpressionInterface|self|array $groupBy * * @return $this */ - public function groupBy($groupBy) + public function groupBy(string|ExpressionInterface|self|array $groupBy): static { $this->groupBy = array_merge( - $this->groupBy === null ? [] : $this->groupBy, + $this->groupBy ?? [], is_array($groupBy) ? $groupBy : [$groupBy] ); @@ -262,9 +264,9 @@ public function groupBy($groupBy) /** * Get the HAVING part of the query * - * @return array|null + * @return ?array */ - public function getHaving() + public function getHaving(): ?array { return $this->having; } @@ -277,7 +279,7 @@ public function getHaving() * * Array format, e.g. ['id' => 1, ...] * * This method does NOT quote the columns you specify for the HAVING. - * If you allow user input here, you must protected yourself against SQL injection using + * If you allow user input here, you must protect yourself against SQL injection using * {@link Connection::quoteIdentifier()} for the field names passed to this method. * If you are using special field names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. @@ -285,13 +287,13 @@ public function getHaving() * Note that this method does not override an already set HAVING part. Instead, multiple calls to this function add * the specified HAVING part using the AND operator. * - * @param string|ExpressionInterface|Select|array $condition The HAVING condition - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|ExpressionInterface|self|array $condition The HAVING condition + * @param string $operator The operator to combine multiple conditions with, + * if the condition is in the array format * * @return $this */ - public function having($condition, $operator = Sql::ALL) + public function having(string|ExpressionInterface|self|array $condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::ALL); @@ -299,17 +301,17 @@ public function having($condition, $operator = Sql::ALL) } /** - * Add a OR part to the HAVING part of the query + * Add an OR part to the HAVING part of the query * * Please see {@link having()} for the supported formats and restrictions regarding quoting of the field names. * - * @param string|ExpressionInterface|Select|array $condition The HAVING condition - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|ExpressionInterface|self|array $condition The HAVING condition + * @param string $operator The operator to combine multiple conditions with, + * if the condition is in the array format * * @return $this */ - public function orHaving($condition, $operator = Sql::ALL) + public function orHaving(string|ExpressionInterface|self|array $condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::ANY); @@ -321,13 +323,13 @@ public function orHaving($condition, $operator = Sql::ALL) * * Please see {@link having()} for the supported formats and restrictions regarding quoting of the field names. * - * @param string|ExpressionInterface|Select|array $condition The HAVING condition - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|ExpressionInterface|self|array $condition The HAVING condition + * @param string $operator The operator to combine multiple conditions with, + * if the condition is in the array format * - * @return $this + * @return $this */ - public function notHaving($condition, $operator = Sql::ALL) + public function notHaving(string|ExpressionInterface|self|array $condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::NOT_ALL); @@ -339,13 +341,13 @@ public function notHaving($condition, $operator = Sql::ALL) * * Please see {@link having()} for the supported formats and restrictions regarding quoting of the field names. * - * @param string|ExpressionInterface|Select|array $condition The HAVING condition - * @param string $operator The operator to combine multiple conditions with, - * if the condition is in the array format + * @param string|ExpressionInterface|self|array $condition The HAVING condition + * @param string $operator The operator to combine multiple conditions with, + * if the condition is in the array format * * @return $this */ - public function orNotHaving($condition, $operator = Sql::ALL) + public function orNotHaving(string|ExpressionInterface|self|array $condition, string $operator = Sql::ALL): static { $this->mergeCondition($this->having, $this->buildCondition($condition, $operator), Sql::NOT_ANY); @@ -355,9 +357,9 @@ public function orNotHaving($condition, $operator = Sql::ALL) /** * Get the UNION parts of the query * - * @return array|null + * @return ?array */ - public function getUnion() + public function getUnion(): ?array { return $this->union; } @@ -365,11 +367,11 @@ public function getUnion() /** * Combine a query with UNION * - * @param Select|string $query + * @param string|self $query * * @return $this */ - public function union($query) + public function union(string|self $query): static { $this->union[] = [$query, false]; @@ -379,11 +381,11 @@ public function union($query) /** * Combine a query with UNION ALL * - * @param Select|string $query + * @param string|self $query * * @return $this */ - public function unionAll($query) + public function unionAll(string|self $query): static { $this->union[] = [$query, true]; @@ -395,7 +397,7 @@ public function unionAll($query) * * @return $this */ - public function resetDistinct() + public function resetDistinct(): static { $this->distinct = false; @@ -407,7 +409,7 @@ public function resetDistinct() * * @return $this */ - public function resetColumns() + public function resetColumns(): static { $this->columns = null; @@ -419,7 +421,7 @@ public function resetColumns() * * @return $this */ - public function resetFrom() + public function resetFrom(): static { $this->from = null; @@ -431,7 +433,7 @@ public function resetFrom() * * @return $this */ - public function resetJoin() + public function resetJoin(): static { $this->join = null; @@ -443,7 +445,7 @@ public function resetJoin() * * @return $this */ - public function resetGroupBy() + public function resetGroupBy(): static { $this->groupBy = null; @@ -455,7 +457,7 @@ public function resetGroupBy() * * @return $this */ - public function resetHaving() + public function resetHaving(): static { $this->having = null; @@ -467,7 +469,7 @@ public function resetHaving() * * @return $this */ - public function resetUnion() + public function resetUnion(): static { $this->union = null; @@ -477,9 +479,9 @@ public function resetUnion() /** * Get the count query * - * @return Select + * @return self */ - public function getCountQuery() + public function getCountQuery(): self { $countQuery = clone $this; @@ -488,7 +490,7 @@ public function getCountQuery() $countQuery->offset = null; if (! empty($countQuery->groupBy) || $countQuery->getDistinct()) { - $countQuery = (new Select())->from(['s' => $countQuery]); + $countQuery = (new self())->from(['s' => $countQuery]); $countQuery->distinct(false); } @@ -505,7 +507,7 @@ public function __clone() if ($this->columns !== null) { foreach ($this->columns as &$value) { - if ($value instanceof ExpressionInterface || $value instanceof Select) { + if ($value instanceof ExpressionInterface || $value instanceof self) { $value = clone $value; } } @@ -514,7 +516,7 @@ public function __clone() if ($this->from !== null) { foreach ($this->from as &$from) { - if ($from instanceof Select) { + if ($from instanceof self) { $from = clone $from; } } @@ -525,12 +527,12 @@ public function __clone() foreach ($this->join as &$join) { if (is_array($join[1])) { foreach ($join[1] as &$table) { - if ($table instanceof Select) { + if ($table instanceof self) { $table = clone $table; } } unset($table); - } elseif ($join[1] instanceof Select) { + } elseif ($join[1] instanceof self) { $join[1] = clone $join[1]; } @@ -541,7 +543,7 @@ public function __clone() if ($this->groupBy !== null) { foreach ($this->groupBy as &$value) { - if ($value instanceof ExpressionInterface || $value instanceof Select) { + if ($value instanceof ExpressionInterface || $value instanceof self) { $value = clone $value; } } diff --git a/src/Sql.php b/src/Sql.php index 000a43a..9c86057 100644 --- a/src/Sql.php +++ b/src/Sql.php @@ -33,17 +33,17 @@ class Sql * * @return Delete */ - public static function delete() + public static function delete(): Delete { return new Delete(); } /** - * Create and return a INSERT statement + * Create and return an INSERT statement * * @return Insert */ - public static function insert() + public static function insert(): Insert { return new Insert(); } @@ -53,7 +53,7 @@ public static function insert() * * @return Select */ - public static function select() + public static function select(): Select { return new Select(); } @@ -63,7 +63,7 @@ public static function select() * * @return Update */ - public static function update() + public static function update(): Update { return new Update(); } diff --git a/src/Test/SqlAssertions.php b/src/Test/SqlAssertions.php index 62d4ab0..1ee80dd 100644 --- a/src/Test/SqlAssertions.php +++ b/src/Test/SqlAssertions.php @@ -11,10 +11,10 @@ trait SqlAssertions { /** @var string The adapter to use */ - protected $adapterClass = TestAdapter::class; + protected string $adapterClass = TestAdapter::class; /** @var QueryBuilder */ - protected $queryBuilder; + protected QueryBuilder $queryBuilder; abstract public function setUp(): void; @@ -33,12 +33,16 @@ protected function setUpSqlAssertions(): void * * @return void */ - public function assertSql(string $sql, $statement, ?array $values = null, string $message = ''): void - { + public function assertSql( + string $sql, + Delete|Insert|Select|Update $statement, + ?array $values = null, + string $message = '' + ): void { // Reduce whitespaces to just one space $sql = preg_replace('/\s+/', ' ', trim($sql)); - list($stmt, $bind) = $this->queryBuilder->assemble($statement); + [$stmt, $bind] = $this->queryBuilder->assemble($statement); $this->assertSame($sql, $stmt, $message); diff --git a/src/Test/TestConnection.php b/src/Test/TestConnection.php index 11d0117..1e149b8 100644 --- a/src/Test/TestConnection.php +++ b/src/Test/TestConnection.php @@ -14,22 +14,22 @@ public function __construct() $this->adapter = new TestAdapter(); } - public function connect() + public function connect(): static { return $this; } - public function beginTransaction() + public function beginTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } - public function commitTransaction() + public function commitTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } - public function rollbackTransaction() + public function rollbackTransaction(): bool { throw new \LogicException('Transactions are not supported by the test connection'); } diff --git a/src/Update.php b/src/Update.php index 356a610..2ed9881 100644 --- a/src/Update.php +++ b/src/Update.php @@ -2,8 +2,6 @@ namespace ipl\Sql; -use InvalidArgumentException; - use function ipl\Stdlib\arrayval; /** @@ -14,18 +12,18 @@ class Update implements CommonTableExpressionInterface, WhereInterface use CommonTableExpression; use Where; - /** @var array|null The table for the UPDATE query */ - protected $table; + /** @var ?array The table for the UPDATE query */ + protected ?array $table = null; - /** @var array|null The columns to update in terms of column-value pairs */ - protected $set = []; + /** @var ?array The columns to update in terms of column-value pairs */ + protected ?array $set = []; /** * Get the table for the UPDATE query * - * @return array|null + * @return ?array */ - public function getTable() + public function getTable(): ?array { return $this->table; } @@ -34,17 +32,17 @@ public function getTable() * Set the table for the UPDATE query * * Note that this method does NOT quote the table you specify for the UPDATE. - * If you allow user input here, you must protected yourself against SQL injection using + * If you allow user input here, you must protect yourself against SQL injection using * {@link Connection::quoteIdentifier()} for the table names passed to this method. * If you are using special table names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. * - * @param string|array $table The table to update. The table specification must be in one of the - * following formats: 'table', 'table alias', ['alias' => 'table'] + * @param string|array $table The table to update. The table specification must be in one of the following formats: + * 'table', 'table alias', ['alias' => 'table'] * * @return $this */ - public function table($table) + public function table(string|array $table): static { $this->table = is_array($table) ? $table : [$table]; @@ -54,9 +52,9 @@ public function table($table) /** * Get the columns to update in terms of column-value pairs * - * @return array|null + * @return ?array */ - public function getSet() + public function getSet(): ?array { return $this->set; } @@ -75,10 +73,8 @@ public function getSet() * @param iterable $set Associative set of column-value pairs * * @return $this - * - * @throws InvalidArgumentException If set type is invalid */ - public function set($set) + public function set(iterable $set): static { $this->set = arrayval($set); diff --git a/src/Where.php b/src/Where.php index f862846..5d26c11 100644 --- a/src/Where.php +++ b/src/Where.php @@ -7,47 +7,47 @@ */ trait Where { - /** @var array|null Internal representation for the WHERE part of the query */ - protected $where; + /** @var ?array Internal representation for the WHERE part of the query */ + protected ?array $where = null; - public function getWhere() + public function getWhere(): ?array { return $this->where; } - public function where($condition, ...$args) + public function where(string|ExpressionInterface|Select|array $condition, mixed ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ALL); return $this; } - public function orWhere($condition, ...$args) + public function orWhere(string|ExpressionInterface|Select|array $condition, mixed ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::ANY); return $this; } - public function notWhere($condition, ...$args) + public function notWhere(string|ExpressionInterface|Select|array $condition, mixed ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ALL); return $this; } - public function orNotWhere($condition, ...$args) + public function orNotWhere(string|ExpressionInterface|Select|array $condition, mixed ...$args): static { - list($condition, $operator) = $this->prepareConditionArguments($condition, $args); + [$condition, $operator] = $this->prepareConditionArguments($condition, $args); $this->mergeCondition($this->where, $this->buildCondition($condition, $operator), Sql::NOT_ANY); return $this; } - public function resetWhere() + public function resetWhere(): static { $this->where = null; @@ -59,12 +59,12 @@ public function resetWhere() * * If $condition is empty, replace it with a boolean constant depending on the operator. * - * @param string|array $condition - * @param string $operator + * @param string|ExpressionInterface|Select|array $condition + * @param string $operator * * @return array */ - protected function buildCondition($condition, $operator) + protected function buildCondition(string|ExpressionInterface|Select|array $condition, string $operator): array { if (is_array($condition)) { if (empty($condition)) { @@ -82,11 +82,11 @@ protected function buildCondition($condition, $operator) /** * Merge the given condition with ours via the given operator * - * @param mixed $base Our condition - * @param array $condition As returned by {@link buildCondition()} + * @param ?array $base Our condition + * @param array $condition As returned by {@link buildCondition()} * @param string $operator */ - protected function mergeCondition(&$base, array $condition, $operator) + protected function mergeCondition(?array &$base, array $condition, string $operator): void { if ($base === null) { $base = [$operator, [$condition]]; @@ -106,12 +106,12 @@ protected function mergeCondition(&$base, array $condition, $operator) /** * Prepare condition arguments from the different supported where styles * - * @param mixed $condition + * @param string|ExpressionInterface|Select|array $condition * @param array $args * * @return array */ - protected function prepareConditionArguments($condition, array $args) + protected function prepareConditionArguments(string|ExpressionInterface|Select|array $condition, array $args): array { // Default operator $operator = Sql::ALL; @@ -132,7 +132,7 @@ protected function prepareConditionArguments($condition, array $args) * * Shall be called by using classes in their __clone() */ - protected function cloneWhere() + protected function cloneWhere(): void { if ($this->where !== null) { $this->cloneCondition($this->where); @@ -144,7 +144,7 @@ protected function cloneWhere() * * @param array $condition As returned by {@link buildCondition()} */ - protected function cloneCondition(array &$condition) + protected function cloneCondition(array &$condition): void { foreach ($condition as &$subCondition) { if (is_array($subCondition)) { diff --git a/src/WhereInterface.php b/src/WhereInterface.php index e724465..2813323 100644 --- a/src/WhereInterface.php +++ b/src/WhereInterface.php @@ -10,9 +10,9 @@ interface WhereInterface /** * Get the WHERE part of the query * - * @return array|null + * @return ?array */ - public function getWhere(); + public function getWhere(): ?array; /** * Add a WHERE part of the query @@ -22,7 +22,7 @@ public function getWhere(); * * Array format, e.g. ['id = ?' => 1, ...], i.e. `where(array $condition [, string $operator])` * * This method does NOT quote the columns you specify for the WHERE. - * If you allow user input here, you must protected yourself against SQL injection using + * If you allow user input here, you must protect yourself against SQL injection using * {@link Connection::quoteIdentifier()} for the field names passed to this method. * If you are using special field names, e.g. reserved keywords for your DBMS, you are required to use * {@link Connection::quoteIdentifier()} as well. @@ -32,12 +32,12 @@ public function getWhere(); * * @param string|ExpressionInterface|Select|array $condition The WHERE condition * @param mixed $args If condition is a string, parameter values for placeholders in the condition can be passed. - * If condition is an array, the only argument that is allowed is the operator to use to combine - * these conditions. By default, this operator is {@link Sql::ALL} (AND) + * If condition is an array, the only argument that is allowed is the operator to use to combine these conditions. + * By default, this operator is {@link Sql::ALL} (AND) * * @return $this */ - public function where($condition, ...$args); + public function where(string|ExpressionInterface|Select|array $condition, mixed ...$args): static; /** * Add a OR part to the WHERE part of the query @@ -45,11 +45,11 @@ public function where($condition, ...$args); * Please see {@link where()} for the supported formats and restrictions regarding quoting of the field names. * * @param string|ExpressionInterface|Select|array $condition The WHERE condition - * @param mixed ...$args Please see {@link where()} for details + * @param mixed ...$args Please see {@link where()} for details * * @return $this */ - public function orWhere($condition, ...$args); + public function orWhere(string|ExpressionInterface|Select|array $condition, mixed ...$args): static; /** * Add a AND NOT part to the WHERE part of the query @@ -57,28 +57,28 @@ public function orWhere($condition, ...$args); * Please see {@link where()} for the supported formats and restrictions regarding quoting of the field names. * * @param string|ExpressionInterface|Select|array $condition The WHERE condition - * @param mixed ...$args Please see {@link where()} for details + * @param mixed ...$args Please see {@link where()} for details * * @return $this */ - public function notWhere($condition, ...$args); + public function notWhere(string|ExpressionInterface|Select|array $condition, mixed ...$args): static; /** - * Add a OR NOT part to the WHERE part of the query + * Add an OR NOT part to the WHERE part of the query * * Please see {@link where()} for the supported formats and restrictions regarding quoting of the field names. * * @param string|ExpressionInterface|Select|array $condition The WHERE condition - * @param mixed ...$args Please see {@link where()} for details + * @param mixed ...$args Please see {@link where()} for details * * @return $this */ - public function orNotWhere($condition, ...$args); + public function orNotWhere(string|ExpressionInterface|Select|array $condition, mixed ...$args): static; /** * Reset the WHERE part of the query * * @return $this */ - public function resetWhere(); + public function resetWhere(): static; } diff --git a/tests/ConfigTest.php b/tests/ConfigTest.php index 58d0324..4f3183e 100644 --- a/tests/ConfigTest.php +++ b/tests/ConfigTest.php @@ -52,7 +52,7 @@ public function testAllPropertiesCanBeSet(): void 'password' => 'test_password', 'use_ssl' => 'true', 'charset' => 'latin1', - 'options' => 'test_options', + 'options' => ['test_options'], 'ssl_key' => 'test_ssl_key', 'ssl_cert' => 'test_ssl_cert', 'ssl_ca' => 'test_ssl_ca', @@ -69,7 +69,7 @@ public function testAllPropertiesCanBeSet(): void $this->assertSame($config->password, 'test_password'); $this->assertSame($config->useSsl, 'true'); $this->assertSame($config->charset, 'latin1'); - $this->assertSame($config->options, 'test_options'); + $this->assertSame($config->options, ['test_options']); $this->assertSame($config->sslKey, 'test_ssl_key'); $this->assertSame($config->sslCert, 'test_ssl_cert'); $this->assertSame($config->sslCa, 'test_ssl_ca'); diff --git a/tests/DeleteTest.php b/tests/DeleteTest.php index d0d37d0..02d5d0a 100644 --- a/tests/DeleteTest.php +++ b/tests/DeleteTest.php @@ -19,7 +19,7 @@ public function testFrom() $this->query->from('table'); $this->assertSame(['table'], $this->query->getFrom()); - $this->assertCorrectStatementAndValues('DELETE FROM table', []); + $this->assertSql('DELETE FROM table', $this->query, []); } public function testFromWithAlias() @@ -28,7 +28,7 @@ public function testFromWithAlias() $this->query->from('table t1'); $this->assertSame(['table t1'], $this->query->getFrom()); - $this->assertCorrectStatementAndValues('DELETE FROM table t1', []); + $this->assertSql('DELETE FROM table t1', $this->query, []); } public function testFromWithArray() @@ -37,6 +37,6 @@ public function testFromWithArray() $this->query->from(['t1' => 'table']); $this->assertSame(['t1' => 'table'], $this->query->getFrom()); - $this->assertCorrectStatementAndValues('DELETE FROM table t1', []); + $this->assertSql('DELETE FROM table t1', $this->query, []); } } diff --git a/tests/HavingTest.php b/tests/HavingTest.php index 84d65b9..128067c 100644 --- a/tests/HavingTest.php +++ b/tests/HavingTest.php @@ -9,19 +9,15 @@ class HavingTest extends TestCase { public function testHavingStringFormat() { - $this->setupTest(); - $this->query->having('c1 = x'); $this->query->having('c2 IS NULL'); $this->query->having('c3 IS NOT NULL'); - $this->assertCorrectStatementAndValues('HAVING (c1 = x) AND (c2 IS NULL) AND (c3 IS NOT NULL)', []); + $this->assertSql('HAVING (c1 = x) AND (c2 IS NULL) AND (c3 IS NOT NULL)', $this->query, []); } public function testHavingArrayFormat() { - $this->setupTest(); - $this->query->having(['c1 = x']); $this->query->having(['c2 = ?' => 1]); $this->query->having(['c3 > ?' => 1]); @@ -30,37 +26,32 @@ public function testHavingArrayFormat() $this->query->having(['c6 IN (?)' => [1, 2, 3]]); $this->query->having(['c7 = ?' => 1, 'c8 = ?' => 1]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'HAVING (c1 = x) AND (c2 = ?) AND (c3 > ?) AND (c4 IS NULL)' . ' AND (c5 IS NOT NULL) AND (c6 IN (?, ?, ?)) AND ((c7 = ?) AND (c8 = ?))', + $this->query, [1, 1, 1, 2, 3, 1, 1] ); } public function testWhereWithExpression() { - $this->setupTest(); - $expression = new Expression('c2 = ?', null, 1); $this->query->having($expression); - $this->assertCorrectStatementAndValues('HAVING c2 = ?', [1]); + $this->assertSql('HAVING c2 = ?', $this->query, [1]); } public function testWhereWithSelect() { - $this->setupTest(); - $select = (new Select())->columns('COUNT(*)')->from('t1')->where(['c2 = ?' => 1]); $this->query->having($select); - $this->assertCorrectStatementAndValues('HAVING (SELECT COUNT(*) FROM t1 WHERE c2 = ?)', [1]); + $this->assertSql('HAVING (SELECT COUNT(*) FROM t1 WHERE c2 = ?)', $this->query, [1]); } public function testResetHaving() { - $this->setupTest(); - $this->query->having('c1 = x'); $this->assertSame( ['AND', [['AND', ['c1 = x']]]], diff --git a/tests/InsertTest.php b/tests/InsertTest.php index 1f3959d..119ae63 100644 --- a/tests/InsertTest.php +++ b/tests/InsertTest.php @@ -8,104 +8,86 @@ class InsertTest extends TestCase { - protected $queryClass = Insert::class; + protected string $queryClass = Insert::class; /** @var Insert */ protected $query; public function testEmptyInsertInto() { - $this->setupTest(); - $this->assertSame(null, $this->query->getInto()); $this->assertSame([], $this->query->getColumns()); $this->assertSame([], $this->query->getValues()); $this->assertSame(null, $this->query->getSelect()); - $this->assertCorrectStatementAndValues('() VALUES()', []); // TODO(el): Should we render anything here? + $this->assertSql('() VALUES()', $this->query, []); // TODO(el): Should we render anything here? } public function testIntoTableSpecification() { - $this->setupTest(); - $this->query->into('table'); $this->assertSame('table', $this->query->getInto()); - $this->assertCorrectStatementAndValues('INSERT INTO table () VALUES()', []); + $this->assertSql('INSERT INTO table () VALUES()', $this->query, []); } public function testIntoTableSpecificationWithSchema() { - $this->setupTest(); - $this->query->into('schema.table'); $this->assertSame('schema.table', $this->query->getInto()); - $this->assertCorrectStatementAndValues('INSERT INTO schema.table () VALUES()', []); + $this->assertSql('INSERT INTO schema.table () VALUES()', $this->query, []); } public function testColumns() { - $this->setupTest(); - $columns = ['c1', 'c2']; $this->query->columns($columns); $this->assertSame($columns, $this->query->getColumns()); - $this->assertCorrectStatementAndValues('(c1,c2) VALUES()', []); + $this->assertSql('(c1,c2) VALUES()', $this->query, []); } public function testValues() { - $this->setupTest(); - $this->query->values(['c1' => 'v1']); $this->assertSame(['c1'], $this->query->getColumns()); $this->assertSame(['v1'], $this->query->getValues()); - $this->assertCorrectStatementAndValues('(c1) VALUES(?)', ['v1']); + $this->assertSql('(c1) VALUES(?)', $this->query, ['v1']); } public function testExpressionValue() { - $this->setupTest(); - $value = new Expression('x = ?', null, 1); $this->query->values(['c1' => $value]); $this->assertSame(['c1'], $this->query->getColumns()); $this->assertSame([$value], $this->query->getValues()); - $this->assertCorrectStatementAndValues('(c1) VALUES(x = ?)', [1]); + $this->assertSql('(c1) VALUES(x = ?)', $this->query, [1]); } public function testSelectValue() { - $this->setupTest(); - $value = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->values(['c1' => $value]); $this->assertSame(['c1'], $this->query->getColumns()); $this->assertSame([$value], $this->query->getValues()); - $this->assertCorrectStatementAndValues('(c1) VALUES((SELECT COUNT(*) FROM table2 WHERE active = ?))', [1]); + $this->assertSql('(c1) VALUES((SELECT COUNT(*) FROM table2 WHERE active = ?))', $this->query, [1]); } public function testColumnsAndValues() { - $this->setupTest(); - $this->query->columns(['c1', 'c2']); $this->query->values(['v1', 'v2']); $this->assertSame(['c1', 'c2'], $this->query->getColumns()); $this->assertSame(['v1', 'v2'], $this->query->getValues()); - $this->assertCorrectStatementAndValues('(c1,c2) VALUES(?,?)', ['v1', 'v2']); + $this->assertSql('(c1,c2) VALUES(?,?)', $this->query, ['v1', 'v2']); } public function testInsertIntoSelectStatement() { - $this->setupTest(); - $select = (new Select()) ->from('table') ->columns(['c1', 'c2']); @@ -116,29 +98,25 @@ public function testInsertIntoSelectStatement() ->select($select); $this->assertSame($select, $this->query->getSelect()); - $this->assertCorrectStatementAndValues('INSERT INTO table (c1,c2) SELECT c1, c2 FROM table', []); + $this->assertSql('INSERT INTO table (c1,c2) SELECT c1, c2 FROM table', $this->query, []); } public function testInsertIntoStatementWithValues() { - $this->setupTest(); - $this->query ->into('table') ->values(['c1' => 'v1', 'c2' => 'v2']); - $this->assertCorrectStatementAndValues('INSERT INTO table (c1,c2) VALUES(?,?)', ['v1', 'v2']); + $this->assertSql('INSERT INTO table (c1,c2) VALUES(?,?)', $this->query, ['v1', 'v2']); } public function testInsertIntoStatementWithColumnsAndValues() { - $this->setupTest(); - $this->query ->into('table') ->columns(['c1', 'c2']) ->values(['v1', 'v2']); - $this->assertCorrectStatementAndValues('INSERT INTO table (c1,c2) VALUES(?,?)', ['v1', 'v2']); + $this->assertSql('INSERT INTO table (c1,c2) VALUES(?,?)', $this->query, ['v1', 'v2']); } } diff --git a/tests/Mssql/SelectTest.php b/tests/Mssql/SelectTest.php index 65652de..18fc9ee 100644 --- a/tests/Mssql/SelectTest.php +++ b/tests/Mssql/SelectTest.php @@ -7,41 +7,33 @@ class SelectTest extends TestCase { - protected $adapterClass = Mssql::class; + protected string $adapterClass = Mssql::class; public function testLimitOffset() { - $this->setupTest(); - $this->query->columns('a')->from('b')->orderBy('a')->limit(10)->offset(20); - $this->assertCorrectStatementAndValues('SELECT a FROM b ORDER BY a OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY'); + $this->assertSql('SELECT a FROM b ORDER BY a OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY', $this->query); } public function testLimitWithoutOffset() { - $this->setupTest(); - $this->query->columns('a')->from('b')->orderBy('a')->limit(10); - $this->assertCorrectStatementAndValues('SELECT a FROM b ORDER BY a OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY'); + $this->assertSql('SELECT a FROM b ORDER BY a OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', $this->query); } public function testOffsetWithoutLimit() { - $this->setupTest(); - $this->query->columns('a')->from('b')->orderBy('a')->offset(20); - $this->assertCorrectStatementAndValues('SELECT a FROM b ORDER BY a OFFSET 20 ROWS'); + $this->assertSql('SELECT a FROM b ORDER BY a OFFSET 20 ROWS', $this->query); } public function testAutomaticallyFixesLimitWithoutOrder() { - $this->setupTest(); - $this->query->columns('a')->from('b')->limit(10)->offset(30); - $this->assertCorrectStatementAndValues('SELECT a FROM b ORDER BY 1 OFFSET 30 ROWS FETCH NEXT 10 ROWS ONLY'); + $this->assertSql('SELECT a FROM b ORDER BY 1 OFFSET 30 ROWS FETCH NEXT 10 ROWS ONLY', $this->query); } } diff --git a/tests/SelectTest.php b/tests/SelectTest.php index 03b1246..ca90d9a 100644 --- a/tests/SelectTest.php +++ b/tests/SelectTest.php @@ -11,71 +11,57 @@ class SelectTest extends TestCase { public function testDistinct() { - $this->setupTest(); - $this->query ->distinct() ->columns('1'); $this->assertSame(true, $this->query->getDistinct()); - $this->assertCorrectStatementAndValues('SELECT DISTINCT 1', []); + $this->assertSql('SELECT DISTINCT 1', $this->query, []); } public function testColumns() { - $this->setupTest(); - $this->query->columns('1'); $this->assertSame(['1'], $this->query->getColumns()); - $this->assertCorrectStatementAndValues('SELECT 1', []); + $this->assertSql('SELECT 1', $this->query, []); } public function testColumnsWithAlias() { - $this->setupTest(); - $this->query->columns('1 AS one'); $this->assertSame(['1 AS one'], $this->query->getColumns()); - $this->assertCorrectStatementAndValues('SELECT 1 AS one', []); + $this->assertSql('SELECT 1 AS one', $this->query, []); } public function testColumnsWithArray() { - $this->setupTest(); - $this->query->columns(['1', '2']); $this->assertSame(['1', '2'], $this->query->getColumns()); - $this->assertCorrectStatementAndValues('SELECT 1, 2', []); + $this->assertSql('SELECT 1, 2', $this->query, []); } public function testColumnsWithArrayAndAlias() { - $this->setupTest(); - $this->query->columns(['one' => '1', '2']); $this->assertSame(['one' => '1', '2'], $this->query->getColumns()); - $this->assertCorrectStatementAndValues('SELECT 1 AS one, 2', []); + $this->assertSql('SELECT 1 AS one, 2', $this->query, []); } public function testColumnsWithExpression() { - $this->setupTest(); - $columns = ['three' => new Expression('? + ?', null, 1, 2)]; $this->query->columns($columns); $this->assertSame($columns, $this->query->getColumns()); - $this->assertCorrectStatementAndValues('SELECT (? + ?) AS three', [1, 2]); + $this->assertSql('SELECT (? + ?) AS three', $this->query, [1, 2]); } public function testColumnsWithSelect() { - $this->setupTest(); - $columns = [ 'customers' => (new Select()) ->columns('COUNT(*)') @@ -86,46 +72,39 @@ public function testColumnsWithSelect() $this->query->columns($columns); $this->assertSame($columns, $this->query->getColumns()); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT (SELECT COUNT(*) FROM customers WHERE ctime > ?) AS customers', + $this->query, [1234567890] ); } public function testFrom() { - $this->setupTest(); - $this->query->from('table'); $this->assertSame(['table'], $this->query->getFrom()); - $this->assertCorrectStatementAndValues('FROM table', []); + $this->assertSql('FROM table', $this->query, []); } public function testFromWithAlias() { - $this->setupTest(); - $this->query->from('table t1'); $this->assertSame(['table t1'], $this->query->getFrom()); - $this->assertCorrectStatementAndValues('FROM table t1', []); + $this->assertSql('FROM table t1', $this->query, []); } public function testFromWithArray() { - $this->setupTest(); - $this->query->from(['t1' => 'table']); $this->assertSame(['t1' => 'table'], $this->query->getFrom()); - $this->assertCorrectStatementAndValues('FROM table t1', []); + $this->assertSql('FROM table t1', $this->query, []); } public function testFromWithSelect() { - $this->setupTest(); - $from = ['t1' => (new Select()) ->columns('*') ->from('table') @@ -134,456 +113,393 @@ public function testFromWithSelect() $this->query->from($from); $this->assertSame($from, $this->query->getFrom()); - $this->assertCorrectStatementAndValues('FROM (SELECT * FROM table WHERE ctime > ?) t1', [1234567890]); + $this->assertSql('FROM (SELECT * FROM table WHERE ctime > ?) t1', $this->query, [1234567890]); } public function testInnerJoin() { - $this->setupTest(); - $this->query->join('table2', 'table2.table1_id = table1.id'); - $this->assertCorrectStatementAndValues('INNER JOIN table2 ON table2.table1_id = table1.id', []); + $this->assertSql('INNER JOIN table2 ON table2.table1_id = table1.id', $this->query, []); } public function testInnerJoinWithAlias() { - $this->setupTest(); - $this->query->join('table2 t2', 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues('INNER JOIN table2 t2 ON t2.table1_id = t1.id', []); + $this->assertSql('INNER JOIN table2 t2 ON t2.table1_id = t1.id', $this->query, []); } public function testInnerJoinWithArray() { - $this->setupTest(); - $this->query->join(['t2' => 'table2'], 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues('INNER JOIN table2 t2 ON t2.table1_id = t1.id', []); + $this->assertSql('INNER JOIN table2 t2 ON t2.table1_id = t1.id', $this->query, []); } public function testInnerJoinWithComplexCondition() { - $this->setupTest(); - $this->query->join('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42']); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'INNER JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = 42)', + $this->query, [] ); } public function testInnerJoinWithOperatorAll() { - $this->setupTest(); - $this->query->join('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42'], Sql::ALL); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'INNER JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = 42)', + $this->query, [] ); } public function testInnerJoinWithOperatorAny() { - $this->setupTest(); - $this->query->join('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42'], Sql::ANY); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'INNER JOIN table2 ON (table2.table1_id = table1.id) OR (table2.table3_id = 42)', + $this->query, [] ); } public function testInnerJoinWithParametrizedCondition() { - $this->setupTest(); - $this->query->join('table2', ['table2.table1_id = table1.id', 'table2.table3_id = ?' => 42]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'INNER JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = ?)', + $this->query, [42] ); } public function testInnerJoinWithSelect() { - $this->setupTest(); - $table2 = ['t2' => (new Select())->columns('*')->from('table2')->where(['active = ?' => 1])]; $this->query->join($table2, 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'INNER JOIN (SELECT * FROM table2 WHERE active = ?) t2 ON t2.table1_id = t1.id', + $this->query, [1] ); } public function testInnerJoinWithExpressionCondition() { - $this->setupTest(); - $condition = new Expression('t2.table1_id = ?', null, 1); $this->query->join('table2', $condition); - $this->assertCorrectStatementAndValues('INNER JOIN table2 ON t2.table1_id = ?', [1]); + $this->assertSql('INNER JOIN table2 ON t2.table1_id = ?', $this->query, [1]); } public function testInnerJoinWithSelectCondition() { - $this->setupTest(); - $condition = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->join('table2', $condition); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'INNER JOIN table2 ON (SELECT COUNT(*) FROM table2 WHERE active = ?)', + $this->query, [1] ); } public function testLeftJoin() { - $this->setupTest(); - $this->query->joinLeft('table2', 'table2.table1_id = table1.id'); - $this->assertCorrectStatementAndValues('LEFT JOIN table2 ON table2.table1_id = table1.id', []); + $this->assertSql('LEFT JOIN table2 ON table2.table1_id = table1.id', $this->query, []); } public function testLeftJoinWithAlias() { - $this->setupTest(); - $this->query->joinLeft('table2 t2', 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues('LEFT JOIN table2 t2 ON t2.table1_id = t1.id', []); + $this->assertSql('LEFT JOIN table2 t2 ON t2.table1_id = t1.id', $this->query, []); } public function testLeftJoinWithArray() { - $this->setupTest(); - $this->query->joinLeft(['t2' => 'table2'], 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues('LEFT JOIN table2 t2 ON t2.table1_id = t1.id', []); + $this->assertSql('LEFT JOIN table2 t2 ON t2.table1_id = t1.id', $this->query, []); } public function testLeftJoinWithComplexCondition() { - $this->setupTest(); - $this->query->joinLeft('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42']); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'LEFT JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = 42)', + $this->query, [] ); } public function testLeftJoinWithOperatorAll() { - $this->setupTest(); - $this->query->joinLeft('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42'], Sql::ALL); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'LEFT JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = 42)', + $this->query, [] ); } public function testLeftJoinWithOperatorAny() { - $this->setupTest(); - $this->query->joinLeft('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42'], Sql::ANY); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'LEFT JOIN table2 ON (table2.table1_id = table1.id) OR (table2.table3_id = 42)', + $this->query, [] ); } public function testLeftJoinWithParametrizedCondition() { - $this->setupTest(); - $this->query->joinLeft('table2', ['table2.table1_id = table1.id', 'table2.table3_id = ?' => 42]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'LEFT JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = ?)', + $this->query, [42] ); } public function testLeftJoinWithSelect() { - $this->setupTest(); - $table2 = ['t2' => (new Select())->columns('*')->from('table2')->where(['active = ?' => 1])]; $this->query->joinLeft($table2, 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'LEFT JOIN (SELECT * FROM table2 WHERE active = ?) t2 ON t2.table1_id = t1.id', + $this->query, [1] ); } public function testLeftJoinWithExpressionCondition() { - $this->setupTest(); - $condition = new Expression('t2.table1_id = ?', null, 1); $this->query->joinLeft('table2', $condition); - $this->assertCorrectStatementAndValues('LEFT JOIN table2 ON t2.table1_id = ?', [1]); + $this->assertSql('LEFT JOIN table2 ON t2.table1_id = ?', $this->query, [1]); } public function testLeftJoinWithSelectCondition() { - $this->setupTest(); - $condition = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->joinLeft('table2', $condition); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'LEFT JOIN table2 ON (SELECT COUNT(*) FROM table2 WHERE active = ?)', + $this->query, [1] ); } public function testRightJoin() { - $this->setupTest(); - $this->query->joinRight('table2', 'table2.table1_id = table1.id'); - $this->assertCorrectStatementAndValues('RIGHT JOIN table2 ON table2.table1_id = table1.id', []); + $this->assertSql('RIGHT JOIN table2 ON table2.table1_id = table1.id', $this->query, []); } public function testRightJoinWithAlias() { - $this->setupTest(); - $this->query->joinRight('table2 t2', 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues('RIGHT JOIN table2 t2 ON t2.table1_id = t1.id', []); + $this->assertSql('RIGHT JOIN table2 t2 ON t2.table1_id = t1.id', $this->query, []); } public function testRightJoinWithArray() { - $this->setupTest(); - $this->query->joinRight(['t2' => 'table2'], 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues('RIGHT JOIN table2 t2 ON t2.table1_id = t1.id', []); + $this->assertSql('RIGHT JOIN table2 t2 ON t2.table1_id = t1.id', $this->query, []); } public function testRightJoinWithComplexCondition() { - $this->setupTest(); - $this->query->joinRight('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42']); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'RIGHT JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = 42)', + $this->query, [] ); } public function testRightJoinWithOperatorAll() { - $this->setupTest(); - $this->query->joinRight('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42'], Sql::ALL); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'RIGHT JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = 42)', + $this->query, [] ); } public function testRightJoinWithOperatorAny() { - $this->setupTest(); - $this->query->joinRight('table2', ['table2.table1_id = table1.id', 'table2.table3_id = 42'], Sql::ANY); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'RIGHT JOIN table2 ON (table2.table1_id = table1.id) OR (table2.table3_id = 42)', + $this->query, [] ); } public function testRightJoinWithParametrizedCondition() { - $this->setupTest(); - $this->query->joinRight('table2', ['table2.table1_id = table1.id', 'table2.table3_id = ?' => 42]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'RIGHT JOIN table2 ON (table2.table1_id = table1.id) AND (table2.table3_id = ?)', + $this->query, [42] ); } public function testRightJoinWithSelect() { - $this->setupTest(); - $table2 = ['t2' => (new Select())->columns('*')->from('table2')->where(['active = ?' => 1])]; $this->query->joinRight($table2, 't2.table1_id = t1.id'); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'RIGHT JOIN (SELECT * FROM table2 WHERE active = ?) t2 ON t2.table1_id = t1.id', + $this->query, [1] ); } public function testRightJoinWithExpressionCondition() { - $this->setupTest(); - $condition = new Expression('t2.table1_id = ?', null, 1); $this->query->joinRight('table2', $condition); - $this->assertCorrectStatementAndValues('RIGHT JOIN table2 ON t2.table1_id = ?', [1]); + $this->assertSql('RIGHT JOIN table2 ON t2.table1_id = ?', $this->query, [1]); } public function testRightJoinWithSelectCondition() { - $this->setupTest(); - $condition = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->joinRight('table2', $condition); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'RIGHT JOIN table2 ON (SELECT COUNT(*) FROM table2 WHERE active = ?)', + $this->query, [1] ); } public function testGroupBy() { - $this->setupTest(); - $this->query->groupBy(['a', 'b']); - $this->assertCorrectStatementAndValues('GROUP BY a, b', []); + $this->assertSql('GROUP BY a, b', $this->query, []); } public function testGroupByWithAlias() { - $this->setupTest(); - $this->query->groupBy(['t.a', 't.b']); - $this->assertCorrectStatementAndValues('GROUP BY t.a, t.b', []); + $this->assertSql('GROUP BY t.a, t.b', $this->query, []); } public function testGroupByWithExpression() { - $this->setupTest(); - $column = new Expression('x = ?', null, 1); $this->query->groupBy([$column]); - $this->assertCorrectStatementAndValues('GROUP BY x = ?', [1]); + $this->assertSql('GROUP BY x = ?', $this->query, [1]); } public function testGroupByWithSelect() { - $this->setupTest(); - $column = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->groupBy([$column]); - $this->assertCorrectStatementAndValues('GROUP BY (SELECT COUNT(*) FROM table2 WHERE active = ?)', [1]); + $this->assertSql('GROUP BY (SELECT COUNT(*) FROM table2 WHERE active = ?)', $this->query, [1]); } public function testOrderBy() { - $this->setupTest(); - $this->query->orderBy(['a', 'b' => 'ASC'], 'DESC'); - $this->assertCorrectStatementAndValues('ORDER BY a DESC, b ASC', []); + $this->assertSql('ORDER BY a DESC, b ASC', $this->query, []); } public function testOrderByWithExpression() { - $this->setupTest(); - $column = new Expression('x = ?', null, 1); $this->query->orderBy($column, 'DESC'); - $this->assertCorrectStatementAndValues('ORDER BY x = ? DESC', [1]); + $this->assertSql('ORDER BY x = ? DESC', $this->query, [1]); } public function testOrderByWithExpressionAndExplicitDirection() { - $this->setupTest(); - $column = new Expression('x = ?', null, 1); $this->query->orderBy([[$column, 'DESC']]); - $this->assertCorrectStatementAndValues('ORDER BY x = ? DESC', [1]); + $this->assertSql('ORDER BY x = ? DESC', $this->query, [1]); } public function testOrderByWithSelect() { - $this->setupTest(); - $column = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->orderBy($column, 'DESC'); - $this->assertCorrectStatementAndValues('ORDER BY (SELECT COUNT(*) FROM table2 WHERE active = ?) DESC', [1]); + $this->assertSql('ORDER BY (SELECT COUNT(*) FROM table2 WHERE active = ?) DESC', $this->query, [1]); } public function testLimitOffset() { - $this->setupTest(); - $this->query = (new Select())->columns(['a'])->from('b')->limit(4)->offset(1); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT a FROM b LIMIT 4 OFFSET 1', + $this->query, [] ); } public function testLimitWithoutOffset() { - $this->setupTest(); - $this->query = (new Select())->columns(['a'])->from('b')->limit(4); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT a FROM b LIMIT 4', + $this->query, [] ); } public function testOffsetWithoutLimit() { - $this->setupTest(); - $this->query = (new Select())->columns(['a'])->from('b')->offset(1); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT a FROM b OFFSET 1', + $this->query, [] ); } public function testUnion() { - $this->setupTest(); - $unionQuery = (new Select()) ->columns('a') ->from('table2') @@ -595,16 +511,15 @@ public function testUnion() ->where(['b > ?' => 1]) ->union($unionQuery); - $this->assertCorrectStatementAndValues( + $this->assertSql( '(SELECT a FROM table1 WHERE b > ?) UNION (SELECT a FROM table2 WHERE b < ?)', + $this->query, [1, 2] ); } public function testUnionAll() { - $this->setupTest(); - $unionQuery = (new Select()) ->columns('a') ->from('table2') @@ -616,16 +531,15 @@ public function testUnionAll() ->where(['b > ?' => 1]) ->unionAll($unionQuery); - $this->assertCorrectStatementAndValues( + $this->assertSql( '(SELECT a FROM table1 WHERE b > ?) UNION ALL (SELECT a FROM table2 WHERE b < ?)', + $this->query, [1, 2] ); } public function testElementOrder() { - $this->setupTest(); - $this->query ->distinct() ->columns(['c.id', 'c.name', 'orders' => 'COUNT(o.customer)']) @@ -641,21 +555,20 @@ public function testElementOrder() ->limit(25) ->unionAll((new Select())->columns(['id' => -1, 'name' => "''", 'orders' => -1])); - $this->assertCorrectStatementAndValues( + $this->assertSql( "(SELECT DISTINCT c.id, c.name, COUNT(o.customer) AS orders" . " FROM customer c LEFT JOIN order o ON o.customer = c.id" . " WHERE (c.name LIKE ?) OR (c.name LIKE ?)" . " GROUP BY c.id HAVING (COUNT(o.customer) >= ?) OR (COUNT(o.customer) <= ?)" . " ORDER BY COUNT(o.customer), c.name LIMIT 25 OFFSET 75)" . " UNION ALL (SELECT -1 AS id, '' AS name, -1 AS orders)", + $this->query, ['%Doe%', '%Deo%', 42, 3] ); } public function testRollupMysql() { - $this->setupTest(); - $this->query ->columns([ 'division' => 'di.name', @@ -667,20 +580,19 @@ public function testRollupMysql() ->joinRight('division di', 'di.id = de.division') ->groupBy(['di.id', 'de.id WITH ROLLUP']); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT di.name AS division, de.name AS department, COUNT(e.id) AS employees' . ' FROM employee e' . ' RIGHT JOIN department de ON de.id = e.department' . ' RIGHT JOIN division di ON di.id = de.division' . ' GROUP BY di.id, de.id WITH ROLLUP', + $this->query, [] ); } public function testRollupPostgresql() { - $this->setupTest(); - $this->query ->columns([ 'division' => 'di.name', @@ -692,20 +604,19 @@ public function testRollupPostgresql() ->joinRight('division di', 'di.id = de.division') ->groupBy(['ROLLUP (di.id, de.id)']); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT di.name AS division, de.name AS department, COUNT(e.id) AS employees' . ' FROM employee e' . ' RIGHT JOIN department de ON de.id = e.department' . ' RIGHT JOIN division di ON di.id = de.division' . ' GROUP BY ROLLUP (di.id, de.id)', + $this->query, [] ); } public function testJustAUnionRendersAsSelect() { - $this->setupTest(); - $unionQuery = (new Select()) ->columns('a') ->from('table2') @@ -714,16 +625,15 @@ public function testJustAUnionRendersAsSelect() $this->query ->union($unionQuery); - $this->assertCorrectStatementAndValues( + $this->assertSql( '(SELECT a FROM table2 WHERE b < ?)', + $this->query, [2] ); } public function testMoreThanOneUnionWithoutSelect() { - $this->setupTest(); - $union1 = (new Select()) ->columns('a') ->from('table1') @@ -738,16 +648,15 @@ public function testMoreThanOneUnionWithoutSelect() ->unionAll($union1) ->unionAll($union2); - $this->assertCorrectStatementAndValues( + $this->assertSql( '(SELECT a FROM table1 WHERE b < ?) UNION ALL (SELECT a FROM table2 WHERE b > ?)', + $this->query, [1, 2] ); } public function testMoreThanOneUnionWithSelect() { - $this->setupTest(); - $union1 = (new Select()) ->columns('a') ->from('table1') @@ -764,34 +673,32 @@ public function testMoreThanOneUnionWithSelect() ->unionAll($union1) ->unionAll($union2); - $this->assertCorrectStatementAndValues( + $this->assertSql( '(SELECT a FROM table3)' . ' UNION ALL (SELECT a FROM table1 WHERE b < ?)' . ' UNION ALL (SELECT a FROM table2 WHERE b > ?)', + $this->query, [1, 2] ); } public function testCountDistinct() { - $this->setupTest(); - $this->query = $this->query ->distinct() ->from('table') ->columns('column') ->getCountQuery(); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'SELECT COUNT(*) AS cnt FROM (SELECT DISTINCT column FROM table) s', + $this->query, [] ); } public function testInvalidOderByDirectionsThrowAnError() { - $this->setupTest(); - $this->query = $this->query ->orderBy([['foo', 'bar']]); diff --git a/tests/TestCase.php b/tests/TestCase.php index 8c315d3..71395bc 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -10,7 +10,7 @@ abstract class TestCase extends \PHPUnit\Framework\TestCase use SqlAssertions; /** @var string The statement to use */ - protected $queryClass = Select::class; + protected string $queryClass = Select::class; /** @var Select The statement in use */ protected $query; @@ -20,22 +20,4 @@ public function setUp(): void $this->query = new $this->queryClass(); $this->setUpSqlAssertions(); } - - /** @deprecated Unused. */ - protected function setupTest() - { - } - - /** - * @deprecated Use {@see self::assertSql} instead. - * - * @param string $statement - * @param array $values - * - * @return void - */ - protected function assertCorrectStatementAndValues($statement, $values = null) - { - $this->assertSql($statement, $this->query, $values); - } } diff --git a/tests/UpdateTest.php b/tests/UpdateTest.php index bb7a1b6..b0d93b0 100644 --- a/tests/UpdateTest.php +++ b/tests/UpdateTest.php @@ -8,80 +8,66 @@ class UpdateTest extends TestCase { - protected $queryClass = Update::class; + protected string $queryClass = Update::class; /** @var Update */ protected $query; public function testEmptyUpdateTable() { - $this->setupTest(); - $this->assertSame(null, $this->query->getTable()); $this->assertSame([], $this->query->getSet()); - $this->assertCorrectStatementAndValues('', []); + $this->assertSql('', $this->query, []); } public function testTableSpecification() { - $this->setupTest(); - $this->query->table('table'); $this->assertSame(['table'], $this->query->getTable()); - $this->assertCorrectStatementAndValues('UPDATE table', []); + $this->assertSql('UPDATE table', $this->query, []); } public function testTableSpecificationWithSchema() { - $this->setupTest(); - $this->query->table('schema.table'); $this->assertSame(['schema.table'], $this->query->getTable()); - $this->assertCorrectStatementAndValues('UPDATE schema.table', []); + $this->assertSql('UPDATE schema.table', $this->query, []); } public function testSet() { - $this->setupTest(); - $this->query->set(['c1' => 'v1', 'c2' => 'v2']); $this->assertSame(['c1' => 'v1', 'c2' => 'v2'], $this->query->getSet()); - $this->assertCorrectStatementAndValues('SET c1 = ?, c2 = ?', ['v1', 'v2']); + $this->assertSql('SET c1 = ?, c2 = ?', $this->query, ['v1', 'v2']); } public function testExpressionValue() { - $this->setupTest(); - $value = new Expression('x = ?', null, 1); $this->query->set(['c1' => $value]); $this->assertSame(['c1' => $value], $this->query->getSet()); - $this->assertCorrectStatementAndValues('SET c1 = x = ?', [1]); + $this->assertSql('SET c1 = x = ?', $this->query, [1]); } public function testSelectValue() { - $this->setupTest(); - $value = (new Select())->columns('COUNT(*)')->from('table2')->where(['active = ?' => 1]); $this->query->set(['c1' => $value]); $this->assertSame(['c1' => $value], $this->query->getSet()); - $this->assertCorrectStatementAndValues('SET c1 = (SELECT COUNT(*) FROM table2 WHERE active = ?)', [1]); + $this->assertSql('SET c1 = (SELECT COUNT(*) FROM table2 WHERE active = ?)', $this->query, [1]); } public function testUpdateStatementWithSet() { - $this->setupTest(); - $this->query ->table('table') ->set(['c1' => 'v1', 'c2' => 'v2']); - $this->assertCorrectStatementAndValues('UPDATE table SET c1 = ?, c2 = ?', ['v1', 'v2']); + $this->assertSql('UPDATE table SET c1 = ?, c2 = ?', $this->query, ['v1', 'v2']); } } diff --git a/tests/WhereTest.php b/tests/WhereTest.php index 00ae5c6..577ce7a 100644 --- a/tests/WhereTest.php +++ b/tests/WhereTest.php @@ -10,19 +10,15 @@ class WhereTest extends TestCase { public function testWhereStringFormat() { - $this->setupTest(); - $this->query->where('c1 = x'); $this->query->where('c2 IS NULL'); $this->query->where('c3 IS NOT NULL'); - $this->assertCorrectStatementAndValues('WHERE (c1 = x) AND (c2 IS NULL) AND (c3 IS NOT NULL)', []); + $this->assertSql('WHERE (c1 = x) AND (c2 IS NULL) AND (c3 IS NOT NULL)', $this->query, []); } public function testWhereArrayFormat() { - $this->setupTest(); - $this->query->where(['c1 = x']); $this->query->where(['c2 = ?' => 1]); $this->query->where(['c3 > ?' => 1]); @@ -31,129 +27,117 @@ public function testWhereArrayFormat() $this->query->where(['c6 IN (?)' => [1, 2, 3]]); $this->query->where(['c7 = ?' => 1, 'c8 = ?' => 1]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE (c1 = x) AND (c2 = ?) AND (c3 > ?) AND (c4 IS NULL)' . ' AND (c5 IS NOT NULL) AND (c6 IN (?, ?, ?)) AND ((c7 = ?) AND (c8 = ?))', + $this->query, [1, 1, 1, 2, 3, 1, 1] ); } public function testSingleNotWhere() { - $this->setupTest(); - $this->query->notWhere('foo = bar'); - $this->assertCorrectStatementAndValues('WHERE NOT (foo = bar)', []); + $this->assertSql('WHERE NOT (foo = bar)', $this->query, []); } public function testVariadicWhereUsedVariadic() { - $this->setupTest(); - $this->query->where('a IN (?) AND b < ?', [1, 2, 3], 4); - $this->assertCorrectStatementAndValues('WHERE a IN (?, ?, ?) AND b < ?', [1, 2, 3, 4]); + $this->assertSql('WHERE a IN (?, ?, ?) AND b < ?', $this->query, [1, 2, 3, 4]); } public function testNotWhereCombiningVariadicAndArrayStyle() { - $this->setupTest(); - $this->query->where('a = ?', 1); $this->query->notWhere('a IN (?) AND b < ?', [2, 3, 4], 5); $this->query->notWhere(['a = ?' => 6, 'b = ?' => 7], Sql::ANY); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE ((a = ?) AND (NOT (a IN (?, ?, ?) AND b < ?))) AND (NOT ((a = ?) OR (b = ?)))', + $this->query, [1, 2, 3, 4, 5, 6, 7] ); } public function testNotWhereArrayFormat() { - $this->setupTest(); - $this->query->notWhere(['c1 = x']); $this->query->notWhere(['c2 = ?' => 1]); $this->query->notWhere(['c3 IN (?)' => [1, 2, 3]]); $this->query->notWhere(['c4 = ?' => 1, 'c5 = ?' => 1], Sql::ANY); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE NOT (c1 = x) AND NOT (c2 = ?) AND NOT (c3 IN (?, ?, ?)) AND NOT ((c4 = ?) OR (c5 = ?))', + $this->query, [1, 1, 2, 3, 1, 1] ); } public function testWhereWithArrayBeforeScalar() { - $this->setupTest(); - $this->query->where(['INTERVAL(a, ?) < ?' => [[1, 2, 3], 4]]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE INTERVAL(a, ?, ?, ?) < ?', + $this->query, [1, 2, 3, 4] ); } public function testWhereWithArrayAfterScalar() { - $this->setupTest(); - $this->query->where(['? < INTERVAL(a, ?)' => [1, [2, 3, 4]]]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE ? < INTERVAL(a, ?, ?, ?)', + $this->query, [1, 2, 3, 4] ); } public function testWhereWithArrayAfterArray() { - $this->setupTest(); - $this->query->where(['a IN (?) AND b IN (?)' => [[1, 2], [3, 4]]]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE a IN (?, ?) AND b IN (?, ?)', + $this->query, [1, 2, 3, 4] ); } public function testWhereWithManyPlaceholders() { - $this->setupTest(); - $this->query->where([ 'c1 IN(?) AND c2 = ? AND INTERVAL(?, ?, 10, 100, ?) < ?' => [[1, 2, 3], 4, [5, 6], 7, 8, 9] ]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE c1 IN(?, ?, ?) AND c2 = ? AND INTERVAL(?, ?, ?, 10, 100, ?) < ?', + $this->query, [1, 2, 3, 4, 5, 6, 7, 8, 9] ); } public function testMixedWhere() { - $this->setupTest(); - $this->query->where('c1 = 1'); $this->query->orWhere(['c2 = ?' => 2]); $this->query->notWhere(['c3 = 3', 'c4 = ?' => 4]); $this->query->where(['c5 = ?' => 5, 'c6 = ?' => 6], Sql::ANY); $this->query->orNotWhere('c7 = 8'); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE (((c1 = 1) OR (c2 = ?)) AND (NOT ((c3 = 3) AND (c4 = ?)))' . ' AND ((c5 = ?) OR (c6 = ?))) OR (NOT (c7 = 8))', + $this->query, [2, 4, 5, 6] ); } public function testWhereNestedArrays() { - $this->setupTest(); - $this->query->where([ Sql::ANY, [ @@ -174,16 +158,15 @@ public function testWhereNestedArrays() ] ]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE ((foo = ?) AND (baz = ?)) OR ((foo = ?) OR (baz = ?))', + $this->query, ['bar', 'plums', 'bar', 'plums'] ); } public function testPartiallyPreparedWhere() { - $this->setupTest(); - $this->query->where([ [ Sql::ALL, @@ -201,59 +184,50 @@ public function testPartiallyPreparedWhere() ] ]); - $this->assertCorrectStatementAndValues( + $this->assertSql( 'WHERE ((foo = ?) AND (baz = plums)) AND ((foo = bar) OR (baz = ?))', + $this->query, ['bar', 'plums'] ); } public function testWhereWithExpression() { - $this->setupTest(); - $expression = new Expression('c2 = ?', null, 1); $this->query->where($expression); - $this->assertCorrectStatementAndValues('WHERE c2 = ?', [1]); + $this->assertSql('WHERE c2 = ?', $this->query, [1]); } public function testWhereWithSelect() { - $this->setupTest(); - $select = (new Select())->columns('COUNT(*)')->from('t1')->where(['c2 = ?' => 1]); $this->query->where($select); - $this->assertCorrectStatementAndValues('WHERE (SELECT COUNT(*) FROM t1 WHERE c2 = ?)', [1]); + $this->assertSql('WHERE (SELECT COUNT(*) FROM t1 WHERE c2 = ?)', $this->query, [1]); } public function testWhereWithSelectAndExpression() { - $this->setupTest(); - $select = (new Select())->columns('1')->from('t1')->where(['c2 = ?' => 1])->limit(1); $this->query->where(['EXISTS ?' => $select]); - $this->assertCorrectStatementAndValues('WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = ? LIMIT 1)', [1]); + $this->assertSql('WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = ? LIMIT 1)', $this->query, [1]); } public function testWhereWithExpressionThatCanBeRenderedToString() { - $this->setupTest(); - $this->query->where( new ExpressionThatCanBeRenderedToString("COALESCE('a', ?) = ?"), [1, 2], 1 ); - $this->assertCorrectStatementAndValues("WHERE COALESCE('a', ?, ?) = ?", [1, 2, 1]); + $this->assertSql("WHERE COALESCE('a', ?, ?) = ?", $this->query, [1, 2, 1]); } public function testResetWhere() { - $this->setupTest(); - $this->query->where('c1 = x'); $this->assertSame( ['AND', [['AND', ['c1 = x']]]],