1
0
mirror of synced 2025-02-02 13:31:45 +03:00

Merge pull request #6742 from Legenyes/feature/DDC-2938_Support_all_time_intervals_on_DATE_ADD

Add support second, minute, week, year on DATE_ADD and DATE_SUB

Fixes #5835
This commit is contained in:
Luís Cobucci 2017-10-31 20:46:02 +01:00 committed by GitHub
commit a82f6c5725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 36 deletions

View File

@ -51,7 +51,11 @@ class DateAddFunction extends FunctionNode
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
case 'minute':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMinutesExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
case 'hour': case 'hour':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddHourExpression( return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddHourExpression(
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
@ -62,16 +66,25 @@ class DateAddFunction extends FunctionNode
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
case 'week':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddWeeksExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
case 'month': case 'month':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression( return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression(
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
case 'year':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddYearsExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
default: default:
throw QueryException::semanticalError( throw QueryException::semanticalError(
'DATE_ADD() only supports units of type second, hour, day and month.' 'DATE_ADD() only supports units of type second, minute, hour, day, week, month and year.'
); );
} }
} }

View File

@ -40,6 +40,16 @@ class DateSubFunction extends DateAddFunction
public function getSql(SqlWalker $sqlWalker) public function getSql(SqlWalker $sqlWalker)
{ {
switch (strtolower($this->unit->value)) { switch (strtolower($this->unit->value)) {
case 'second':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubSecondsExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
case 'minute':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMinutesExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
case 'hour': case 'hour':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubHourExpression( return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubHourExpression(
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
@ -50,16 +60,25 @@ class DateSubFunction extends DateAddFunction
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
case 'week':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubWeeksExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
case 'month': case 'month':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression( return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression(
$this->firstDateExpression->dispatch($sqlWalker), $this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker) $this->intervalExpression->dispatch($sqlWalker)
); );
case 'year':
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubYearsExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
default: default:
throw QueryException::semanticalError( throw QueryException::semanticalError(
'DATE_SUB() only supports units of type hour, day and month.' 'DATE_SUB() only supports units of type second, minute, hour, day, week, month and year.'
); );
} }
} }

View File

@ -2,6 +2,7 @@
namespace Doctrine\Tests\ORM\Functional; namespace Doctrine\Tests\ORM\Functional;
use Doctrine\ORM\AbstractQuery;
use Doctrine\Tests\Models\Company\CompanyManager; use Doctrine\Tests\Models\Company\CompanyManager;
use Doctrine\Tests\OrmFunctionalTestCase; use Doctrine\Tests\OrmFunctionalTestCase;
@ -287,51 +288,70 @@ class QueryDqlFunctionTest extends OrmFunctionalTestCase
/** /**
* @group DDC-1014 * @group DDC-1014
* @group DDC-2938
*
* @dataProvider dateAddSubProvider
*/ */
public function testDateAdd() public function testDateAdd(string $unit, int $amount, int $expectedValue, int $delta = 0) : void
{ {
$arg = $this->_em->createQuery("SELECT DATE_ADD(CURRENT_TIMESTAMP(), 10, 'day') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m") $query = sprintf(
->getArrayResult(); 'SELECT CURRENT_TIMESTAMP() as now, DATE_ADD(CURRENT_TIMESTAMP(), %d, \'%s\') AS add FROM %s m',
$amount,
$unit,
CompanyManager::class
);
$this->assertTrue(strtotime($arg[0]['add']) > 0); $result = $this->_em->createQuery($query)
->setMaxResults(1)
->getSingleResult(AbstractQuery::HYDRATE_ARRAY);
$arg = $this->_em->createQuery("SELECT DATE_ADD(CURRENT_TIMESTAMP(), 10, 'month') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m") self::assertArrayHasKey('now', $result);
->getArrayResult(); self::assertArrayHasKey('add', $result);
$this->assertTrue(strtotime($arg[0]['add']) > 0); $diff = strtotime($result['add']) - strtotime($result['now']);
}
public function testDateAddSecond() self::assertEquals($expectedValue, $diff, '', $delta);
{
$dql = "SELECT CURRENT_TIMESTAMP() now, DATE_ADD(CURRENT_TIMESTAMP(), 10, 'second') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m";
$query = $this->_em->createQuery($dql)->setMaxResults(1);
$result = $query->getArrayResult();
$this->assertCount(1, $result);
$this->assertArrayHasKey('now', $result[0]);
$this->assertArrayHasKey('add', $result[0]);
$now = strtotime($result[0]['now']);
$add = strtotime($result[0]['add']);
$diff = $add - $now;
$this->assertSQLEquals(10, $diff);
} }
/** /**
* @group DDC-1014 * @group DDC-1014
* @group DDC-2938
*
* @dataProvider dateAddSubProvider
*/ */
public function testDateSub() public function testDateSub(string $unit, int $amount, int $expectedValue, int $delta = 0) : void
{ {
$arg = $this->_em->createQuery("SELECT DATE_SUB(CURRENT_TIMESTAMP(), 10, 'day') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m") $query = sprintf(
->getArrayResult(); 'SELECT CURRENT_TIMESTAMP() as now, DATE_SUB(CURRENT_TIMESTAMP(), %d, \'%s\') AS sub FROM %s m',
$amount,
$unit,
CompanyManager::class
);
$this->assertTrue(strtotime($arg[0]['add']) > 0); $result = $this->_em->createQuery($query)
->setMaxResults(1)
->getSingleResult(AbstractQuery::HYDRATE_ARRAY);
$arg = $this->_em->createQuery("SELECT DATE_SUB(CURRENT_TIMESTAMP(), 10, 'month') AS add FROM Doctrine\Tests\Models\Company\CompanyManager m") self::assertArrayHasKey('now', $result);
->getArrayResult(); self::assertArrayHasKey('sub', $result);
$this->assertTrue(strtotime($arg[0]['add']) > 0); $diff = strtotime($result['now']) - strtotime($result['sub']);
self::assertEquals($expectedValue, $diff, '', $delta);
}
public function dateAddSubProvider() : array
{
$secondsInDay = 86400;
return [
'year' => ['year', 1, 365 * $secondsInDay, 3 * $secondsInDay],
'month' => ['month', 1, 30 * $secondsInDay, 2 * $secondsInDay],
'week' => ['week', 1, 7 * $secondsInDay, $secondsInDay],
'hour' => ['hour', 1, 3600],
'minute' => ['minute', 1, 60],
'second' => ['second', 10, 10],
];
} }
/** /**