Commit ada2c5c5 authored by jwage's avatar jwage

[2.0] Work on datetime dbal type and date portability

parent f2812766
...@@ -1236,6 +1236,28 @@ abstract class AbstractPlatform ...@@ -1236,6 +1236,28 @@ abstract class AbstractPlatform
return 'SET NAMES ' . $this->quote($charset); return 'SET NAMES ' . $this->quote($charset);
} }
/**
* Gets the SQL specific for the platform to get the current date.
*
* @return string
*/
public function getCurrentDateSql()
{
return 'CURRENT_DATE';
}
/**
* Gets the SQL specific for the platform to get the current time.
*
* @return string
*/
public function getCurrentTimeSql()
{
return 'CURRENT_TIME';
}
/** /**
* Get sql for transaction isolation level Connection constant * Get sql for transaction isolation level Connection constant
* *
...@@ -1360,6 +1382,18 @@ abstract class AbstractPlatform ...@@ -1360,6 +1382,18 @@ abstract class AbstractPlatform
throw DoctrineException::updateMe('Get charset field declaration not supported by this platform.'); throw DoctrineException::updateMe('Get charset field declaration not supported by this platform.');
} }
/**
* Obtain DBMS specific SQL to be used to create datetime fields in
* statements like CREATE TABLE
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTimeTypeDeclarationSql(array $fieldDeclaration)
{
throw DoctrineException::updateMe('Get datetime type declaration not supported by this platform.');
}
/** /**
* Gets the default transaction isolation level of the platform. * Gets the default transaction isolation level of the platform.
* *
...@@ -1461,6 +1495,15 @@ abstract class AbstractPlatform ...@@ -1461,6 +1495,15 @@ abstract class AbstractPlatform
return ""; return "";
} }
/**
* TODO: We need to get the specific format for each dbms and override this
* function for each platform
*/
public function getDateTimeFormatString()
{
return 'Y-m-d H:i:s';
}
/** /**
* Gets the SQL snippet used to declare a VARCHAR column type. * Gets the SQL snippet used to declare a VARCHAR column type.
* *
......
<?php
namespace Doctrine\DBAL\Platforms;
class MockPlatform extends AbstractPlatform
{
public function getNativeDeclaration(array $field) {}
public function getPortableDeclaration(array $field) {}
/**
* Get the platform name for this instance
*
* @return string
*/
public function getName()
{
return 'mock';
}
}
\ No newline at end of file
...@@ -400,6 +400,14 @@ class MsSqlPlatform extends AbstractPlatform ...@@ -400,6 +400,14 @@ class MsSqlPlatform extends AbstractPlatform
return 'CHARACTER SET ' . $charset; return 'CHARACTER SET ' . $charset;
} }
/**
* @override
*/
public function getDateTimeTypeDeclarationSql(array $fieldDeclaration)
{
return 'CHAR(' . strlen('YYYY-MM-DD HH:MM:SS') . ')';
}
/** /**
* Get the platform name for this instance * Get the platform name for this instance
* *
......
...@@ -258,6 +258,14 @@ class MySqlPlatform extends AbstractPlatform ...@@ -258,6 +258,14 @@ class MySqlPlatform extends AbstractPlatform
return 'CHARACTER SET ' . $charset; return 'CHARACTER SET ' . $charset;
} }
/**
* @override
*/
public function getDateTimeTypeDeclarationSql(array $fieldDeclaration)
{
return 'DATETIME';
}
/** /**
* Obtain DBMS specific SQL code portion needed to set the COLLATION * Obtain DBMS specific SQL code portion needed to set the COLLATION
* of a field declaration to be used in statements like CREATE TABLE. * of a field declaration to be used in statements like CREATE TABLE.
......
...@@ -176,6 +176,14 @@ class OraclePlatform extends AbstractPlatform ...@@ -176,6 +176,14 @@ class OraclePlatform extends AbstractPlatform
return 'NUMBER(5)'; return 'NUMBER(5)';
} }
/**
* @override
*/
public function getDateTimeTypeDeclarationSql(array $fieldDeclaration)
{
return 'DATE';
}
/** /**
* @override * @override
*/ */
......
...@@ -690,6 +690,14 @@ class PostgreSqlPlatform extends AbstractPlatform ...@@ -690,6 +690,14 @@ class PostgreSqlPlatform extends AbstractPlatform
return 'SMALLINT'; return 'SMALLINT';
} }
/**
* @override
*/
public function getDateTimeTypeDeclarationSql(array $fieldDeclaration)
{
return 'TIMESTAMP without time zone';
}
/** /**
* @override * @override
*/ */
......
...@@ -229,13 +229,19 @@ class SqlitePlatform extends AbstractPlatform ...@@ -229,13 +229,19 @@ class SqlitePlatform extends AbstractPlatform
return $this->_getCommonIntegerTypeDeclarationSql($field); return $this->_getCommonIntegerTypeDeclarationSql($field);
} }
/** @override */
public function getDateTimeTypeDeclarationSql(array $fieldDeclaration)
{
return 'DATETIME';
}
/** @override */ /** @override */
protected function _getCommonIntegerTypeDeclarationSql(array $columnDef) protected function _getCommonIntegerTypeDeclarationSql(array $columnDef)
{ {
$autoinc = ! empty($columnDef['autoincrement']) ? ' AUTOINCREMENT' : ''; $autoinc = ! empty($columnDef['autoincrement']) ? ' AUTOINCREMENT' : '';
$pk = ! empty($columnDef['primary']) && ! empty($autoinc) ? ' PRIMARY KEY' : ''; $pk = ! empty($columnDef['primary']) && ! empty($autoinc) ? ' PRIMARY KEY' : '';
return "INTEGER" . $pk . $autoinc; return 'INTEGER' . $pk . $autoinc;
} }
/** /**
......
...@@ -24,7 +24,7 @@ class BooleanType extends Type ...@@ -24,7 +24,7 @@ class BooleanType extends Type
* *
* @override * @override
*/ */
public function convertToPHPValue($value) public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
return (bool) $value; return (bool) $value;
} }
......
...@@ -9,6 +9,11 @@ namespace Doctrine\DBAL\Types; ...@@ -9,6 +9,11 @@ namespace Doctrine\DBAL\Types;
*/ */
class DateTimeType extends Type class DateTimeType extends Type
{ {
public function getName()
{
return 'DateTime';
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -24,8 +29,7 @@ class DateTimeType extends Type ...@@ -24,8 +29,7 @@ class DateTimeType extends Type
*/ */
public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
//TODO: howto? dbms specific? delegate to platform? return $value->format($platform->getDateTimeFormatString());
return $value;
} }
/** /**
...@@ -33,8 +37,8 @@ class DateTimeType extends Type ...@@ -33,8 +37,8 @@ class DateTimeType extends Type
* *
* @override * @override
*/ */
public function convertToObjectValue($value) public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
return new \DateTime($value); return \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value);
} }
} }
\ No newline at end of file
...@@ -19,7 +19,7 @@ class DecimalType extends Type ...@@ -19,7 +19,7 @@ class DecimalType extends Type
return $platform->getDecimalTypeDeclarationSql($fieldDeclaration); return $platform->getDecimalTypeDeclarationSql($fieldDeclaration);
} }
public function convertToPHPValue($value) public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
return (double) $value; return (double) $value;
} }
......
...@@ -18,7 +18,7 @@ class IntegerType extends Type ...@@ -18,7 +18,7 @@ class IntegerType extends Type
return $platform->getIntegerTypeDeclarationSql($fieldDeclaration); return $platform->getIntegerTypeDeclarationSql($fieldDeclaration);
} }
public function convertToPHPValue($value) public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
return (int) $value; return (int) $value;
} }
......
...@@ -19,7 +19,7 @@ class SmallIntType ...@@ -19,7 +19,7 @@ class SmallIntType
return $platform->getSmallIntTypeDeclarationSql($fieldDeclaration); return $platform->getSmallIntTypeDeclarationSql($fieldDeclaration);
} }
public function convertToPHPValue($value) public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
return (int) $value; return (int) $value;
} }
......
...@@ -45,7 +45,7 @@ abstract class Type ...@@ -45,7 +45,7 @@ abstract class Type
return $value; return $value;
} }
public function convertToPHPValue($value) public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{ {
return $value; return $value;
} }
......
...@@ -61,6 +61,7 @@ abstract class AbstractHydrator ...@@ -61,6 +61,7 @@ abstract class AbstractHydrator
public function __construct(\Doctrine\ORM\EntityManager $em) public function __construct(\Doctrine\ORM\EntityManager $em)
{ {
$this->_em = $em; $this->_em = $em;
$this->_platform = $em->getConnection()->getDatabasePlatform();
$this->_uow = $em->getUnitOfWork(); $this->_uow = $em->getUnitOfWork();
} }
...@@ -213,7 +214,7 @@ abstract class AbstractHydrator ...@@ -213,7 +214,7 @@ abstract class AbstractHydrator
$id[$dqlAlias] .= '|' . $value; $id[$dqlAlias] .= '|' . $value;
} }
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $cache[$key]['type']->convertToPHPValue($value); $rowData[$dqlAlias][$cache[$key]['fieldName']] = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) { if ( ! isset($nonemptyComponents[$dqlAlias]) && $value !== null) {
$nonemptyComponents[$dqlAlias] = true; $nonemptyComponents[$dqlAlias] = true;
...@@ -221,7 +222,7 @@ abstract class AbstractHydrator ...@@ -221,7 +222,7 @@ abstract class AbstractHydrator
/* TODO: Consider this instead of the above 4 lines. */ /* TODO: Consider this instead of the above 4 lines. */
/*if ($value !== null) { /*if ($value !== null) {
$rowData[$dqlAlias][$fieldName] = $cache[$key]['type']->convertToPHPValue($value); $rowData[$dqlAlias][$fieldName] = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
}*/ }*/
} }
...@@ -268,7 +269,7 @@ abstract class AbstractHydrator ...@@ -268,7 +269,7 @@ abstract class AbstractHydrator
$rowData[/*$dqlAlias . '_' . */$fieldName] = $value; $rowData[/*$dqlAlias . '_' . */$fieldName] = $value;
} else { } else {
$dqlAlias = $cache[$key]['dqlAlias']; $dqlAlias = $cache[$key]['dqlAlias'];
$rowData[$dqlAlias . '_' . $fieldName] = $cache[$key]['type']->convertToPHPValue($value); $rowData[$dqlAlias . '_' . $fieldName] = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
} }
} }
......
...@@ -90,6 +90,7 @@ class StandardEntityPersister ...@@ -90,6 +90,7 @@ class StandardEntityPersister
public function __construct(EntityManager $em, ClassMetadata $class) public function __construct(EntityManager $em, ClassMetadata $class)
{ {
$this->_em = $em; $this->_em = $em;
$this->_platform = $em->getConnection()->getDatabasePlatform();
$this->_evm = $em->getEventManager(); $this->_evm = $em->getEventManager();
$this->_entityName = $class->name; $this->_entityName = $class->name;
$this->_conn = $em->getConnection(); $this->_conn = $em->getConnection();
...@@ -343,7 +344,7 @@ class StandardEntityPersister ...@@ -343,7 +344,7 @@ class StandardEntityPersister
foreach ($stmt->fetch(Connection::FETCH_ASSOC) as $column => $value) { foreach ($stmt->fetch(Connection::FETCH_ASSOC) as $column => $value) {
$fieldName = $this->_class->fieldNames[$column]; $fieldName = $this->_class->fieldNames[$column];
$data[$fieldName] = Type::getType($this->_class->getTypeOfField($fieldName)) $data[$fieldName] = Type::getType($this->_class->getTypeOfField($fieldName))
->convertToPHPValue($value); ->convertToPHPValue($value, $this->_platform);
} }
$stmt->closeCursor(); $stmt->closeCursor();
......
<?php <?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
namespace Doctrine\ORM\Query\AST\Functions; namespace Doctrine\ORM\Query\AST\Functions;
...@@ -18,8 +14,7 @@ class CurrentDateFunction extends FunctionNode ...@@ -18,8 +14,7 @@ class CurrentDateFunction extends FunctionNode
*/ */
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{ {
//TODO: Use platform to get SQL return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentDateSql();
return 'CURRENT_DATE';
} }
/** /**
...@@ -29,6 +24,7 @@ class CurrentDateFunction extends FunctionNode ...@@ -29,6 +24,7 @@ class CurrentDateFunction extends FunctionNode
{ {
$lexer = $parser->getLexer(); $lexer = $parser->getLexer();
$parser->match($lexer->lookahead['value']); $parser->match($lexer->lookahead['value']);
$parser->match('(');
$parser->match(')');
} }
} }
\ No newline at end of file
...@@ -18,8 +18,7 @@ class CurrentTimeFunction extends FunctionNode ...@@ -18,8 +18,7 @@ class CurrentTimeFunction extends FunctionNode
*/ */
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{ {
//TODO: Use platform to get SQL return $sqlWalker->getConnection()->getDatabasePlatform()->getCurrentTimeSql();
return 'CURRENT_TIME';
} }
/** /**
......
...@@ -28,6 +28,8 @@ class AllTests ...@@ -28,6 +28,8 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\DBAL\Platforms\PostgreSqlPlatformTest'); $suite->addTestSuite('Doctrine\Tests\DBAL\Platforms\PostgreSqlPlatformTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Platforms\MsSqlPlatformTest'); $suite->addTestSuite('Doctrine\Tests\DBAL\Platforms\MsSqlPlatformTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Types\DateTimeTest');
$suite->addTest(Functional\AllTests::suite()); $suite->addTest(Functional\AllTests::suite());
return $suite; return $suite;
......
<?php
namespace Doctrine\Tests\DBAL\Mocks;
use Doctrine\DBAL\Platforms;
class MockPlatform extends \Doctrine\DBAL\Platforms\AbstractPlatform
{
public function getIntegerTypeDeclarationSql(array $columnDef) {}
public function getBigIntTypeDeclarationSql(array $columnDef) {}
public function getSmallIntTypeDeclarationSql(array $columnDef) {}
public function _getCommonIntegerTypeDeclarationSql(array $columnDef) {}
public function getVarcharTypeDeclarationSql(array $field) {}
public function getName()
{
return 'mock';
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\DBAL\Types;
use Doctrine\DBAL\Types\Type;
use Doctrine\Tests\DBAL\Mocks;
require_once __DIR__ . '/../../TestInit.php';
class DateTimeTest extends \Doctrine\Tests\DbalTestCase
{
protected
$_platform,
$_type;
protected function setUp()
{
$this->_platform = new \Doctrine\Tests\DBAL\Mocks\MockPlatform();
$this->_type = Type::getType('datetime');
}
public function testDateTimeConvertsToDatabaseValue()
{
$this->assertTrue(
is_string($this->_type->convertToDatabaseValue(new \DateTime(), $this->_platform))
);
}
public function testDateTimeConvertsToPHPValue()
{
// Birthday of jwage and also birthday of Doctrine. Send him a present ;)
$this->assertTrue(
$this->_type->convertToPHPValue('1985-09-01 00:00:00', $this->_platform)
instanceof \DateTime
);
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\Models\Generic;
/**
* @Entity
* @Table(name="date_time_model")
*/
class DateTimeModel
{
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @Column(type="datetime")
*/
public $datetime;
}
\ No newline at end of file
...@@ -281,6 +281,12 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -281,6 +281,12 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
); );
} }
public function testCurrentDateFunction()
{
$q = $this->_em->createQuery('SELECT d.id FROM Doctrine\Tests\Models\Generic\DateTimeModel d WHERE d.datetime > current_date()');
$this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.datetime > CURRENT_DATE', $q->getSql());
}
/*public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition() /*public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
......
...@@ -44,7 +44,10 @@ class OrmFunctionalTestCase extends OrmTestCase ...@@ -44,7 +44,10 @@ class OrmFunctionalTestCase extends OrmTestCase
'Doctrine\Tests\Models\Company\CompanyEmployee', 'Doctrine\Tests\Models\Company\CompanyEmployee',
'Doctrine\Tests\Models\Company\CompanyManager' 'Doctrine\Tests\Models\Company\CompanyManager'
), ),
'ecommerce' => array() 'ecommerce' => array(),
'generic' => array(
'Doctrine\Tests\Models\Generic\DateTimeModel'
)
); );
protected function useModelSet($setName) protected function useModelSet($setName)
...@@ -72,7 +75,9 @@ class OrmFunctionalTestCase extends OrmTestCase ...@@ -72,7 +75,9 @@ class OrmFunctionalTestCase extends OrmTestCase
$conn->exec('DELETE FROM company_employees'); $conn->exec('DELETE FROM company_employees');
$conn->exec('DELETE FROM company_persons'); $conn->exec('DELETE FROM company_persons');
} }
if (isset($this->_usedModelSets['generic'])) {
$conn->exec('DELETE FROM date_time_model');
}
$this->_em->clear(); $this->_em->clear();
} }
......
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