Merge pull request #21030 from owncloud/querybuilder-new-features

Querybuilder new features
This commit is contained in:
Thomas Müller 2015-12-08 13:51:45 +01:00
commit 45fe8271ab
4 changed files with 177 additions and 7 deletions

View File

@ -324,6 +324,28 @@ class QueryBuilder implements IQueryBuilder {
return $this; return $this;
} }
/**
* 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. * Adds an item that is to be returned in the query result.
* *
@ -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 * @param string $table
* @return string * @return string
*/ */
private function getTableName($table) { public function getTableName($table) {
if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) { if ($this->automaticTablePrefix === false || strpos($table, '*PREFIX*') === 0) {
return $this->helper->quoteColumnName($table); return $this->helper->quoteColumnName($table);
} }
return $this->helper->quoteColumnName('*PREFIX*' . $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);
}
} }

View File

@ -61,7 +61,7 @@ class QuoteHelper {
} }
if (substr_count($string, '.')) { if (substr_count($string, '.')) {
list($alias, $columnName) = explode('.', $string); list($alias, $columnName) = explode('.', $string, 2);
if ($columnName === '*') { if ($columnName === '*') {
return $string; return $string;

View File

@ -256,6 +256,22 @@ interface IQueryBuilder {
*/ */
public function selectAlias($select, $alias); 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. * Adds an item that is to be returned in the query result.
* *
@ -796,4 +812,31 @@ interface IQueryBuilder {
* @since 8.2.0 * @since 8.2.0
*/ */
public function createFunction($call); 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 = '');
} }

View File

@ -48,12 +48,12 @@ class QueryBuilderTest extends \Test\TestCase {
$this->queryBuilder = new QueryBuilder($this->connection); $this->queryBuilder = new QueryBuilder($this->connection);
} }
protected function createTestingRows() { protected function createTestingRows($appId = 'testFirstResult') {
$qB = $this->connection->getQueryBuilder(); $qB = $this->connection->getQueryBuilder();
for ($i = 1; $i < 10; $i++) { for ($i = 1; $i < 10; $i++) {
$qB->insert('*PREFIX*appconfig') $qB->insert('*PREFIX*appconfig')
->values([ ->values([
'appid' => $qB->expr()->literal('testFirstResult'), 'appid' => $qB->expr()->literal($appId),
'configkey' => $qB->expr()->literal('testing' . $i), 'configkey' => $qB->expr()->literal('testing' . $i),
'configvalue' => $qB->expr()->literal(100 - $i), 'configvalue' => $qB->expr()->literal(100 - $i),
]) ])
@ -80,11 +80,11 @@ class QueryBuilderTest extends \Test\TestCase {
return $rows; return $rows;
} }
protected function deleteTestingRows() { protected function deleteTestingRows($appId = 'testFirstResult') {
$qB = $this->connection->getQueryBuilder(); $qB = $this->connection->getQueryBuilder();
$qB->delete('*PREFIX*appconfig') $qB->delete('*PREFIX*appconfig')
->where($qB->expr()->eq('appid', $qB->expr()->literal('testFirstResult'))) ->where($qB->expr()->eq('appid', $qB->expr()->literal($appId)))
->execute(); ->execute();
} }
@ -272,6 +272,34 @@ class QueryBuilderTest extends \Test\TestCase {
$this->deleteTestingRows(); $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() { public function dataAddSelect() {
$queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection()); $queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection());
return [ 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() { public function dataGetTableName() {
return [ return [
['*PREFIX*table', null, '`*PREFIX*table`'], ['*PREFIX*table', null, '`*PREFIX*table`'],
@ -1112,7 +1165,27 @@ class QueryBuilderTest extends \Test\TestCase {
$this->assertSame( $this->assertSame(
$expected, $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)
); );
} }
} }