diff options
Diffstat (limited to 'lib/private/DB/QueryBuilder/ExpressionBuilder')
5 files changed, 199 insertions, 277 deletions
diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php index d4c1a9db881..b922c861630 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/ExpressionBuilder.php @@ -1,29 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OC\DB\QueryBuilder\ExpressionBuilder; use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder; @@ -33,12 +14,14 @@ use OC\DB\QueryBuilder\FunctionBuilder\FunctionBuilder; use OC\DB\QueryBuilder\Literal; use OC\DB\QueryBuilder\QueryFunction; use OC\DB\QueryBuilder\QuoteHelper; +use OCP\DB\QueryBuilder\ICompositeExpression; use OCP\DB\QueryBuilder\IExpressionBuilder; use OCP\DB\QueryBuilder\ILiteral; use OCP\DB\QueryBuilder\IParameter; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryFunction; use OCP\IDBConnection; +use Psr\Log\LoggerInterface; class ExpressionBuilder implements IExpressionBuilder { /** @var \Doctrine\DBAL\Query\Expression\ExpressionBuilder */ @@ -50,17 +33,15 @@ class ExpressionBuilder implements IExpressionBuilder { /** @var IDBConnection */ protected $connection; + /** @var LoggerInterface */ + protected $logger; + /** @var FunctionBuilder */ protected $functionBuilder; - /** - * Initializes a new <tt>ExpressionBuilder</tt>. - * - * @param ConnectionAdapter $connection - * @param IQueryBuilder $queryBuilder - */ - public function __construct(ConnectionAdapter $connection, IQueryBuilder $queryBuilder) { + public function __construct(ConnectionAdapter $connection, IQueryBuilder $queryBuilder, LoggerInterface $logger) { $this->connection = $connection; + $this->logger = $logger; $this->helper = new QuoteHelper(); $this->expressionBuilder = new DoctrineExpressionBuilder($connection->getInner()); $this->functionBuilder = $queryBuilder->func(); @@ -76,13 +57,15 @@ class ExpressionBuilder implements IExpressionBuilder { * $expr->andX('u.type = ?', 'u.role = ?')); * * @param mixed ...$x Optional clause. Defaults = null, but requires - * at least one defined when converting to string. + * at least one defined when converting to string. * * @return \OCP\DB\QueryBuilder\ICompositeExpression */ - public function andX(...$x) { - $compositeExpression = call_user_func_array([$this->expressionBuilder, 'andX'], $x); - return new CompositeExpression($compositeExpression); + public function andX(...$x): ICompositeExpression { + if (empty($x)) { + $this->logger->debug('Calling ' . IQueryBuilder::class . '::' . __FUNCTION__ . ' without parameters is deprecated and will throw soon.', ['exception' => new \Exception('No parameters in call to ' . __METHOD__)]); + } + return new CompositeExpression(CompositeExpression::TYPE_AND, $x); } /** @@ -95,13 +78,15 @@ class ExpressionBuilder implements IExpressionBuilder { * $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?')); * * @param mixed ...$x Optional clause. Defaults = null, but requires - * at least one defined when converting to string. + * at least one defined when converting to string. * * @return \OCP\DB\QueryBuilder\ICompositeExpression */ - public function orX(...$x) { - $compositeExpression = call_user_func_array([$this->expressionBuilder, 'orX'], $x); - return new CompositeExpression($compositeExpression); + public function orX(...$x): ICompositeExpression { + if (empty($x)) { + $this->logger->debug('Calling ' . IQueryBuilder::class . '::' . __FUNCTION__ . ' without parameters is deprecated and will throw soon.', ['exception' => new \Exception('No parameters in call to ' . __METHOD__)]); + } + return new CompositeExpression(CompositeExpression::TYPE_OR, $x); } /** @@ -111,13 +96,13 @@ class ExpressionBuilder implements IExpressionBuilder { * @param string $operator One of the IExpressionBuilder::* constants. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function comparison($x, $operator, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function comparison($x, string $operator, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->comparison($x, $operator, $y); } @@ -134,13 +119,13 @@ class ExpressionBuilder implements IExpressionBuilder { * @param mixed $x The left expression. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function eq($x, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function eq($x, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->eq($x, $y); } @@ -156,13 +141,13 @@ class ExpressionBuilder implements IExpressionBuilder { * @param mixed $x The left expression. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function neq($x, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function neq($x, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->neq($x, $y); } @@ -178,13 +163,13 @@ class ExpressionBuilder implements IExpressionBuilder { * @param mixed $x The left expression. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function lt($x, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function lt($x, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->lt($x, $y); } @@ -200,13 +185,13 @@ class ExpressionBuilder implements IExpressionBuilder { * @param mixed $x The left expression. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function lte($x, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function lte($x, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->lte($x, $y); } @@ -222,13 +207,13 @@ class ExpressionBuilder implements IExpressionBuilder { * @param mixed $x The left expression. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function gt($x, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function gt($x, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->gt($x, $y); } @@ -244,24 +229,24 @@ class ExpressionBuilder implements IExpressionBuilder { * @param mixed $x The left expression. * @param mixed $y The right expression. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function gte($x, $y, $type = null) { - $x = $this->helper->quoteColumnName($x); - $y = $this->helper->quoteColumnName($y); + public function gte($x, $y, $type = null): string { + $x = $this->prepareColumn($x, $type); + $y = $this->prepareColumn($y, $type); return $this->expressionBuilder->gte($x, $y); } /** * Creates an IS NULL expression with the given arguments. * - * @param string $x The field in string format to be restricted by IS NULL. + * @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be restricted by IS NULL. * * @return string */ - public function isNull($x) { + public function isNull($x): string { $x = $this->helper->quoteColumnName($x); return $this->expressionBuilder->isNull($x); } @@ -269,11 +254,11 @@ class ExpressionBuilder implements IExpressionBuilder { /** * Creates an IS NOT NULL expression with the given arguments. * - * @param string $x The field in string format to be restricted by IS NOT NULL. + * @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be restricted by IS NOT NULL. * * @return string */ - public function isNotNull($x) { + public function isNotNull($x): string { $x = $this->helper->quoteColumnName($x); return $this->expressionBuilder->isNotNull($x); } @@ -284,11 +269,11 @@ class ExpressionBuilder implements IExpressionBuilder { * @param ILiteral|IParameter|IQueryFunction|string $x Field in string format to be inspected by LIKE() comparison. * @param mixed $y Argument to be used in LIKE() comparison. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function like($x, $y, $type = null) { + public function like($x, $y, $type = null): string { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnName($y); return $this->expressionBuilder->like($x, $y); @@ -300,12 +285,12 @@ class ExpressionBuilder implements IExpressionBuilder { * @param string $x Field in string format to be inspected by ILIKE() comparison. * @param mixed $y Argument to be used in ILIKE() comparison. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string * @since 9.0.0 */ - public function iLike($x, $y, $type = null) { + public function iLike($x, $y, $type = null): string { return $this->expressionBuilder->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y)); } @@ -315,11 +300,11 @@ class ExpressionBuilder implements IExpressionBuilder { * @param ILiteral|IParameter|IQueryFunction|string $x Field in string format to be inspected by NOT LIKE() comparison. * @param mixed $y Argument to be used in NOT LIKE() comparison. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function notLike($x, $y, $type = null) { + public function notLike($x, $y, $type = null): string { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnName($y); return $this->expressionBuilder->notLike($x, $y); @@ -331,11 +316,11 @@ class ExpressionBuilder implements IExpressionBuilder { * @param ILiteral|IParameter|IQueryFunction|string $x The field in string format to be inspected by IN() comparison. * @param ILiteral|IParameter|IQueryFunction|string|array $y The placeholder or the array of values to be used by IN() comparison. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function in($x, $y, $type = null) { + public function in($x, $y, $type = null): string { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnNames($y); return $this->expressionBuilder->in($x, $y); @@ -347,11 +332,11 @@ class ExpressionBuilder implements IExpressionBuilder { * @param ILiteral|IParameter|IQueryFunction|string $x The field in string format to be inspected by NOT IN() comparison. * @param ILiteral|IParameter|IQueryFunction|string|array $y The placeholder or the array of values to be used by NOT IN() comparison. * @param mixed|null $type one of the IQueryBuilder::PARAM_* constants - * required when comparing text fields for oci compatibility + * required when comparing text fields for oci compatibility * * @return string */ - public function notIn($x, $y, $type = null) { + public function notIn($x, $y, $type = null): string { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnNames($y); return $this->expressionBuilder->notIn($x, $y); @@ -360,22 +345,22 @@ class ExpressionBuilder implements IExpressionBuilder { /** * Creates a $x = '' statement, because Oracle needs a different check * - * @param string $x The field in string format to be inspected by the comparison. + * @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison. * @return string * @since 13.0.0 */ - public function emptyString($x) { + public function emptyString($x): string { return $this->eq($x, $this->literal('', IQueryBuilder::PARAM_STR)); } /** * Creates a `$x <> ''` statement, because Oracle needs a different check * - * @param string $x The field in string format to be inspected by the comparison. + * @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison. * @return string * @since 13.0.0 */ - public function nonEmptyString($x) { + public function nonEmptyString($x): string { return $this->neq($x, $this->literal('', IQueryBuilder::PARAM_STR)); } @@ -387,7 +372,7 @@ class ExpressionBuilder implements IExpressionBuilder { * @return IQueryFunction * @since 12.0.0 */ - public function bitwiseAnd($x, $y) { + public function bitwiseAnd($x, int $y): IQueryFunction { return new QueryFunction($this->connection->getDatabasePlatform()->getBitAndComparisonExpression( $this->helper->quoteColumnName($x), $y @@ -402,7 +387,7 @@ class ExpressionBuilder implements IExpressionBuilder { * @return IQueryFunction * @since 12.0.0 */ - public function bitwiseOr($x, $y) { + public function bitwiseOr($x, int $y): IQueryFunction { return new QueryFunction($this->connection->getDatabasePlatform()->getBitOrComparisonExpression( $this->helper->quoteColumnName($x), $y @@ -413,24 +398,34 @@ class ExpressionBuilder implements IExpressionBuilder { * Quotes a given input parameter. * * @param mixed $input The parameter to be quoted. - * @param mixed|null $type One of the IQueryBuilder::PARAM_* constants + * @param int $type One of the IQueryBuilder::PARAM_* constants * * @return ILiteral */ - public function literal($input, $type = null) { + public function literal($input, $type = IQueryBuilder::PARAM_STR): ILiteral { return new Literal($this->expressionBuilder->literal($input, $type)); } /** * Returns a IQueryFunction that casts the column to the given type * - * @param string $column + * @param string|IQueryFunction $column * @param mixed $type One of IQueryBuilder::PARAM_* - * @return string + * @psalm-param IQueryBuilder::PARAM_* $type + * @return IQueryFunction */ - public function castColumn($column, $type) { + public function castColumn($column, $type): IQueryFunction { return new QueryFunction( $this->helper->quoteColumnName($column) ); } + + /** + * @param mixed $column + * @param mixed|null $type + * @return array|IQueryFunction|string + */ + protected function prepareColumn($column, $type) { + return $this->helper->quoteColumnNames($column); + } } diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php index 3e4119bb11c..7216fd8807b 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/MySqlExpressionBuilder.php @@ -1,54 +1,51 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OC\DB\QueryBuilder\ExpressionBuilder; use OC\DB\ConnectionAdapter; +use OC\DB\QueryBuilder\QueryFunction; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\DB\QueryBuilder\IQueryFunction; +use Psr\Log\LoggerInterface; class MySqlExpressionBuilder extends ExpressionBuilder { + protected string $collation; - /** @var string */ - protected $charset; - - /** - * @param ConnectionAdapter $connection - * @param IQueryBuilder $queryBuilder - */ - public function __construct(ConnectionAdapter $connection, IQueryBuilder $queryBuilder) { - parent::__construct($connection, $queryBuilder); + public function __construct(ConnectionAdapter $connection, IQueryBuilder $queryBuilder, LoggerInterface $logger) { + parent::__construct($connection, $queryBuilder, $logger); $params = $connection->getInner()->getParams(); - $this->charset = isset($params['charset']) ? $params['charset'] : 'utf8'; + $this->collation = $params['collation'] ?? (($params['charset'] ?? 'utf8') . '_general_ci'); } /** * @inheritdoc */ - public function iLike($x, $y, $type = null) { + public function iLike($x, $y, $type = null): string { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnName($y); - return $this->expressionBuilder->comparison($x, ' COLLATE ' . $this->charset . '_general_ci LIKE', $y); + return $this->expressionBuilder->comparison($x, ' COLLATE ' . $this->collation . ' LIKE', $y); + } + + /** + * Returns a IQueryFunction that casts the column to the given type + * + * @param string|IQueryFunction $column + * @param mixed $type One of IQueryBuilder::PARAM_* + * @psalm-param IQueryBuilder::PARAM_* $type + * @return IQueryFunction + */ + public function castColumn($column, $type): IQueryFunction { + switch ($type) { + case IQueryBuilder::PARAM_STR: + return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS CHAR)'); + default: + return parent::castColumn($column, $type); + } } } diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php index f41242fdc60..542e8d62ede 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/OCIExpressionBuilder.php @@ -1,27 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OC\DB\QueryBuilder\ExpressionBuilder; use OC\DB\QueryBuilder\QueryFunction; @@ -31,7 +14,6 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryFunction; class OCIExpressionBuilder extends ExpressionBuilder { - /** * @param mixed $column * @param mixed|null $type @@ -40,86 +22,15 @@ class OCIExpressionBuilder extends ExpressionBuilder { protected function prepareColumn($column, $type) { if ($type === IQueryBuilder::PARAM_STR && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) { $column = $this->castColumn($column, $type); - } else { - $column = $this->helper->quoteColumnNames($column); } - return $column; - } - - /** - * @inheritdoc - */ - public function comparison($x, $operator, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - - return $this->expressionBuilder->comparison($x, $operator, $y); - } - - /** - * @inheritdoc - */ - public function eq($x, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - - return $this->expressionBuilder->eq($x, $y); - } - - /** - * @inheritdoc - */ - public function neq($x, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - - return $this->expressionBuilder->neq($x, $y); - } - - /** - * @inheritdoc - */ - public function lt($x, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - - return $this->expressionBuilder->lt($x, $y); - } - - /** - * @inheritdoc - */ - public function lte($x, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - - return $this->expressionBuilder->lte($x, $y); - } - - /** - * @inheritdoc - */ - public function gt($x, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - - return $this->expressionBuilder->gt($x, $y); - } - - /** - * @inheritdoc - */ - public function gte($x, $y, $type = null) { - $x = $this->prepareColumn($x, $type); - $y = $this->prepareColumn($y, $type); - return $this->expressionBuilder->gte($x, $y); + return parent::prepareColumn($column, $type); } /** * @inheritdoc */ - public function in($x, $y, $type = null) { + public function in($x, $y, $type = null): string { $x = $this->prepareColumn($x, $type); $y = $this->prepareColumn($y, $type); @@ -129,7 +40,7 @@ class OCIExpressionBuilder extends ExpressionBuilder { /** * @inheritdoc */ - public function notIn($x, $y, $type = null) { + public function notIn($x, $y, $type = null): string { $x = $this->prepareColumn($x, $type); $y = $this->prepareColumn($y, $type); @@ -139,33 +50,34 @@ class OCIExpressionBuilder extends ExpressionBuilder { /** * Creates a $x = '' statement, because Oracle needs a different check * - * @param string $x The field in string format to be inspected by the comparison. + * @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison. * @return string * @since 13.0.0 */ - public function emptyString($x) { + public function emptyString($x): string { return $this->isNull($x); } /** * Creates a `$x <> ''` statement, because Oracle needs a different check * - * @param string $x The field in string format to be inspected by the comparison. + * @param string|ILiteral|IParameter|IQueryFunction $x The field in string format to be inspected by the comparison. * @return string * @since 13.0.0 */ - public function nonEmptyString($x) { + public function nonEmptyString($x): string { return $this->isNotNull($x); } /** * Returns a IQueryFunction that casts the column to the given type * - * @param string $column + * @param string|IQueryFunction $column * @param mixed $type One of IQueryBuilder::PARAM_* + * @psalm-param IQueryBuilder::PARAM_* $type * @return IQueryFunction */ - public function castColumn($column, $type) { + public function castColumn($column, $type): IQueryFunction { if ($type === IQueryBuilder::PARAM_STR) { $column = $this->helper->quoteColumnName($column); return new QueryFunction('to_char(' . $column . ')'); @@ -181,14 +93,14 @@ class OCIExpressionBuilder extends ExpressionBuilder { /** * @inheritdoc */ - public function like($x, $y, $type = null) { + public function like($x, $y, $type = null): string { return parent::like($x, $y, $type) . " ESCAPE '\\'"; } /** * @inheritdoc */ - public function iLike($x, $y, $type = null) { + public function iLike($x, $y, $type = null): string { return $this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y)); } } diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php index 141a93ff75a..53a566a7eb6 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/PgSqlExpressionBuilder.php @@ -1,45 +1,29 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Robin Appelman <robin@icewind.nl> - * @author Thomas Müller <thomas.mueller@tmit.eu> - * - * @license AGPL-3.0 - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * + * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2016 ownCloud, Inc. + * SPDX-License-Identifier: AGPL-3.0-only */ - namespace OC\DB\QueryBuilder\ExpressionBuilder; use OC\DB\QueryBuilder\QueryFunction; use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\DB\QueryBuilder\IQueryFunction; class PgSqlExpressionBuilder extends ExpressionBuilder { - /** * Returns a IQueryFunction that casts the column to the given type * - * @param string $column + * @param string|IQueryFunction $column * @param mixed $type One of IQueryBuilder::PARAM_* - * @return string + * @psalm-param IQueryBuilder::PARAM_* $type + * @return IQueryFunction */ - public function castColumn($column, $type) { + public function castColumn($column, $type): IQueryFunction { switch ($type) { case IQueryBuilder::PARAM_INT: - return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS INT)'); + return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS BIGINT)'); case IQueryBuilder::PARAM_STR: return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS TEXT)'); default: @@ -50,7 +34,7 @@ class PgSqlExpressionBuilder extends ExpressionBuilder { /** * @inheritdoc */ - public function iLike($x, $y, $type = null) { + public function iLike($x, $y, $type = null): string { $x = $this->helper->quoteColumnName($x); $y = $this->helper->quoteColumnName($y); return $this->expressionBuilder->comparison($x, 'ILIKE', $y); diff --git a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php index 1fa0d79663a..52f82db2232 100644 --- a/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php +++ b/lib/private/DB/QueryBuilder/ExpressionBuilder/SqliteExpressionBuilder.php @@ -1,37 +1,71 @@ <?php + /** - * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> - * - * @author Robin Appelman <robin@icewind.nl> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * + * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OC\DB\QueryBuilder\ExpressionBuilder; +use OC\DB\QueryBuilder\QueryFunction; +use OCP\DB\QueryBuilder\ILiteral; +use OCP\DB\QueryBuilder\IParameter; +use OCP\DB\QueryBuilder\IQueryBuilder; +use OCP\DB\QueryBuilder\IQueryFunction; + class SqliteExpressionBuilder extends ExpressionBuilder { /** * @inheritdoc */ - public function like($x, $y, $type = null) { + public function like($x, $y, $type = null): string { return parent::like($x, $y, $type) . " ESCAPE '\\'"; } - public function iLike($x, $y, $type = null) { + public function iLike($x, $y, $type = null): string { return $this->like($this->functionBuilder->lower($x), $this->functionBuilder->lower($y), $type); } + + /** + * @param mixed $column + * @param mixed|null $type + * @return array|IQueryFunction|string + */ + protected function prepareColumn($column, $type) { + if ($type !== null + && !is_array($column) + && !($column instanceof IParameter) + && !($column instanceof ILiteral) + && (str_starts_with($type, 'date') || str_starts_with($type, 'time'))) { + return $this->castColumn($column, $type); + } + + return parent::prepareColumn($column, $type); + } + + /** + * Returns a IQueryFunction that casts the column to the given type + * + * @param string $column + * @param mixed $type One of IQueryBuilder::PARAM_* + * @return IQueryFunction + */ + public function castColumn($column, $type): IQueryFunction { + switch ($type) { + case IQueryBuilder::PARAM_DATE_MUTABLE: + case IQueryBuilder::PARAM_DATE_IMMUTABLE: + $column = $this->helper->quoteColumnName($column); + return new QueryFunction('DATE(' . $column . ')'); + case IQueryBuilder::PARAM_DATETIME_MUTABLE: + case IQueryBuilder::PARAM_DATETIME_IMMUTABLE: + case IQueryBuilder::PARAM_DATETIME_TZ_MUTABLE: + case IQueryBuilder::PARAM_DATETIME_TZ_IMMUTABLE: + $column = $this->helper->quoteColumnName($column); + return new QueryFunction('DATETIME(' . $column . ')'); + case IQueryBuilder::PARAM_TIME_MUTABLE: + case IQueryBuilder::PARAM_TIME_IMMUTABLE: + $column = $this->helper->quoteColumnName($column); + return new QueryFunction('TIME(' . $column . ')'); + } + + return parent::castColumn($column, $type); + } } |