Browse Source

Merge pull request #30378 from nextcloud/feature/accept-multiple-args-on-concat

Accept multipe args on concat
tags/v24.0.0beta1
Joas Schilling 2 years ago
parent
commit
55986382e8
No account linked to committer's email address

+ 7
- 2
lib/private/DB/QueryBuilder/FunctionBuilder/FunctionBuilder.php View File

return new QueryFunction('MD5(' . $this->helper->quoteColumnName($input) . ')'); return new QueryFunction('MD5(' . $this->helper->quoteColumnName($input) . ')');
} }


public function concat($x, $y): IQueryFunction {
return new QueryFunction('CONCAT(' . $this->helper->quoteColumnName($x) . ', ' . $this->helper->quoteColumnName($y) . ')');
public function concat($x, ...$expr): IQueryFunction {
$args = func_get_args();
$list = [];
foreach ($args as $item) {
$list[] = $this->helper->quoteColumnName($item);
}
return new QueryFunction(sprintf('CONCAT(%s)', implode(', ', $list)));
} }


public function groupConcat($expr, ?string $separator = ','): IQueryFunction { public function groupConcat($expr, ?string $separator = ','): IQueryFunction {

+ 9
- 0
lib/private/DB/QueryBuilder/FunctionBuilder/OCIFunctionBuilder.php View File

return parent::least($x, $y); return parent::least($x, $y);
} }


public function concat($x, ...$expr): IQueryFunction {
$args = func_get_args();
$list = [];
foreach ($args as $item) {
$list[] = $this->helper->quoteColumnName($item);
}
return new QueryFunction(sprintf('(%s)', implode(' || ', $list)));
}

public function groupConcat($expr, ?string $separator = ','): IQueryFunction { public function groupConcat($expr, ?string $separator = ','): IQueryFunction {
$orderByClause = ' WITHIN GROUP(ORDER BY NULL)'; $orderByClause = ' WITHIN GROUP(ORDER BY NULL)';
if (is_null($separator)) { if (is_null($separator)) {

+ 7
- 2
lib/private/DB/QueryBuilder/FunctionBuilder/PgSqlFunctionBuilder.php View File

use OCP\DB\QueryBuilder\IQueryFunction; use OCP\DB\QueryBuilder\IQueryFunction;


class PgSqlFunctionBuilder extends FunctionBuilder { class PgSqlFunctionBuilder extends FunctionBuilder {
public function concat($x, $y): IQueryFunction {
return new QueryFunction('(' . $this->helper->quoteColumnName($x) . ' || ' . $this->helper->quoteColumnName($y) . ')');
public function concat($x, ...$expr): IQueryFunction {
$args = func_get_args();
$list = [];
foreach ($args as $item) {
$list[] = $this->queryBuilder->expr()->castColumn($item, IQueryBuilder::PARAM_STR);
}
return new QueryFunction(sprintf('(%s)', implode(' || ', $list)));
} }


public function groupConcat($expr, ?string $separator = ','): IQueryFunction { public function groupConcat($expr, ?string $separator = ','): IQueryFunction {

+ 7
- 2
lib/private/DB/QueryBuilder/FunctionBuilder/SqliteFunctionBuilder.php View File

use OCP\DB\QueryBuilder\IQueryFunction; use OCP\DB\QueryBuilder\IQueryFunction;


class SqliteFunctionBuilder extends FunctionBuilder { class SqliteFunctionBuilder extends FunctionBuilder {
public function concat($x, $y): IQueryFunction {
return new QueryFunction('(' . $this->helper->quoteColumnName($x) . ' || ' . $this->helper->quoteColumnName($y) . ')');
public function concat($x, ...$expr): IQueryFunction {
$args = func_get_args();
$list = [];
foreach ($args as $item) {
$list[] = $this->helper->quoteColumnName($item);
}
return new QueryFunction(sprintf('(%s)', implode(' || ', $list)));
} }


public function groupConcat($expr, ?string $separator = ','): IQueryFunction { public function groupConcat($expr, ?string $separator = ','): IQueryFunction {

+ 3
- 3
lib/public/DB/QueryBuilder/IFunctionBuilder.php View File

/** /**
* Combines two input strings * Combines two input strings
* *
* @param string|ILiteral|IParameter|IQueryFunction $x The first input string
* @param string|ILiteral|IParameter|IQueryFunction $y The second input string
* @param string|ILiteral|IParameter|IQueryFunction $x Expressions or literal strings
* @param string|ILiteral|IParameter|IQueryFunction ...$exprs Expressions or literal strings
* *
* @return IQueryFunction * @return IQueryFunction
* @since 12.0.0 * @since 12.0.0
*/ */
public function concat($x, $y): IQueryFunction;
public function concat($x, ...$expr): IQueryFunction;


/** /**
* Returns a string which is the concatenation of all non-NULL values of X * Returns a string which is the concatenation of all non-NULL values of X

+ 54
- 6
tests/lib/DB/QueryBuilder/FunctionBuilderTest.php View File

$this->connection = \OC::$server->getDatabaseConnection(); $this->connection = \OC::$server->getDatabaseConnection();
} }


public function testConcat() {
/**
* @dataProvider providerTestConcatString
*/
public function testConcatString($closure) {
$query = $this->connection->getQueryBuilder(); $query = $this->connection->getQueryBuilder();
[$real, $arguments, $return] = $closure($query);
if ($real) {
$this->addDummyData();
$query->where($query->expr()->eq('appid', $query->createNamedParameter('group_concat')));
}


$query->select($query->func()->concat($query->createNamedParameter('foo'), new Literal("'bar'")));
$query->select($query->func()->concat(...$arguments));
$query->from('appconfig') $query->from('appconfig')
->setMaxResults(1); ->setMaxResults(1);


$result = $query->execute(); $result = $query->execute();
$column = $result->fetchOne(); $column = $result->fetchOne();
$result->closeCursor(); $result->closeCursor();
$this->assertEquals('foobar', $column);
$this->assertEquals($return, $column);
}

public function providerTestConcatString(): array {
return [
'1 column: string param unicode' =>
[function ($q) {
return [false, [$q->createNamedParameter('👍')], '👍'];
}],
'2 columns: string param and string param' =>
[function ($q) {
return [false, [$q->createNamedParameter('foo'), $q->createNamedParameter('bar')], 'foobar'];
}],
'2 columns: string param and int literal' =>
[function ($q) {
return [false, [$q->createNamedParameter('foo'), $q->expr()->literal(1)], 'foo1'];
}],
'2 columns: string param and string literal' =>
[function ($q) {
return [false, [$q->createNamedParameter('foo'), $q->expr()->literal('bar')], 'foobar'];
}],
'2 columns: string real and int literal' =>
[function ($q) {
return [true, ['configkey', $q->expr()->literal(2)], '12'];
}],
'4 columns: string literal' =>
[function ($q) {
return [false, [$q->expr()->literal('foo'), $q->expr()->literal('bar'), $q->expr()->literal('foo'), $q->expr()->literal('bar')], 'foobarfoobar'];
}],
'4 columns: int literal' =>
[function ($q) {
return [false, [$q->expr()->literal(1), $q->expr()->literal(2), $q->expr()->literal(3), $q->expr()->literal(4)], '1234'];
}],
'5 columns: string param with special chars used in the function' =>
[function ($q) {
return [false, [$q->createNamedParameter("b"), $q->createNamedParameter("'"), $q->createNamedParameter('||'), $q->createNamedParameter(','), $q->createNamedParameter('a')], "b'||,a"];
}],
];
} }


protected function clearDummyData(): void { protected function clearDummyData(): void {
$result = $query->execute(); $result = $query->execute();
$column = $result->fetchOne(); $column = $result->fetchOne();
$result->closeCursor(); $result->closeCursor();
$this->assertEquals('1,2,3', $column);
$this->assertStringContainsString(',', $column); $this->assertStringContainsString(',', $column);
$actual = explode(',', $column); $actual = explode(',', $column);
$this->assertEqualsCanonicalizing([1,2,3], $actual); $this->assertEqualsCanonicalizing([1,2,3], $actual);
$result = $query->execute(); $result = $query->execute();
$column = $result->fetchOne(); $column = $result->fetchOne();
$result->closeCursor(); $result->closeCursor();
$this->assertEquals('1\'2\'3', $column);
$this->assertStringContainsString("'", $column);
$actual = explode("'", $column);
$this->assertEqualsCanonicalizing([1,2,3], $actual);
} }


public function testGroupConcatWithDoubleQuoteSeparator(): void { public function testGroupConcatWithDoubleQuoteSeparator(): void {
$result = $query->execute(); $result = $query->execute();
$column = $result->fetchOne(); $column = $result->fetchOne();
$result->closeCursor(); $result->closeCursor();
$this->assertEquals('1"2"3', $column);
$this->assertStringContainsString('"', $column);
$actual = explode('"', $column);
$this->assertEqualsCanonicalizing([1,2,3], $actual);
} }


protected function clearIntDummyData(): void { protected function clearIntDummyData(): void {

Loading…
Cancel
Save