Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
hrach committed Aug 1, 2021
1 parent 53d3b52 commit d666ad8
Show file tree
Hide file tree
Showing 19 changed files with 338 additions and 113 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"nette/caching": "~2.5 || ~3.0",
"nette/utils": "~2.5 || ~3.0",
"nette/tokenizer": "~2.3 || ~3.0",
"nextras/dbal": "~4.0"
"nextras/dbal": "~5.0@dev"
},
"require-dev": {
"nette/bootstrap": "~2.4 || ~3.0",
Expand Down
24 changes: 17 additions & 7 deletions src/Collection/DbalCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,13 @@ public function getByIdChecked($id): IEntity
public function findBy(array $conds): ICollection
{
$collection = clone $this;
$expression = $collection->getHelper()->processFilterFunction($collection->queryBuilder, $conds);
$expression = $collection->getHelper()->processFilterFunction($collection->queryBuilder, $conds, null);
$expression = $expression->applyAggregator($collection->queryBuilder);

foreach ($expression->joins as $join) {
$join->applyJoin($collection->queryBuilder);
}

if ($expression->isHavingClause) {
$collection->queryBuilder->andHaving(...$expression->args);
} else {
Expand All @@ -135,16 +141,20 @@ public function orderBy($expression, string $direction = ICollection::ASC): ICol
$expression = $expression; // no-op for PHPStan

foreach ($expression as $subExpression => $subDirection) {
$orderArgs = $collection->getHelper()
->processOrder($collection->queryBuilder, $subExpression, $subDirection);
$collection->queryBuilder->addOrderBy('%ex', $orderArgs);
$collection->getHelper()->processOrder(
$collection->queryBuilder,
$subExpression,
$subDirection
);
}
} else {
/** @phpstan-var string|list<mixed> $expression */
$expression = $expression; // no-op for PHPStan

$orderArgs = $collection->getHelper()->processOrder($collection->queryBuilder, $expression, $direction);
$collection->queryBuilder->addOrderBy('%ex', $orderArgs);
$collection->getHelper()->processOrder(
$collection->queryBuilder,
$expression,
$direction
);
}
return $collection;
}
Expand Down
37 changes: 31 additions & 6 deletions src/Collection/Functions/BaseAggregateFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use Nextras\Orm\Collection\Helpers\ArrayCollectionHelper;
use Nextras\Orm\Collection\Helpers\DbalExpressionResult;
use Nextras\Orm\Collection\Helpers\DbalQueryBuilderHelper;
use Nextras\Orm\Collection\Helpers\IDbalAggregator;
use Nextras\Orm\Entity\IEntity;
use Nextras\Orm\Exception\InvalidArgumentException;
use Nextras\Orm\Exception\InvalidStateException;
use function assert;
use function count;
use function is_array;
Expand Down Expand Up @@ -51,15 +53,38 @@ public function processArrayExpression(ArrayCollectionHelper $helper, IEntity $e
public function processQueryBuilderExpression(
DbalQueryBuilderHelper $helper,
QueryBuilder $builder,
array $args
array $args,
?IDbalAggregator $aggregator = null
): DbalExpressionResult
{
assert(count($args) === 1 && is_string($args[0]));

$expression = $helper->processPropertyExpr($builder, $args[0]);
return new DbalExpressionResult(
["{$this->sqlFunction}(%ex)", $expression->args],
true
);
if ($aggregator !== null) {
throw new InvalidStateException("Cannot apply two aggregations simultaneously.");
}

$aggregator = new class implements IDbalAggregator {
/** @var string */
public $sqlFunction;


public function aggregate(
QueryBuilder $queryBuilder,
DbalExpressionResult $expression
): DbalExpressionResult
{
return new DbalExpressionResult(
["{$this->sqlFunction}(%ex)", $expression->args],
$expression->joins,
null,
true,
null,
null
);
}
};
$aggregator->sqlFunction = $this->sqlFunction;

return $helper->processPropertyExpr($builder, $args[0], $aggregator)->applyAggregator($builder);
}
}
26 changes: 12 additions & 14 deletions src/Collection/Functions/BaseCompareFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Nextras\Orm\Collection\Helpers\ArrayCollectionHelper;
use Nextras\Orm\Collection\Helpers\DbalExpressionResult;
use Nextras\Orm\Collection\Helpers\DbalQueryBuilderHelper;
use Nextras\Orm\Collection\Helpers\IDbalAggregator;
use Nextras\Orm\Entity\IEntity;
use function assert;
use function count;
Expand Down Expand Up @@ -41,25 +42,22 @@ public function processArrayExpression(ArrayCollectionHelper $helper, IEntity $e
public function processQueryBuilderExpression(
DbalQueryBuilderHelper $helper,
QueryBuilder $builder,
array $args
array $args,
?IDbalAggregator $aggregator = null
): DbalExpressionResult
{
assert(count($args) === 2);

return $helper->processPropertyExpr(
$builder,
$args[0],
function (DbalExpressionResult $expression) use ($args): DbalExpressionResult {
if ($expression->valueNormalizer !== null) {
$cb = $expression->valueNormalizer;
$value = $cb($args[1]);
} else {
$value = $args[1];
}
$expression = $helper->processPropertyExpr($builder, $args[0], $aggregator);

return $this->evaluateInDb($expression, $value);
}
);
if ($expression->valueNormalizer !== null) {
$cb = $expression->valueNormalizer;
$value = $cb($args[1]);
} else {
$value = $args[1];
}

return $this->evaluateInDb($expression, $value);
}


Expand Down
4 changes: 2 additions & 2 deletions src/Collection/Functions/CompareEqualsFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ protected function evaluateInDb(DbalExpressionResult $expression, $value): DbalE
}
return $combined;
}, $value);
return new DbalExpressionResult(['%multiOr', $value], $expression->isHavingClause);
return $expression->withArgs(['%multiOr', $value]);
} else {
return $expression->append('IN %any', $value);
}
} else {
return new DbalExpressionResult(['1=0'], $expression->isHavingClause);
return $expression->withArgs(['1=0']);
}
} elseif ($value === null) {
return $expression->append('IS NULL');
Expand Down
6 changes: 4 additions & 2 deletions src/Collection/Functions/CompareLikeFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Nextras\Orm\Collection\Helpers\ArrayCollectionHelper;
use Nextras\Orm\Collection\Helpers\DbalExpressionResult;
use Nextras\Orm\Collection\Helpers\DbalQueryBuilderHelper;
use Nextras\Orm\Collection\Helpers\IDbalAggregator;
use Nextras\Orm\Entity\IEntity;
use Nextras\Orm\Exception\InvalidStateException;
use function preg_quote;
Expand Down Expand Up @@ -49,12 +50,13 @@ public function processArrayExpression(ArrayCollectionHelper $helper, IEntity $e
public function processQueryBuilderExpression(
DbalQueryBuilderHelper $helper,
QueryBuilder $builder,
array $args
array $args,
?IDbalAggregator $aggregator = null,
): DbalExpressionResult
{
assert(count($args) === 2);

$expression = $helper->processPropertyExpr($builder, $args[0]);
$expression = $helper->processPropertyExpr($builder, $args[0], $aggregator);

$likeExpression = $args[1];
assert($likeExpression instanceof LikeExpression);
Expand Down
4 changes: 2 additions & 2 deletions src/Collection/Functions/CompareNotEqualsFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ protected function evaluateInDb(DbalExpressionResult $expression, $value): DbalE
}
return $combined;
}, $value);
return new DbalExpressionResult(['NOT (%multiOr)', $value], $expression->isHavingClause);
return $expression->withArgs(['NOT (%multiOr)', $value]);
} else {
return $expression->append('NOT IN %any', $value);
}
} else {
return new DbalExpressionResult(['1=1'], $expression->isHavingClause);
return $expression->withArgs(['1=1']);
}
} elseif ($value === null) {
return $expression->append('IS NOT NULL');
Expand Down
20 changes: 17 additions & 3 deletions src/Collection/Functions/ConjunctionOperatorFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Nextras\Orm\Collection\Helpers\ConditionParser;
use Nextras\Orm\Collection\Helpers\DbalExpressionResult;
use Nextras\Orm\Collection\Helpers\DbalQueryBuilderHelper;
use Nextras\Orm\Collection\Helpers\IDbalAggregator;
use Nextras\Orm\Entity\IEntity;


Expand Down Expand Up @@ -38,17 +39,30 @@ public function processArrayExpression(ArrayCollectionHelper $helper, IEntity $e
public function processQueryBuilderExpression(
DbalQueryBuilderHelper $helper,
QueryBuilder $builder,
array $args
array $args,
?IDbalAggregator $aggregator = null
): DbalExpressionResult
{
$isHavingClause = false;
$processedArgs = [];
$joins = [];

foreach ($this->normalizeFunctions($args) as $collectionFunctionArgs) {
$expression = $helper->processFilterFunction($builder, $collectionFunctionArgs);
$expression = $helper->processFilterFunction($builder, $collectionFunctionArgs, $aggregator);
$expression = $expression->applyAggregator($builder);
$processedArgs[] = $expression->args;
$joins = array_merge($joins, $expression->joins);
$isHavingClause = $isHavingClause || $expression->isHavingClause;
}
return new DbalExpressionResult(['%and', $processedArgs], $isHavingClause);

return new DbalExpressionResult(
['%and', $processedArgs],
$joins,
null,
$isHavingClause,
null,
null
);
}


Expand Down
20 changes: 17 additions & 3 deletions src/Collection/Functions/DisjunctionOperatorFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Nextras\Orm\Collection\Helpers\ConditionParser;
use Nextras\Orm\Collection\Helpers\DbalExpressionResult;
use Nextras\Orm\Collection\Helpers\DbalQueryBuilderHelper;
use Nextras\Orm\Collection\Helpers\IDbalAggregator;
use Nextras\Orm\Entity\IEntity;


Expand Down Expand Up @@ -38,17 +39,30 @@ public function processArrayExpression(ArrayCollectionHelper $helper, IEntity $e
public function processQueryBuilderExpression(
DbalQueryBuilderHelper $helper,
QueryBuilder $builder,
array $args
array $args,
?IDbalAggregator $aggregator = null
): DbalExpressionResult
{
$isHavingClause = false;
$processedArgs = [];
$joins = [];

foreach ($this->normalizeFunctions($args) as $collectionFunctionArgs) {
$expression = $helper->processFilterFunction($builder, $collectionFunctionArgs);
$expression = $helper->processFilterFunction($builder, $collectionFunctionArgs, $aggregator);
$expression = $expression->applyAggregator($builder);
$processedArgs[] = $expression->args;
$joins = array_merge($joins, $expression->joins);
$isHavingClause = $isHavingClause || $expression->isHavingClause;
}
return new DbalExpressionResult(['%or', $processedArgs], $isHavingClause);

return new DbalExpressionResult(
['%or', $processedArgs],
$joins,
null,
$isHavingClause,
null,
null
);
}


Expand Down
4 changes: 3 additions & 1 deletion src/Collection/Functions/IQueryBuilderFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Nextras\Dbal\QueryBuilder\QueryBuilder;
use Nextras\Orm\Collection\Helpers\DbalExpressionResult;
use Nextras\Orm\Collection\Helpers\DbalQueryBuilderHelper;
use Nextras\Orm\Collection\Helpers\IDbalAggregator;


/**
Expand All @@ -22,6 +23,7 @@ interface IQueryBuilderFunction
public function processQueryBuilderExpression(
DbalQueryBuilderHelper $helper,
QueryBuilder $builder,
array $args
array $args,
?IDbalAggregator $aggregator = null
): DbalExpressionResult;
}
42 changes: 42 additions & 0 deletions src/Collection/Helpers/DbalAnyAggregator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Nextras\Orm\Collection\Helpers;


use Nextras\Dbal\QueryBuilder\QueryBuilder;
use function array_merge;
use function array_pop;
use function array_shift;


class DbalAnyAggregator implements IDbalAggregator
{
public function aggregate(
QueryBuilder $queryBuilder,
DbalExpressionResult $expression
): DbalExpressionResult
{
$joinExpression = array_shift($expression->args);
$joinArgs = $expression->args;
$joins = $expression->joins;
$join = array_pop($joins);

$joins[] = new DbalJoinEntry(
$join->toExpression,
$join->alias,
"($join->onExpression) AND $joinExpression",
array_merge($join->args, $joinArgs),
$join->conventions
);

$primaryKey = $join->conventions->getStoragePrimaryKey()[0];
return new DbalExpressionResult(
['COUNT(%table.%column) > 0', $join->alias, $primaryKey],
$joins,
null,
true,
null,
null
);
}
}
Loading

0 comments on commit d666ad8

Please sign in to comment.