From 065141f6f4212dbbca4633b0138f6e5ac3ec4f7a Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Fri, 5 Feb 2016 15:32:34 +0100 Subject: [PATCH] Move casting to IExpressionBuilder --- .../lib/backgroundjob/deleteorphaneditems.php | 5 ++- .../expressionbuilder.php | 19 +++++++- .../ociexpressionbuilder.php | 25 +++++++++-- .../pgsqlexpressionbuilder.php | 45 +++++++++++++++++++ lib/private/db/querybuilder/querybuilder.php | 6 +++ .../db/querybuilder/iexpressionbuilder.php | 10 +++++ .../db/querybuilder/expressionbuildertest.php | 2 +- tests/lib/share/share.php | 8 ++-- 8 files changed, 108 insertions(+), 12 deletions(-) rename lib/private/db/querybuilder/{ => expressionbuilder}/expressionbuilder.php (95%) rename lib/private/db/querybuilder/{ => expressionbuilder}/ociexpressionbuilder.php (84%) create mode 100644 lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php diff --git a/apps/files/lib/backgroundjob/deleteorphaneditems.php b/apps/files/lib/backgroundjob/deleteorphaneditems.php index dc9f781e40..cefa1d655d 100644 --- a/apps/files/lib/backgroundjob/deleteorphaneditems.php +++ b/apps/files/lib/backgroundjob/deleteorphaneditems.php @@ -22,6 +22,7 @@ namespace OCA\Files\BackgroundJob; use OC\BackgroundJob\TimedJob; +use OCP\DB\QueryBuilder\IQueryBuilder; /** * Delete all share entries that have no matching entries in the file cache table. @@ -111,7 +112,7 @@ class DeleteOrphanedItems extends TimedJob { */ protected function cleanComments() { $qb = $this->connection->getQueryBuilder(); - $deletedEntries = $this->cleanUp('comments', $qb->createFunction('CAST(`object_id` as INT)'), 'object_type'); + $deletedEntries = $this->cleanUp('comments', $qb->expr()->castColumn('object_id', IQueryBuilder::PARAM_INT), 'object_type'); $this->logger->debug("$deletedEntries orphaned comments deleted", ['app' => 'DeleteOrphanedItems']); return $deletedEntries; } @@ -123,7 +124,7 @@ class DeleteOrphanedItems extends TimedJob { */ protected function cleanCommentMarkers() { $qb = $this->connection->getQueryBuilder(); - $deletedEntries = $this->cleanUp('comments_read_markers', $qb->createFunction('CAST(`object_id` as INT)'), 'object_type'); + $deletedEntries = $this->cleanUp('comments_read_markers', $qb->expr()->castColumn('object_id', IQueryBuilder::PARAM_INT), 'object_type'); $this->logger->debug("$deletedEntries orphaned comment read marks deleted", ['app' => 'DeleteOrphanedItems']); return $deletedEntries; } diff --git a/lib/private/db/querybuilder/expressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder/expressionbuilder.php similarity index 95% rename from lib/private/db/querybuilder/expressionbuilder.php rename to lib/private/db/querybuilder/expressionbuilder/expressionbuilder.php index b688ebfabb..7ab4c03d97 100644 --- a/lib/private/db/querybuilder/expressionbuilder.php +++ b/lib/private/db/querybuilder/expressionbuilder/expressionbuilder.php @@ -19,9 +19,13 @@ * */ -namespace OC\DB\QueryBuilder; +namespace OC\DB\QueryBuilder\ExpressionBuilder; use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder; +use OC\DB\QueryBuilder\CompositeExpression; +use OC\DB\QueryBuilder\Literal; +use OC\DB\QueryBuilder\QueryFunction; +use OC\DB\QueryBuilder\QuoteHelper; use OCP\DB\QueryBuilder\IExpressionBuilder; use OCP\IDBConnection; @@ -331,4 +335,17 @@ class ExpressionBuilder implements IExpressionBuilder { public function literal($input, $type = null) { return new Literal($this->expressionBuilder->literal($input, $type)); } + + /** + * Returns a IQueryFunction that casts the column to the given type + * + * @param string $column + * @param mixed $type One of IQueryBuilder::PARAM_* + * @return string + */ + public function castColumn($column, $type) { + return new QueryFunction( + $this->helper->quoteColumnName($column) + ); + } } diff --git a/lib/private/db/querybuilder/ociexpressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder/ociexpressionbuilder.php similarity index 84% rename from lib/private/db/querybuilder/ociexpressionbuilder.php rename to lib/private/db/querybuilder/expressionbuilder/ociexpressionbuilder.php index 4c127bd752..6a6d0f455f 100644 --- a/lib/private/db/querybuilder/ociexpressionbuilder.php +++ b/lib/private/db/querybuilder/expressionbuilder/ociexpressionbuilder.php @@ -19,24 +19,25 @@ * */ -namespace OC\DB\QueryBuilder; +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 OCIExpressionBuilder extends ExpressionBuilder { /** * @param mixed $column * @param mixed|null $type - * @return array|QueryFunction|string + * @return array|IQueryFunction|string */ protected function prepareColumn($column, $type) { if ($type === IQueryBuilder::PARAM_STR && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) { - $column = $this->helper->quoteColumnName($column); - $column = new QueryFunction('to_char(' . $column . ')'); + $column = $this->castColumn($column, $type); } else { $column = $this->helper->quoteColumnNames($column); } @@ -132,4 +133,20 @@ class OCIExpressionBuilder extends ExpressionBuilder { return $this->expressionBuilder->notIn($x, $y); } + + /** + * 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) { + if ($type === IQueryBuilder::PARAM_STR) { + $column = $this->helper->quoteColumnName($column); + return new QueryFunction('to_char(' . $column . ')'); + } + + return parent::castColumn($column, $type); + } } diff --git a/lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php b/lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php new file mode 100644 index 0000000000..8a0b68db99 --- /dev/null +++ b/lib/private/db/querybuilder/expressionbuilder/pgsqlexpressionbuilder.php @@ -0,0 +1,45 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @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 + * + */ + +namespace OC\DB\QueryBuilder\ExpressionBuilder; + + +use OC\DB\QueryBuilder\QueryFunction; +use OCP\DB\QueryBuilder\IQueryBuilder; + +class PgSqlExpressionBuilder extends ExpressionBuilder { + + /** + * Returns a IQueryFunction that casts the column to the given type + * + * @param string $column + * @param mixed $type One of IQueryBuilder::PARAM_* + * @return string + */ + public function castColumn($column, $type) { + if ($type === IQueryBuilder::PARAM_INT) { + $column = $this->helper->quoteColumnName($column); + return new QueryFunction('CAST(' . $column . ' AS INT)'); + } + + return parent::castColumn($column, $type); + } +} diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php index 42b290b90e..ff31ffbc04 100644 --- a/lib/private/db/querybuilder/querybuilder.php +++ b/lib/private/db/querybuilder/querybuilder.php @@ -21,7 +21,11 @@ namespace OC\DB\QueryBuilder; +use Doctrine\DBAL\Platforms\PostgreSqlPlatform; use OC\DB\OracleConnection; +use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder; +use OC\DB\QueryBuilder\ExpressionBuilder\OCIExpressionBuilder; +use OC\DB\QueryBuilder\ExpressionBuilder\PgSqlExpressionBuilder; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryFunction; use OCP\DB\QueryBuilder\IParameter; @@ -85,6 +89,8 @@ class QueryBuilder implements IQueryBuilder { public function expr() { if ($this->connection instanceof OracleConnection) { return new OCIExpressionBuilder($this->connection); + } else if ($this->connection->getDatabasePlatform() instanceof PostgreSqlPlatform) { + return new PgSqlExpressionBuilder($this->connection); } else { return new ExpressionBuilder($this->connection); } diff --git a/lib/public/db/querybuilder/iexpressionbuilder.php b/lib/public/db/querybuilder/iexpressionbuilder.php index a53ae3846c..4b53a0e0b8 100644 --- a/lib/public/db/querybuilder/iexpressionbuilder.php +++ b/lib/public/db/querybuilder/iexpressionbuilder.php @@ -299,4 +299,14 @@ interface IExpressionBuilder { * @since 8.2.0 */ public function literal($input, $type = null); + + /** + * Returns a IQueryFunction that casts the column to the given type + * + * @param string $column + * @param mixed $type One of IQueryBuilder::PARAM_* + * @return string + * @since 9.0.0 + */ + public function castColumn($column, $type); } diff --git a/tests/lib/db/querybuilder/expressionbuildertest.php b/tests/lib/db/querybuilder/expressionbuildertest.php index 8310c4adf6..f38faab916 100644 --- a/tests/lib/db/querybuilder/expressionbuildertest.php +++ b/tests/lib/db/querybuilder/expressionbuildertest.php @@ -22,7 +22,7 @@ namespace Test\DB\QueryBuilder; use Doctrine\DBAL\Query\Expression\ExpressionBuilder as DoctrineExpressionBuilder; -use OC\DB\QueryBuilder\ExpressionBuilder; +use OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder; use OCP\DB\QueryBuilder\IQueryBuilder; use Test\TestCase; diff --git a/tests/lib/share/share.php b/tests/lib/share/share.php index 5162a03f36..4519c33f9d 100644 --- a/tests/lib/share/share.php +++ b/tests/lib/share/share.php @@ -1423,7 +1423,7 @@ class Test_Share extends \Test\TestCase { $userSession->method('getUser')->willReturn($user); - $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder') + $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder') ->disableOriginalConstructor() ->getMock(); $qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder') @@ -1478,7 +1478,7 @@ class Test_Share extends \Test\TestCase { $userSession->method('getUser')->willReturn($user); - $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder') + $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder') ->disableOriginalConstructor() ->getMock(); $qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder') @@ -1531,7 +1531,7 @@ class Test_Share extends \Test\TestCase { $userSession->method('getUser')->willReturn($user); - $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder') + $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder') ->disableOriginalConstructor() ->getMock(); $qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder') @@ -1584,7 +1584,7 @@ class Test_Share extends \Test\TestCase { $userSession->method('getUser')->willReturn($user); - $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder') + $ex = $this->getMockBuilder('\OC\DB\QueryBuilder\ExpressionBuilder\ExpressionBuilder') ->disableOriginalConstructor() ->getMock(); $qb = $this->getMockBuilder('\OC\DB\QueryBuilder\QueryBuilder')