From 6e11a000e732aa34da617e46ccc8a2eab9972a0a Mon Sep 17 00:00:00 2001 From: Sergei Morozov Date: Thu, 21 Mar 2019 22:15:03 -0700 Subject: [PATCH] Reworked AbstractPlatform::get*Expression() methods --- UPGRADE.md | 27 ++ .../DBAL/Platforms/AbstractPlatform.php | 404 +++++++----------- lib/Doctrine/DBAL/Platforms/DB2Platform.php | 16 +- lib/Doctrine/DBAL/Platforms/MySqlPlatform.php | 11 +- .../DBAL/Platforms/OraclePlatform.php | 14 +- .../DBAL/Platforms/PostgreSqlPlatform.php | 12 +- .../DBAL/Platforms/SQLAnywherePlatform.php | 15 +- .../DBAL/Platforms/SQLServerPlatform.php | 19 +- .../DBAL/Platforms/SqlitePlatform.php | 45 +- .../Tests/DBAL/Functional/DataAccessTest.php | 343 +++++++++++++-- .../Tests/DBAL/Platforms/DB2PlatformTest.php | 8 +- .../DBAL/Platforms/SqlitePlatformTest.php | 4 +- 12 files changed, 554 insertions(+), 364 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 097e5abcfac..ade59907b2a 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,32 @@ # Upgrade to 3.0 +## BC BREAK `AbstractPlatform::get*Expression()` methods no loner accept integer values as arguments + +The following methods' arguments do not longer accept integer value: + +- the `$expression` argument in `::getCountExpression()`, +- the `$decimals` argument in `::getRoundExpression()`, +- the `$seconds` argument in `::getDateAddSecondsExpression()`, +- the `$seconds` argument in `::getDateSubSecondsExpression()`, +- the `$minutes` argument in `::getDateAddMinutesExpression()`, +- the `$minutes` argument in `::getDateSubMinutesExpression()`, +- the `$hours` argument in `::getDateAddHourExpression()`, +- the `$hours` argument in `::getDateAddHourExpression()`, +- the `$days` argument in `::getDateAddDaysExpression()`, +- the `$days` argument in `::getDateSubDaysExpression()`, +- the `$weeks` argument in `::getDateAddWeeksExpression()`, +- the `$weeks` argument in `::getDateSubWeeksExpression()`, +- the `$months` argument in `::getDateAddMonthExpression()`, +- the `$months` argument in `::getDateSubMonthExpression()`, +- the `$quarters` argument in `::getDateAddQuartersExpression()`, +- the `$quarters` argument in `::getDateSubQuartersExpression()`, +- the `$years` argument in `::getDateAddYearsExpression()`, +- the `$years` argument in `::getDateSubYearsExpression()`. + +Please use the strings representing numeric SQL literals instead (e.g. `'1'` instead of `1`). + +The signature of `AbstractPlatform::getConcatExpression()` changed to `::getConcatExpression(string ...$string)`. + ## BC BREAK The type of `$start` in `AbstractPlatform::getLocateExpression()` changed from `string|false` to `?string` The default value of `$start` is now `null`, not `false`. diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 78108e47a10..9f970c606d4 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -37,7 +37,6 @@ use function assert; use function count; use function explode; -use function func_get_args; use function implode; use function in_array; use function is_array; @@ -611,11 +610,9 @@ public function getWildcards() /** * Returns the regular expression operator. * - * @return string - * * @throws DBALException If not supported on this platform. */ - public function getRegexpExpression() + public function getRegexpExpression() : string { throw DBALException::notSupported(__METHOD__); } @@ -623,13 +620,11 @@ public function getRegexpExpression() /** * Returns the SQL snippet to get the average value of a column. * - * @param string $column The column to use. - * - * @return string Generated SQL including an AVG aggregate function. + * @param string $value SQL expression producing the value. */ - public function getAvgExpression($column) + public function getAvgExpression(string $value) : string { - return 'AVG(' . $column . ')'; + return 'AVG(' . $value . ')'; } /** @@ -637,115 +632,97 @@ public function getAvgExpression($column) * * If a '*' is used instead of a column the number of selected rows is returned. * - * @param string|int $column The column to use. - * - * @return string Generated SQL including a COUNT aggregate function. + * @param string $expression The expression to count. */ - public function getCountExpression($column) + public function getCountExpression(string $expression) : string { - return 'COUNT(' . $column . ')'; + return 'COUNT(' . $expression . ')'; } /** - * Returns the SQL snippet to get the highest value of a column. - * - * @param string $column The column to use. + * Returns the SQL snippet to get the maximum value in a set of values. * - * @return string Generated SQL including a MAX aggregate function. + * @param string $value SQL expression producing the value. */ - public function getMaxExpression($column) + public function getMaxExpression(string $value) : string { - return 'MAX(' . $column . ')'; + return 'MAX(' . $value . ')'; } /** - * Returns the SQL snippet to get the lowest value of a column. - * - * @param string $column The column to use. + * Returns the SQL snippet to get the minimum value in a set of values. * - * @return string Generated SQL including a MIN aggregate function. + * @param string $value SQL expression producing the value. */ - public function getMinExpression($column) + public function getMinExpression(string $value) : string { - return 'MIN(' . $column . ')'; + return 'MIN(' . $value . ')'; } /** - * Returns the SQL snippet to get the total sum of a column. + * Returns the SQL snippet to get the total sum of the values in a set. * - * @param string $column The column to use. - * - * @return string Generated SQL including a SUM aggregate function. + * @param string $value SQL expression producing the value. */ - public function getSumExpression($column) + public function getSumExpression(string $value) : string { - return 'SUM(' . $column . ')'; + return 'SUM(' . $value . ')'; } // scalar functions /** - * Returns the SQL snippet to get the md5 sum of a field. + * Returns the SQL snippet to get the md5 sum of the value. * * Note: Not SQL92, but common functionality. * - * @param string $column - * - * @return string + * @param string $string SQL expression producing the string. */ - public function getMd5Expression($column) + public function getMd5Expression(string $string) : string { - return 'MD5(' . $column . ')'; + return 'MD5(' . $string . ')'; } /** * Returns the SQL snippet to get the length of a text field. * - * @param string $column - * - * @return string + * @param string $string SQL expression producing the string. */ - public function getLengthExpression($column) + public function getLengthExpression(string $string) : string { - return 'LENGTH(' . $column . ')'; + return 'LENGTH(' . $string . ')'; } /** - * Returns the SQL snippet to get the squared value of a column. - * - * @param string $column The column to use. + * Returns the SQL snippet to get the square root of the value. * - * @return string Generated SQL including an SQRT aggregate function. + * @param string $number SQL expression producing the number. */ - public function getSqrtExpression($column) + public function getSqrtExpression(string $number) : string { - return 'SQRT(' . $column . ')'; + return 'SQRT(' . $number . ')'; } /** - * Returns the SQL snippet to round a numeric field to the number of decimals specified. + * Returns the SQL snippet to round a number to the number of decimals specified. * - * @param string $column - * @param int $decimals - * - * @return string + * @param string $number SQL expression producing the number to round. + * @param string $decimals SQL expression producing the number of decimals. */ - public function getRoundExpression($column, $decimals = 0) + public function getRoundExpression(string $number, string $decimals = '0') : string { - return 'ROUND(' . $column . ', ' . $decimals . ')'; + return 'ROUND(' . $number . ', ' . $decimals . ')'; } /** - * Returns the SQL snippet to get the remainder of the division operation $expression1 / $expression2. - * - * @param string $expression1 - * @param string $expression2 + * Returns the SQL snippet to get the remainder of the operation of division of dividend by divisor. * - * @return string + * @param string $dividend SQL expression producing the dividend. + * @param string $divisor SQL expression producing the divisor. */ - public function getModExpression($expression1, $expression2) + public function getModExpression(string $dividend, string $divisor) : string { - return 'MOD(' . $expression1 . ', ' . $expression2 . ')'; + return 'MOD(' . $dividend . ', ' . $divisor . ')'; } /** @@ -800,53 +777,45 @@ public function getTrimExpression(string $str, int $mode = TrimMode::UNSPECIFIED } /** - * Returns the SQL snippet to trim trailing space characters from the expression. - * - * @param string $str Literal string or column name. + * Returns the SQL snippet to trim trailing space characters from the string. * - * @return string + * @param string $string SQL expression producing the string. */ - public function getRtrimExpression($str) + public function getRtrimExpression(string $string) : string { - return 'RTRIM(' . $str . ')'; + return 'RTRIM(' . $string . ')'; } /** - * Returns the SQL snippet to trim leading space characters from the expression. + * Returns the SQL snippet to trim leading space characters from the string. * - * @param string $str Literal string or column name. - * - * @return string + * @param string $string SQL expression producing the string. */ - public function getLtrimExpression($str) + public function getLtrimExpression(string $string) : string { - return 'LTRIM(' . $str . ')'; + return 'LTRIM(' . $string . ')'; } /** - * Returns the SQL snippet to change all characters from the expression to uppercase, + * Returns the SQL snippet to change all characters from the string to uppercase, * according to the current character set mapping. * - * @param string $str Literal string or column name. - * - * @return string + * @param string $string SQL expression producing the string. */ - public function getUpperExpression($str) + public function getUpperExpression(string $string) : string { - return 'UPPER(' . $str . ')'; + return 'UPPER(' . $string . ')'; } /** - * Returns the SQL snippet to change all characters from the expression to lowercase, + * Returns the SQL snippet to change all characters from the string to lowercase, * according to the current character set mapping. * - * @param string $str Literal string or column name. - * - * @return string + * @param string $string SQL expression producing the string. */ - public function getLowerExpression($str) + public function getLowerExpression(string $string) : string { - return 'LOWER(' . $str . ')'; + return 'LOWER(' . $string . ')'; } /** @@ -866,10 +835,8 @@ public function getLocateExpression(string $string, string $substring, ?string $ /** * Returns the SQL snippet to get the current system date. - * - * @return string */ - public function getNowExpression() + public function getNowExpression() : string { return 'NOW()'; } @@ -894,111 +861,87 @@ public function getSubstringExpression(string $string, string $start, ?string $l } /** - * Returns a SQL snippet to concatenate the given expressions. + * Returns a SQL snippet to concatenate the given strings. * - * Accepts an arbitrary number of string parameters. Each parameter must contain an expression. - * - * @return string + * @param string[] ...$string */ - public function getConcatExpression() + public function getConcatExpression(string ...$string) : string { - return implode(' || ', func_get_args()); + return implode(' || ', $string); } /** * Returns the SQL for a logical not. * - * Example: - * - * $q = new Doctrine_Query(); - * $e = $q->expr; - * $q->select('*')->from('table') - * ->where($e->eq('id', $e->not('null')); - * - * - * @param string $expression - * - * @return string The logical expression. + * @param string $value SQL expression producing the value to negate. */ - public function getNotExpression($expression) + public function getNotExpression(string $value) : string { - return 'NOT(' . $expression . ')'; + return 'NOT(' . $value . ')'; } /** * Returns the SQL that checks if an expression is null. * - * @param string $expression The expression that should be compared to null. - * - * @return string The logical expression. + * @param string $value SQL expression producing the to be compared to null. */ - public function getIsNullExpression($expression) + public function getIsNullExpression(string $value) : string { - return $expression . ' IS NULL'; + return $value . ' IS NULL'; } /** * Returns the SQL that checks if an expression is not null. * - * @param string $expression The expression that should be compared to null. - * - * @return string The logical expression. + * @param string $value SQL expression producing the to be compared to null. */ - public function getIsNotNullExpression($expression) + public function getIsNotNullExpression(string $value) : string { - return $expression . ' IS NOT NULL'; + return $value . ' IS NOT NULL'; } /** * Returns the SQL that checks if an expression evaluates to a value between two values. * - * The parameter $expression is checked if it is between $value1 and $value2. + * The parameter $value is checked if it is between $min and $max. * * Note: There is a slight difference in the way BETWEEN works on some databases. * http://www.w3schools.com/sql/sql_between.asp. If you want complete database * independence you should avoid using between(). * - * @param string $expression The value to compare to. - * @param string $value1 The lower value to compare with. - * @param string $value2 The higher value to compare with. - * - * @return string The logical expression. + * @param string $value SQL expression producing the value to compare. + * @param string $min SQL expression producing the lower value to compare with. + * @param string $max SQL expression producing the higher value to compare with. */ - public function getBetweenExpression($expression, $value1, $value2) + public function getBetweenExpression(string $value, string $min, string $max) : string { - return $expression . ' BETWEEN ' . $value1 . ' AND ' . $value2; + return $value . ' BETWEEN ' . $min . ' AND ' . $max; } /** * Returns the SQL to get the arccosine of a value. * - * @param string $value - * - * @return string + * @param string $number SQL expression producing the number. */ - public function getAcosExpression($value) + public function getAcosExpression(string $number) : string { - return 'ACOS(' . $value . ')'; + return 'ACOS(' . $number . ')'; } /** * Returns the SQL to get the sine of a value. * - * @param string $value - * - * @return string + * @param string $number SQL expression producing the number. */ - public function getSinExpression($value) + public function getSinExpression(string $number) : string { - return 'SIN(' . $value . ')'; + return 'SIN(' . $number . ')'; } /** * Returns the SQL to get the PI value. - * - * @return string */ - public function getPiExpression() + public function getPiExpression() : string { return 'PI()'; } @@ -1006,13 +949,11 @@ public function getPiExpression() /** * Returns the SQL to get the cosine of a value. * - * @param string $value - * - * @return string + * @param string $number SQL expression producing the number. */ - public function getCosExpression($value) + public function getCosExpression(string $number) : string { - return 'COS(' . $value . ')'; + return 'COS(' . $number . ')'; } /** @@ -1020,14 +961,9 @@ public function getCosExpression($value) * * Computes diff = date1 - date2. * - * @param string $date1 - * @param string $date2 - * - * @return string - * * @throws DBALException If not supported on this platform. */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { throw DBALException::notSupported(__METHOD__); } @@ -1035,14 +971,12 @@ public function getDateDiffExpression($date1, $date2) /** * Returns the SQL to add the number of given seconds to a date. * - * @param string $date - * @param int $seconds - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $seconds SQL expression producing the number of seconds. * * @throws DBALException If not supported on this platform. */ - public function getDateAddSecondsExpression($date, $seconds) + public function getDateAddSecondsExpression(string $date, string $seconds) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $seconds, DateIntervalUnit::SECOND); } @@ -1050,14 +984,12 @@ public function getDateAddSecondsExpression($date, $seconds) /** * Returns the SQL to subtract the number of given seconds from a date. * - * @param string $date - * @param int $seconds - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $seconds SQL expression producing the number of seconds. * * @throws DBALException If not supported on this platform. */ - public function getDateSubSecondsExpression($date, $seconds) + public function getDateSubSecondsExpression(string $date, string $seconds) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $seconds, DateIntervalUnit::SECOND); } @@ -1065,14 +997,12 @@ public function getDateSubSecondsExpression($date, $seconds) /** * Returns the SQL to add the number of given minutes to a date. * - * @param string $date - * @param int $minutes - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $minutes SQL expression producing the number of minutes. * * @throws DBALException If not supported on this platform. */ - public function getDateAddMinutesExpression($date, $minutes) + public function getDateAddMinutesExpression(string $date, string $minutes) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $minutes, DateIntervalUnit::MINUTE); } @@ -1080,14 +1010,12 @@ public function getDateAddMinutesExpression($date, $minutes) /** * Returns the SQL to subtract the number of given minutes from a date. * - * @param string $date - * @param int $minutes - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $minutes SQL expression producing the number of minutes. * * @throws DBALException If not supported on this platform. */ - public function getDateSubMinutesExpression($date, $minutes) + public function getDateSubMinutesExpression(string $date, string $minutes) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $minutes, DateIntervalUnit::MINUTE); } @@ -1095,14 +1023,12 @@ public function getDateSubMinutesExpression($date, $minutes) /** * Returns the SQL to add the number of given hours to a date. * - * @param string $date - * @param int $hours - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $hours SQL expression producing the number of hours. * * @throws DBALException If not supported on this platform. */ - public function getDateAddHourExpression($date, $hours) + public function getDateAddHourExpression(string $date, string $hours) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $hours, DateIntervalUnit::HOUR); } @@ -1110,14 +1036,12 @@ public function getDateAddHourExpression($date, $hours) /** * Returns the SQL to subtract the number of given hours to a date. * - * @param string $date - * @param int $hours - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $hours SQL expression producing the number of hours. * * @throws DBALException If not supported on this platform. */ - public function getDateSubHourExpression($date, $hours) + public function getDateSubHourExpression(string $date, string $hours) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $hours, DateIntervalUnit::HOUR); } @@ -1125,14 +1049,12 @@ public function getDateSubHourExpression($date, $hours) /** * Returns the SQL to add the number of given days to a date. * - * @param string $date - * @param int $days - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $days SQL expression producing the number of days. * * @throws DBALException If not supported on this platform. */ - public function getDateAddDaysExpression($date, $days) + public function getDateAddDaysExpression(string $date, string $days) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $days, DateIntervalUnit::DAY); } @@ -1140,14 +1062,12 @@ public function getDateAddDaysExpression($date, $days) /** * Returns the SQL to subtract the number of given days to a date. * - * @param string $date - * @param int $days - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $days SQL expression producing the number of days. * * @throws DBALException If not supported on this platform. */ - public function getDateSubDaysExpression($date, $days) + public function getDateSubDaysExpression(string $date, string $days) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $days, DateIntervalUnit::DAY); } @@ -1155,14 +1075,12 @@ public function getDateSubDaysExpression($date, $days) /** * Returns the SQL to add the number of given weeks to a date. * - * @param string $date - * @param int $weeks - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $weeks SQL expression producing the number of weeks. * * @throws DBALException If not supported on this platform. */ - public function getDateAddWeeksExpression($date, $weeks) + public function getDateAddWeeksExpression(string $date, string $weeks) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $weeks, DateIntervalUnit::WEEK); } @@ -1170,14 +1088,12 @@ public function getDateAddWeeksExpression($date, $weeks) /** * Returns the SQL to subtract the number of given weeks from a date. * - * @param string $date - * @param int $weeks - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $weeks SQL expression producing the number of weeks. * * @throws DBALException If not supported on this platform. */ - public function getDateSubWeeksExpression($date, $weeks) + public function getDateSubWeeksExpression(string $date, string $weeks) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $weeks, DateIntervalUnit::WEEK); } @@ -1185,14 +1101,12 @@ public function getDateSubWeeksExpression($date, $weeks) /** * Returns the SQL to add the number of given months to a date. * - * @param string $date - * @param int $months - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $months SQL expression producing the number of months. * * @throws DBALException If not supported on this platform. */ - public function getDateAddMonthExpression($date, $months) + public function getDateAddMonthExpression(string $date, string $months) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $months, DateIntervalUnit::MONTH); } @@ -1200,14 +1114,12 @@ public function getDateAddMonthExpression($date, $months) /** * Returns the SQL to subtract the number of given months to a date. * - * @param string $date - * @param int $months - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $months SQL expression producing the number of months. * * @throws DBALException If not supported on this platform. */ - public function getDateSubMonthExpression($date, $months) + public function getDateSubMonthExpression(string $date, string $months) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $months, DateIntervalUnit::MONTH); } @@ -1215,14 +1127,12 @@ public function getDateSubMonthExpression($date, $months) /** * Returns the SQL to add the number of given quarters to a date. * - * @param string $date - * @param int $quarters - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $quarters SQL expression producing the number of quarters. * * @throws DBALException If not supported on this platform. */ - public function getDateAddQuartersExpression($date, $quarters) + public function getDateAddQuartersExpression(string $date, string $quarters) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $quarters, DateIntervalUnit::QUARTER); } @@ -1230,14 +1140,12 @@ public function getDateAddQuartersExpression($date, $quarters) /** * Returns the SQL to subtract the number of given quarters from a date. * - * @param string $date - * @param int $quarters - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $quarters SQL expression producing the number of quarters. * * @throws DBALException If not supported on this platform. */ - public function getDateSubQuartersExpression($date, $quarters) + public function getDateSubQuartersExpression(string $date, string $quarters) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $quarters, DateIntervalUnit::QUARTER); } @@ -1245,14 +1153,12 @@ public function getDateSubQuartersExpression($date, $quarters) /** * Returns the SQL to add the number of given years to a date. * - * @param string $date - * @param int $years - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $years SQL expression producing the number of years. * * @throws DBALException If not supported on this platform. */ - public function getDateAddYearsExpression($date, $years) + public function getDateAddYearsExpression(string $date, string $years) : string { return $this->getDateArithmeticIntervalExpression($date, '+', $years, DateIntervalUnit::YEAR); } @@ -1260,14 +1166,12 @@ public function getDateAddYearsExpression($date, $years) /** * Returns the SQL to subtract the number of given years from a date. * - * @param string $date - * @param int $years - * - * @return string + * @param string $date SQL expression producing the date. + * @param string $years SQL expression producing the number of years. * * @throws DBALException If not supported on this platform. */ - public function getDateSubYearsExpression($date, $years) + public function getDateSubYearsExpression(string $date, string $years) : string { return $this->getDateArithmeticIntervalExpression($date, '-', $years, DateIntervalUnit::YEAR); } @@ -1275,30 +1179,40 @@ public function getDateSubYearsExpression($date, $years) /** * Returns the SQL for a date arithmetic expression. * - * @param string $date The column or literal representing a date to perform the arithmetic operation on. + * @param string $date SQL expression representing a date to perform the arithmetic operation on. * @param string $operator The arithmetic operator (+ or -). - * @param int $interval The interval that shall be calculated into the date. + * @param string $interval SQL expression representing the value of the interval that shall be calculated + * into the date. * @param string $unit The unit of the interval that shall be calculated into the date. * One of the DATE_INTERVAL_UNIT_* constants. * - * @return string - * * @throws DBALException If not supported on this platform. */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { throw DBALException::notSupported(__METHOD__); } /** - * Returns the SQL bit AND comparison expression. + * Generates the SQL expression which represents the given date interval multiplied by a number * - * @param string $value1 - * @param string $value2 + * @param string $interval SQL expression describing the interval value + * @param int $multiplier Interval multiplier * - * @return string + * @throws DBALException */ - public function getBitAndComparisonExpression($value1, $value2) + protected function multiplyInterval(string $interval, int $multiplier) : string + { + return sprintf('(%s * %d)', $interval, $multiplier); + } + + /** + * Returns the SQL bit AND comparison expression. + * + * @param string $value1 SQL expression producing the first value. + * @param string $value2 SQL expression producing the second value. + */ + public function getBitAndComparisonExpression(string $value1, string $value2) : string { return '(' . $value1 . ' & ' . $value2 . ')'; } @@ -1306,12 +1220,10 @@ public function getBitAndComparisonExpression($value1, $value2) /** * Returns the SQL bit OR comparison expression. * - * @param string $value1 - * @param string $value2 - * - * @return string + * @param string $value1 SQL expression producing the first value. + * @param string $value2 SQL expression producing the second value. */ - public function getBitOrComparisonExpression($value1, $value2) + public function getBitOrComparisonExpression(string $value1, string $value2) : string { return '(' . $value1 . ' | ' . $value2 . ')'; } diff --git a/lib/Doctrine/DBAL/Platforms/DB2Platform.php b/lib/Doctrine/DBAL/Platforms/DB2Platform.php index 00a33909595..9569076c112 100644 --- a/lib/Doctrine/DBAL/Platforms/DB2Platform.php +++ b/lib/Doctrine/DBAL/Platforms/DB2Platform.php @@ -186,7 +186,7 @@ protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) /** * {@inheritdoc} */ - public function getBitAndComparisonExpression($value1, $value2) + public function getBitAndComparisonExpression(string $value1, string $value2) : string { return 'BITAND(' . $value1 . ', ' . $value2 . ')'; } @@ -194,7 +194,7 @@ public function getBitAndComparisonExpression($value1, $value2) /** * {@inheritdoc} */ - public function getBitOrComparisonExpression($value1, $value2) + public function getBitOrComparisonExpression(string $value1, string $value2) : string { return 'BITOR(' . $value1 . ', ' . $value2 . ')'; } @@ -202,17 +202,17 @@ public function getBitOrComparisonExpression($value1, $value2) /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { switch ($unit) { case DateIntervalUnit::WEEK: - $interval *= 7; - $unit = DateIntervalUnit::DAY; + $interval = $this->multiplyInterval($interval, 7); + $unit = DateIntervalUnit::DAY; break; case DateIntervalUnit::QUARTER: - $interval *= 3; - $unit = DateIntervalUnit::MONTH; + $interval = $this->multiplyInterval($interval, 3); + $unit = DateIntervalUnit::MONTH; break; } @@ -222,7 +222,7 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv /** * {@inheritdoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return 'DAYS(' . $date1 . ') - DAYS(' . $date2 . ')'; } diff --git a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index 052835ceb62..8d53b2b7289 100644 --- a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -16,7 +16,6 @@ use function array_unique; use function array_values; use function count; -use function func_get_args; use function implode; use function in_array; use function is_numeric; @@ -73,7 +72,7 @@ public function getIdentifierQuoteCharacter() /** * {@inheritDoc} */ - public function getRegexpExpression() + public function getRegexpExpression() : string { return 'RLIKE'; } @@ -93,15 +92,15 @@ public function getLocateExpression(string $string, string $substring, ?string $ /** * {@inheritDoc} */ - public function getConcatExpression() + public function getConcatExpression(string ...$string) : string { - return sprintf('CONCAT(%s)', implode(', ', func_get_args())); + return sprintf('CONCAT(%s)', implode(', ', $string)); } /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { $function = $operator === '+' ? 'DATE_ADD' : 'DATE_SUB'; @@ -111,7 +110,7 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv /** * {@inheritDoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; } diff --git a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php index 03ed1839371..d7738657534 100644 --- a/lib/Doctrine/DBAL/Platforms/OraclePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -59,7 +59,7 @@ public function getSubstringExpression(string $string, string $start, ?string $l /** * {@inheritDoc} */ - public function getNowExpression($type = 'timestamp') + public function getNowExpression($type = 'timestamp') : string { switch ($type) { case 'date': @@ -85,7 +85,7 @@ public function getLocateExpression(string $string, string $substring, ?string $ /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { switch ($unit) { case DateIntervalUnit::MONTH: @@ -93,11 +93,11 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv case DateIntervalUnit::YEAR: switch ($unit) { case DateIntervalUnit::QUARTER: - $interval *= 3; + $interval = $this->multiplyInterval($interval, 3); break; case DateIntervalUnit::YEAR: - $interval *= 12; + $interval = $this->multiplyInterval($interval, 12); break; } @@ -131,7 +131,7 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv /** * {@inheritDoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return sprintf('TRUNC(%s) - TRUNC(%s)', $date1, $date2); } @@ -139,7 +139,7 @@ public function getDateDiffExpression($date1, $date2) /** * {@inheritDoc} */ - public function getBitAndComparisonExpression($value1, $value2) + public function getBitAndComparisonExpression(string $value1, string $value2) : string { return 'BITAND(' . $value1 . ', ' . $value2 . ')'; } @@ -147,7 +147,7 @@ public function getBitAndComparisonExpression($value1, $value2) /** * {@inheritDoc} */ - public function getBitOrComparisonExpression($value1, $value2) + public function getBitOrComparisonExpression(string $value1, string $value2) : string { return '(' . $value1 . '-' . $this->getBitAndComparisonExpression($value1, $value2) diff --git a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php index 47bc71ae251..a4fc3f10b51 100644 --- a/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -78,7 +78,7 @@ public function setUseBooleanTrueFalseStrings($flag) /** * {@inheritDoc} */ - public function getNowExpression() + public function getNowExpression() : string { return 'LOCALTIMESTAMP(0)'; } @@ -86,7 +86,7 @@ public function getNowExpression() /** * {@inheritDoc} */ - public function getRegexpExpression() + public function getRegexpExpression() : string { return 'SIMILAR TO'; } @@ -108,11 +108,11 @@ public function getLocateExpression(string $string, string $substring, ?string $ /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { if ($unit === DateIntervalUnit::QUARTER) { - $interval *= 3; - $unit = DateIntervalUnit::MONTH; + $interval = $this->multiplyInterval($interval, 3); + $unit = DateIntervalUnit::MONTH; } return '(' . $date . ' ' . $operator . ' (' . $interval . " || ' " . $unit . "')::interval)"; @@ -121,7 +121,7 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv /** * {@inheritDoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; } diff --git a/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php b/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php index 91f2334fe8a..36714143b85 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLAnywherePlatform.php @@ -21,7 +21,6 @@ use function array_values; use function count; use function explode; -use function func_get_args; use function get_class; use function implode; use function in_array; @@ -373,9 +372,9 @@ public function getCommentOnColumnSQL($tableName, $columnName, $comment) /** * {@inheritdoc} */ - public function getConcatExpression() + public function getConcatExpression(string ...$string) : string { - return 'STRING(' . implode(', ', (array) func_get_args()) . ')'; + return 'STRING(' . implode(', ', $string) . ')'; } /** @@ -470,7 +469,7 @@ public function getCurrentTimestampSQL() /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { $factorClause = ''; @@ -484,7 +483,7 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv /** * {@inheritdoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return 'DATEDIFF(day, ' . $date2 . ', ' . $date1 . ')'; } @@ -986,15 +985,15 @@ public function getMaxIdentifierLength() /** * {@inheritdoc} */ - public function getMd5Expression($column) + public function getMd5Expression(string $string) : string { - return 'HASH(' . $column . ", 'MD5')"; + return 'HASH(' . $string . ", 'MD5')"; } /** * {@inheritdoc} */ - public function getRegexpExpression() + public function getRegexpExpression() : string { return 'REGEXP'; } diff --git a/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php b/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php index e8b891f351c..7b894f64c31 100644 --- a/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SQLServerPlatform.php @@ -18,7 +18,6 @@ use function crc32; use function dechex; use function explode; -use function func_get_args; use function implode; use function in_array; use function is_array; @@ -74,7 +73,7 @@ private function getConvertExpression($dataType, $expression) /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { $factorClause = ''; @@ -88,7 +87,7 @@ protected function getDateArithmeticIntervalExpression($date, $operator, $interv /** * {@inheritDoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; } @@ -1028,9 +1027,9 @@ public function getLocateExpression(string $string, string $substring, ?string $ /** * {@inheritDoc} */ - public function getModExpression($expression1, $expression2) + public function getModExpression(string $dividend, string $divisor) : string { - return $expression1 . ' % ' . $expression2; + return $dividend . ' % ' . $divisor; } /** @@ -1082,11 +1081,9 @@ public function getTrimExpression(string $str, int $mode = TrimMode::UNSPECIFIED /** * {@inheritDoc} */ - public function getConcatExpression() + public function getConcatExpression(string ...$string) : string { - $args = func_get_args(); - - return '(' . implode(' + ', $args) . ')'; + return '(' . implode(' + ', $string) . ')'; } /** @@ -1120,9 +1117,9 @@ public function getSubstringExpression(string $string, string $start, ?string $l /** * {@inheritDoc} */ - public function getLengthExpression($column) + public function getLengthExpression(string $string) : string { - return 'LEN(' . $column . ')'; + return 'LEN(' . $string . ')'; } /** diff --git a/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php b/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php index 7b504533cd2..7f4839a8a21 100644 --- a/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php +++ b/lib/Doctrine/DBAL/Platforms/SqlitePlatform.php @@ -17,7 +17,6 @@ use function array_unique; use function array_values; use function implode; -use function is_numeric; use function sprintf; use function sqrt; use function str_replace; @@ -37,7 +36,7 @@ class SqlitePlatform extends AbstractPlatform /** * {@inheritDoc} */ - public function getRegexpExpression() + public function getRegexpExpression() : string { return 'REGEXP'; } @@ -45,7 +44,7 @@ public function getRegexpExpression() /** * {@inheritDoc} */ - public function getNowExpression($type = 'timestamp') + public function getNowExpression($type = 'timestamp') : string { switch ($type) { case 'time': @@ -122,39 +121,31 @@ public function getLocateExpression(string $string, string $substring, ?string $ /** * {@inheritdoc} */ - protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) + protected function getDateArithmeticIntervalExpression(string $date, string $operator, string $interval, string $unit) : string { switch ($unit) { - case DateIntervalUnit::SECOND: - case DateIntervalUnit::MINUTE: - case DateIntervalUnit::HOUR: - return 'DATETIME(' . $date . ",'" . $operator . $interval . ' ' . $unit . "')"; - - default: - switch ($unit) { - case DateIntervalUnit::WEEK: - $interval *= 7; - $unit = DateIntervalUnit::DAY; - break; - - case DateIntervalUnit::QUARTER: - $interval *= 3; - $unit = DateIntervalUnit::MONTH; - break; - } - - if (! is_numeric($interval)) { - $interval = "' || " . $interval . " || '"; - } + case DateIntervalUnit::WEEK: + $interval = $this->multiplyInterval($interval, 7); + $unit = DateIntervalUnit::DAY; + break; - return 'DATE(' . $date . ",'" . $operator . $interval . ' ' . $unit . "')"; + case DateIntervalUnit::QUARTER: + $interval = $this->multiplyInterval($interval, 3); + $unit = DateIntervalUnit::MONTH; + break; } + + return 'DATETIME(' . $date . ',' . $this->getConcatExpression( + $this->quoteStringLiteral($operator), + $interval, + $this->quoteStringLiteral(' ' . $unit) + ) . ')'; } /** * {@inheritDoc} */ - public function getDateDiffExpression($date1, $date2) + public function getDateDiffExpression(string $date1, string $date2) : string { return sprintf("JULIANDAY(%s, 'start of day') - JULIANDAY(%s, 'start of day')", $date1, $date2); } diff --git a/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php b/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php index a6d3a425621..39be5159b3e 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php @@ -12,6 +12,7 @@ use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver; use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\ParameterType; +use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Platforms\TrimMode; use Doctrine\DBAL\Schema\Table; @@ -577,49 +578,313 @@ public function testTrimExpressionInvalidMode() : void } /** - * @group DDC-1014 + * @dataProvider modeProvider */ - public function testDateArithmetics() : void + public function testDateAddSeconds(callable $buildQuery, callable $bindParams) : void { - $p = $this->connection->getDatabasePlatform(); - $sql = 'SELECT '; - $sql .= $p->getDateAddSecondsExpression('test_datetime', 1) . ' AS add_seconds, '; - $sql .= $p->getDateSubSecondsExpression('test_datetime', 1) . ' AS sub_seconds, '; - $sql .= $p->getDateAddMinutesExpression('test_datetime', 5) . ' AS add_minutes, '; - $sql .= $p->getDateSubMinutesExpression('test_datetime', 5) . ' AS sub_minutes, '; - $sql .= $p->getDateAddHourExpression('test_datetime', 3) . ' AS add_hour, '; - $sql .= $p->getDateSubHourExpression('test_datetime', 3) . ' AS sub_hour, '; - $sql .= $p->getDateAddDaysExpression('test_datetime', 10) . ' AS add_days, '; - $sql .= $p->getDateSubDaysExpression('test_datetime', 10) . ' AS sub_days, '; - $sql .= $p->getDateAddWeeksExpression('test_datetime', 1) . ' AS add_weeks, '; - $sql .= $p->getDateSubWeeksExpression('test_datetime', 1) . ' AS sub_weeks, '; - $sql .= $p->getDateAddMonthExpression('test_datetime', 2) . ' AS add_month, '; - $sql .= $p->getDateSubMonthExpression('test_datetime', 2) . ' AS sub_month, '; - $sql .= $p->getDateAddQuartersExpression('test_datetime', 3) . ' AS add_quarters, '; - $sql .= $p->getDateSubQuartersExpression('test_datetime', 3) . ' AS sub_quarters, '; - $sql .= $p->getDateAddYearsExpression('test_datetime', 6) . ' AS add_years, '; - $sql .= $p->getDateSubYearsExpression('test_datetime', 6) . ' AS sub_years '; - $sql .= 'FROM fetch_table'; + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddSecondsExpression('test_datetime', $interval); + }, + 1, + '2010-01-01 10:10:11' + ); + } - $row = $this->connection->fetchAssoc($sql); - $row = array_change_key_case($row, CASE_LOWER); + /** + * @dataProvider modeProvider + */ + public function testDateSubSeconds(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubSecondsExpression('test_datetime', $interval); + }, + 1, + '2010-01-01 10:10:09' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddMinutes(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddMinutesExpression('test_datetime', $interval); + }, + 5, + '2010-01-01 10:15:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateSubMinutes(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubMinutesExpression('test_datetime', $interval); + }, + 5, + '2010-01-01 10:05:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddHours(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddHourExpression('test_datetime', $interval); + }, + 3, + '2010-01-01 13:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateSubHours(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubHourExpression('test_datetime', $interval); + }, + 3, + '2010-01-01 07:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddDays(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddDaysExpression('test_datetime', $interval); + }, + 10, + '2010-01-11 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateSubDays(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubDaysExpression('test_datetime', $interval); + }, + 10, + '2009-12-22 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddWeeks(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddWeeksExpression('test_datetime', $interval); + }, + 1, + '2010-01-08 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateSubWeeks(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubWeeksExpression('test_datetime', $interval); + }, + 1, + '2009-12-25 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddMonths(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddMonthExpression('test_datetime', $interval); + }, + 2, + '2010-03-01 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateSubMonths(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubMonthExpression('test_datetime', $interval); + }, + 2, + '2009-11-01 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddQuarters(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddQuartersExpression('test_datetime', $interval); + }, + 3, + '2010-10-01 10:10:10' + ); + } - self::assertEquals('2010-01-01 10:10:11', date('Y-m-d H:i:s', strtotime($row['add_seconds'])), 'Adding second should end up on 2010-01-01 10:10:11'); - self::assertEquals('2010-01-01 10:10:09', date('Y-m-d H:i:s', strtotime($row['sub_seconds'])), 'Subtracting second should end up on 2010-01-01 10:10:09'); - self::assertEquals('2010-01-01 10:15:10', date('Y-m-d H:i:s', strtotime($row['add_minutes'])), 'Adding minutes should end up on 2010-01-01 10:15:10'); - self::assertEquals('2010-01-01 10:05:10', date('Y-m-d H:i:s', strtotime($row['sub_minutes'])), 'Subtracting minutes should end up on 2010-01-01 10:05:10'); - self::assertEquals('2010-01-01 13:10', date('Y-m-d H:i', strtotime($row['add_hour'])), 'Adding date should end up on 2010-01-01 13:10'); - self::assertEquals('2010-01-01 07:10', date('Y-m-d H:i', strtotime($row['sub_hour'])), 'Subtracting date should end up on 2010-01-01 07:10'); - self::assertEquals('2010-01-11', date('Y-m-d', strtotime($row['add_days'])), 'Adding date should end up on 2010-01-11'); - self::assertEquals('2009-12-22', date('Y-m-d', strtotime($row['sub_days'])), 'Subtracting date should end up on 2009-12-22'); - self::assertEquals('2010-01-08', date('Y-m-d', strtotime($row['add_weeks'])), 'Adding week should end up on 2010-01-08'); - self::assertEquals('2009-12-25', date('Y-m-d', strtotime($row['sub_weeks'])), 'Subtracting week should end up on 2009-12-25'); - self::assertEquals('2010-03-01', date('Y-m-d', strtotime($row['add_month'])), 'Adding month should end up on 2010-03-01'); - self::assertEquals('2009-11-01', date('Y-m-d', strtotime($row['sub_month'])), 'Subtracting month should end up on 2009-11-01'); - self::assertEquals('2010-10-01', date('Y-m-d', strtotime($row['add_quarters'])), 'Adding quarters should end up on 2010-04-01'); - self::assertEquals('2009-04-01', date('Y-m-d', strtotime($row['sub_quarters'])), 'Subtracting quarters should end up on 2009-10-01'); - self::assertEquals('2016-01-01', date('Y-m-d', strtotime($row['add_years'])), 'Adding years should end up on 2016-01-01'); - self::assertEquals('2004-01-01', date('Y-m-d', strtotime($row['sub_years'])), 'Subtracting years should end up on 2004-01-01'); + /** + * @dataProvider modeProvider + */ + public function testDateSubQuarters(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubQuartersExpression('test_datetime', $interval); + }, + 3, + '2009-04-01 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateAddYears(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateAddYearsExpression('test_datetime', $interval); + }, + 6, + '2016-01-01 10:10:10' + ); + } + + /** + * @dataProvider modeProvider + */ + public function testDateSubYears(callable $buildQuery, callable $bindParams) : void + { + $this->assertDateExpression( + $buildQuery, + $bindParams, + static function (AbstractPlatform $platform, string $interval) : string { + return $platform->getDateSubYearsExpression('test_datetime', $interval); + }, + 6, + '2004-01-01 10:10:10' + ); + } + + /** + * @param callable $buildQuery Builds the portion of the query representing the interval value + * @param callable $bindParams Binds the interval value to the statement + * @param callable $expression Builds the platform-specific interval expression + * @param int $interval Interval value + * @param string $expected Expected value + */ + private function assertDateExpression(callable $buildQuery, callable $bindParams, callable $expression, int $interval, string $expected) : void + { + $connection = $this->connection; + $platform = $connection->getDatabasePlatform(); + + $query = sprintf('SELECT %s FROM fetch_table', $expression($platform, $buildQuery($interval))); + $stmt = $connection->prepare($query); + $bindParams($stmt, $interval); + + $stmt->execute(); + + $date = $stmt->fetchColumn(); + + $this->assertEquals($expected, date('Y-m-d H:i:s', strtotime($date))); + } + + /** + * @return mixed[][] + */ + public static function modeProvider() : array + { + return [ + 'bind' => [ + static function (int $interval) : string { + return '?'; + }, + static function (Statement $stmt, int $interval) : void { + $stmt->bindParam(1, $interval, ParameterType::INTEGER); + }, + ], + 'literal' => [ + static function (int $interval) : string { + return sprintf('%d', $interval); + }, + static function (Statement $stmt, int $interval) : void { + }, + ], + 'expression' => [ + static function (int $interval) : string { + return sprintf('(0 + %d)', $interval); + }, + static function (Statement $stmt, int $interval) : void { + }, + ], + ]; } public function testSqliteDateArithmeticWithDynamicInterval() : void diff --git a/tests/Doctrine/Tests/DBAL/Platforms/DB2PlatformTest.php b/tests/Doctrine/Tests/DBAL/Platforms/DB2PlatformTest.php index d0ba92df563..db2c444d1f5 100644 --- a/tests/Doctrine/Tests/DBAL/Platforms/DB2PlatformTest.php +++ b/tests/Doctrine/Tests/DBAL/Platforms/DB2PlatformTest.php @@ -348,18 +348,18 @@ public function testGeneratesSQLSnippets() : void self::assertEquals("'1987/05/02' + 12 HOUR", $this->platform->getDateAddHourExpression("'1987/05/02'", 12)); self::assertEquals("'1987/05/02' + 2 MINUTE", $this->platform->getDateAddMinutesExpression("'1987/05/02'", 2)); self::assertEquals("'1987/05/02' + 102 MONTH", $this->platform->getDateAddMonthExpression("'1987/05/02'", 102)); - self::assertEquals("'1987/05/02' + 15 MONTH", $this->platform->getDateAddQuartersExpression("'1987/05/02'", 5)); + self::assertEquals("'1987/05/02' + (5 * 3) MONTH", $this->platform->getDateAddQuartersExpression("'1987/05/02'", 5)); self::assertEquals("'1987/05/02' + 1 SECOND", $this->platform->getDateAddSecondsExpression("'1987/05/02'", 1)); - self::assertEquals("'1987/05/02' + 21 DAY", $this->platform->getDateAddWeeksExpression("'1987/05/02'", 3)); + self::assertEquals("'1987/05/02' + (3 * 7) DAY", $this->platform->getDateAddWeeksExpression("'1987/05/02'", 3)); self::assertEquals("'1987/05/02' + 10 YEAR", $this->platform->getDateAddYearsExpression("'1987/05/02'", 10)); self::assertEquals("DAYS('1987/05/02') - DAYS('1987/04/01')", $this->platform->getDateDiffExpression("'1987/05/02'", "'1987/04/01'")); self::assertEquals("'1987/05/02' - 4 DAY", $this->platform->getDateSubDaysExpression("'1987/05/02'", 4)); self::assertEquals("'1987/05/02' - 12 HOUR", $this->platform->getDateSubHourExpression("'1987/05/02'", 12)); self::assertEquals("'1987/05/02' - 2 MINUTE", $this->platform->getDateSubMinutesExpression("'1987/05/02'", 2)); self::assertEquals("'1987/05/02' - 102 MONTH", $this->platform->getDateSubMonthExpression("'1987/05/02'", 102)); - self::assertEquals("'1987/05/02' - 15 MONTH", $this->platform->getDateSubQuartersExpression("'1987/05/02'", 5)); + self::assertEquals("'1987/05/02' - (5 * 3) MONTH", $this->platform->getDateSubQuartersExpression("'1987/05/02'", 5)); self::assertEquals("'1987/05/02' - 1 SECOND", $this->platform->getDateSubSecondsExpression("'1987/05/02'", 1)); - self::assertEquals("'1987/05/02' - 21 DAY", $this->platform->getDateSubWeeksExpression("'1987/05/02'", 3)); + self::assertEquals("'1987/05/02' - (3 * 7) DAY", $this->platform->getDateSubWeeksExpression("'1987/05/02'", 3)); self::assertEquals("'1987/05/02' - 10 YEAR", $this->platform->getDateSubYearsExpression("'1987/05/02'", 10)); self::assertEquals(' WITH RR USE AND KEEP UPDATE LOCKS', $this->platform->getForUpdateSQL()); self::assertEquals('LOCATE(substring_column, string_column)', $this->platform->getLocateExpression('string_column', 'substring_column')); diff --git a/tests/Doctrine/Tests/DBAL/Platforms/SqlitePlatformTest.php b/tests/Doctrine/Tests/DBAL/Platforms/SqlitePlatformTest.php index 2cf891ce97d..24201953d4f 100644 --- a/tests/Doctrine/Tests/DBAL/Platforms/SqlitePlatformTest.php +++ b/tests/Doctrine/Tests/DBAL/Platforms/SqlitePlatformTest.php @@ -791,12 +791,12 @@ public function testQuotesTableNameInListTableForeignKeysSQL() : void public function testDateAddStaticNumberOfDays() : void { - self::assertSame("DATE(rentalBeginsOn,'+12 DAY')", $this->platform->getDateAddDaysExpression('rentalBeginsOn', 12)); + self::assertSame("DATETIME(rentalBeginsOn,'+' || 12 || ' DAY')", $this->platform->getDateAddDaysExpression('rentalBeginsOn', 12)); } public function testDateAddNumberOfDaysFromColumn() : void { - self::assertSame("DATE(rentalBeginsOn,'+' || duration || ' DAY')", $this->platform->getDateAddDaysExpression('rentalBeginsOn', 'duration')); + self::assertSame("DATETIME(rentalBeginsOn,'+' || duration || ' DAY')", $this->platform->getDateAddDaysExpression('rentalBeginsOn', 'duration')); } public function testSupportsColumnCollation() : void