Commit 05d5fe49 authored by jwage's avatar jwage

[2.0] Finishing optimistic locking with timestamp support

parent 25be43c3
...@@ -1742,6 +1742,29 @@ final class ClassMetadata ...@@ -1742,6 +1742,29 @@ final class ClassMetadata
$this->sequenceGeneratorDefinition = $definition; $this->sequenceGeneratorDefinition = $definition;
} }
/**
* Sets the version field mapping used for versioning. Sets the default
* value to use depending on the column type
*
* @param array $mapping The version field mapping array
* @return void
*/
public function setVersionMapping(array &$mapping)
{
$this->isVersioned = true;
$this->versionField = $mapping['fieldName'];
if ( ! isset($mapping['default'])) {
if ($mapping['type'] == 'integer') {
$mapping['default'] = 1;
} else if ($mapping['type'] == 'datetime') {
$mapping['default'] = 'CURRENT_TIMESTAMP';
} else {
throw DoctrineException::unsupportedOptimisticLockingType($mapping['type']);
}
}
}
/** /**
* Checks whether this class is versioned for optimistic locking. * Checks whether this class is versioned for optimistic locking.
* *
......
...@@ -179,15 +179,7 @@ class AnnotationDriver implements Driver ...@@ -179,15 +179,7 @@ class AnnotationDriver implements Driver
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy)); $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy));
} }
if ($versionAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) { if ($versionAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) {
$metadata->setVersioned(true); $metadata->setVersionMapping($mapping);
$metadata->setVersionField($mapping['fieldName']);
if ( ! isset($mapping['default'])) {
// TODO: When we have timestamp optimistic locking
// we'll have to figure out a better way to do this?
// Can we set the default value to be NOW() ?
$mapping['default'] = 1;
}
} }
$metadata->mapField($mapping); $metadata->mapField($mapping);
......
...@@ -90,6 +90,9 @@ class XmlDriver extends AbstractFileDriver ...@@ -90,6 +90,9 @@ class XmlDriver extends AbstractFileDriver
if (isset($fieldMapping['scale'])) { if (isset($fieldMapping['scale'])) {
$mapping['scale'] = (int)$fieldMapping['scale']; $mapping['scale'] = (int)$fieldMapping['scale'];
} }
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
$metadata->setVersionMapping($mapping);
}
$metadata->mapField($mapping); $metadata->mapField($mapping);
} }
} }
......
...@@ -70,6 +70,9 @@ class YamlDriver extends AbstractFileDriver ...@@ -70,6 +70,9 @@ class YamlDriver extends AbstractFileDriver
if (isset($fieldMapping['length'])) { if (isset($fieldMapping['length'])) {
$mapping['length'] = $fieldMapping['length']; $mapping['length'] = $fieldMapping['length'];
} }
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
$metadata->setVersionMapping($mapping);
}
$metadata->mapField($mapping); $metadata->mapField($mapping);
} }
} }
......
...@@ -233,9 +233,16 @@ class StandardEntityPersister ...@@ -233,9 +233,16 @@ class StandardEntityPersister
if ($isVersioned = $this->_class->isVersioned) { if ($isVersioned = $this->_class->isVersioned) {
$versionField = $this->_class->versionField; $versionField = $this->_class->versionField;
$where[$this->_class->fieldNames[$versionField]] = $entity->version; $versionFieldType = $this->_class->getTypeOfField($versionField);
$where[$this->_class->fieldNames[$versionField]] = Type::getType(
$this->_class->fieldMappings[$versionField]['type']
)->convertToDatabaseValue($entity->version, $this->_platform);
$versionFieldColumnName = $this->_class->getQuotedColumnName($versionField, $this->_platform); $versionFieldColumnName = $this->_class->getQuotedColumnName($versionField, $this->_platform);
$set[] = $versionFieldColumnName . ' = ' . $versionFieldColumnName . ' + 1'; if ($versionFieldType == 'integer') {
$set[] = $versionFieldColumnName . ' = ' . $versionFieldColumnName . ' + 1';
} else if ($versionFieldType == 'datetime') {
$set[] = $versionFieldColumnName . ' = CURRENT_TIMESTAMP';
}
} }
$params = array_merge(array_values($data), array_values($where)); $params = array_merge(array_values($data), array_values($where));
......
...@@ -24,7 +24,8 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -24,7 +24,8 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
$this->_schemaTool->createSchema(array( $this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedParent'), $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedParent'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedChild'), $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticJoinedChild'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticStandard') $this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticStandard'),
$this->_em->getClassMetadata('Doctrine\Tests\ORM\Functional\Locking\OptimisticTimestamp')
)); ));
} catch (\Exception $e) { } catch (\Exception $e) {
// Swallow all exceptions. We do not test the schema tool here. // Swallow all exceptions. We do not test the schema tool here.
...@@ -119,6 +120,33 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -119,6 +120,33 @@ class OptimisticTest extends \Doctrine\Tests\OrmFunctionalTestCase
$test->name = 'WHATT???'; $test->name = 'WHATT???';
$this->_em->flush(); $this->_em->flush();
} }
public function testOptimisticTimestampSetsDefaultValue()
{
$test = new OptimisticTimestamp();
$test->name = 'Testing';
$this->_em->persist($test);
$this->_em->flush();
$this->assertTrue(strtotime($test->version) > 0);
}
/**
* @expectedException Doctrine\ORM\OptimisticLockException
*/
public function testOptimisticTimestampFailureThrowsException()
{
$q = $this->_em->createQuery('SELECT t FROM Doctrine\Tests\ORM\Functional\Locking\OptimisticTimestamp t WHERE t.name = :name');
$q->setParameter('name', 'Testing');
$test = $q->getSingleResult();
// Manually increment the version datetime column
$this->_conn->execute('UPDATE optimistic_timestamp SET version = ? WHERE id = ?', array(date('Y-m-d H:i:s', strtotime($test->version->format('Y-m-d H:i:s')) + 3600), $test->id));
// Try and update the record and it should throw an exception
$test->name = 'Testing again';
$this->_em->flush();
}
} }
/** /**
...@@ -180,4 +208,27 @@ class OptimisticStandard ...@@ -180,4 +208,27 @@ class OptimisticStandard
* @Version @Column(type="integer") * @Version @Column(type="integer")
*/ */
public $version; public $version;
}
/**
* @Entity
* @Table(name="optimistic_timestamp")
*/
class OptimisticTimestamp
{
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* @Column(type="string", length=255)
*/
public $name;
/**
* @Version @Column(type="datetime")
*/
public $version;
} }
\ No newline at end of file
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