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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ includes:
- phpstan-baseline.neon

parameters:
level: 8
level: 9
paths:
- src
- tests
27 changes: 14 additions & 13 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use Artemeon\Database\Schema\DataType;
use Artemeon\Database\Schema\Table;
use Artemeon\Database\Schema\TableIndex;
use BackedEnum;
use Generator;
use InvalidArgumentException;
use Override;
Expand All @@ -45,7 +46,7 @@ class Connection implements ConnectionInterface
/**
* Array to cache queries.
*
* @var array<string, list<mixed>>
* @var array<string, array<int, array<string, mixed>>>
*/
private array $queryCache = [];

Expand Down Expand Up @@ -310,8 +311,6 @@ public function _pQuery(string $query, array $params = [], array $escapes = []):
$this->dbconnect();
}

$output = false;

$query = $this->processQuery($query);

// Increasing the counter
Expand Down Expand Up @@ -445,6 +444,8 @@ public function getPArray(
/**
* @inheritDoc
* @throws ConnectionException
*
* @return Generator<list<array<non-empty-string, mixed>>>
*/
#[Override]
public function getGenerator(string $query, array $params = [], int $chunkSize = 2048, bool $paging = true): Generator
Expand Down Expand Up @@ -605,7 +606,7 @@ public function iterateColumn(string $query, array $params = []): Generator
/**
* Writes the last DB-Error to the screen.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*
* @throws QueryException
* @throws ConnectionException
Expand Down Expand Up @@ -1149,7 +1150,7 @@ private function processQuery(string $query): string
}

/**
* @param list<mixed> $params
* @param list<scalar|null> $params
*/
private function addQueryToList(string $query, array $params, bool $cached, float $startTime): void
{
Expand Down Expand Up @@ -1220,19 +1221,19 @@ public function getCacheSize(): int
* An internal wrapper to dbsafeString, used to process a complete array of parameters
* as used by prepared statements.
*
* @param array<array-key, mixed> $params
* @param array<array-key, BackedEnum|EscapeableParameterInterface|scalar|null> $params
* @param list<bool>|false $escapes An array of boolean for each param, used to block the escaping of html-special chars.
* If not passed, all params will be cleaned.
*
* @return list<mixed>
* @return list<scalar|null>
*
* @see Db::dbsafeString($string, $htmlSpecialChars = true)
*/
private function dbsafeParams(array $params, array | false $escapes = []): array
{
$replace = [];
foreach ($params as $key => $param) {
if ($param instanceof \BackedEnum) {
if ($param instanceof BackedEnum) {
$replace[$key] = $param->value;

continue;
Expand Down Expand Up @@ -1261,7 +1262,7 @@ private function dbsafeParams(array $params, array | false $escapes = []): array
/**
* Makes a string db-safe.
*
* @return int|float|null|string
* @return ($input is float ? float : ($input is int ? int : ($input is bool ? int<0,1> : ($input is null ? null : ($input is scalar ? string : mixed)))))
* @deprecated we need to get rid of this
*/
public function dbsafeString(mixed $input, bool $htmlSpecialChars = true, bool $addSlashes = true): mixed
Expand All @@ -1284,12 +1285,12 @@ public function dbsafeString(mixed $input, bool $htmlSpecialChars = true, bool $
}

// escape special chars
if ($htmlSpecialChars) {
if (is_scalar($input) && $htmlSpecialChars) {
$input = html_entity_decode((string) $input, ENT_COMPAT, 'UTF-8');
$input = htmlspecialchars($input, ENT_COMPAT, 'UTF-8');
}

if ($addSlashes) {
if (is_scalar($input) && $addSlashes) {
$input = addslashes((string) $input);
}

Expand Down Expand Up @@ -1392,7 +1393,7 @@ public function escape(mixed $value): mixed
public function prettifyQuery(string $query, array $params): string
{
foreach ($params as $param) {
if (!is_numeric($param) && $param !== null) {
if (is_string($param)) {
$param = "'$param'";
}

Expand All @@ -1403,7 +1404,7 @@ public function prettifyQuery(string $query, array $params): string
}

$pos = strpos($query, '?');
if ($pos !== false) {
if ($pos !== false && is_string($param)) {
$query = substr_replace($query, $param, $pos, 1);
}
}
Expand Down
26 changes: 17 additions & 9 deletions src/ConnectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ interface ConnectionInterface extends DoctrineConnectionInterface
* Method to get an array of rows for a given query from the database.
* Makes use of prepared statements.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
* @param list<bool> $escapes
*
* @throws QueryException
Expand All @@ -54,7 +54,7 @@ public function getPArray(string $query, array $params = [], ?int $start = null,
* Returns one row from a result-set.
* Makes use of prepared statements.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
* @param list<bool> $escapes
*
* @throws QueryException
Expand All @@ -69,7 +69,7 @@ public function getPRow(string $query, array $params = [], int $number = 0, bool
*
* @param string $tableName the table name from which to select the row
* @param list<string> $columns a flat list of column names to select
* @param array<string, mixed> $identifiers mapping of column name to value to search for (e.g. ["id" => 1])
* @param array<string, scalar|null> $identifiers mapping of column name to value to search for (e.g. ["id" => 1])
* @param bool $cached whether a previously selected result can be reused
* @param list<bool>|null $escapes which parameters to escape (described in {@see dbsafeParams})
* @throws QueryException
Expand All @@ -91,7 +91,7 @@ public function selectRow(string $tableName, array $columns, array $identifiers,
* false and don't modify the result set you will get an endless loop, so you must get sure that in the end the
* result set will be empty.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*
* @throws QueryException
* @see iterateAssociative
Expand All @@ -103,7 +103,7 @@ public function getGenerator(string $query, array $params = [], int $chunkSize =
*
* Sending a prepared statement to the database
*
* @param list<mixed> $params
* @param list<scalar|null> $params
* @param list<bool> $escapes An array of booleans for each param, used to block the escaping of html-special chars.
* If not passed, all params will be cleaned.
* @throws QueryException
Expand All @@ -122,7 +122,7 @@ public function getAffectedRowsCount(): int;
* INSERT INTO $table ($columns) VALUES (?, ?), (?, ?)...
*
* @param list<string> $columns
* @param list<mixed> $valueSets
* @param list<array<scalar|null>> $valueSets
* @param list<bool>|null $escapes
* @throws QueryException
*/
Expand All @@ -135,7 +135,7 @@ public function multiInsert(string $tableName, array $columns, array $valueSets,
* otherwise data might be lost. And: params are sent to the database unescaped.
*
* @param list<string> $columns
* @param list<mixed> $values
* @param list<scalar|null> $values
* @param list<string> $primaryColumns
*
* @throws QueryException
Expand Down Expand Up @@ -196,7 +196,7 @@ public function getDatatype(DataType $type): string;
* Used to send a `CREATE TABLE` statement to the database.
* By passing the query through this method, the driver can add db-specific commands.
*
* @param array<non-empty-string, array{0: DataType, 1: bool, 2?: mixed}> $columns
* @param array<non-empty-string, array{0: DataType, 1: bool, 2?: string}> $columns
* @param list<string> $keys
* @param list<list<string>|string> $indices
*
Expand Down Expand Up @@ -312,7 +312,7 @@ public function encloseTableName(string $tableName): string;
* Helper to replace all param-placeholder with the matching value, only to be used
* to render a debuggable-statement.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*/
public function prettifyQuery(string $query, array $params): string;

Expand Down Expand Up @@ -349,6 +349,10 @@ public function getStringLengthExpression(string $targetString): string;
/**
* Converts a PHP value to a value, which can be inserted into a table. I.e. it truncates the value to
* the fitting length for the provided datatype.
*
* @param scalar|null $value
*
* @return scalar|null
*/
public function convertToDatabaseValue(mixed $value, DataType $type): mixed;

Expand Down Expand Up @@ -427,6 +431,10 @@ public function flushPreparedStatementsCache(): void;
*/
public function getColumnsOfTable(string $tableName): array;

/**
* @param scalar|null $value
* @return scalar|null
*/
public function escape(mixed $value): mixed;

public function hasOpenTransactions(): bool;
Expand Down
22 changes: 11 additions & 11 deletions src/DoctrineConnectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface DoctrineConnectionInterface
/**
* Prepares and executes an SQL query and returns the result as an array of associative arrays.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*
* @return list<array<string, mixed>>
*/
Expand All @@ -37,7 +37,7 @@ public function fetchAllAssociative(string $query, array $params = []): array;
* Prepares and executes an SQL query and returns the first row of the result
* as an associative array.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*
* @return array<string, mixed>|false
*/
Expand All @@ -46,7 +46,7 @@ public function fetchAssociative(string $query, array $params = []): array | fal
/**
* Prepares and executes an SQL query and returns the result as an array of the first column values.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*
* @return list<mixed>
*/
Expand All @@ -55,22 +55,22 @@ public function fetchFirstColumn(string $query, array $params = []): array;
/**
* Prepares and executes an SQL query and returns the value of a single column of the first row of the result.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*/
public function fetchOne(string $query, array $params = []): mixed;

/**
* Prepares and executes an SQL query and returns the result as an iterator over rows represented
* as associative arrays.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*/
public function iterateAssociative(string $query, array $params = []): Generator;

/**
* Prepares and executes an SQL query and returns the result as an iterator over the first column values.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*/
public function iterateColumn(string $query, array $params = []): Generator;

Expand All @@ -84,32 +84,32 @@ public function iterateColumn(string $query, array $params = []): Generator;
* - Session control statements: ALTER SESSION, SET, DECLARE, etc.
* - Other statements that don't yield a row set.
*
* @param list<mixed> $params
* @param list<scalar|null> $params
*/
public function executeStatement(string $query, array $params = []): int;

/**
* Creates a simple insert for a single row where the values parameter is an associative array with column names to
* value mapping.
*
* @param array<string, mixed> $values
* @param array<non-empty-string, scalar|null> $values
* @param list<bool>|null $escapes
*/
public function insert(string $tableName, array $values, ?array $escapes = null): int;

/**
* Updates a row on the provided table by the identifier columns.
*
* @param array<string, mixed> $values
* @param array<string, mixed> $identifier
* @param array<string, scalar|null> $values
* @param array<string, scalar|null> $identifier
* @param list<bool>|null $escapes
*/
public function update(string $tableName, array $values, array $identifier, ?array $escapes = null): int;

/**
* Deletes a row on the provided table by the identifier columns.
*
* @param array<string, mixed> $identifier
* @param array<string, scalar|null> $identifier
*/
public function delete(string $tableName, array $identifier): int;

Expand Down
5 changes: 3 additions & 2 deletions src/Driver/DriverAbstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
/**
* Base class for all database-drivers, holds methods to be used by all drivers.
*
* @author sidler@mulchprod.de
* @template CacheType
*/
abstract class DriverAbstract implements DriverInterface
{
/**
* @var array<array-key, mixed>
* @var array<array-key, CacheType>
*/
protected array $statementsCache = [];

Expand Down Expand Up @@ -225,6 +225,7 @@ public function insertOrUpdate(string $table, array $columns, array $values, arr

$enclosedTableName = $this->encloseTableName($table);

/** @var list<array{cnt:numeric-string}>|false $rows */
$rows = $this->getPArray("SELECT COUNT(*) AS cnt FROM $enclosedTableName WHERE " . implode(' AND ', $primaryCompares), $primaryValues)->current();

if ($rows === false) {
Expand Down
6 changes: 6 additions & 0 deletions src/Driver/MysqliDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

/**
* DB-driver for MySQL using the php-mysqli-interface.
*
* @template-extends DriverAbstract<false|mysqli_stmt>
*/
class MysqliDriver extends DriverAbstract
{
Expand Down Expand Up @@ -257,6 +259,7 @@ public function getTables(): array
{
$generator = $this->getPArray('SHOW TABLE STATUS', []);
$result = [];
/** @var array{Name:string} $row */
foreach ($generator as $row) {
$result[] = ['name' => $row['Name']];
}
Expand All @@ -275,6 +278,7 @@ public function getTableInformation(string $tableName): Table

// fetch all columns
$columnInfo = $this->getPArray("SHOW COLUMNS FROM $tableName", []);
/** @var array{Field:non-empty-string,Type:string,Null:string} $column */
foreach ($columnInfo as $column) {
$table->addColumn(
TableColumn::make($column['Field'])
Expand All @@ -287,6 +291,7 @@ public function getTableInformation(string $tableName): Table
// fetch all indexes
$indexes = $this->getPArray("SHOW INDEX FROM $tableName WHERE Key_name != 'PRIMARY'", []);
$indexAggr = [];
/** @var array{Key_name:string,Column_name:string} $indexInfo */
foreach ($indexes as $indexInfo) {
$indexAggr[$indexInfo['Key_name']] ??= [];
$indexAggr[$indexInfo['Key_name']][] = $indexInfo['Column_name'];
Expand All @@ -299,6 +304,7 @@ public function getTableInformation(string $tableName): Table

// fetch all keys
$keys = $this->getPArray("SHOW KEYS FROM $tableName WHERE Key_name = 'PRIMARY'", []);
/** @var array{Column_name:string} $keyInfo */
foreach ($keys as $keyInfo) {
$key = new TableKey($keyInfo['Column_name']);
$table->addPrimaryKey($key);
Expand Down
Loading
Loading