Skip to content

Commit

Permalink
Merge pull request #1 from orocrm/ticket/BAP-5305_timestampdiff
Browse files Browse the repository at this point in the history
BAP-5305: Add TIMESTAMPDIFF function
  • Loading branch information
x86demon committed Sep 18, 2014
2 parents 766b09c + 924a478 commit 50d1114
Show file tree
Hide file tree
Showing 43 changed files with 560 additions and 81 deletions.
38 changes: 20 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Available functions:
* `DATE(expr)` - Extract the date part of a date or datetime expression
* `TIME(expr)` - Extract the time portion of the expression passed
* `TIMESTAMP(expr)` - Convert expression to TIMESTAMP
* `TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2)` - Returns *datetime_expr2**datetime_expr1*, where *datetime_expr1* and *datetime_expr2* are date or datetime expressions. The *unit* should be one of the following values: *MICROSECOND* (microseconds), *SECOND*, *MINUTE*, *HOUR*, *DAY*, *WEEK*, *MONTH*, *QUARTER*, or *YEAR*.
* `CONVERT_TZ(expr, from_tz, to_tz)` - Converts a datetime value expr from the time zone given by from_tz to the time zone given by to_tz and returns the resulting datetime value
* `DAY(expr)` - Return the day of the month (0-31)
* `DAYOFWEEK(expr)` - Returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday). These index values correspond to the ODBC standard.
Expand Down Expand Up @@ -87,26 +88,27 @@ doctrine:
orm:
dql:
datetime_functions:
date: Oro\ORM\Query\AST\Functions\SimpleFunction
time: Oro\ORM\Query\AST\Functions\SimpleFunction
timestamp: Oro\ORM\Query\AST\Functions\SimpleFunction
convert_tz: Oro\ORM\Query\AST\Functions\DateTime\ConvertTz
date: Oro\ORM\Query\AST\Functions\SimpleFunction
time: Oro\ORM\Query\AST\Functions\SimpleFunction
timestamp: Oro\ORM\Query\AST\Functions\SimpleFunction
convert_tz: Oro\ORM\Query\AST\Functions\DateTime\ConvertTz
numeric_functions:
weekday: Oro\ORM\Query\AST\Functions\SimpleFunction
dayofyear: Oro\ORM\Query\AST\Functions\SimpleFunction
dayofweek: Oro\ORM\Query\AST\Functions\SimpleFunction
week: Oro\ORM\Query\AST\Functions\SimpleFunction
day: Oro\ORM\Query\AST\Functions\SimpleFunction
hour: Oro\ORM\Query\AST\Functions\SimpleFunction
minute: Oro\ORM\Query\AST\Functions\SimpleFunction
month: Oro\ORM\Query\AST\Functions\SimpleFunction
quarter: Oro\ORM\Query\AST\Functions\SimpleFunction
second: Oro\ORM\Query\AST\Functions\SimpleFunction
year: Oro\ORM\Query\AST\Functions\SimpleFunction
sign: Oro\ORM\Query\AST\Functions\Numeric\Sign
pow: Oro\ORM\Query\AST\Functions\Numeric\Pow
timestampdiff: Oro\ORM\Query\AST\Functions\Numeric\TimestampDiff
dayofyear: Oro\ORM\Query\AST\Functions\SimpleFunction
dayofweek: Oro\ORM\Query\AST\Functions\SimpleFunction
week: Oro\ORM\Query\AST\Functions\SimpleFunction
day: Oro\ORM\Query\AST\Functions\SimpleFunction
hour: Oro\ORM\Query\AST\Functions\SimpleFunction
minute: Oro\ORM\Query\AST\Functions\SimpleFunction
month: Oro\ORM\Query\AST\Functions\SimpleFunction
quarter: Oro\ORM\Query\AST\Functions\SimpleFunction
second: Oro\ORM\Query\AST\Functions\SimpleFunction
year: Oro\ORM\Query\AST\Functions\SimpleFunction
sign: Oro\ORM\Query\AST\Functions\Numeric\Sign
pow: Oro\ORM\Query\AST\Functions\Numeric\Pow
string_functions:
group_concat: Oro\ORM\Query\AST\Functions\String\GroupConcat
group_concat: Oro\ORM\Query\AST\Functions\String\GroupConcat
cast: Oro\ORM\Query\AST\Functions\Cast
```
Extendability and Database Support
Expand Down
71 changes: 71 additions & 0 deletions src/Oro/ORM/Query/AST/Functions/Numeric/TimestampDiff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace Oro\ORM\Query\AST\Functions\Numeric;

use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\Lexer;
use Oro\ORM\Query\AST\Functions\AbstractPlatformAwareFunctionNode;

class TimestampDiff extends AbstractPlatformAwareFunctionNode
{
const UNIT_KEY = 'unit';
const VAL1_KEY = 'val1';
const VAL2_KEY = 'val2';

/**
* List of supported units.
*
* @var array
*/
protected $supportedUnits = array(
'MICROSECOND',
'SECOND',
'MINUTE',
'HOUR',
'DAY',
'WEEK',
'MONTH',
'QUARTER',
'YEAR'
);

/**
* {@inheritdoc}
*/
public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$parser->match(Lexer::T_IDENTIFIER);

$lexer = $parser->getLexer();
$unit = strtoupper(trim($lexer->token['value']));
if (!$this->checkUnit($unit)) {
$parser->syntaxError(
sprintf(
'Unit is not valid for TIMESTAMPDIFF function. Supported units are: "%s"',
implode(', ', $this->supportedUnits)
),
$lexer->token
);
}

$this->parameters[self::UNIT_KEY] = $unit;
$parser->match(Lexer::T_COMMA);
$this->parameters[self::VAL1_KEY] = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$this->parameters[self::VAL2_KEY] = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}

/**
* Check that unit is supported.
*
* @param string $unit
* @return bool
*/
protected function checkUnit($unit)
{
return in_array($unit, $this->supportedUnits);
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Cast.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ public function getSql(SqlWalker $sqlWalker)
$type = 'unsigned';
}

return 'CAST(' . $value->dispatch($sqlWalker) . ' AS ' . $type . ')';
return 'CAST(' . $this->getExpressionValue($value, $sqlWalker) . ' AS ' . $type . ')';
}
}
6 changes: 3 additions & 3 deletions src/Oro/ORM/Query/AST/Platform/Functions/Mysql/ConvertTz.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ public function getSql(SqlWalker $sqlWalker)
$toTz = $this->parameters[BaseFunction::TO_TZ_KEY];

return 'CONVERT_TZ('
. $value->dispatch($sqlWalker)
. $this->getExpressionValue($value, $sqlWalker)
. ', '
. $fromTz->dispatch($sqlWalker)
. $this->getExpressionValue($fromTz, $sqlWalker)
. ', '
. $toTz->dispatch($sqlWalker)
. $this->getExpressionValue($toTz, $sqlWalker)
. ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Date.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'DATE(' . $expression->dispatch($sqlWalker) . ')';
return 'DATE(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Day.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'DAY(' . $expression->dispatch($sqlWalker) . ')';
return 'DAY(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'DAYOFWEEK(' . $expression->dispatch($sqlWalker) . ')';
return 'DAYOFWEEK(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'DAYOFYEAR(' . $expression->dispatch($sqlWalker) . ')';
return 'DAYOFYEAR(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Hour.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'HOUR(' . $expression->dispatch($sqlWalker) . ')';
return 'HOUR(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Minute.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'MINUTE(' . $expression->dispatch($sqlWalker) . ')';
return 'MINUTE(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Month.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'MONTH(' . $expression->dispatch($sqlWalker) . ')';
return 'MONTH(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
4 changes: 2 additions & 2 deletions src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Pow.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public function getSql(SqlWalker $sqlWalker)
$power = $this->parameters[Base::POWER_KEY];

return 'POW('
. $value->dispatch($sqlWalker)
. $this->getExpressionValue($value, $sqlWalker)
. ', '
. $power->dispatch($sqlWalker)
. $this->getExpressionValue($power, $sqlWalker)
. ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Quarter.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'QUARTER(' . $expression->dispatch($sqlWalker) . ')';
return 'QUARTER(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Second.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'SECOND(' . $expression->dispatch($sqlWalker) . ')';
return 'SECOND(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Sign.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'SIGN(' . $expression->dispatch($sqlWalker) . ')';
return 'SIGN(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Time.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'TIME(' . $expression->dispatch($sqlWalker) . ')';
return 'TIME(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'TIMESTAMP(' . $expression->dispatch($sqlWalker) . ')';
return 'TIMESTAMP(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
32 changes: 32 additions & 0 deletions src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Timestampdiff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Oro\ORM\Query\AST\Platform\Functions\Mysql;

use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\SqlWalker;
use Oro\ORM\Query\AST\Functions\Numeric\TimestampDiff as BaseFunction;
use Oro\ORM\Query\AST\Platform\Functions\PlatformFunctionNode;

class Timestampdiff extends PlatformFunctionNode
{
/**
* {@inheritdoc}
*/
public function getSql(SqlWalker $sqlWalker)
{
/** @var string $unit */
$unit = $this->parameters[BaseFunction::UNIT_KEY];
/** @var Node $val1 */
$val1 = $this->parameters[BaseFunction::VAL1_KEY];
/** @var Node $val2 */
$val2 = $this->parameters[BaseFunction::VAL2_KEY];

return 'TIMESTAMPDIFF('
. $unit
. ', '
. $this->getExpressionValue($val1, $sqlWalker)
. ', '
. $this->getExpressionValue($val2, $sqlWalker)
. ')';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Week.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'WEEK(' . $expression->dispatch($sqlWalker) . ', 3)';
return 'WEEK(' . $this->getExpressionValue($expression, $sqlWalker) . ', 3)';
}
}
2 changes: 1 addition & 1 deletion src/Oro/ORM/Query/AST/Platform/Functions/Mysql/Year.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'YEAR(' . $expression->dispatch($sqlWalker) . ')';
return 'YEAR(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
17 changes: 17 additions & 0 deletions src/Oro/ORM/Query/AST/Platform/Functions/PlatformFunctionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Oro\ORM\Query\AST\Platform\Functions;

use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\SqlWalker;

abstract class PlatformFunctionNode
Expand All @@ -25,4 +26,20 @@ public function __construct(array $parameters)
* @return string
*/
abstract public function getSql(SqlWalker $sqlWalker);

/**
* Get expression value string.
*
* @param string|Node $expression
* @param SqlWalker $sqlWalker
* @return string
*/
protected function getExpressionValue($expression, SqlWalker $sqlWalker)
{
if ($expression instanceof Node) {
$expression = $expression->dispatch($sqlWalker);
}

return $expression;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Oro\ORM\Query\AST\Platform\Functions\Postgresql;

use Doctrine\ORM\Query\AST\Node;
use Doctrine\ORM\Query\SqlWalker;
use Oro\ORM\Query\AST\Functions\SimpleFunction;
use Oro\ORM\Query\AST\Platform\Functions\PlatformFunctionNode;

abstract class AbstractTimestampAwarePlatformFunctionNode extends PlatformFunctionNode
{
/**
* Get timestamp value for given expression.
*
* @param Node|string $expression
* @param SqlWalker $sqlWalker
* @return string
*/
protected function getTimestampValue($expression, SqlWalker $sqlWalker)
{
$value = $this->getExpressionValue($expression, $sqlWalker);
$value = trim(trim($value), '\'"');
if (is_numeric(substr($value, 0, 1))) {
$timestampFunction = new Timestamp(array(SimpleFunction::PARAMETER_KEY => "'$value'"));
$value = $timestampFunction->getSql($sqlWalker);
}

return $value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ public function getSql(SqlWalker $sqlWalker)
return $timestampFunction->getSql($sqlWalker);
}

return 'CAST(' . $value->dispatch($sqlWalker) . ' AS ' . $type . ')';
return 'CAST(' . $this->getExpressionValue($value, $sqlWalker) . ' AS ' . $type . ')';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public function getSql(SqlWalker $sqlWalker)
$toTz = $this->parameters[BaseFunction::TO_TZ_KEY];

return '"timestamp"('
. $value->dispatch($sqlWalker)
. $this->getExpressionValue($value, $sqlWalker)
. ')'
. ' AT TIME ZONE ' . $toTz->dispatch($sqlWalker)
. ' AT TIME ZONE ' . $fromTz->dispatch($sqlWalker);
. ' AT TIME ZONE ' . $this->getExpressionValue($toTz, $sqlWalker)
. ' AT TIME ZONE ' . $this->getExpressionValue($fromTz, $sqlWalker);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public function getSql(SqlWalker $sqlWalker)
{
/** @var Node $expression */
$expression = $this->parameters[SimpleFunction::PARAMETER_KEY];
return 'DATE(' . $expression->dispatch($sqlWalker) . ')';
return 'DATE(' . $this->getExpressionValue($expression, $sqlWalker) . ')';
}
}
Loading

0 comments on commit 50d1114

Please sign in to comment.