Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
forrest79 committed Sep 25, 2024
1 parent afea147 commit 5cc7ef7
Show file tree
Hide file tree
Showing 15 changed files with 211 additions and 375 deletions.
2 changes: 1 addition & 1 deletion docs/db.md
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ dump($cnt); // (integer) 7
```php
$departmentsQuery = Forrest79\PhPgSql\Db\Sql\Query::createArgs('SELECT id FROM departments WHERE id = ?', [1]);

$query = $departmentsQuery->createQuery();
$query = $departmentsQuery->toDbQuery();

dump($query->sql); // (string) 'SELECT id FROM departments WHERE id = $1'
dump($query->params); // (array) [1]
Expand Down
3 changes: 1 addition & 2 deletions docs/fluent.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ $query = $fluent
->select(['*'])
->from('users')
->where('id', 1)
->createSqlQuery()
->createQuery();
->toDbQuery();

dump($query->sql); // (string) 'SELECT * FROM users WHERE id = $1'
dump($query->params); // (array) [1]
Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ parameters:
count: 47

-
message: '#^Parameter \#2 \$queryParams of method Forrest79\\PhPgSql\\Fluent\\QueryBuilder::createSqlQuery\(\) expects array\{.+\}, array\{.*\} given\.$#'
message: '#^Parameter \#2 \$queryParams of method Forrest79\\PhPgSql\\Fluent\\QueryBuilder::createSql\(\) expects array\{.+\}, array\{.*\} given\.$#'
path: %rootDir%/../../../tests/Unit/FluentQueryTest.php
count: 1

Expand Down
28 changes: 6 additions & 22 deletions src/Db/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ private function getDataTypesCache(): array|NULL
* @throws Exceptions\ConnectionException
* @throws Exceptions\QueryException
*/
public function query(string|Query|Sql\Query $sql, mixed ...$params): Result
public function query(string|Query|Sql $sql, mixed ...$params): Result
{
\assert(\array_is_list($params));
return $this->queryArgs($sql, $params);
Expand All @@ -308,9 +308,9 @@ public function query(string|Query|Sql\Query $sql, mixed ...$params): Result
* @throws Exceptions\ConnectionException
* @throws Exceptions\QueryException
*/
public function queryArgs(string|Query|Sql\Query $sql, array $params): Result
public function queryArgs(string|Query|Sql $sql, array $params): Result
{
$query = $this->prepareQuery($this->normalizeQuery($sql, $params));
$query = $this->prepareQuery(Query::from($sql, $params));

$startTime = $this->events->hasOnQuery() ? \hrtime(TRUE) : NULL;

Expand Down Expand Up @@ -379,7 +379,7 @@ public function execute(string $sql): static
* @throws Exceptions\ConnectionException
* @throws Exceptions\QueryException
*/
public function asyncQuery(string|Query|Sql\Query $sql, mixed ...$params): AsyncQuery
public function asyncQuery(string|Query|Sql $sql, mixed ...$params): AsyncQuery
{
\assert(\array_is_list($params));
return $this->asyncQueryArgs($sql, $params);
Expand All @@ -391,9 +391,9 @@ public function asyncQuery(string|Query|Sql\Query $sql, mixed ...$params): Async
* @throws Exceptions\ConnectionException
* @throws Exceptions\QueryException
*/
public function asyncQueryArgs(string|Query|Sql\Query $sql, array $params): AsyncQuery
public function asyncQueryArgs(string|Query|Sql $sql, array $params): AsyncQuery
{
$query = $this->prepareQuery($this->normalizeQuery($sql, $params));
$query = $this->prepareQuery(Query::from($sql, $params));

$queryParams = $query->params;
if ($queryParams === []) {
Expand Down Expand Up @@ -546,22 +546,6 @@ public function getResource(): PgSql\Connection
}


/**
* @param list<mixed> $params
* @throws Exceptions\QueryException
*/
private function normalizeQuery(string|Query|Sql\Query $sql, array $params): Query
{
if (\is_string($sql)) {
$sql = new Sql\Query($sql, $params);
} else if ($params !== []) {
throw Exceptions\QueryException::cantPassParams();
}

return $sql instanceof Query ? $sql : $sql->createQuery();
}


/**
* Extend this method to update query before execution.
*
Expand Down
8 changes: 2 additions & 6 deletions src/Db/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,15 @@ public function __construct(public readonly string $sql, public readonly array $
/**
* @param list<mixed> $params
*/
public static function from(string|self|Sql $query, array $params): self
public static function from(string|self|Sql $query, array $params = []): self
{
if (is_string($query)) {
$query = new Sql\Expression($query, $params);
} else if ($params !== []) {
throw Exceptions\QueryException::cantPassParams();
}

if ($query instanceof Sql) {
$query = self::prepareQuery($query->getSql(), $query->getParams(), 0);
}

return $query;
return $query instanceof Sql ? self::prepareQuery($query->getSql(), $query->getParams(), 0) : $query;
}


Expand Down
70 changes: 5 additions & 65 deletions src/Db/Sql/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Query implements Db\Sql
/** @var list<mixed> */
private array $params;

private Db\Query|NULL $query = NULL;
private Db\Query|NULL $dbQuery = NULL;


/**
Expand Down Expand Up @@ -42,73 +42,13 @@ public function getParams(): array
/**
* Create SQL query for pg_query_params function.
*/
public function createQuery(): Db\Query
public function toDbQuery(): Db\Query
{
if ($this->query === NULL) {
$this->query = self::prepareQuery($this->sql, $this->params, 0);
if ($this->dbQuery === NULL) {
$this->dbQuery = Db\Query::from($this->sql, $this->params);
}

return $this->query;
}


/**
* @param list<mixed> $params
*/
private static function prepareQuery(string $sql, array $params, int $paramIndex): Db\Query
{
$origParamIndex = 0;
$parsedParams = [];

$sql = \preg_replace_callback(
'/([\\\\]?)\?/',
static function ($matches) use (&$params, &$parsedParams, &$origParamIndex, &$paramIndex): string {
if ($matches[1] === '\\') {
return '?';
}

if (!\array_key_exists($origParamIndex, $params)) {
throw Db\Exceptions\QueryException::missingParam($origParamIndex);
}

$param = $params[$origParamIndex];
unset($params[$origParamIndex]);
$origParamIndex++;

if (\is_array($param)) {
$keys = [];
foreach ($param as $value) {
$keys[] = '$' . ++$paramIndex;
$parsedParams[] = ($value instanceof \BackedEnum) ? $value->value : $value;
}
return \implode(', ', $keys);
} else if (\is_bool($param)) {
return $param === TRUE ? 'TRUE' : 'FALSE';
} else if ($param instanceof Db\Sql) {
$subquerySql = self::prepareQuery($param->getSql(), $param->getParams(), $paramIndex);
$paramIndex += \count($subquerySql->params);
$parsedParams = \array_merge($parsedParams, $subquerySql->params);
return $subquerySql->sql;
}

$parsedParams[] = ($param instanceof \BackedEnum) ? $param->value : $param;

return '$' . ++$paramIndex;
},
$sql,
);

\assert(\is_string($sql));

if (($origParamIndex > 0) && ($params !== [])) {
throw Db\Exceptions\QueryException::extraParam(\array_values($params));
}

if ($parsedParams === []) {
$parsedParams = \array_values($params);
}

return new Db\Query($sql, $parsedParams);
return $this->dbQuery;
}


Expand Down
38 changes: 22 additions & 16 deletions src/Fluent/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class Query implements Db\Sql
/** @phpstan-var QueryParams */
private array $params = self::DEFAULT_PARAMS;

private Db\Sql\Query|NULL $query = NULL;
private Db\Sql\Expression|NULL $sqlExpression = NULL;


public function __construct(QueryBuilder $queryBuilder)
Expand Down Expand Up @@ -931,7 +931,7 @@ public function reset(string $param): static

protected function resetQuery(): void
{
$this->query = NULL;
$this->sqlExpression = NULL;
}


Expand All @@ -946,31 +946,37 @@ private function checkAlias(mixed $data, string|NULL $alias): void
}


/**
* @throws Exceptions\QueryBuilderException
*/
public function createSqlQuery(): Db\Sql\Query
public function getSql(): string
{
if ($this->query === NULL) {
$this->query = $this->queryBuilder->createSqlQuery($this->queryType, $this->params);
}

return $this->query;
return $this->buildSql()->getSql();
}


public function getSql(): string
/**
* @return list<mixed>
*/
public function getParams(): array
{
return $this->createSqlQuery()->getSql();
return $this->buildSql()->getParams();
}


/**
* @return list<mixed>
* @throws Exceptions\QueryBuilderException
*/
public function getParams(): array
protected function buildSql(): Db\Sql\Expression
{
if ($this->sqlExpression === NULL) {
$this->sqlExpression = $this->queryBuilder->createSql($this->queryType, $this->params);
}

return $this->sqlExpression;
}


public function toDbQuery(): Db\Query
{
return $this->createSqlQuery()->getParams();
return Db\Query::from($this->buildSql());
}


Expand Down
10 changes: 5 additions & 5 deletions src/Fluent/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class QueryBuilder
* @throws Exceptions\QueryBuilderException
* @phpstan-param QueryParams $queryParams
*/
public function createSqlQuery(string $queryType, array $queryParams): Db\Sql\Query
public function createSql(string $queryType, array $queryParams): Db\Sql\Expression
{
$params = [];

Expand All @@ -68,16 +68,16 @@ public function createSqlQuery(string $queryType, array $queryParams): Db\Sql\Qu
throw Exceptions\QueryBuilderException::badQueryType($queryType);
}

return $this->prepareSqlQuery($sql, $params);
return $this->prepareSql($sql, $params);
}


/**
* @param list<mixed> $params
*/
protected function prepareSqlQuery(string $sql, array $params): Db\Sql\Query
protected function prepareSql(string $sql, array $params): Db\Sql\Expression
{
return new Db\Sql\Query($sql, $params);
return new Db\Sql\Expression($sql, $params);
}


Expand Down Expand Up @@ -815,7 +815,7 @@ private function processCondition(Condition $condition, array &$params): string

private static function areParenthesisNeeded(Db\Sql $sql): bool
{
return $sql instanceof Db\Sql\Query || $sql instanceof Query;
return $sql instanceof Query;
}

}
4 changes: 2 additions & 2 deletions src/Fluent/QueryExecute.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ protected function resetQuery(): void
public function execute(): Db\Result
{
if ($this->result === NULL) {
$this->result = $this->connection->query($this->createSqlQuery());
$this->result = $this->connection->query($this);

if ($this->rowFetchMutator !== NULL) {
$this->result->setRowFetchMutator($this->rowFetchMutator);
Expand Down Expand Up @@ -256,7 +256,7 @@ public function fetchIterator(): Db\ResultIterator
*/
public function asyncExecute(): Db\AsyncQuery
{
return $this->connection->asyncQuery($this->createSqlQuery());
return $this->connection->asyncQuery($this);
}


Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/BasicTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public function testFailedQuery(): void
public function testPassParamToQuery(): void
{
Tester\Assert::exception(function (): void {
$query = Db\Sql\Query::create('SELECT 1');
$query = Db\Sql\Expression::create('SELECT 1');
$this->connection->query($query, 1);
}, Db\Exceptions\QueryException::class, NULL, Db\Exceptions\QueryException::CANT_PASS_PARAMS);
}
Expand Down
Loading

0 comments on commit 5cc7ef7

Please sign in to comment.