From ed825b2727ea74c0c09e059bc25362cb954e393e Mon Sep 17 00:00:00 2001 From: Morton Jonuschat <m.jonuschat@mojocode.de> Date: Wed, 20 Apr 2016 19:11:46 +0200 Subject: [PATCH] [TASK] Doctrine: Add support for column aliases in select() Add support for selecting a column under a different identifier (alias) when building a SELECT query. Releases: master Resolves: #75823 Change-Id: I3464c9d848c4892ea57b92cc1257654ff9e14110 Reviewed-on: https://review.typo3.org/47820 Reviewed-by: Michael Oehlhof <typo3@oehlhof.de> Tested-by: Michael Oehlhof <typo3@oehlhof.de> Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl> Tested-by: Wouter Wolters <typo3@wouterwolters.nl> --- .../Classes/Database/Query/QueryBuilder.php | 30 +++++--- .../Unit/Database/Query/QueryBuilderTest.php | 69 +++++++++++++++++++ 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/typo3/sysext/core/Classes/Database/Query/QueryBuilder.php b/typo3/sysext/core/Classes/Database/Query/QueryBuilder.php index c6f6218b6d3a..576ec2c3b737 100644 --- a/typo3/sysext/core/Classes/Database/Query/QueryBuilder.php +++ b/typo3/sysext/core/Classes/Database/Query/QueryBuilder.php @@ -923,18 +923,32 @@ class QueryBuilder * @param array $input * * @return array + * @throws \InvalidArgumentException */ public function quoteIdentifiersForSelect(array $input): array { - // The SQL * operator must not be quoted. As it can only occur either by itself - // or preceded by a tablename (tablename.*) check if the last character of a select - // expression is the * and quote only prepended table name. In all other cases the - // full expression is being quoted. foreach ($input as &$select) { - if (substr($select, -2) === '.*') { - $select = $this->quoteIdentifier(substr($select, 0, -2)) . '.*'; - } elseif ($select !== '*') { - $select = $this->quoteIdentifier($select); + list($fieldName, $alias, $suffix) = GeneralUtility::trimExplode(' AS ', $select, 3); + if (!empty($suffix)) { + throw new \InvalidArgumentException( + 'QueryBuilder::quoteIdentifiersForSelect() could not parse the input "' . $input . '"', + 1461170686 + ); + } + + // The SQL * operator must not be quoted. As it can only occur either by itself + // or preceded by a tablename (tablename.*) check if the last character of a select + // expression is the * and quote only prepended table name. In all other cases the + // full expression is being quoted. + if (substr($fieldName, -2) === '.*') { + $select = $this->quoteIdentifier(substr($fieldName, 0, -2)) . '.*'; + } elseif ($fieldName !== '*') { + $select = $this->quoteIdentifier($fieldName); + } + + // Quote the alias for the current fieldName, if given + if (!empty($alias)) { + $select .= ' AS ' . $this->quoteIdentifier($alias); } } return $input; diff --git a/typo3/sysext/core/Tests/Unit/Database/Query/QueryBuilderTest.php b/typo3/sysext/core/Tests/Unit/Database/Query/QueryBuilderTest.php index 35a547d0de08..03c8e4aab8dd 100644 --- a/typo3/sysext/core/Tests/Unit/Database/Query/QueryBuilderTest.php +++ b/typo3/sysext/core/Tests/Unit/Database/Query/QueryBuilderTest.php @@ -279,6 +279,75 @@ class QueryBuilderTest extends UnitTestCase $this->subject->select('aField', 'anotherField'); } + public function quoteIdentifiersForSelectDataProvider() + { + return [ + 'fieldName' => [ + 'fieldName', + '"fieldName"', + ], + 'tableName.fieldName' => [ + 'tableName.fieldName', + '"tableName"."fieldName"', + ], + 'tableName.*' => [ + 'tableName.*', + '"tableName".*', + ], + '*' => [ + '*', + '*', + ], + 'fieldName AS anotherFieldName' => [ + 'fieldName AS anotherFieldName', + '"fieldName" AS "anotherFieldName"', + ], + 'tableName.fieldName AS anotherFieldName' => [ + 'tableName.fieldName AS anotherFieldName', + '"tableName"."fieldName" AS "anotherFieldName"', + ], + 'tableName.fieldName AS anotherTable.anotherFieldName' => [ + 'tableName.fieldName AS anotherTable.anotherFieldName', + '"tableName"."fieldName" AS "anotherTable"."anotherFieldName"', + ], + ]; + } + + /** + * @test + * @dataProvider quoteIdentifiersForSelectDataProvider + * @param string $identifier + * @param string $expectedResult + */ + public function quoteIdentifiersForSelect($identifier, $expectedResult) + { + $this->connection->quoteIdentifier(Argument::cetera())->will( + function ($args) { + $platform = new MockPlatform(); + + return $platform->quoteIdentifier($args[0]); + } + ); + + $this->assertSame([$expectedResult], $this->subject->quoteIdentifiersForSelect([$identifier])); + } + + /** + * @test + * @expectedException \InvalidArgumentException + */ + public function quoteIdentifiersForSelectWithInvalidAlias() + { + $this->connection->quoteIdentifier(Argument::cetera())->will( + function ($args) { + $platform = new MockPlatform(); + + return $platform->quoteIdentifier($args[0]); + } + ); + $this->subject->quoteIdentifiersForSelect(['aField AS anotherField,someField AS someThing']); + } + /** * @test */ -- GitLab