diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php index 1d97faf77c..02d8ee4344 100644 --- a/lib/private/db/querybuilder/querybuilder.php +++ b/lib/private/db/querybuilder/querybuilder.php @@ -300,6 +300,30 @@ class QueryBuilder implements IQueryBuilder { return $this; } + /** + * Specifies an item that is to be returned with a different name in the query result. + * + * + * $qb = $conn->getQueryBuilder() + * ->selectAlias('u.id', 'user_id') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); + * + * + * @param mixed $select The selection expressions. + * @param string $alias The column alias used in the constructed query. + * + * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance. + */ + public function selectAlias($select, $alias) { + + $this->queryBuilder->addSelect( + $this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias) + ); + + return $this; + } + /** * Adds an item that is to be returned in the query result. * diff --git a/lib/public/db/querybuilder/iquerybuilder.php b/lib/public/db/querybuilder/iquerybuilder.php index 3fc07af1a4..beb922b7fe 100644 --- a/lib/public/db/querybuilder/iquerybuilder.php +++ b/lib/public/db/querybuilder/iquerybuilder.php @@ -238,6 +238,24 @@ interface IQueryBuilder { */ public function select($select = null); + /** + * Specifies an item that is to be returned with a different name in the query result. + * + * + * $qb = $conn->getQueryBuilder() + * ->selectAlias('u.id', 'user_id') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); + * + * + * @param mixed $select The selection expressions. + * @param string $alias The column alias used in the constructed query. + * + * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance. + * @since 8.2.1 + */ + public function selectAlias($select, $alias); + /** * Adds an item that is to be returned in the query result. * diff --git a/tests/lib/db/querybuilder/querybuildertest.php b/tests/lib/db/querybuilder/querybuildertest.php index 75e62ba944..bbc45fc64f 100644 --- a/tests/lib/db/querybuilder/querybuildertest.php +++ b/tests/lib/db/querybuilder/querybuildertest.php @@ -159,24 +159,25 @@ class QueryBuilderTest extends \Test\TestCase { } public function dataSelect() { + $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection()); return [ // select('column1') - [['column1'], ['`column1`'], '`column1`'], + [['configvalue'], ['configvalue' => '99']], // select('column1', 'column2') - [['column1', 'column2'], ['`column1`', '`column2`'], '`column1`, `column2`'], + [['configvalue', 'configkey'], ['configvalue' => '99', 'configkey' => 'testing1']], // select(['column1', 'column2']) - [[['column1', 'column2']], ['`column1`', '`column2`'], '`column1`, `column2`'], + [[['configvalue', 'configkey']], ['configvalue' => '99', 'configkey' => 'testing1']], // select(new Literal('column1')) - [[new Literal('column1')], ['column1'], 'column1'], + [[$queryBuilder->expr()->literal('column1')], [], 'column1'], // select('column1', 'column2') - [[new Literal('column1'), 'column2'], ['column1', '`column2`'], 'column1, `column2`'], + [[$queryBuilder->expr()->literal('column1'), 'configkey'], ['configkey' => 'testing1'], 'column1'], // select(['column1', 'column2']) - [[[new Literal('column1'), 'column2']], ['column1', '`column2`'], 'column1, `column2`'], + [[[$queryBuilder->expr()->literal('column1'), 'configkey']], ['configkey' => 'testing1'], 'column1'], ]; } @@ -184,45 +185,106 @@ class QueryBuilderTest extends \Test\TestCase { * @dataProvider dataSelect * * @param array $selectArguments - * @param array $expectedQueryPart - * @param string $expectedSelect + * @param array $expected + * @param string $expectedLiteral */ - public function testSelect($selectArguments, $expectedQueryPart, $expectedSelect) { + public function testSelect($selectArguments, $expected, $expectedLiteral = '') { + $this->deleteTestingRows(); + $this->createTestingRows(); + call_user_func_array( [$this->queryBuilder, 'select'], $selectArguments ); - $this->assertSame( - $expectedQueryPart, - $this->queryBuilder->getQueryPart('select') + $this->queryBuilder->from('*PREFIX*appconfig') + ->where($this->queryBuilder->expr()->eq( + 'appid', + $this->queryBuilder->expr()->literal('testFirstResult') + )) + ->orderBy('configkey', 'ASC') + ->setMaxResults(1); + + $query = $this->queryBuilder->execute(); + $row = $query->fetch(); + $query->closeCursor(); + + foreach ($expected as $key => $value) { + $this->assertArrayHasKey($key, $row); + $this->assertEquals($value, $row[$key]); + unset($row[$key]); + } + + if ($expectedLiteral) { + $this->assertEquals([$expectedLiteral], array_values($row)); + } else { + $this->assertEmpty($row); + } + + $this->deleteTestingRows(); + } + + public function dataSelectAlias() { + $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection()); + return [ + ['configvalue', 'cv', ['cv' => '99']], + [$queryBuilder->expr()->literal('column1'), 'thing', ['thing' => 'column1']], + ]; + } + + /** + * @dataProvider dataSelectAlias + * + * @param mixed $select + * @param array $alias + * @param array $expected + */ + public function testSelectAlias($select, $alias, $expected) { + $this->deleteTestingRows(); + $this->createTestingRows(); + + $this->queryBuilder->selectAlias($select, $alias); + + $this->queryBuilder->from('*PREFIX*appconfig') + ->where($this->queryBuilder->expr()->eq( + 'appid', + $this->queryBuilder->expr()->literal('testFirstResult') + )) + ->orderBy('configkey', 'ASC') + ->setMaxResults(1); + + $query = $this->queryBuilder->execute(); + $row = $query->fetch(); + $query->closeCursor(); + + $this->assertEquals( + $expected, + $row ); - $this->assertSame( - 'SELECT ' . $expectedSelect . ' FROM ', - $this->queryBuilder->getSQL() - ); + $this->deleteTestingRows(); } public function dataAddSelect() { + $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection()); return [ // addSelect('column1') - [['column1'], ['`column`', '`column1`'], '`column`, `column1`'], + [['configvalue'], ['appid' => 'testFirstResult', 'configvalue' => '99']], // addSelect('column1', 'column2') - [['column1', 'column2'], ['`column`', '`column1`', '`column2`'], '`column`, `column1`, `column2`'], + [['configvalue', 'configkey'], ['appid' => 'testFirstResult', 'configvalue' => '99', 'configkey' => 'testing1']], // addSelect(['column1', 'column2']) - [[['column1', 'column2']], ['`column`', '`column1`', '`column2`'], '`column`, `column1`, `column2`'], + [[['configvalue', 'configkey']], ['appid' => 'testFirstResult', 'configvalue' => '99', 'configkey' => 'testing1']], // select(new Literal('column1')) - [[new Literal('column1')], ['`column`', 'column1'], '`column`, column1'], + [[$queryBuilder->expr()->literal('column1')], ['appid' => 'testFirstResult'], 'column1'], // select('column1', 'column2') - [[new Literal('column1'), 'column2'], ['`column`', 'column1', '`column2`'], '`column`, column1, `column2`'], + [[$queryBuilder->expr()->literal('column1'), 'configkey'], ['appid' => 'testFirstResult', 'configkey' => 'testing1'], 'column1'], // select(['column1', 'column2']) - [[[new Literal('column1'), 'column2']], ['`column`', 'column1', '`column2`'], '`column`, column1, `column2`'], + [[[$queryBuilder->expr()->literal('column1'), 'configkey']], ['appid' => 'testFirstResult', 'configkey' => 'testing1'], 'column1'], ]; } @@ -230,25 +292,45 @@ class QueryBuilderTest extends \Test\TestCase { * @dataProvider dataAddSelect * * @param array $selectArguments - * @param array $expectedQueryPart - * @param string $expectedSelect + * @param array $expected + * @param string $expectedLiteral */ - public function testAddSelect($selectArguments, $expectedQueryPart, $expectedSelect) { - $this->queryBuilder->select('column'); + public function testAddSelect($selectArguments, $expected, $expectedLiteral = '') { + $this->deleteTestingRows(); + $this->createTestingRows(); + + $this->queryBuilder->select('appid'); + call_user_func_array( [$this->queryBuilder, 'addSelect'], $selectArguments ); - $this->assertSame( - $expectedQueryPart, - $this->queryBuilder->getQueryPart('select') - ); + $this->queryBuilder->from('*PREFIX*appconfig') + ->where($this->queryBuilder->expr()->eq( + 'appid', + $this->queryBuilder->expr()->literal('testFirstResult') + )) + ->orderBy('configkey', 'ASC') + ->setMaxResults(1); - $this->assertSame( - 'SELECT ' . $expectedSelect . ' FROM ', - $this->queryBuilder->getSQL() - ); + $query = $this->queryBuilder->execute(); + $row = $query->fetch(); + $query->closeCursor(); + + foreach ($expected as $key => $value) { + $this->assertArrayHasKey($key, $row); + $this->assertEquals($value, $row[$key]); + unset($row[$key]); + } + + if ($expectedLiteral) { + $this->assertEquals([$expectedLiteral], array_values($row)); + } else { + $this->assertEmpty($row); + } + + $this->deleteTestingRows(); } public function dataDelete() {