diff options
Diffstat (limited to 'lib/public/DB/QueryBuilder')
-rw-r--r-- | lib/public/DB/QueryBuilder/ICompositeExpression.php | 33 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/IExpressionBuilder.php | 194 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/IFunctionBuilder.php | 65 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/ILiteral.php | 25 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/IParameter.php | 25 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/IQueryBuilder.php | 324 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/IQueryFunction.php | 25 | ||||
-rw-r--r-- | lib/public/DB/QueryBuilder/Sharded/IShardMapper.php | 25 |
8 files changed, 472 insertions, 244 deletions
diff --git a/lib/public/DB/QueryBuilder/ICompositeExpression.php b/lib/public/DB/QueryBuilder/ICompositeExpression.php index 905465ba9e0..12f321d9e54 100644 --- a/lib/public/DB/QueryBuilder/ICompositeExpression.php +++ b/lib/public/DB/QueryBuilder/ICompositeExpression.php @@ -1,27 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Joas Schilling <coding@schilljs.com> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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 OCP\DB\QueryBuilder; /** @@ -37,7 +20,7 @@ interface ICompositeExpression { * @return ICompositeExpression * @since 8.2.0 */ - public function addMultiple(array $parts = []); + public function addMultiple(array $parts = []): ICompositeExpression; /** * Adds an expression to composite expression. @@ -47,7 +30,7 @@ interface ICompositeExpression { * @return ICompositeExpression * @since 8.2.0 */ - public function add($part); + public function add($part): ICompositeExpression; /** * Retrieves the amount of expressions on composite expression. @@ -55,7 +38,7 @@ interface ICompositeExpression { * @return integer * @since 8.2.0 */ - public function count(); + public function count(): int; /** * Returns the type of this composite expression (AND/OR). @@ -63,5 +46,5 @@ interface ICompositeExpression { * @return string * @since 8.2.0 */ - public function getType(); + public function getType(): string; } diff --git a/lib/public/DB/QueryBuilder/IExpressionBuilder.php b/lib/public/DB/QueryBuilder/IExpressionBuilder.php index c62221305d5..12e30a45071 100644 --- a/lib/public/DB/QueryBuilder/IExpressionBuilder.php +++ b/lib/public/DB/QueryBuilder/IExpressionBuilder.php @@ -1,30 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @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 OCP\DB\QueryBuilder; use Doctrine\DBAL\Query\Expression\ExpressionBuilder; @@ -32,6 +12,8 @@ use Doctrine\DBAL\Query\Expression\ExpressionBuilder; /** * This class provides a wrapper around Doctrine's ExpressionBuilder * @since 8.2.0 + * + * @psalm-taint-specialize */ interface IExpressionBuilder { /** @@ -69,12 +51,15 @@ interface 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 * @since 8.2.0 + * @since 30.0.0 Calling the method without any arguments is deprecated and will throw with the next Doctrine/DBAL update + * + * @psalm-taint-sink sql $x */ - public function andX(...$x); + public function andX(...$x): ICompositeExpression; /** * Creates a disjunction of the given boolean expressions. @@ -86,12 +71,15 @@ interface 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 * @since 8.2.0 + * @since 30.0.0 Calling the method without any arguments is deprecated and will throw with the next Doctrine/DBAL update + * + * @psalm-taint-sink sql $x */ - public function orX(...$x); + public function orX(...$x): ICompositeExpression; /** * Creates a comparison expression. @@ -100,12 +88,17 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $operator + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function comparison($x, $operator, $y, $type = null); + public function comparison($x, string $operator, $y, $type = null): string; /** * Creates an equality comparison expression with the given arguments. @@ -120,12 +113,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function eq($x, $y, $type = null); + public function eq($x, $y, $type = null): string; /** * Creates a non equality comparison expression with the given arguments. @@ -139,12 +136,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function neq($x, $y, $type = null); + public function neq($x, $y, $type = null): string; /** * Creates a lower-than comparison expression with the given arguments. @@ -158,12 +159,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function lt($x, $y, $type = null); + public function lt($x, $y, $type = null): string; /** * Creates a lower-than-equal comparison expression with the given arguments. @@ -177,12 +182,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function lte($x, $y, $type = null); + public function lte($x, $y, $type = null): string; /** * Creates a greater-than comparison expression with the given arguments. @@ -196,12 +205,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function gt($x, $y, $type = null); + public function gt($x, $y, $type = null): string; /** * Creates a greater-than-equal comparison expression with the given arguments. @@ -215,32 +228,40 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function gte($x, $y, $type = null); + public function gte($x, $y, $type = null): string; /** * 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 * @since 8.2.0 + * + * @psalm-taint-sink sql $x */ - public function isNull($x); + public function isNull($x): string; /** * 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 * @since 8.2.0 + * + * @psalm-taint-sink sql $x */ - public function isNotNull($x); + public function isNotNull($x): string; /** * Creates a LIKE() comparison expression with the given arguments. @@ -248,12 +269,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function like($x, $y, $type = null); + public function like($x, $y, $type = null): string; /** * Creates a NOT LIKE() comparison expression with the given arguments. @@ -261,12 +286,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function notLike($x, $y, $type = null); + public function notLike($x, $y, $type = null): string; /** * Creates a ILIKE() comparison expression with the given arguments. @@ -274,12 +303,16 @@ interface 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 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function iLike($x, $y, $type = null); + public function iLike($x, $y, $type = null): string; /** * Creates a IN () comparison expression with the given arguments. @@ -287,12 +320,16 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function in($x, $y, $type = null); + public function in($x, $y, $type = null): string; /** * Creates a NOT IN () comparison expression with the given arguments. @@ -300,30 +337,38 @@ interface 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 * @since 8.2.0 - Parameter $type was added in 9.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y + * @psalm-taint-sink sql $type */ - public function notIn($x, $y, $type = null); + public function notIn($x, $y, $type = null): string; /** * 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 + * + * @psalm-taint-sink sql $x */ - public function emptyString($x); + public function emptyString($x): string; /** * 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 + * + * @psalm-taint-sink sql $x */ - public function nonEmptyString($x); + public function nonEmptyString($x): string; /** @@ -333,8 +378,11 @@ interface IExpressionBuilder { * @param int $y Bitmap that must be set * @return IQueryFunction * @since 12.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y */ - public function bitwiseAnd($x, $y); + public function bitwiseAnd($x, int $y): IQueryFunction; /** * Creates a bitwise OR comparison @@ -343,27 +391,37 @@ interface IExpressionBuilder { * @param int $y Bitmap that must be set * @return IQueryFunction * @since 12.0.0 + * + * @psalm-taint-sink sql $x + * @psalm-taint-sink sql $y */ - public function bitwiseOr($x, $y); + public function bitwiseOr($x, int $y): IQueryFunction; /** * 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 string + * @return ILiteral * @since 8.2.0 + * + * @psalm-taint-sink sql $input + * @psalm-taint-sink sql $type */ - public function literal($input, $type = null); + public function literal($input, $type = IQueryBuilder::PARAM_STR): ILiteral; /** * 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 * @since 9.0.0 + * + * @psalm-taint-sink sql $column + * @psalm-taint-sink sql $type */ - public function castColumn($column, $type); + public function castColumn($column, $type): IQueryFunction; } diff --git a/lib/public/DB/QueryBuilder/IFunctionBuilder.php b/lib/public/DB/QueryBuilder/IFunctionBuilder.php index 569bc7485d4..480ec1cb1ac 100644 --- a/lib/public/DB/QueryBuilder/IFunctionBuilder.php +++ b/lib/public/DB/QueryBuilder/IFunctionBuilder.php @@ -1,28 +1,9 @@ <?php + /** - * @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> - * - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @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 OCP\DB\QueryBuilder; /** @@ -44,13 +25,29 @@ interface IFunctionBuilder { /** * Combines two input strings * - * @param string|ILiteral|IParameter|IQueryFunction $x The first input string - * @param string|ILiteral|IParameter|IQueryFunction $y The seccond input string + * @param string|ILiteral|IParameter|IQueryFunction $x Expressions or literal strings + * @param string|ILiteral|IParameter|IQueryFunction ...$exprs Expressions or literal strings * * @return IQueryFunction * @since 12.0.0 */ - public function concat($x, $y): IQueryFunction; + public function concat($x, ...$expr): IQueryFunction; + + /** + * Returns a string which is the concatenation of all non-NULL values of X + * + * Usage examples: + * + * groupConcat('column') -- with comma as separator (default separator) + * + * groupConcat('column', ';') -- with different separator + * + * @param string|IQueryFunction $expr The expression to group + * @param string|null $separator The separator + * @return IQueryFunction + * @since 24.0.0 + */ + public function groupConcat($expr, ?string $separator = ','): IQueryFunction; /** * Takes a substring from the input string @@ -109,6 +106,24 @@ interface IFunctionBuilder { public function count($count = '', $alias = ''): IQueryFunction; /** + * @param string|ILiteral|IParameter|IQueryFunction $field The input to be measured + * @param string $alias Alias for the length + * + * @return IQueryFunction + * @since 24.0.0 + */ + public function octetLength($field, $alias = ''): IQueryFunction; + + /** + * @param string|ILiteral|IParameter|IQueryFunction $field The input to be measured + * @param string $alias Alias for the length + * + * @return IQueryFunction + * @since 24.0.0 + */ + public function charLength($field, $alias = ''): IQueryFunction; + + /** * Takes the maximum of all rows in a column * * If you want to get the maximum value of multiple columns in the same row, use `greatest` instead diff --git a/lib/public/DB/QueryBuilder/ILiteral.php b/lib/public/DB/QueryBuilder/ILiteral.php index 8fe5c62d3f8..574eb0894eb 100644 --- a/lib/public/DB/QueryBuilder/ILiteral.php +++ b/lib/public/DB/QueryBuilder/ILiteral.php @@ -1,27 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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 OCP\DB\QueryBuilder; /** diff --git a/lib/public/DB/QueryBuilder/IParameter.php b/lib/public/DB/QueryBuilder/IParameter.php index 1636dd8c438..86ea9437e9c 100644 --- a/lib/public/DB/QueryBuilder/IParameter.php +++ b/lib/public/DB/QueryBuilder/IParameter.php @@ -1,27 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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 OCP\DB\QueryBuilder; /** diff --git a/lib/public/DB/QueryBuilder/IQueryBuilder.php b/lib/public/DB/QueryBuilder/IQueryBuilder.php index 24de7b4ce60..4794e7e8877 100644 --- a/lib/public/DB/QueryBuilder/IQueryBuilder.php +++ b/lib/public/DB/QueryBuilder/IQueryBuilder.php @@ -1,83 +1,127 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Daniel Kesselberg <mail@danielkesselberg.de> - * @author J0WI <J0WI@users.noreply.github.com> - * @author Joas Schilling <coding@schilljs.com> - * @author Lukas Reschke <lukas@statuscode.ch> - * @author Robin Appelman <robin@icewind.nl> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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 OCP\DB\QueryBuilder; +use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\ParameterType; +use Doctrine\DBAL\Types\Types; use OCP\DB\Exception; use OCP\DB\IResult; +use OCP\IDBConnection; /** * This class provides a wrapper around Doctrine's QueryBuilder * @since 8.2.0 + * + * @psalm-taint-specialize */ interface IQueryBuilder { - /** * @since 9.0.0 */ - public const PARAM_NULL = \PDO::PARAM_NULL; + public const PARAM_NULL = ParameterType::NULL; /** * @since 9.0.0 */ - public const PARAM_BOOL = \PDO::PARAM_BOOL; + public const PARAM_BOOL = Types::BOOLEAN; /** * @since 9.0.0 */ - public const PARAM_INT = \PDO::PARAM_INT; + public const PARAM_INT = ParameterType::INTEGER; /** * @since 9.0.0 */ - public const PARAM_STR = \PDO::PARAM_STR; + public const PARAM_STR = ParameterType::STRING; + /** + * @since 9.0.0 + */ + public const PARAM_LOB = ParameterType::LARGE_OBJECT; + /** * @since 9.0.0 + * @deprecated 31.0.0 - use PARAM_DATETIME_MUTABLE instead + */ + public const PARAM_DATE = Types::DATETIME_MUTABLE; + + /** + * For passing a \DateTime instance when only interested in the time part (without timezone support) + * @since 31.0.0 + */ + public const PARAM_TIME_MUTABLE = Types::TIME_MUTABLE; + + /** + * For passing a \DateTime instance when only interested in the date part (without timezone support) + * @since 31.0.0 + */ + public const PARAM_DATE_MUTABLE = Types::DATE_MUTABLE; + + /** + * For passing a \DateTime instance (without timezone support) + * @since 31.0.0 + */ + public const PARAM_DATETIME_MUTABLE = Types::DATETIME_MUTABLE; + + /** + * For passing a \DateTime instance with timezone support + * @since 31.0.0 + */ + public const PARAM_DATETIME_TZ_MUTABLE = Types::DATETIMETZ_MUTABLE; + + /** + * For passing a \DateTimeImmutable instance when only interested in the time part (without timezone support) + * @since 31.0.0 */ - public const PARAM_LOB = \PDO::PARAM_LOB; + public const PARAM_TIME_IMMUTABLE = Types::TIME_MUTABLE; + /** + * For passing a \DateTime instance when only interested in the date part (without timezone support) * @since 9.0.0 */ - public const PARAM_DATE = 'datetime'; + public const PARAM_DATE_IMMUTABLE = Types::DATE_IMMUTABLE; + + /** + * For passing a \DateTime instance (without timezone support) + * @since 31.0.0 + */ + public const PARAM_DATETIME_IMMUTABLE = Types::DATETIME_IMMUTABLE; + + /** + * For passing a \DateTime instance with timezone support + * @since 31.0.0 + */ + public const PARAM_DATETIME_TZ_IMMUTABLE = Types::DATETIMETZ_IMMUTABLE; + + /** + * @since 24.0.0 + */ + public const PARAM_JSON = 'json'; /** * @since 9.0.0 */ - public const PARAM_INT_ARRAY = Connection::PARAM_INT_ARRAY; + public const PARAM_INT_ARRAY = ArrayParameterType::INTEGER; /** * @since 9.0.0 */ - public const PARAM_STR_ARRAY = Connection::PARAM_STR_ARRAY; + public const PARAM_STR_ARRAY = ArrayParameterType::STRING; + /** + * @since 24.0.0 Indicates how many rows can be deleted at once with MySQL + * database server. + */ + public const MAX_ROW_DELETION = 100000; /** * Enable/disable automatic prefixing of table names with the oc_ prefix * * @param bool $enabled If set to true table names will be prefixed with the - * owncloud database prefix automatically. + * owncloud database prefix automatically. * @since 8.2.0 */ public function automaticTablePrefix($enabled); @@ -141,24 +185,52 @@ interface IQueryBuilder { * * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. * @since 8.2.0 + * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update + * and we can not fix this in our wrapper. */ public function getState(); /** * Executes this query using the bound parameters and their types. * - * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} + * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeStatement} * for insert, update and delete statements. * * Warning: until Nextcloud 20, this method could return a \Doctrine\DBAL\Driver\Statement but since * that interface changed in a breaking way the adapter \OCP\DB\QueryBuilder\IStatement is returned * to bridge old code to the new API * + * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0 * @return IResult|int * @throws Exception since 21.0.0 * @since 8.2.0 + * @deprecated 22.0.0 Use executeQuery or executeStatement */ - public function execute(); + public function execute(?IDBConnection $connection = null); + + /** + * Execute for select statements + * + * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0 + * @return IResult + * @since 22.0.0 + * + * @throws Exception + * @throws \RuntimeException in case of usage with non select query + */ + public function executeQuery(?IDBConnection $connection = null): IResult; + + /** + * Execute insert, update and delete statements + * + * @param ?IDBConnection $connection (optional) the connection to run the query against. since 30.0 + * @return int the number of affected rows + * @since 22.0.0 + * + * @throws Exception + * @throws \RuntimeException in case of usage with select query + */ + public function executeStatement(?IDBConnection $connection = null): int; /** * Gets the complete SQL string formed by the current specifications of this QueryBuilder. @@ -256,7 +328,7 @@ interface IQueryBuilder { /** * Sets the position of the first result to retrieve (the "offset"). * - * @param integer $firstResult The first result to return. + * @param int $firstResult The first result to return. * * @return $this This QueryBuilder instance. * @since 8.2.0 @@ -265,9 +337,9 @@ interface IQueryBuilder { /** * Gets the position of the first result the query object was set to retrieve (the "offset"). - * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. + * Returns 0 if {@link setFirstResult} was not applied to this QueryBuilder. * - * @return integer The position of the first result. + * @return int The position of the first result. * @since 8.2.0 */ public function getFirstResult(); @@ -275,7 +347,7 @@ interface IQueryBuilder { /** * Sets the maximum number of results to retrieve (the "limit"). * - * @param integer $maxResults The maximum number of results to retrieve. + * @param int|null $maxResults The maximum number of results to retrieve. * * @return $this This QueryBuilder instance. * @since 8.2.0 @@ -306,6 +378,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $selects */ public function select(...$selects); @@ -324,6 +398,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.1 + * + * @psalm-taint-sink sql $select + * @psalm-taint-sink sql $alias */ public function selectAlias($select, $alias); @@ -340,6 +417,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 9.0.0 + * + * @psalm-taint-sink sql $select */ public function selectDistinct($select); @@ -358,6 +437,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $select */ public function addSelect(...$select); @@ -367,8 +448,8 @@ interface IQueryBuilder { * * <code> * $qb = $conn->getQueryBuilder() - * ->delete('users', 'u') - * ->where('u.id = :user_id'); + * ->delete('users') + * ->where('id = :user_id'); * ->setParameter(':user_id', 1); * </code> * @@ -377,6 +458,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update + * + * @psalm-taint-sink sql $delete */ public function delete($delete = null, $alias = null); @@ -386,9 +470,10 @@ interface IQueryBuilder { * * <code> * $qb = $conn->getQueryBuilder() - * ->update('users', 'u') - * ->set('u.password', md5('password')) - * ->where('u.id = ?'); + * ->update('users') + * ->set('email', ':email') + * ->where('id = :user_id'); + * ->setParameter(':user_id', 1); * </code> * * @param string $update The table whose rows are subject to the update. @@ -396,6 +481,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * @since 30.0.0 Alias is deprecated and will no longer be used with the next Doctrine/DBAL update + * + * @psalm-taint-sink sql $update */ public function update($update = null, $alias = null); @@ -418,6 +506,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $insert */ public function insert($insert = null); @@ -431,11 +521,13 @@ interface IQueryBuilder { * ->from('users', 'u') * </code> * - * @param string $from The table. + * @param string|IQueryFunction $from The table. * @param string|null $alias The alias of the table. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $from */ public function from($from, $alias = null); @@ -452,10 +544,15 @@ interface IQueryBuilder { * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. + * @param string|ICompositeExpression|null $condition The condition for the join. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function join($fromAlias, $join, $alias, $condition = null); @@ -472,10 +569,15 @@ interface IQueryBuilder { * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. + * @param string|ICompositeExpression|null $condition The condition for the join. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function innerJoin($fromAlias, $join, $alias, $condition = null); @@ -490,12 +592,18 @@ interface IQueryBuilder { * </code> * * @param string $fromAlias The alias that points to a from clause. - * @param string $join The table name to join. + * @param string|IQueryFunction $join The table name to join. * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. + * @param string|ICompositeExpression|null $condition The condition for the join. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * @since 30.0.0 Allow passing IQueryFunction as parameter for `$join` to allow join with a sub-query. + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function leftJoin($fromAlias, $join, $alias, $condition = null); @@ -512,10 +620,15 @@ interface IQueryBuilder { * @param string $fromAlias The alias that points to a from clause. * @param string $join The table name to join. * @param string $alias The alias of the join table. - * @param string $condition The condition for the join. + * @param string|ICompositeExpression|null $condition The condition for the join. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $fromAlias + * @psalm-taint-sink sql $join + * @psalm-taint-sink sql $alias + * @psalm-taint-sink sql $condition */ public function rightJoin($fromAlias, $join, $alias, $condition = null); @@ -534,6 +647,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $key + * @psalm-taint-sink sql $value */ public function set($key, $value); @@ -547,12 +663,13 @@ interface IQueryBuilder { * ->from('users', 'u') * ->where('u.id = ?'); * - * // You can optionally programatically build and/or expressions + * // You can optionally programmatically build and/or expressions * $qb = $conn->getQueryBuilder(); * - * $or = $qb->expr()->orx(); - * $or->add($qb->expr()->eq('u.id', 1)); - * $or->add($qb->expr()->eq('u.id', 2)); + * $or = $qb->expr()->orx( + * $qb->expr()->eq('u.id', 1), + * $qb->expr()->eq('u.id', 2), + * ); * * $qb->update('users', 'u') * ->set('u.password', md5('password')) @@ -563,6 +680,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $predicates */ public function where(...$predicates); @@ -584,6 +703,8 @@ interface IQueryBuilder { * * @see where() * @since 8.2.0 + * + * @psalm-taint-sink sql $where */ public function andWhere(...$where); @@ -605,6 +726,8 @@ interface IQueryBuilder { * * @see where() * @since 8.2.0 + * + * @psalm-taint-sink sql $where */ public function orWhere(...$where); @@ -623,6 +746,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $groupBys */ public function groupBy(...$groupBys); @@ -641,6 +766,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $groupby */ public function addGroupBy(...$groupBy); @@ -663,6 +790,9 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $column + * @psalm-taint-sink sql $value */ public function setValue($column, $value); @@ -685,6 +815,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $values */ public function values(array $values); @@ -696,6 +828,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $having */ public function having(...$having); @@ -707,6 +841,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $andHaving */ public function andHaving(...$having); @@ -718,6 +854,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $having */ public function orHaving(...$having); @@ -725,22 +863,28 @@ interface IQueryBuilder { * Specifies an ordering for the query results. * Replaces any previously specified orderings, if any. * - * @param string $sort The ordering expression. + * @param string|IQueryFunction|ILiteral|IParameter $sort The ordering expression. * @param string $order The ordering direction. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $sort + * @psalm-taint-sink sql $order */ public function orderBy($sort, $order = null); /** * Adds an ordering to the query results. * - * @param string $sort The ordering expression. + * @param string|ILiteral|IParameter|IQueryFunction $sort The ordering expression. * @param string $order The ordering direction. * * @return $this This QueryBuilder instance. * @since 8.2.0 + * + * @psalm-taint-sink sql $sort + * @psalm-taint-sink sql $order */ public function addOrderBy($sort, $order = null); @@ -751,6 +895,8 @@ interface IQueryBuilder { * * @return mixed * @since 8.2.0 + * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update + * and we can not fix this in our wrapper. Please track the details you need, outside the object. */ public function getQueryPart($queryPartName); @@ -759,6 +905,8 @@ interface IQueryBuilder { * * @return array * @since 8.2.0 + * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update + * and we can not fix this in our wrapper. Please track the details you need, outside the object. */ public function getQueryParts(); @@ -769,6 +917,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update + * and we can not fix this in our wrapper. Please create a new IQueryBuilder instead. */ public function resetQueryParts($queryPartNames = null); @@ -779,6 +929,8 @@ interface IQueryBuilder { * * @return $this This QueryBuilder instance. * @since 8.2.0 + * @deprecated 30.0.0 This function is going to be removed with the next Doctrine/DBAL update + * and we can not fix this in our wrapper. Please create a new IQueryBuilder instead. */ public function resetQueryPart($queryPartName); @@ -806,11 +958,13 @@ interface IQueryBuilder { * @link http://www.zetacomponents.org * * @param mixed $value - * @param mixed $type + * @param self::PARAM_* $type * @param string $placeHolder The name to bind with. The string must start with a colon ':'. * * @return IParameter * @since 8.2.0 + * + * @psalm-taint-escape sql */ public function createNamedParameter($value, $type = self::PARAM_STR, $placeHolder = null); @@ -832,10 +986,12 @@ interface IQueryBuilder { * </code> * * @param mixed $value - * @param integer $type + * @param self::PARAM_* $type * * @return IParameter * @since 8.2.0 + * + * @psalm-taint-escape sql */ public function createPositionalParameter($value, $type = self::PARAM_STR); @@ -855,6 +1011,8 @@ interface IQueryBuilder { * * @return IParameter * @since 8.2.0 + * + * @psalm-taint-escape sql */ public function createParameter($name); @@ -881,6 +1039,8 @@ interface IQueryBuilder { * * @return IQueryFunction * @since 8.2.0 + * + * @psalm-taint-sink sql $call */ public function createFunction($call); @@ -890,18 +1050,30 @@ interface IQueryBuilder { * @throws \BadMethodCallException When being called before an insert query has been run. * @since 9.0.0 */ - public function getLastInsertId(); + public function getLastInsertId(): int; /** - * Returns the table name quoted and with database prefix as needed by the implementation + * Returns the table name quoted and with database prefix as needed by the implementation. + * If a query function is passed the function is casted to string, + * this allows passing functions as sub-queries for join expression. * - * @param string $table + * @param string|IQueryFunction $table * @return string * @since 9.0.0 + * @since 24.0.0 accepts IQueryFunction as parameter */ public function getTableName($table); /** + * Returns the table name with database prefix as needed by the implementation + * + * @param string $table + * @return string + * @since 30.0.0 + */ + public function prefixTableName(string $table): string; + + /** * Returns the column name quoted and with table alias prefix as needed by the implementation * * @param string $column @@ -910,4 +1082,30 @@ interface IQueryBuilder { * @since 9.0.0 */ public function getColumnName($column, $tableAlias = ''); + + /** + * Provide a hint for the shard key for queries where this can't be detected otherwise + * + * @param string $column + * @param mixed $value + * @return $this + * @since 30.0.0 + */ + public function hintShardKey(string $column, mixed $value, bool $overwrite = false): self; + + /** + * Set the query to run across all shards if sharding is enabled. + * + * @return $this + * @since 30.0.0 + */ + public function runAcrossAllShards(): self; + + /** + * Get a list of column names that are expected in the query output + * + * @return array + * @since 30.0.0 + */ + public function getOutputColumns(): array; } diff --git a/lib/public/DB/QueryBuilder/IQueryFunction.php b/lib/public/DB/QueryBuilder/IQueryFunction.php index 22ac6081f1f..e19fc2959db 100644 --- a/lib/public/DB/QueryBuilder/IQueryFunction.php +++ b/lib/public/DB/QueryBuilder/IQueryFunction.php @@ -1,27 +1,10 @@ <?php + /** - * @copyright Copyright (c) 2016, ownCloud, Inc. - * - * @author Joas Schilling <coding@schilljs.com> - * @author Morris Jobke <hey@morrisjobke.de> - * @author Roeland Jago Douma <roeland@famdouma.nl> - * - * @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 OCP\DB\QueryBuilder; /** diff --git a/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php b/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php new file mode 100644 index 00000000000..fa00fb68719 --- /dev/null +++ b/lib/public/DB/QueryBuilder/Sharded/IShardMapper.php @@ -0,0 +1,25 @@ +<?php + +declare(strict_types=1); +/** + * SPDX-FileCopyrightText: 2024 Robin Appelman <robin@icewind.nl> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace OCP\DB\QueryBuilder\Sharded; + +/** + * Implementation of logic of mapping shard keys to shards. + * @since 30.0.0 + */ +interface IShardMapper { + /** + * Get the shard number for a given shard key and total shard count + * + * @param int $key + * @param int $count + * @return int + * @since 30.0.0 + */ + public function getShardForKey(int $key, int $count): int; +} |