From 479facee528eaa1da5bbc89f9d597faddfdf8490 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 13 Oct 2019 20:38:25 +0200 Subject: [PATCH] Implementd query aliases --- DataStorage/Database/DataMapperAbstract.php | 2 +- DataStorage/Database/GrammarAbstract.php | 8 +- DataStorage/Database/Query/Builder.php | 129 ++++++++++++++---- .../Database/Query/Grammar/Grammar.php | 12 +- tests/Model/Message/DomTest.php | 1 - tests/Model/Message/FormValidationTest.php | 1 - tests/Model/Message/NotifyTest.php | 1 - tests/Model/Message/RedirectTest.php | 1 - tests/Model/Message/ReloadTest.php | 1 - 9 files changed, 119 insertions(+), 37 deletions(-) diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index d7d285532..cde79553d 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -676,7 +676,7 @@ class DataMapperAbstract implements DataMapperInterface $objsIds = []; $relReflectionClass = null; - foreach ($values as $key => &$value) { + foreach ($values as $key => $value) { if (!\is_object($value)) { // Is scalar => already in database $objsIds[$key] = $value; diff --git a/DataStorage/Database/GrammarAbstract.php b/DataStorage/Database/GrammarAbstract.php index 9ecf6385e..16ead9d1a 100644 --- a/DataStorage/Database/GrammarAbstract.php +++ b/DataStorage/Database/GrammarAbstract.php @@ -82,6 +82,8 @@ abstract class GrammarAbstract */ protected array $specialKeywords = [ 'COUNT(', + 'MAX(', + 'MIN(', ]; /** @@ -207,13 +209,13 @@ abstract class GrammarAbstract foreach ($elements as $key => $element) { if (\is_string($element) && $element !== '*') { $prefix = \stripos($element, '.') !== false || $column ? $prefix : ''; - $expression .= $this->compileSystem($element, $prefix) . ', '; + $expression .= $this->compileSystem($element, $prefix) . (\is_string($key) ? ' as ' . $prefix . $key : '') . ', '; } elseif (\is_string($element) && $element === '*') { $expression .= '*, '; } elseif ($element instanceof \Closure) { - $expression .= $element() . ', '; + $expression .= $element() . (\is_string($key) ? ' as ' . $prefix . $key : '') . ', '; } elseif ($element instanceof BuilderAbstract) { - $expression .= $element->toSql() . ', '; + $expression .= $element->toSql() . (\is_string($key) ? ' as ' . $prefix . $key : '') . ', '; } else { throw new \InvalidArgumentException(); } diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index 776220162..15d6061ce 100644 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -278,6 +278,24 @@ class Builder extends BuilderAbstract return $this; } + /** + * Select with alias. + * + * @param mixed $column Column query + * @param string $alias Alias + * + * @return Builder + * + * @since 1.0.0 + */ + public function selectAs($column, string $alias) : self + { + $this->type = QueryType::SELECT; + $this->selects[$alias] = $column; + + return $this; + } + /** * Select. * @@ -448,6 +466,23 @@ class Builder extends BuilderAbstract return $this; } + /** + * From with alias. + * + * @param mixed $column Column query + * @param string $alias Alias + * + * @return Builder + * + * @since 1.0.0 + */ + public function fromAs($column, string $alias) : self + { + $this->from[$alias] = $column; + + return $this; + } + /** * Make raw from. * @@ -1050,16 +1085,24 @@ class Builder extends BuilderAbstract /** * Join. * + * @param mixed $table Join query + * @param string $type Join type + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function join($table, string $type = JoinType::JOIN) : self + public function join($table, string $type = JoinType::JOIN, string $alias = null) : self { - if (\is_string($table) || $table instanceof \Closure) { + if (!\is_string($table)&& !($table instanceof self) && !($table instanceof \Closure)) { + throw new \InvalidArgumentException(); + } + + if ($alias === null) { $this->joins[] = ['type' => $type, 'table' => $table]; } else { - throw new \InvalidArgumentException(); + $this->joins[$alias] = ['type' => $type, 'table' => $table]; } return $this; @@ -1068,133 +1111,166 @@ class Builder extends BuilderAbstract /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function leftJoin($column) : self + public function leftJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::LEFT_JOIN); + return $this->join($column, JoinType::LEFT_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function leftOuterJoin($column) : self + public function leftOuterJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::LEFT_OUTER_JOIN); + return $this->join($column, JoinType::LEFT_OUTER_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function leftInnerJoin($column) : self + public function leftInnerJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::LEFT_INNER_JOIN); + return $this->join($column, JoinType::LEFT_INNER_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function rightJoin($column) : self + public function rightJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::RIGHT_JOIN); + return $this->join($column, JoinType::RIGHT_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function rightOuterJoin($column) : self + public function rightOuterJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::RIGHT_OUTER_JOIN); + return $this->join($column, JoinType::RIGHT_OUTER_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function rightInnerJoin($column) : self + public function rightInnerJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::RIGHT_INNER_JOIN); + return $this->join($column, JoinType::RIGHT_INNER_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function outerJoin($column) : self + public function outerJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::OUTER_JOIN); + return $this->join($column, JoinType::OUTER_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function innerJoin($column) : self + public function innerJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::INNER_JOIN); + return $this->join($column, JoinType::INNER_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function crossJoin($column) : self + public function crossJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::CROSS_JOIN); + return $this->join($column, JoinType::CROSS_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function fullJoin($column) : self + public function fullJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::FULL_JOIN); + return $this->join($column, JoinType::FULL_JOIN, $alias); } /** * Join. * + * @param mixed $column Join query + * @param null|string $alias Alias name (empty = none) + * * @return Builder * * @since 1.0.0 */ - public function fullOuterJoin($column) : self + public function fullOuterJoin($column, string $alias = null) : self { - return $this->join($column, JoinType::FULL_OUTER_JOIN); + return $this->join($column, JoinType::FULL_OUTER_JOIN, $alias); } /** @@ -1237,7 +1313,8 @@ class Builder extends BuilderAbstract throw new \InvalidArgumentException('Unknown operator.'); } - $this->ons[$joinCount][] = [ + // @todo: this is bad! ons needs to have the same key as the join for the grammar to work. since alias are possible this is nec3essary. + $this->ons[\array_keys($this->joins)[$joinCount]][] = [ 'column' => $column, 'operator' => $operator[$i], 'value' => $values[$i], diff --git a/DataStorage/Database/Query/Grammar/Grammar.php b/DataStorage/Database/Query/Grammar/Grammar.php index 4c91cb65b..b1afe37c9 100644 --- a/DataStorage/Database/Query/Grammar/Grammar.php +++ b/DataStorage/Database/Query/Grammar/Grammar.php @@ -252,7 +252,7 @@ class Grammar extends GrammarAbstract } elseif ($element['column'] instanceof \Closure) { $expression .= $element['column'](); } elseif ($element['column'] instanceof Builder) { - $expression .= '(' . $element['column']->toSql() . ')'; + $expression .= '(' . \rtrim($element['column']->toSql(), ';') . ')'; } elseif ($element['column'] instanceof Where) { $expression .= '(' . \rtrim($this->compileWhereQuery($element['column']), ';') . ')'; } @@ -409,7 +409,15 @@ class Grammar extends GrammarAbstract foreach ($joins as $key => $join) { $expression .= $join['type'] . ' '; - $expression .= $this->compileSystem($join['table'], $query->getPrefix()); + + if (\is_string($join['table'])) { + $expression .= $this->compileSystem($join['table'], $query->getPrefix()) . (\is_string($key) ? ' as ' . $query->getPrefix() . $key : ''); + } elseif ($join['table'] instanceof \Closure) { + $expression .= $join['table']() . (\is_string($key) ? ' as ' . $query->getPrefix() . $key : ''); + } elseif ($join['table'] instanceof Builder) { + $expression .= '(' . \rtrim($join['table']->toSql(), ';') . ')' . (\is_string($key) ? ' as ' . $query->getPrefix() . $key : ''); + } + $expression .= $this->compileOn($query, $query->ons[$key]); } diff --git a/tests/Model/Message/DomTest.php b/tests/Model/Message/DomTest.php index 9b9e1f859..a62771c96 100644 --- a/tests/Model/Message/DomTest.php +++ b/tests/Model/Message/DomTest.php @@ -12,7 +12,6 @@ */ declare(strict_types=1); - namespace phpOMS\tests\phpOMS\Model\Message; use phpOMS\Model\Message\Dom; diff --git a/tests/Model/Message/FormValidationTest.php b/tests/Model/Message/FormValidationTest.php index 83986cc94..c2f633c6d 100644 --- a/tests/Model/Message/FormValidationTest.php +++ b/tests/Model/Message/FormValidationTest.php @@ -12,7 +12,6 @@ */ declare(strict_types=1); - namespace phpOMS\tests\phpOMS\Model\Message; use phpOMS\Model\Message\FormValidation; diff --git a/tests/Model/Message/NotifyTest.php b/tests/Model/Message/NotifyTest.php index b6bcd17bc..7d718bd08 100644 --- a/tests/Model/Message/NotifyTest.php +++ b/tests/Model/Message/NotifyTest.php @@ -12,7 +12,6 @@ */ declare(strict_types=1); - namespace phpOMS\tests\phpOMS\Model\Message; use phpOMS\Model\Message\Notify; diff --git a/tests/Model/Message/RedirectTest.php b/tests/Model/Message/RedirectTest.php index 05cfb62dd..43ef02414 100644 --- a/tests/Model/Message/RedirectTest.php +++ b/tests/Model/Message/RedirectTest.php @@ -12,7 +12,6 @@ */ declare(strict_types=1); - namespace phpOMS\tests\phpOMS\Model\Message; use phpOMS\Model\Message\Redirect; diff --git a/tests/Model/Message/ReloadTest.php b/tests/Model/Message/ReloadTest.php index 2850e12b2..790e41c8a 100644 --- a/tests/Model/Message/ReloadTest.php +++ b/tests/Model/Message/ReloadTest.php @@ -12,7 +12,6 @@ */ declare(strict_types=1); - namespace phpOMS\tests\phpOMS\Model\Message; use phpOMS\Model\Message\Reload;