summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Müller <thomas.mueller@tmit.eu>2015-12-08 13:51:45 +0100
committerThomas Müller <thomas.mueller@tmit.eu>2015-12-08 13:51:45 +0100
commit45fe8271ab1efb90ad0394bec0285f83b1ccd55c (patch)
treebd73ff50105f9ac125b7a8c02d1a367725d0005c
parent85409b6701ffd46806f4a53b69dce0fa6a09d2a9 (diff)
parent9f9884930609addad3e37325731fb5406dd3aa44 (diff)
downloadnextcloud-server-45fe8271ab1efb90ad0394bec0285f83b1ccd55c.tar.gz
nextcloud-server-45fe8271ab1efb90ad0394bec0285f83b1ccd55c.zip
Merge pull request #21030 from owncloud/querybuilder-new-features
Querybuilder new features
-rw-r--r--lib/private/db/querybuilder/querybuilder.php56
-rw-r--r--lib/private/db/querybuilder/quotehelper.php2
-rw-r--r--lib/public/db/querybuilder/iquerybuilder.php43
-rw-r--r--tests/lib/db/querybuilder/querybuildertest.php83
4 files changed, 177 insertions, 7 deletions
diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php
index 02d8ee4344d..741da4efc27 100644
--- a/lib/private/db/querybuilder/querybuilder.php
+++ b/lib/private/db/querybuilder/querybuilder.php
@@ -325,6 +325,28 @@ class QueryBuilder implements IQueryBuilder {
}
/**
+ * Specifies an item that is to be returned uniquely in the query result.
+ *
+ * <code>
+ * $qb = $conn->getQueryBuilder()
+ * ->selectDistinct('type')
+ * ->from('users');
+ * </code>
+ *
+ * @param mixed $select The selection expressions.
+ *
+ * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
+ */
+ public function selectDistinct($select) {
+
+ $this->queryBuilder->addSelect(
+ 'DISTINCT ' . $this->helper->quoteColumnName($select)
+ );
+
+ return $this;
+ }
+
+ /**
* Adds an item that is to be returned in the query result.
*
* <code>
@@ -1024,14 +1046,46 @@ class QueryBuilder implements IQueryBuilder {
}
/**
+ * Used to get the id of the last inserted element
+ * @return int
+ * @throws \BadMethodCallException When being called before an insert query has been run.
+ */
+ public function getLastInsertId() {
+ $from = $this->getQueryPart('from');
+
+ if ($this->getType() === \Doctrine\DBAL\Query\QueryBuilder::INSERT && !empty($from)) {
+ return (int) $this->connection->lastInsertId($from['table']);
+ }
+
+ throw new \BadMethodCallException('Invalid call to getLastInsertId without using insert() before.');
+ }
+
+ /**
+ * Returns the table name quoted and with database prefix as needed by the implementation
+ *
* @param string $table
* @return string
*/
- private function getTableName($table) {
+ public function getTableName($table) {
if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) {
return $this->helper->quoteColumnName($table);
}
return $this->helper->quoteColumnName('*PREFIX*' . $table);
}
+
+ /**
+ * Returns the column name quoted and with table alias prefix as needed by the implementation
+ *
+ * @param string $column
+ * @param string $tableAlias
+ * @return string
+ */
+ public function getColumnName($column, $tableAlias = '') {
+ if ($tableAlias !== '') {
+ $tableAlias .= '.';
+ }
+
+ return $this->helper->quoteColumnName($tableAlias . $column);
+ }
}
diff --git a/lib/private/db/querybuilder/quotehelper.php b/lib/private/db/querybuilder/quotehelper.php
index 4b62fee6a6c..5ceb76bbf93 100644
--- a/lib/private/db/querybuilder/quotehelper.php
+++ b/lib/private/db/querybuilder/quotehelper.php
@@ -61,7 +61,7 @@ class QuoteHelper {
}
if (substr_count($string, '.')) {
- list($alias, $columnName) = explode('.', $string);
+ list($alias, $columnName) = explode('.', $string, 2);
if ($columnName === '*') {
return $string;
diff --git a/lib/public/db/querybuilder/iquerybuilder.php b/lib/public/db/querybuilder/iquerybuilder.php
index beb922b7feb..dd3ee7da5f5 100644
--- a/lib/public/db/querybuilder/iquerybuilder.php
+++ b/lib/public/db/querybuilder/iquerybuilder.php
@@ -257,6 +257,22 @@ interface IQueryBuilder {
public function selectAlias($select, $alias);
/**
+ * Specifies an item that is to be returned uniquely in the query result.
+ *
+ * <code>
+ * $qb = $conn->getQueryBuilder()
+ * ->selectDistinct('type')
+ * ->from('users');
+ * </code>
+ *
+ * @param mixed $select The selection expressions.
+ *
+ * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
+ * @since 9.0.0
+ */
+ public function selectDistinct($select);
+
+ /**
* Adds an item that is to be returned in the query result.
*
* <code>
@@ -796,4 +812,31 @@ interface IQueryBuilder {
* @since 8.2.0
*/
public function createFunction($call);
+
+ /**
+ * Used to get the id of the last inserted element
+ * @return int
+ * @throws \BadMethodCallException When being called before an insert query has been run.
+ * @since 9.0.0
+ */
+ public function getLastInsertId();
+
+ /**
+ * Returns the table name quoted and with database prefix as needed by the implementation
+ *
+ * @param string $table
+ * @return string
+ * @since 9.0.0
+ */
+ public function getTableName($table);
+
+ /**
+ * Returns the column name quoted and with table alias prefix as needed by the implementation
+ *
+ * @param string $column
+ * @param string $tableAlias
+ * @return string
+ * @since 9.0.0
+ */
+ public function getColumnName($column, $tableAlias = '');
}
diff --git a/tests/lib/db/querybuilder/querybuildertest.php b/tests/lib/db/querybuilder/querybuildertest.php
index ca3901ad049..c8e029d9e40 100644
--- a/tests/lib/db/querybuilder/querybuildertest.php
+++ b/tests/lib/db/querybuilder/querybuildertest.php
@@ -48,12 +48,12 @@ class QueryBuilderTest extends \Test\TestCase {
$this->queryBuilder = new QueryBuilder($this->connection);
}
- protected function createTestingRows() {
+ protected function createTestingRows($appId = 'testFirstResult') {
$qB = $this->connection->getQueryBuilder();
for ($i = 1; $i < 10; $i++) {
$qB->insert('*PREFIX*appconfig')
->values([
- 'appid' => $qB->expr()->literal('testFirstResult'),
+ 'appid' => $qB->expr()->literal($appId),
'configkey' => $qB->expr()->literal('testing' . $i),
'configvalue' => $qB->expr()->literal(100 - $i),
])
@@ -80,11 +80,11 @@ class QueryBuilderTest extends \Test\TestCase {
return $rows;
}
- protected function deleteTestingRows() {
+ protected function deleteTestingRows($appId = 'testFirstResult') {
$qB = $this->connection->getQueryBuilder();
$qB->delete('*PREFIX*appconfig')
- ->where($qB->expr()->eq('appid', $qB->expr()->literal('testFirstResult')))
+ ->where($qB->expr()->eq('appid', $qB->expr()->literal($appId)))
->execute();
}
@@ -272,6 +272,34 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows();
}
+ public function testSelectDistinct() {
+ $this->deleteTestingRows('testFirstResult1');
+ $this->deleteTestingRows('testFirstResult2');
+ $this->createTestingRows('testFirstResult1');
+ $this->createTestingRows('testFirstResult2');
+
+ $this->queryBuilder->selectDistinct('appid');
+
+ $this->queryBuilder->from('*PREFIX*appconfig')
+ ->where($this->queryBuilder->expr()->in(
+ 'appid',
+ [$this->queryBuilder->expr()->literal('testFirstResult1'), $this->queryBuilder->expr()->literal('testFirstResult2')]
+ ))
+ ->orderBy('appid', 'DESC');
+
+ $query = $this->queryBuilder->execute();
+ $rows = $query->fetchAll();
+ $query->closeCursor();
+
+ $this->assertEquals(
+ [['appid' => 'testFirstResult2'], ['appid' => 'testFirstResult1']],
+ $rows
+ );
+
+ $this->deleteTestingRows('testFirstResult1');
+ $this->deleteTestingRows('testFirstResult2');
+ }
+
public function dataAddSelect() {
$queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection());
return [
@@ -1086,6 +1114,31 @@ class QueryBuilderTest extends \Test\TestCase {
);
}
+ public function testGetLastInsertId() {
+ $qB = $this->connection->getQueryBuilder();
+
+ try {
+ $qB->getLastInsertId();
+ $this->fail('getLastInsertId() should throw an exception, when being called before insert()');
+ } catch (\BadMethodCallException $e) {
+ $this->assertTrue(true);
+ }
+
+ $qB->insert('appconfig')
+ ->values([
+ 'appid' => $qB->expr()->literal('testFirstResult'),
+ 'configkey' => $qB->expr()->literal('testing' . 50),
+ 'configvalue' => $qB->expr()->literal(100 - 50),
+ ])
+ ->execute();
+
+ $actual = $qB->getLastInsertId();
+
+ $this->assertNotNull($actual);
+ $this->assertInternalType('int', $actual);
+ $this->assertEquals($this->connection->lastInsertId('*PREFIX*appconfig'), $actual);
+ }
+
public function dataGetTableName() {
return [
['*PREFIX*table', null, '`*PREFIX*table`'],
@@ -1112,7 +1165,27 @@ class QueryBuilderTest extends \Test\TestCase {
$this->assertSame(
$expected,
- $this->invokePrivate($this->queryBuilder, 'getTableName', [$tableName])
+ $this->queryBuilder->getTableName($tableName)
+ );
+ }
+
+ public function dataGetColumnName() {
+ return [
+ ['column', '', '`column`'],
+ ['column', 'a', 'a.`column`'],
+ ];
+ }
+
+ /**
+ * @dataProvider dataGetColumnName
+ * @param string $column
+ * @param string $prefix
+ * @param string $expected
+ */
+ public function testGetColumnName($column, $prefix, $expected) {
+ $this->assertSame(
+ $expected,
+ $this->queryBuilder->getColumnName($column, $prefix)
);
}
}