Skip to content
This repository has been archived by the owner on Nov 8, 2020. It is now read-only.

Commit

Permalink
Merge f6d52b5 into 18d85f4
Browse files Browse the repository at this point in the history
  • Loading branch information
klapuch committed May 18, 2019
2 parents 18d85f4 + f6d52b5 commit b9721f3
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 55 deletions.
45 changes: 26 additions & 19 deletions Core/SelectiveStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,56 @@

namespace Klapuch\Dataset;

use Klapuch\Sql;
use Characterice\Sql\Expression;
use Characterice\Sql\Statement\Select;
use Characterice\Sql\Statement\Statement;

/**
* Statement using Selection for building SQL with bind parameters
*/
final class SelectiveStatement implements Sql\Statement {

/** @var \Klapuch\Sql\Selection */
final class SelectiveStatement extends Statement {
/** @var \Characterice\Sql\Statement\Select\Query */
private $origin;

/** @var \Klapuch\Dataset\Selection */
private $selection;

public function __construct(Sql\Selection $origin, Selection $selection) {
public function __construct(Select\Query $origin, Selection $selection) {
$this->origin = $origin;
$this->selection = $selection;
}

public function sql(): string {
return $this->statement($this->selection->criteria())->sql();
protected function orders(): array {
return $this->origin->orders();
}

public function parameters(): Sql\Parameters {
return $this->statement($this->selection->criteria())->parameters();
public function sql(): string {
$criteria = $this->selection->criteria();
return $this->withWhere($criteria['filter'] ?? [])
->orderBy(new Expression\OrderBy($criteria['sort'] ?? []))
->limit($criteria['paging']['limit'] ?? \PHP_INT_MAX)
->offset($criteria['paging']['offset'] ?? 0)
->sql();
}

private function statement(array $criteria): Sql\Statement {
[$filter, $sort, $paging] = [
$criteria['filter'] ?? [],
$criteria['sort'] ?? [],
$criteria['paging'] ?? [],
];
public function parameters(): array {
$criteria = $this->selection->criteria();
return $this->withWhere($criteria['filter'] ?? [])
->orderBy(new Expression\OrderBy($criteria['sort'] ?? []))
->parameters();
}

private function withWhere(array $filter): Select\Query {
return array_reduce(
array_keys($filter),
static function (Sql\Selection $sql, string $parameter) use ($filter): Sql\Where {
static function (Select\Query $sql, string $parameter) use ($filter): Select\Query {
$value = $filter[$parameter];
if (is_array($value)) {
return $sql->whereIn($parameter, [$parameter => $value]);
return $sql->where(new Expression\WhereIn($parameter, $value));
}
return $sql->where(sprintf('%1$s = :%1$s', $parameter), [$parameter => $value]);
return $sql->where(new Expression\Where($parameter, $value));
},
$this->origin
)->orderBy($sort)->limit($paging['limit'] ?? \PHP_INT_MAX)->offset($paging['offset'] ?? 0);
);
}
}
44 changes: 9 additions & 35 deletions Tests/Unit/SelectiveStatement.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ declare(strict_types = 1);

namespace Klapuch\Dataset\Unit;

use Characterice\Sql\Expression;
use Characterice\Sql\Statement\Select;
use Klapuch\Dataset;
use Klapuch\Sql;
use Tester;
use Tester\Assert;

require __DIR__ . '/../bootstrap.php';

final class SelectiveStatement extends Tester\TestCase {
public function testOrderOfStatements() {
public function testApplying() {
$statement = new Dataset\SelectiveStatement(
new Sql\AnsiWhere(new Sql\FakeStatement(), 'foo = :bar', ['bar' => 10]),
(new Select\Query())->select(new Expression\Select(['firstname']))->from(new Expression\From(['world'])),
new Dataset\FakeSelection(
[
'filter' => ['name' => 'Dom'],
Expand All @@ -28,46 +29,19 @@ final class SelectiveStatement extends Tester\TestCase {
)
);
Assert::same(
' WHERE foo = :bar AND name = :name ORDER BY age ASC LIMIT 10 OFFSET 4',
'SELECT firstname FROM world WHERE name = :name ORDER BY age ASC LIMIT 10 OFFSET 4',
$statement->sql()
);
Assert::same(['bar' => 10, 'name' => 'Dom'], $statement->parameters()->binds());
}

public function testFilterRelatedStatement() {
$statement = new Dataset\SelectiveStatement(
new Sql\AnsiWhere(new Sql\FakeStatement(), 'foo = :bar', ['bar' => 10]),
new Dataset\FakeSelection(['filter' => ['name' => 'Dom', 'age' => 20]])
);
Assert::same(' WHERE foo = :bar AND name = :name AND age = :age', $statement->sql());
Assert::same(['bar' => 10, 'name' => 'Dom', 'age' => 20], $statement->parameters()->binds());
}

public function testSortRelatedStatement() {
$statement = new Dataset\SelectiveStatement(
new Sql\AnsiWhere(new Sql\FakeStatement(), 'foo = :bar', ['bar' => 10]),
new Dataset\FakeSelection(['sort' => ['name' => 'ASC', 'age' => 'DESC']])
);
Assert::same(' WHERE foo = :bar ORDER BY name ASC, age DESC', $statement->sql());
Assert::same(['bar' => 10], $statement->parameters()->binds());
}

public function testPagingRelatedStatement() {
$statement = new Dataset\SelectiveStatement(
new Sql\AnsiWhere(new Sql\FakeStatement(), 'foo = :bar', ['bar' => 10]),
new Dataset\FakeSelection(['paging' => ['limit' => 20, 'offset' => 5]])
);
Assert::same(' WHERE foo = :bar LIMIT 20 OFFSET 5', $statement->sql());
Assert::same(['bar' => 10], $statement->parameters()->binds());
Assert::same(['name' => 'Dom'], $statement->parameters());
}

public function testArrayValueToInClause() {
$statement = new Dataset\SelectiveStatement(
new Sql\AnsiWhere(new Sql\FakeStatement(), 'foo = :bar', ['bar' => 10]),
(new Select\Query())->select(new Expression\Select(['firstname']))->from(new Expression\From(['world'])),
new Dataset\FakeSelection(['filter' => ['name' => 'Dom', 'age' => [10, 20]]])
);
Assert::same(' WHERE foo = :bar AND name = :name AND age IN (:age_0, :age_1)', $statement->sql());
Assert::same(['bar' => 10, 'name' => 'Dom', ':age_0' => 10, ':age_1' => 20], $statement->parameters()->binds());
Assert::same('SELECT firstname FROM world WHERE name = :name AND age IN (:age__1, :age__2)', $statement->sql());
Assert::same(['name' => 'Dom', 'age__1' => 10, 'age__2' => 20], $statement->parameters());
}
}

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
],
"require": {
"php": ">=7.3",
"klapuch/sql": "*"
"characterice/sql": "^0.0.5"
},
"require-dev": {
"nette/tester": "^2.0",
Expand Down

0 comments on commit b9721f3

Please sign in to comment.