From 6f356799115b1edf17309f826345da82b16ce7f2 Mon Sep 17 00:00:00 2001 From: Jan Sorgalla Date: Sat, 19 Nov 2011 00:35:29 +0100 Subject: [PATCH] Initial implementation of Doctrine\DBAL\Types\Type::convertToDatabaseValueSQL() and Doctrine\DBAL\Types\Type::convertToPHPValueSQL() integration --- .../AbstractEntityInheritancePersister.php | 5 + .../ORM/Persisters/BasicEntityPersister.php | 43 +++++++- lib/Doctrine/ORM/Query/SqlWalker.php | 82 ++++++++++++-- .../DbalTypes/NegativeToPositiveType.php | 34 ++++++ .../Tests/DbalTypes/UpperCaseStringType.php | 29 +++++ tests/Doctrine/Tests/Mocks/ConnectionMock.php | 14 +++ .../Models/CustomType/CustomTypeChild.php | 21 ++++ .../Models/CustomType/CustomTypeParent.php | 68 ++++++++++++ .../Models/CustomType/CustomTypeUpperCase.php | 21 ++++ .../Tests/ORM/Functional/TypeValueSqlTest.php | 104 ++++++++++++++++++ .../BasicEntityPersisterTypeValueSqlTest.php | 73 ++++++++++++ .../ORM/Query/SelectSqlGenerationTest.php | 43 ++++++++ .../ORM/Query/UpdateSqlGenerationTest.php | 24 ++++ .../Doctrine/Tests/OrmFunctionalTestCase.php | 12 ++ 14 files changed, 559 insertions(+), 14 deletions(-) create mode 100644 tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php create mode 100644 tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php create mode 100644 tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php create mode 100644 tests/Doctrine/Tests/Models/CustomType/CustomTypeParent.php create mode 100644 tests/Doctrine/Tests/Models/CustomType/CustomTypeUpperCase.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/TypeValueSqlTest.php create mode 100644 tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php diff --git a/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php b/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php index 84540a337..4f45f0877 100644 --- a/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php +++ b/lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php @@ -65,6 +65,11 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister $columnAlias = $this->getSQLColumnAlias($columnName); $this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name); + if (!$class->isIdentifier($field)) { + $type = Type::getType($class->getTypeOfField($field)); + $sql = $type->convertToPHPValueSQL($sql, $this->_platform); + } + return $sql . ' AS ' . $columnAlias; } diff --git a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php index 4deece2e9..41fb01a75 100644 --- a/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php +++ b/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php @@ -338,10 +338,19 @@ class BasicEntityPersister $set = $params = $types = array(); foreach ($updateData as $columnName => $value) { - $set[] = (isset($this->_class->fieldNames[$columnName])) - ? $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?' - : $columnName . ' = ?'; + $column = $columnName; + $placeholder = '?'; + + if (isset($this->_class->fieldNames[$columnName])) { + $column = $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform); + if (!$this->_class->isIdentifier($this->_class->fieldNames[$columnName])) { + $type = Type::getType($this->_columnTypes[$columnName]); + $placeholder = $type->convertToDatabaseValueSQL('?', $this->_platform); + } + } + + $set[] = $column . ' = ' . $placeholder; $params[] = $value; $types[] = $this->_columnTypes[$columnName]; } @@ -1117,7 +1126,18 @@ class BasicEntityPersister ); } else { $columns = array_unique($columns); - $values = array_fill(0, count($columns), '?'); + + $values = array(); + foreach ($columns AS $column) { + $placeholder = '?'; + + if (isset($this->_columnTypes[$column])) { + $type = Type::getType($this->_columnTypes[$column]); + $placeholder = $type->convertToDatabaseValueSQL('?', $this->_platform); + } + + $values[] = $placeholder; + } $insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform) . ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')'; @@ -1156,6 +1176,7 @@ class BasicEntityPersister } } else if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->_class->identifier[0] != $name) { $columns[] = $this->_class->getQuotedColumnName($name, $this->_platform); + $this->_columnTypes[$name] = $this->_class->fieldMappings[$name]['type']; } } @@ -1177,6 +1198,11 @@ class BasicEntityPersister $columnAlias = $this->getSQLColumnAlias($class->columnNames[$field]); $this->_rsm->addFieldResult($alias, $columnAlias, $field); + + if (!$class->isIdentifier($field)) { + $type = Type::getType($class->getTypeOfField($field)); + $sql = $type->convertToPHPValueSQL($sql, $this->_platform); + } return $sql . ' AS ' . $columnAlias; } @@ -1259,6 +1285,8 @@ class BasicEntityPersister foreach ($criteria as $field => $value) { $conditionSql .= $conditionSql ? ' AND ' : ''; + + $placeholder = '?'; if (isset($this->_class->columnNames[$field])) { $className = (isset($this->_class->fieldMappings[$field]['inherited'])) @@ -1266,6 +1294,11 @@ class BasicEntityPersister : $this->_class->name; $conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform); + + if (!$this->_class->isIdentifier($field)) { + $type = Type::getType($this->_class->getTypeOfField($field)); + $placeholder = $type->convertToDatabaseValueSQL($placeholder, $this->_platform); + } } else if (isset($this->_class->associationMappings[$field])) { if ( ! $this->_class->associationMappings[$field]['isOwningSide']) { throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field); @@ -1286,7 +1319,7 @@ class BasicEntityPersister throw ORMException::unrecognizedField($field); } - $conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?'); + $conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ' . $placeholder); } return $conditionSql; } diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 624f14b89..382796631 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -20,6 +20,7 @@ namespace Doctrine\ORM\Query; use Doctrine\DBAL\LockMode, + Doctrine\DBAL\Types\Type, Doctrine\ORM\Mapping\ClassMetadata, Doctrine\ORM\Query, Doctrine\ORM\Query\QueryException, @@ -96,6 +97,17 @@ class SqlWalker implements TreeWalker * These should only be generated for SELECT queries, not for UPDATE/DELETE. */ private $_useSqlTableAliases = true; + + /** + * Flag that indicates whether to pass columns through Type::convertToPHPValueSQL(). + * These should only be done for SELECT queries, not for UPDATE. + */ + private $_useDbalTypeValueSql = true; + + /** + * Holds the current columns type. + */ + private $_currentColumnType; /** * The database platform abstraction. @@ -409,6 +421,7 @@ class SqlWalker implements TreeWalker public function walkUpdateStatement(AST\UpdateStatement $AST) { $this->_useSqlTableAliases = false; + $this->_useDbalTypeValueSql = false; return $this->walkUpdateClause($AST->updateClause) . $this->walkWhereClause($AST->whereClause); } @@ -464,11 +477,20 @@ class SqlWalker implements TreeWalker $dqlAlias = $pathExpr->identificationVariable; $class = $this->_queryComponents[$dqlAlias]['metadata']; + $column = ''; + if ($this->_useSqlTableAliases) { - $sql .= $this->walkIdentificationVariable($dqlAlias, $fieldName) . '.'; + $column .= $this->walkIdentificationVariable($dqlAlias, $fieldName) . '.'; } - $sql .= $class->getQuotedColumnName($fieldName, $this->_platform); + $column .= $class->getQuotedColumnName($fieldName, $this->_platform); + + if ($this->_useDbalTypeValueSql && !$class->isIdentifier($fieldName)) { + $type = Type::getType($class->getTypeOfField($fieldName)); + $column = $type->convertToPHPValueSQL($column, $this->_conn->getDatabasePlatform()); + } + + $sql .= $column; break; case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION: @@ -1002,9 +1024,16 @@ class SqlWalker implements TreeWalker $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias); $columnName = $class->getQuotedColumnName($fieldName, $this->_platform); - $columnAlias = $this->getSQLColumnAlias($columnName); + $columnAlias = $this->getSQLColumnAlias($columnName); - $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias; + $col = $sqlTableAlias . '.' . $columnName; + + if (!$class->isIdentifier($fieldName)) { + $type = Type::getType($class->getTypeOfField($fieldName)); + $col = $type->convertToPHPValueSQL($col, $this->_conn->getDatabasePlatform()); + } + + $sql .= $col . ' AS ' . $columnAlias; if ( ! $hidden) { $this->_rsm->addScalarResult($columnAlias, $resultAlias); @@ -1086,7 +1115,14 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); $quotedColumnName = $class->getQuotedColumnName($fieldName, $this->_platform); - $sqlParts[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS '. $columnAlias; + $col = $sqlTableAlias . '.' . $quotedColumnName; + + if (!$class->isIdentifier($fieldName)) { + $type = Type::getType($class->getTypeOfField($fieldName)); + $col = $type->convertToPHPValueSQL($col, $this->_platform); + } + + $sqlParts[] = $col . ' AS '. $columnAlias; $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name); } @@ -1108,7 +1144,14 @@ class SqlWalker implements TreeWalker $columnAlias = $this->getSQLColumnAlias($mapping['columnName']); $quotedColumnName = $subClass->getQuotedColumnName($fieldName, $this->_platform); - $sqlParts[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias; + $col = $sqlTableAlias . '.' . $quotedColumnName; + + if (!$subClass->isIdentifier($fieldName)) { + $type = Type::getType($subClass->getTypeOfField($fieldName)); + $col = $type->convertToPHPValueSQL($col, $this->_platform); + } + + $sqlParts[] = $col . ' AS ' . $columnAlias; $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName); } @@ -1386,7 +1429,18 @@ class SqlWalker implements TreeWalker switch (true) { case ($newValue instanceof AST\Node): + $currentColumnTypeBefore = $this->_currentColumnType; + $this->_currentColumnType = null; + + if ($updateItem->pathExpression->type == AST\PathExpression::TYPE_STATE_FIELD) { + $class = $this->_queryComponents[$updateItem->pathExpression->identificationVariable]['metadata']; + if (!$class->isIdentifier($updateItem->pathExpression->field)) { + $this->_currentColumnType = $class->getTypeOfField($updateItem->pathExpression->field); + } + } + $sql .= $newValue->dispatch($this); + $this->_currentColumnType = $currentColumnTypeBefore; break; case ($newValue === null): @@ -1759,20 +1813,30 @@ class SqlWalker implements TreeWalker { switch ($literal->type) { case AST\Literal::STRING: - return $this->_conn->quote($literal->value); + $value = $this->_conn->quote($literal->value); + break; case AST\Literal::BOOLEAN: $bool = strtolower($literal->value) == 'true' ? true : false; $boolVal = $this->_conn->getDatabasePlatform()->convertBooleans($bool); - return $boolVal; + $value = $boolVal; + break; case AST\Literal::NUMERIC: - return $literal->value; + $value = $literal->value; + break; default: throw QueryException::invalidLiteral($literal); } + + if ($this->_currentColumnType !== null) { + $type = Type::getType($this->_currentColumnType); + $value = $type->convertToDatabaseValueSQL($value, $this->_conn->getDatabasePlatform()); + } + + return $value; } /** diff --git a/tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php b/tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php new file mode 100644 index 000000000..e477ecd3c --- /dev/null +++ b/tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php @@ -0,0 +1,34 @@ +getIntegerTypeDeclarationSQL($fieldDeclaration); + } + + public function canRequireSQLConversion() + { + return true; + } + + public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) + { + return 'ABS(' . $sqlExpr . ')'; + } + + public function convertToPHPValueSQL($sqlExpr, $platform) + { + return '((' . $sqlExpr . ') * -1)'; + } +} diff --git a/tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php b/tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php new file mode 100644 index 000000000..47e8c790d --- /dev/null +++ b/tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php @@ -0,0 +1,29 @@ +_inserts[$tableName][] = $data; } + /** + * @override + */ + public function executeUpdate($query, array $params = array(), array $types = array()) + { + $this->_executeUpdates[] = array('query' => $query, 'params' => $params, 'types' => $types); + } + /** * @override */ @@ -84,6 +93,11 @@ class ConnectionMock extends \Doctrine\DBAL\Connection return $this->_inserts; } + public function getExecuteUpdates() + { + return $this->_executeUpdates; + } + public function reset() { $this->_inserts = array(); diff --git a/tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php b/tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php new file mode 100644 index 000000000..799ad5016 --- /dev/null +++ b/tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php @@ -0,0 +1,21 @@ +friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection(); + $this->myFriends = new \Doctrine\Common\Collections\ArrayCollection(); + } + + public function addMyFriend(CustomTypeParent $friend) + { + $this->getMyFriends()->add($friend); + $friend->addFriendWithMe($this); + } + + public function getMyFriends() + { + return $this->myFriends; + } + + public function addFriendWithMe(CustomTypeParent $friend) + { + $this->getFriendsWithMe()->add($friend); + } + + public function getFriendsWithMe() + { + return $this->friendsWithMe; + } +} diff --git a/tests/Doctrine/Tests/Models/CustomType/CustomTypeUpperCase.php b/tests/Doctrine/Tests/Models/CustomType/CustomTypeUpperCase.php new file mode 100644 index 000000000..26e0ec115 --- /dev/null +++ b/tests/Doctrine/Tests/Models/CustomType/CustomTypeUpperCase.php @@ -0,0 +1,21 @@ +useModelSet('customtype'); + parent::setUp(); + } + + public function testUpperCaseStringType() + { + $entity = new CustomTypeUpperCase(); + $entity->lowerCaseString = 'foo'; + + $this->_em->persist($entity); + $this->_em->flush(); + + $id = $entity->id; + + $this->_em->clear(); + + $entity = $this->_em->find('\Doctrine\Tests\Models\CustomType\CustomTypeUpperCase', $id); + + $this->assertEquals('foo', $entity->lowerCaseString, 'Entity holds lowercase string'); + $this->assertEquals('FOO', $this->_em->getConnection()->fetchColumn("select lowerCaseString from customtype_uppercases where id=".$entity->id.""), 'Database holds uppercase string'); + } + + public function testTypeValueSqlWithAssociations() + { + $parent = new CustomTypeParent(); + $parent->customInteger = -1; + $parent->child = new CustomTypeChild(); + + $friend1 = new CustomTypeParent(); + $friend2 = new CustomTypeParent(); + + $parent->addMyFriend($friend1); + $parent->addMyFriend($friend2); + + $this->_em->persist($parent); + $this->_em->persist($friend1); + $this->_em->persist($friend2); + $this->_em->flush(); + + $parentId = $parent->id; + + $this->_em->clear(); + + $entity = $this->_em->find('Doctrine\Tests\Models\CustomType\CustomTypeParent', $parentId); + + $this->assertTrue($entity->customInteger < 0, 'Fetched customInteger negative'); + $this->assertEquals(1, $this->_em->getConnection()->fetchColumn("select customInteger from customtype_parents where id=".$entity->id.""), 'Database has stored customInteger positive'); + + $this->assertNotNull($parent->child, 'Child attached'); + $this->assertCount(2, $entity->getMyFriends(), '2 friends attached'); + } + + public function testSelectDQL() + { + $parent = new CustomTypeParent(); + $parent->customInteger = -1; + $parent->child = new CustomTypeChild(); + + $this->_em->persist($parent); + $this->_em->flush(); + + $parentId = $parent->id; + + $this->_em->clear(); + + $query = $this->_em->createQuery("SELECT p, p.customInteger, c from Doctrine\Tests\Models\CustomType\CustomTypeParent p JOIN p.child c where p.id = " . $parentId . " AND p.customInteger = -1"); + + $result = $query->getResult(); + + $this->assertEquals(1, count($result)); + $this->assertInstanceOf('Doctrine\Tests\Models\CustomType\CustomTypeParent', $result[0][0]); + + $this->assertEquals(-1, $result[0]['customInteger']); + + $this->assertEquals('foo', $result[0][0]->child->lowerCaseString); + } +} diff --git a/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php b/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php new file mode 100644 index 000000000..e608e6ba8 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php @@ -0,0 +1,73 @@ +_em = $this->_getTestEntityManager(); + + $this->_persister = new BasicEntityPersister($this->_em, $this->_em->getClassMetadata("Doctrine\Tests\Models\CustomType\CustomTypeParent")); + + if (DBALType::hasType('negative_to_positive')) { + DBALType::overrideType('negative_to_positive', '\Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } else { + DBALType::addType('negative_to_positive', '\Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } + } + + public function testGetInsertSQLUsesTypeValuesSQL() + { + $method = new \ReflectionMethod($this->_persister, '_getInsertSQL'); + $method->setAccessible(true); + + $sql = $method->invoke($this->_persister); + + $this->assertEquals('INSERT INTO customtype_parents (customInteger, child_id) VALUES (ABS(?), ?)', $sql); + } + + public function testUpdateUsesTypeValuesSQL() + { + $child = new CustomTypeChild(); + + $parent = new CustomTypeParent(); + $parent->customInteger = 1; + $parent->child = $child; + + $this->_em->getUnitOfWork()->registerManaged($parent, array('id' => 1), array('customInteger' => 0, 'child' => null)); + $this->_em->getUnitOfWork()->registerManaged($child, array('id' => 1), array()); + + $this->_em->getUnitOfWork()->propertyChanged($parent, 'customInteger', 0, 1); + $this->_em->getUnitOfWork()->propertyChanged($parent, 'child', null, $child); + + $this->_persister->update($parent); + + $executeUpdates = $this->_em->getConnection()->getExecuteUpdates(); + + $this->assertEquals('UPDATE customtype_parents SET customInteger = ABS(?), child_id = ? WHERE id = ?', $executeUpdates[0]['query']); + } + + public function testGetSelectConditionSQLUsesTypeValuesSQL() + { + $method = new \ReflectionMethod($this->_persister, '_getSelectConditionSQL'); + $method->setAccessible(true); + + $sql = $method->invoke($this->_persister, array('customInteger' => 1, 'child' => 1)); + + $this->assertEquals('t0.customInteger = ABS(?) AND t0.child_id = ?', $sql); + } +} diff --git a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php index 7ddfe77b8..028406068 100644 --- a/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php @@ -2,6 +2,7 @@ namespace Doctrine\Tests\ORM\Query; +use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\ORM\Query; require_once __DIR__ . '/../../TestInit.php'; @@ -1333,6 +1334,48 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase 'SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_ GROUP BY c0_.id, c0_.name, c0_.spouse_id' ); } + + public function testCustomTypeValueSql() + { + if (DBALType::hasType('negative_to_positive')) { + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } else { + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } + + $this->assertSqlGeneration( + 'SELECT p.customInteger FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p WHERE p.id = 1', + 'SELECT ((c0_.customInteger) * -1) AS customInteger0 FROM customtype_parents c0_ WHERE c0_.id = 1' + ); + } + + public function testCustomTypeValueSqlIgnoresIdentifierColumn() + { + if (DBALType::hasType('negative_to_positive')) { + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } else { + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } + + $this->assertSqlGeneration( + 'SELECT p.id FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p WHERE p.id = 1', + 'SELECT c0_.id AS id0 FROM customtype_parents c0_ WHERE c0_.id = 1' + ); + } + + public function testCustomTypeValueSqlForAllFields() + { + if (DBALType::hasType('negative_to_positive')) { + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } else { + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } + + $this->assertSqlGeneration( + 'SELECT p FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p', + 'SELECT c0_.id AS id0, ((c0_.customInteger) * -1) AS customInteger1 FROM customtype_parents c0_' + ); + } } diff --git a/tests/Doctrine/Tests/ORM/Query/UpdateSqlGenerationTest.php b/tests/Doctrine/Tests/ORM/Query/UpdateSqlGenerationTest.php index a8a59ff63..34658c95a 100644 --- a/tests/Doctrine/Tests/ORM/Query/UpdateSqlGenerationTest.php +++ b/tests/Doctrine/Tests/ORM/Query/UpdateSqlGenerationTest.php @@ -21,6 +21,8 @@ namespace Doctrine\Tests\ORM\Query; +use Doctrine\DBAL\Types\Type as DBALType; + require_once __DIR__ . '/../../TestInit.php'; /** @@ -42,6 +44,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase private $_em; protected function setUp() { + if (DBALType::hasType('negative_to_positive')) { + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } else { + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType'); + } + $this->_em = $this->_getTestEntityManager(); } @@ -186,4 +194,20 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase "UPDATE cms_users SET status = 'inactive' WHERE (SELECT COUNT(*) FROM cms_users_groups c0_ WHERE c0_.user_id = cms_users.id) = 10" ); } + + public function testCustomTypeValueSql() + { + $this->assertSqlGeneration( + 'UPDATE Doctrine\Tests\Models\CustomType\CustomTypeParent p SET p.customInteger = 1 WHERE p.id = 1', + 'UPDATE customtype_parents SET customInteger = ABS(1) WHERE id = 1' + ); + } + + public function testCustomTypeValueSqlIgnoresIdentifierColumns() + { + $this->assertSqlGeneration( + 'UPDATE Doctrine\Tests\Models\CustomType\CustomTypeParent p SET p.id = 2 WHERE p.id = 1', + 'UPDATE customtype_parents SET id = 2 WHERE id = 1' + ); + } } diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 0900e4e99..e0b9d7bee 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -112,6 +112,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase 'Doctrine\Tests\Models\Legacy\LegacyArticle', 'Doctrine\Tests\Models\Legacy\LegacyCar', ), + 'customtype' => array( + 'Doctrine\Tests\Models\CustomType\CustomTypeChild', + 'Doctrine\Tests\Models\CustomType\CustomTypeParent', + 'Doctrine\Tests\Models\CustomType\CustomTypeUpperCase', + ), ); protected function useModelSet($setName) @@ -219,6 +224,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase $conn->executeUpdate('DELETE FROM legacy_users'); } + if (isset($this->_usedModelSets['customtype'])) { + $conn->executeUpdate('DELETE FROM customtype_parent_friends'); + $conn->executeUpdate('DELETE FROM customtype_parents'); + $conn->executeUpdate('DELETE FROM customtype_children'); + $conn->executeUpdate('DELETE FROM customtype_uppercases'); + } + $this->_em->clear(); }