Unverified Commit 758a6c71 authored by Marco Pivetta's avatar Marco Pivetta Committed by Sergei Morozov

Merge pull request #3491 from morozov/get-trim-expr

Changed the type of $char in AbstractPlatform::getTrimExpression()`from string|false to ?string
parents 37cce803 6eef1d45
# Upgrade to 3.0 # Upgrade to 3.0
## BC BREAK The type of `$char` in `AbstractPlatform::getTrimExpression()` changed from `string|false` to `?string`
The default value of `$char` is now `null`, not `false`. Additionally, the method will throw an `InvalidArgumentException` in an invalid value of `$mode` is passed.
## BC BREAK `Statement::quote()` only accepts strings. ## BC BREAK `Statement::quote()` only accepts strings.
`Statement::quote()` and `ExpressionBuilder::literal()` no longer accept arguments of an arbitrary type and and don't implement type-specific handling. Only strings can be quoted. `Statement::quote()` and `ExpressionBuilder::literal()` no longer accept arguments of an arbitrary type and and don't implement type-specific handling. Only strings can be quoted.
......
...@@ -753,37 +753,50 @@ abstract class AbstractPlatform ...@@ -753,37 +753,50 @@ abstract class AbstractPlatform
* *
* @param string $str The expression to apply the trim to. * @param string $str The expression to apply the trim to.
* @param int $mode The position of the trim (leading/trailing/both). * @param int $mode The position of the trim (leading/trailing/both).
* @param string|bool $char The char to trim, has to be quoted already. Defaults to space. * @param string|null $char The char to trim, has to be quoted already. Defaults to space.
* *
* @return string * @throws InvalidArgumentException
*/ */
public function getTrimExpression($str, $mode = TrimMode::UNSPECIFIED, $char = false) public function getTrimExpression(string $str, int $mode = TrimMode::UNSPECIFIED, ?string $char = null) : string
{ {
$expression = ''; $tokens = [];
switch ($mode) { switch ($mode) {
case TrimMode::UNSPECIFIED:
break;
case TrimMode::LEADING: case TrimMode::LEADING:
$expression = 'LEADING '; $tokens[] = 'LEADING';
break; break;
case TrimMode::TRAILING: case TrimMode::TRAILING:
$expression = 'TRAILING '; $tokens[] = 'TRAILING';
break; break;
case TrimMode::BOTH: case TrimMode::BOTH:
$expression = 'BOTH '; $tokens[] = 'BOTH';
break; break;
default:
throw new InvalidArgumentException(
sprintf(
'The value of $mode is expected to be one of the TrimMode constants, %d given',
$mode
)
);
} }
if ($char !== false) { if ($char !== null) {
$expression .= $char . ' '; $tokens[] = $char;
} }
if ($mode || $char !== false) { if (count($tokens) > 0) {
$expression .= 'FROM '; $tokens[] = 'FROM';
} }
return 'TRIM(' . $expression . $str . ')'; $tokens[] = $str;
return sprintf('TRIM(%s)', implode(' ', $tokens));
} }
/** /**
......
...@@ -24,6 +24,7 @@ use function explode; ...@@ -24,6 +24,7 @@ use function explode;
use function func_get_args; use function func_get_args;
use function get_class; use function get_class;
use function implode; use function implode;
use function in_array;
use function is_string; use function is_string;
use function preg_match; use function preg_match;
use function sprintf; use function sprintf;
...@@ -1124,10 +1125,16 @@ SQL ...@@ -1124,10 +1125,16 @@ SQL
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) public function getTrimExpression(string $str, int $mode = TrimMode::UNSPECIFIED, ?string $char = null) : string
{ {
if (! $char) { if (! in_array($mode, [TrimMode::UNSPECIFIED, TrimMode::LEADING, TrimMode::TRAILING, TrimMode::BOTH], true)) {
switch ($pos) { throw new InvalidArgumentException(
sprintf('The value of $mode is expected to be one of the TrimMode constants, %d given', $mode)
);
}
if ($char === null) {
switch ($mode) {
case TrimMode::LEADING: case TrimMode::LEADING:
return $this->getLtrimExpression($str); return $this->getLtrimExpression($str);
case TrimMode::TRAILING: case TrimMode::TRAILING:
...@@ -1139,7 +1146,7 @@ SQL ...@@ -1139,7 +1146,7 @@ SQL
$pattern = "'%[^' + " . $char . " + ']%'"; $pattern = "'%[^' + " . $char . " + ']%'";
switch ($pos) { switch ($mode) {
case TrimMode::LEADING: case TrimMode::LEADING:
return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))'; return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))';
case TrimMode::TRAILING: case TrimMode::TRAILING:
......
...@@ -20,6 +20,7 @@ use function dechex; ...@@ -20,6 +20,7 @@ use function dechex;
use function explode; use function explode;
use function func_get_args; use function func_get_args;
use function implode; use function implode;
use function in_array;
use function is_array; use function is_array;
use function is_bool; use function is_bool;
use function is_numeric; use function is_numeric;
...@@ -1035,23 +1036,25 @@ SQL ...@@ -1035,23 +1036,25 @@ SQL
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) public function getTrimExpression(string $str, int $mode = TrimMode::UNSPECIFIED, ?string $char = null) : string
{ {
if (! $char) { if (! in_array($mode, [TrimMode::UNSPECIFIED, TrimMode::LEADING, TrimMode::TRAILING, TrimMode::BOTH], true)) {
switch ($pos) { throw new InvalidArgumentException(
sprintf('The value of $mode is expected to be one of the TrimMode constants, %d given', $mode)
);
}
if ($char === null) {
switch ($mode) {
case TrimMode::LEADING: case TrimMode::LEADING:
$trimFn = 'LTRIM'; return 'LTRIM(' . $str . ')';
break;
case TrimMode::TRAILING: case TrimMode::TRAILING:
$trimFn = 'RTRIM'; return 'RTRIM(' . $str . ')';
break;
default: default:
return 'LTRIM(RTRIM(' . $str . '))'; return 'LTRIM(RTRIM(' . $str . '))';
} }
return $trimFn . '(' . $str . ')';
} }
/** Original query used to get those expressions /** Original query used to get those expressions
...@@ -1065,11 +1068,11 @@ SQL ...@@ -1065,11 +1068,11 @@ SQL
*/ */
$pattern = "'%[^' + " . $char . " + ']%'"; $pattern = "'%[^' + " . $char . " + ']%'";
if ($pos === TrimMode::LEADING) { if ($mode === TrimMode::LEADING) {
return 'stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)'; return 'stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)';
} }
if ($pos === TrimMode::TRAILING) { if ($mode === TrimMode::TRAILING) {
return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))'; return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))';
} }
......
...@@ -12,6 +12,7 @@ use Doctrine\DBAL\Schema\Table; ...@@ -12,6 +12,7 @@ use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Schema\TableDiff;
use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\TransactionIsolationLevel;
use Doctrine\DBAL\Types; use Doctrine\DBAL\Types;
use InvalidArgumentException;
use function array_merge; use function array_merge;
use function array_unique; use function array_unique;
use function array_values; use function array_values;
...@@ -60,11 +61,14 @@ class SqlitePlatform extends AbstractPlatform ...@@ -60,11 +61,14 @@ class SqlitePlatform extends AbstractPlatform
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false) public function getTrimExpression(string $str, int $mode = TrimMode::UNSPECIFIED, ?string $char = null) : string
{ {
$trimChar = $char !== false ? (', ' . $char) : ''; switch ($mode) {
case TrimMode::UNSPECIFIED:
case TrimMode::BOTH:
$trimFn = 'TRIM';
break;
switch ($pos) {
case TrimMode::LEADING: case TrimMode::LEADING:
$trimFn = 'LTRIM'; $trimFn = 'LTRIM';
break; break;
...@@ -74,10 +78,21 @@ class SqlitePlatform extends AbstractPlatform ...@@ -74,10 +78,21 @@ class SqlitePlatform extends AbstractPlatform
break; break;
default: default:
$trimFn = 'TRIM'; throw new InvalidArgumentException(
sprintf(
'The value of $mode is expected to be one of the TrimMode constants, %d given',
$mode
)
);
}
$arguments = [$str];
if ($char !== null) {
$arguments[] = $char;
} }
return $trimFn . '(' . $str . $trimChar . ')'; return sprintf('%s(%s)', $trimFn, implode(', ', $arguments));
} }
/** /**
......
...@@ -18,6 +18,7 @@ use Doctrine\DBAL\Schema\Table; ...@@ -18,6 +18,7 @@ use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Statement; use Doctrine\DBAL\Statement;
use Doctrine\DBAL\Types\Types; use Doctrine\DBAL\Types\Types;
use Doctrine\Tests\DbalFunctionalTestCase; use Doctrine\Tests\DbalFunctionalTestCase;
use InvalidArgumentException;
use PDO; use PDO;
use const CASE_LOWER; use const CASE_LOWER;
use const PHP_EOL; use const PHP_EOL;
...@@ -530,10 +531,10 @@ class DataAccessTest extends DbalFunctionalTestCase ...@@ -530,10 +531,10 @@ class DataAccessTest extends DbalFunctionalTestCase
public static function getTrimExpressionData() : iterable public static function getTrimExpressionData() : iterable
{ {
return [ return [
['test_string', TrimMode::UNSPECIFIED, false, 'foo'], ['test_string', TrimMode::UNSPECIFIED, null, 'foo'],
['test_string', TrimMode::LEADING, false, 'foo'], ['test_string', TrimMode::LEADING, null, 'foo'],
['test_string', TrimMode::TRAILING, false, 'foo'], ['test_string', TrimMode::TRAILING, null, 'foo'],
['test_string', TrimMode::BOTH, false, 'foo'], ['test_string', TrimMode::BOTH, null, 'foo'],
['test_string', TrimMode::UNSPECIFIED, "'f'", 'oo'], ['test_string', TrimMode::UNSPECIFIED, "'f'", 'oo'],
['test_string', TrimMode::UNSPECIFIED, "'o'", 'f'], ['test_string', TrimMode::UNSPECIFIED, "'o'", 'f'],
['test_string', TrimMode::UNSPECIFIED, "'.'", 'foo'], ['test_string', TrimMode::UNSPECIFIED, "'.'", 'foo'],
...@@ -546,10 +547,10 @@ class DataAccessTest extends DbalFunctionalTestCase ...@@ -546,10 +547,10 @@ class DataAccessTest extends DbalFunctionalTestCase
['test_string', TrimMode::BOTH, "'f'", 'oo'], ['test_string', TrimMode::BOTH, "'f'", 'oo'],
['test_string', TrimMode::BOTH, "'o'", 'f'], ['test_string', TrimMode::BOTH, "'o'", 'f'],
['test_string', TrimMode::BOTH, "'.'", 'foo'], ['test_string', TrimMode::BOTH, "'.'", 'foo'],
["' foo '", TrimMode::UNSPECIFIED, false, 'foo'], ["' foo '", TrimMode::UNSPECIFIED, null, 'foo'],
["' foo '", TrimMode::LEADING, false, 'foo '], ["' foo '", TrimMode::LEADING, null, 'foo '],
["' foo '", TrimMode::TRAILING, false, ' foo'], ["' foo '", TrimMode::TRAILING, null, ' foo'],
["' foo '", TrimMode::BOTH, false, 'foo'], ["' foo '", TrimMode::BOTH, null, 'foo'],
["' foo '", TrimMode::UNSPECIFIED, "'f'", ' foo '], ["' foo '", TrimMode::UNSPECIFIED, "'f'", ' foo '],
["' foo '", TrimMode::UNSPECIFIED, "'o'", ' foo '], ["' foo '", TrimMode::UNSPECIFIED, "'o'", ' foo '],
["' foo '", TrimMode::UNSPECIFIED, "'.'", ' foo '], ["' foo '", TrimMode::UNSPECIFIED, "'.'", ' foo '],
...@@ -569,6 +570,12 @@ class DataAccessTest extends DbalFunctionalTestCase ...@@ -569,6 +570,12 @@ class DataAccessTest extends DbalFunctionalTestCase
]; ];
} }
public function testTrimExpressionInvalidMode() : void
{
$this->expectException(InvalidArgumentException::class);
$this->connection->getDatabasePlatform()->getTrimExpression('Trim me!', 0xBEEF);
}
/** /**
* @group DDC-1014 * @group DDC-1014
*/ */
......
...@@ -697,11 +697,6 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase ...@@ -697,11 +697,6 @@ class SQLAnywherePlatformTest extends AbstractPlatformTestCase
"REVERSE(SUBSTR(REVERSE(column), PATINDEX('%[^' + c + ']%', REVERSE(column))))", "REVERSE(SUBSTR(REVERSE(column), PATINDEX('%[^' + c + ']%', REVERSE(column))))",
$this->platform->getTrimExpression('column', TrimMode::TRAILING, 'c') $this->platform->getTrimExpression('column', TrimMode::TRAILING, 'c')
); );
self::assertEquals(
"REVERSE(SUBSTR(REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))), PATINDEX('%[^' + c + ']%', " .
"REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))))))",
$this->platform->getTrimExpression('column', null, 'c')
);
self::assertEquals( self::assertEquals(
"REVERSE(SUBSTR(REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))), PATINDEX('%[^' + c + ']%', " . "REVERSE(SUBSTR(REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))), PATINDEX('%[^' + c + ']%', " .
"REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))))))", "REVERSE(SUBSTR(column, PATINDEX('%[^' + c + ']%', column))))))",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment