Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
44 changes: 41 additions & 3 deletions src/Driver/Test/TestTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Aternos\Model\ModelRegistry;
use Aternos\Model\Query\DeleteQuery;
use Aternos\Model\Query\Direction;
use Aternos\Model\Query\Field;
use Aternos\Model\Query\GroupField;
use Aternos\Model\Query\OrderField;
use Aternos\Model\Query\Query;
Expand Down Expand Up @@ -57,7 +58,15 @@ public function addEntry(TestTableEntry ...$entry): static
*/
public function query(Query $query): QueryResult
{
$entries = $this->findEntries($query->getWhere(), $query->getLimit()?->start, $query->getLimit()?->length, $query->getOrder());
$distinct = $query instanceof SelectQuery && $query->isDistinct();
$entries = $this->findEntries(
$query->getWhere(),
$query->getLimit()?->start,
$query->getLimit()?->length,
$query->getOrder(),
$distinct,
$query->getFields(),
);
Comment thread
JulianVennen marked this conversation as resolved.
Resolved

if ($query instanceof SelectQuery) {
$clonedEntries = [];
Expand All @@ -72,7 +81,8 @@ public function query(Query $query): QueryResult
if ($query instanceof SelectQuery) {
/** @var class-string<ModelInterface> $modelClass */
$modelClass = $query->modelClassName;
$model = $modelClass::getModelFromData($entry->getDataForFields($query->getFields()));
$entryData = $entry->getDataForFields($query->getFields());
Comment thread
JulianVennen marked this conversation as resolved.
Resolved
$model = $modelClass::getModelFromData($entryData);
$queryResult->add($model);
}
if ($query instanceof UpdateQuery) {
Expand Down Expand Up @@ -128,10 +138,20 @@ public function groupAndAggregateEntries(array $entries, ?array $group, ?array $
* @param int|null $offset
* @param int|null $limit
* @param array|null $order
* @param bool $distinct
* @param Field[]|null $fields
* @return TestTableEntry[]
*/
protected function findEntries(?WhereGroup $where, ?int $offset = null, ?int $limit = null, ?array $order = null): array
protected function findEntries(
?WhereGroup $where,
?int $offset = null,
?int $limit = null,
?array $order = null,
bool $distinct = false,
?array $fields = null,
): array
{
/** @var TestTableEntry[] $entries */
$entries = [];
if ($offset === null) {
$offset = 0;
Expand All @@ -140,6 +160,24 @@ protected function findEntries(?WhereGroup $where, ?int $offset = null, ?int $li
if (!$entry->matchesWhereGroup($where)) {
continue;
}

if ($distinct && $fields) {
foreach ($entries as $item) {
$same = true;
foreach ($fields as $field) {
$key = $field->key;
Comment thread
JulianVennen marked this conversation as resolved.
Resolved
if ($item->getField($key) !== $entry->getField($key)) {
$same = false;
break;
}
}

if ($same) {
continue 2;
}
}
}
Comment thread
JulianVennen marked this conversation as resolved.
Resolved

$entries[] = $entry;
}

Expand Down
4 changes: 4 additions & 0 deletions src/Query/Generator/SQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public function generate(Query $query): string
if ($query instanceof SelectQuery) {
$queryString .= "SELECT";

if ($query->isDistinct()) {
$queryString .= " DISTINCT";
}

if ($query->getFields()) {
$queryString .= " " . $this->generateFields($query);
} else {
Expand Down
25 changes: 24 additions & 1 deletion src/Query/SelectQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ class SelectQuery extends Query
* @param array|int|Limit|null $limit
* @param array|GroupField[]|string[]|null $group
* @param bool $saveResultsToRegistry Whether results of this query should be saved in the model registry.
* @param bool $distinct only select unique rows
Comment thread
JulianVennen marked this conversation as resolved.
Resolved
*/
public function __construct(null|WhereCondition|array|WhereGroup $where = null,
null|array $order = null,
null|array $fields = null,
null|Limit|array|int $limit = null,
null|array $group = null,
protected bool $saveResultsToRegistry = true)
protected bool $saveResultsToRegistry = true,
protected bool $distinct = false,
)
{
if ($where) {
$this->where($where);
Expand Down Expand Up @@ -100,6 +103,26 @@ public function getGroup(): ?array
return $this->group;
}

/**
* @param bool $distinct
* @return $this
*/
public function distinct(bool $distinct = true): static
{
$this->distinct = $distinct;
return $this;
}

/**
* Get whether this query should be distinct
*
* @return bool
*/
public function isDistinct(): bool
{
return $this->distinct;
}

/**
* Set whether results of this query should be saved in the model registry
*
Expand Down
8 changes: 8 additions & 0 deletions test/tests/SQLTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,14 @@ public function testSelectGroup()
$this->assertEquals("SELECT * FROM `test` GROUP BY `number`, `text`", $this->sql->generate($query));
}

public function testSelectDistinct()
{
$query = new SelectQuery()->distinct();
$query->modelClassName = TestModel::class;

$this->assertEquals("SELECT DISTINCT * FROM `test`", $this->sql->generate($query));
}

public function testDelete()
{
$query = new DeleteQuery();
Expand Down
135 changes: 135 additions & 0 deletions test/tests/TestDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Aternos\Model\Query\MaxField;
use Aternos\Model\Query\MinField;
use Aternos\Model\Query\SelectField;
use Aternos\Model\Query\SelectQuery;
use Aternos\Model\Query\SumField;
use Aternos\Model\Query\WhereCondition;
use Aternos\Model\Query\WhereGroup;
Expand Down Expand Up @@ -564,6 +565,140 @@ public function testOrderBeforeLimit(): void
$this->assertEquals(7, $result[2]->number);
}

public function testSelectDistinct(): void
{
TestModel::clearTestEntries();

$testData = "AABCCDDDEEFG";
foreach (str_split($testData) as $i => $char) {
TestModel::addTestEntry([
"id" => $i . $char,
"text" => $char,
"number" => $i
]);
}

$result = TestModel::query(new SelectQuery()->distinct());

$this->assertEquals(12, $result->count());
for ($i = 0; $i < 12; $i++) {
$this->assertEquals($i, $result[$i]->number);
$this->assertEquals($testData[$i], $result[$i]->text);
}
}
Comment thread
JulianVennen marked this conversation as resolved.
Resolved

Comment thread
JulianVennen marked this conversation as resolved.
Resolved
public function testSelectDistinctField(): void
{
TestModel::clearTestEntries();

$testData = "AABCCDDDEEFG";
foreach (str_split($testData) as $i => $char) {
TestModel::addTestEntry([
"id" => $i . $char,
"text" => $char,
"number" => $i
]);
}

$result = TestModel::query(new SelectQuery()->distinct()->fields(["text"]));
Comment thread
JulianVennen marked this conversation as resolved.
Resolved

$this->assertEquals(7, $result->count());
$this->assertEquals("A", $result[0]->text);
$this->assertEquals("B", $result[1]->text);
$this->assertEquals("C", $result[2]->text);
$this->assertEquals("D", $result[3]->text);
$this->assertEquals("E", $result[4]->text);
$this->assertEquals("F", $result[5]->text);
$this->assertEquals("G", $result[6]->text);
}

public function testSelectDistinctBeforeLimit(): void
{
TestModel::clearTestEntries();

$testData = "AABCCDDDEEFG";
foreach (str_split($testData) as $i => $char) {
TestModel::addTestEntry([
"id" => $i . $char,
"text" => $char,
"number" => $i
]);
}

$result = TestModel::query(new SelectQuery()->distinct()->fields(["text"])->limit(5));

$this->assertEquals(5, $result->count());
$this->assertEquals("A", $result[0]->text);
$this->assertEquals("B", $result[1]->text);
$this->assertEquals("C", $result[2]->text);
$this->assertEquals("D", $result[3]->text);
$this->assertEquals("E", $result[4]->text);
}

public function testSelectDistinctWithNull(): void
{
TestModel::clearTestEntries();

$testData = "AABCCDDDEEFG";
foreach (str_split($testData) as $i => $char) {
TestModel::addTestEntry([
"id" => $i . $char,
"text" => $char,
"number" => $i
]);
}
TestModel::addTestEntry([
"id" => "101",
"text" => null,
"number" => 101
]);

$result = TestModel::query(new SelectQuery()->distinct()->fields(["text"]));

$this->assertEquals(8, $result->count());
$this->assertEquals("A", $result[0]->text);
$this->assertEquals("B", $result[1]->text);
$this->assertEquals("C", $result[2]->text);
$this->assertEquals("D", $result[3]->text);
$this->assertEquals("E", $result[4]->text);
$this->assertEquals("F", $result[5]->text);
$this->assertEquals("G", $result[6]->text);
$this->assertEquals(null, $result[7]->text);
}

public function testSelectDistinctWithNullAlias(): void
{
TestModel::clearTestEntries();

$testData = "AABCCDDDEEFG";
foreach (str_split($testData) as $i => $char) {
TestModel::addTestEntry([
"id" => $i . $char,
"text" => $char,
"number" => $i
]);
}
TestModel::addTestEntry([
"id" => "101",
"text" => null,
"number" => 101
]);

$result = TestModel::query(new SelectQuery()->distinct()->fields([
new SelectField("text")->setAlias("text_alias")
]));

$this->assertEquals(8, $result->count());
$this->assertEquals("A", $result[0]->getField("text_alias"));
$this->assertEquals("B", $result[1]->getField("text_alias"));
$this->assertEquals("C", $result[2]->getField("text_alias"));
$this->assertEquals("D", $result[3]->getField("text_alias"));
$this->assertEquals("E", $result[4]->getField("text_alias"));
$this->assertEquals("F", $result[5]->getField("text_alias"));
$this->assertEquals("G", $result[6]->getField("text_alias"));
$this->assertEquals(null, $result[7]->getField("text_alias"));
}

protected function tearDown(): void
{
TestModel::clearTestEntries();
Expand Down
Loading