Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge branch 'DBAL-15'

  • Loading branch information...
commit be4eb63c62921b3006ae28ba063b5561b91c76be 2 parents 135e515 + 16aa558
Benjamin Eberlei beberlei authored
9 lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
@@ -20,6 +20,7 @@
20 20 namespace Doctrine\ORM\Mapping;
21 21
22 22 use Doctrine\Common\Persistence\Mapping\ClassMetadata;
  23 +use Doctrine\DBAL\Types\Type;
23 24 use ReflectionClass;
24 25
25 26 /**
@@ -746,6 +747,14 @@ protected function _validateAndCompleteFieldMapping(array &$mapping)
746 747 $this->isIdentifierComposite = true;
747 748 }
748 749 }
  750 +
  751 + if (Type::hasType($mapping['type']) && Type::getType($mapping['type'])->canRequireSQLConversion()) {
  752 + if (isset($mapping['id']) && $mapping['id'] === true) {
  753 + throw MappingException::sqlConversionNotAllowedForIdentifiers($this->name, $mapping['fieldName'], $mapping['type']);
  754 + }
  755 +
  756 + $mapping['requireSQLConversion'] = true;
  757 + }
749 758 }
750 759
751 760 /**
5 lib/Doctrine/ORM/Mapping/MappingException.php
@@ -226,6 +226,11 @@ public static function cannotVersionIdField($className, $fieldName)
226 226 return new self("Setting Id field '$fieldName' as versionale in entity class '$className' is not supported.");
227 227 }
228 228
  229 + public static function sqlConversionNotAllowedForIdentifiers($className, $fieldName, $type)
  230 + {
  231 + return new self("It is not possible to set id field '$fieldName' to type '$type' in entity class '$className'. The type '$type' requires conversion SQL which is not allowed for identifiers.");
  232 + }
  233 +
229 234 /**
230 235 * @param string $className
231 236 * @param string $columnName
5 lib/Doctrine/ORM/Persisters/AbstractEntityInheritancePersister.php
@@ -65,6 +65,11 @@ protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r
65 65 $columnAlias = $this->getSQLColumnAlias($columnName);
66 66 $this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
67 67
  68 + if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
  69 + $type = Type::getType($class->getTypeOfField($field));
  70 + $sql = $type->convertToPHPValueSQL($sql, $this->_platform);
  71 + }
  72 +
68 73 return $sql . ' AS ' . $columnAlias;
69 74 }
70 75
44 lib/Doctrine/ORM/Persisters/BasicEntityPersister.php
@@ -338,10 +338,19 @@ public function update($entity)
338 338 $set = $params = $types = array();
339 339
340 340 foreach ($updateData as $columnName => $value) {
341   - $set[] = (isset($this->_class->fieldNames[$columnName]))
342   - ? $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?'
343   - : $columnName . ' = ?';
  341 + $column = $columnName;
  342 + $placeholder = '?';
  343 +
  344 + if (isset($this->_class->fieldNames[$columnName])) {
  345 + $column = $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform);
  346 +
  347 + if (isset($this->_class->fieldMappings[$this->_class->fieldNames[$columnName]]['requireSQLConversion'])) {
  348 + $type = Type::getType($this->_columnTypes[$columnName]);
  349 + $placeholder = $type->convertToDatabaseValueSQL('?', $this->_platform);
  350 + }
  351 + }
344 352
  353 + $set[] = $column . ' = ' . $placeholder;
345 354 $params[] = $value;
346 355 $types[] = $this->_columnTypes[$columnName];
347 356 }
@@ -1121,7 +1130,19 @@ protected function _getInsertSQL()
1121 1130 );
1122 1131 } else {
1123 1132 $columns = array_unique($columns);
1124   - $values = array_fill(0, count($columns), '?');
  1133 +
  1134 + $values = array();
  1135 + foreach ($columns AS $column) {
  1136 + $placeholder = '?';
  1137 +
  1138 + if (isset($this->_columnTypes[$column]) &&
  1139 + isset($this->_class->fieldMappings[$this->_class->fieldNames[$column]]['requireSQLConversion'])) {
  1140 + $type = Type::getType($this->_columnTypes[$column]);
  1141 + $placeholder = $type->convertToDatabaseValueSQL('?', $this->_platform);
  1142 + }
  1143 +
  1144 + $values[] = $placeholder;
  1145 + }
1125 1146
1126 1147 $insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
1127 1148 . ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
@@ -1160,6 +1181,7 @@ protected function _getInsertColumnList()
1160 1181 }
1161 1182 } else if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->_class->identifier[0] != $name) {
1162 1183 $columns[] = $this->_class->getQuotedColumnName($name, $this->_platform);
  1184 + $this->_columnTypes[$name] = $this->_class->fieldMappings[$name]['type'];
1163 1185 }
1164 1186 }
1165 1187
@@ -1182,6 +1204,11 @@ protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r
1182 1204
1183 1205 $this->_rsm->addFieldResult($alias, $columnAlias, $field);
1184 1206
  1207 + if (isset($class->fieldMappings[$field]['requireSQLConversion'])) {
  1208 + $type = Type::getType($class->getTypeOfField($field));
  1209 + $sql = $type->convertToPHPValueSQL($sql, $this->_platform);
  1210 + }
  1211 +
1185 1212 return $sql . ' AS ' . $columnAlias;
1186 1213 }
1187 1214
@@ -1263,6 +1290,8 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
1263 1290
1264 1291 foreach ($criteria as $field => $value) {
1265 1292 $conditionSql .= $conditionSql ? ' AND ' : '';
  1293 +
  1294 + $placeholder = '?';
1266 1295
1267 1296 if (isset($this->_class->columnNames[$field])) {
1268 1297 $className = (isset($this->_class->fieldMappings[$field]['inherited']))
@@ -1270,6 +1299,11 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
1270 1299 : $this->_class->name;
1271 1300
1272 1301 $conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
  1302 +
  1303 + if (isset($this->_class->fieldMappings[$field]['requireSQLConversion'])) {
  1304 + $type = Type::getType($this->_class->getTypeOfField($field));
  1305 + $placeholder = $type->convertToDatabaseValueSQL($placeholder, $this->_platform);
  1306 + }
1273 1307 } else if (isset($this->_class->associationMappings[$field])) {
1274 1308 if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
1275 1309 throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
@@ -1290,7 +1324,7 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
1290 1324 throw ORMException::unrecognizedField($field);
1291 1325 }
1292 1326
1293   - $conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ?');
  1327 + $conditionSql .= (is_array($value)) ? ' IN (?)' : (($value === null) ? ' IS NULL' : ' = ' . $placeholder);
1294 1328 }
1295 1329 return $conditionSql;
1296 1330 }
30 lib/Doctrine/ORM/Query/SqlWalker.php
@@ -20,6 +20,7 @@
20 20 namespace Doctrine\ORM\Query;
21 21
22 22 use Doctrine\DBAL\LockMode,
  23 + Doctrine\DBAL\Types\Type,
23 24 Doctrine\ORM\Mapping\ClassMetadata,
24 25 Doctrine\ORM\Query,
25 26 Doctrine\ORM\Query\QueryException,
@@ -1002,9 +1003,16 @@ public function walkSelectExpression($selectExpression)
1002 1003
1003 1004 $sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
1004 1005 $columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
1005   - $columnAlias = $this->getSQLColumnAlias($columnName);
  1006 + $columnAlias = $this->getSQLColumnAlias($columnName);
1006 1007
1007   - $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
  1008 + $col = $sqlTableAlias . '.' . $columnName;
  1009 +
  1010 + if (isset($class->fieldMappings[$fieldName]['requireSQLConversion'])) {
  1011 + $type = Type::getType($class->getTypeOfField($fieldName));
  1012 + $col = $type->convertToPHPValueSQL($col, $this->_conn->getDatabasePlatform());
  1013 + }
  1014 +
  1015 + $sql .= $col . ' AS ' . $columnAlias;
1008 1016
1009 1017 if ( ! $hidden) {
1010 1018 $this->_rsm->addScalarResult($columnAlias, $resultAlias);
@@ -1086,7 +1094,14 @@ public function walkSelectExpression($selectExpression)
1086 1094 $columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
1087 1095 $quotedColumnName = $class->getQuotedColumnName($fieldName, $this->_platform);
1088 1096
1089   - $sqlParts[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS '. $columnAlias;
  1097 + $col = $sqlTableAlias . '.' . $quotedColumnName;
  1098 +
  1099 + if (isset($class->fieldMappings[$fieldName]['requireSQLConversion'])) {
  1100 + $type = Type::getType($class->getTypeOfField($fieldName));
  1101 + $col = $type->convertToPHPValueSQL($col, $this->_platform);
  1102 + }
  1103 +
  1104 + $sqlParts[] = $col . ' AS '. $columnAlias;
1090 1105
1091 1106 $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
1092 1107 }
@@ -1108,7 +1123,14 @@ public function walkSelectExpression($selectExpression)
1108 1123 $columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
1109 1124 $quotedColumnName = $subClass->getQuotedColumnName($fieldName, $this->_platform);
1110 1125
1111   - $sqlParts[] = $sqlTableAlias . '.' . $quotedColumnName . ' AS ' . $columnAlias;
  1126 + $col = $sqlTableAlias . '.' . $quotedColumnName;
  1127 +
  1128 + if (isset($subClass->fieldMappings[$fieldName]['requireSQLConversion'])) {
  1129 + $type = Type::getType($subClass->getTypeOfField($fieldName));
  1130 + $col = $type->convertToPHPValueSQL($col, $this->_platform);
  1131 + }
  1132 +
  1133 + $sqlParts[] = $col . ' AS ' . $columnAlias;
1112 1134
1113 1135 $this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
1114 1136 }
34 tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php
... ... @@ -0,0 +1,34 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\DbalTypes;
  4 +
  5 +use Doctrine\DBAL\Types\Type;
  6 +use Doctrine\DBAL\Platforms\AbstractPlatform;
  7 +
  8 +class NegativeToPositiveType extends Type
  9 +{
  10 + public function getName()
  11 + {
  12 + return 'negative_to_positive';
  13 + }
  14 +
  15 + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
  16 + {
  17 + return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration);
  18 + }
  19 +
  20 + public function canRequireSQLConversion()
  21 + {
  22 + return true;
  23 + }
  24 +
  25 + public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
  26 + {
  27 + return 'ABS(' . $sqlExpr . ')';
  28 + }
  29 +
  30 + public function convertToPHPValueSQL($sqlExpr, $platform)
  31 + {
  32 + return '-(' . $sqlExpr . ')';
  33 + }
  34 +}
29 tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php
... ... @@ -0,0 +1,29 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\DbalTypes;
  4 +
  5 +use Doctrine\DBAL\Types\StringType;
  6 +use Doctrine\DBAL\Platforms\AbstractPlatform;
  7 +
  8 +class UpperCaseStringType extends StringType
  9 +{
  10 + public function getName()
  11 + {
  12 + return 'upper_case_string';
  13 + }
  14 +
  15 + public function canRequireSQLConversion()
  16 + {
  17 + return true;
  18 + }
  19 +
  20 + public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
  21 + {
  22 + return 'UPPER(' . $sqlExpr . ')';
  23 + }
  24 +
  25 + public function convertToPHPValueSQL($sqlExpr, $platform)
  26 + {
  27 + return 'LOWER(' . $sqlExpr . ')';
  28 + }
  29 +}
14 tests/Doctrine/Tests/Mocks/ConnectionMock.php
@@ -8,6 +8,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
8 8 private $_platformMock;
9 9 private $_lastInsertId = 0;
10 10 private $_inserts = array();
  11 + private $_executeUpdates = array();
11 12
12 13 public function __construct(array $params, $driver, $config = null, $eventManager = null)
13 14 {
@@ -38,6 +39,14 @@ public function insert($tableName, array $data, array $types = array())
38 39 /**
39 40 * @override
40 41 */
  42 + public function executeUpdate($query, array $params = array(), array $types = array())
  43 + {
  44 + $this->_executeUpdates[] = array('query' => $query, 'params' => $params, 'types' => $types);
  45 + }
  46 +
  47 + /**
  48 + * @override
  49 + */
41 50 public function lastInsertId($seqName = null)
42 51 {
43 52 return $this->_lastInsertId;
@@ -84,6 +93,11 @@ public function getInserts()
84 93 return $this->_inserts;
85 94 }
86 95
  96 + public function getExecuteUpdates()
  97 + {
  98 + return $this->_executeUpdates;
  99 + }
  100 +
87 101 public function reset()
88 102 {
89 103 $this->_inserts = array();
21 tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php
... ... @@ -0,0 +1,21 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\Models\CustomType;
  4 +
  5 +/**
  6 + * @Entity
  7 + * @Table(name="customtype_children")
  8 + */
  9 +class CustomTypeChild
  10 +{
  11 + /**
  12 + * @Id @Column(type="integer")
  13 + * @GeneratedValue(strategy="AUTO")
  14 + */
  15 + public $id;
  16 +
  17 + /**
  18 + * @Column(type="upper_case_string")
  19 + */
  20 + public $lowerCaseString = 'foo';
  21 +}
68 tests/Doctrine/Tests/Models/CustomType/CustomTypeParent.php
... ... @@ -0,0 +1,68 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\Models\CustomType;
  4 +
  5 +/**
  6 + * @Entity
  7 + * @Table(name="customtype_parents")
  8 + */
  9 +class CustomTypeParent
  10 +{
  11 + /**
  12 + * @Id @Column(type="integer")
  13 + * @GeneratedValue(strategy="AUTO")
  14 + */
  15 + public $id;
  16 +
  17 + /**
  18 + * @Column(type="negative_to_positive", nullable=true)
  19 + */
  20 + public $customInteger;
  21 +
  22 + /**
  23 + * @OneToOne(targetEntity="Doctrine\Tests\Models\CustomType\CustomTypeChild", cascade={"persist", "remove"})
  24 + */
  25 + public $child;
  26 +
  27 + /**
  28 + * @ManyToMany(targetEntity="Doctrine\Tests\Models\CustomType\CustomTypeParent", mappedBy="myFriends")
  29 + */
  30 + private $friendsWithMe;
  31 +
  32 + /**
  33 + * @ManyToMany(targetEntity="Doctrine\Tests\Models\CustomType\CustomTypeParent", inversedBy="friendsWithMe")
  34 + * @JoinTable(
  35 + * name="customtype_parent_friends",
  36 + * joinColumns={@JoinColumn(name="customtypeparent_id", referencedColumnName="id")},
  37 + * inverseJoinColumns={@JoinColumn(name="friend_customtypeparent_id", referencedColumnName="id")}
  38 + * )
  39 + */
  40 + private $myFriends;
  41 +
  42 + public function __construct()
  43 + {
  44 + $this->friendsWithMe = new \Doctrine\Common\Collections\ArrayCollection();
  45 + $this->myFriends = new \Doctrine\Common\Collections\ArrayCollection();
  46 + }
  47 +
  48 + public function addMyFriend(CustomTypeParent $friend)
  49 + {
  50 + $this->getMyFriends()->add($friend);
  51 + $friend->addFriendWithMe($this);
  52 + }
  53 +
  54 + public function getMyFriends()
  55 + {
  56 + return $this->myFriends;
  57 + }
  58 +
  59 + public function addFriendWithMe(CustomTypeParent $friend)
  60 + {
  61 + $this->getFriendsWithMe()->add($friend);
  62 + }
  63 +
  64 + public function getFriendsWithMe()
  65 + {
  66 + return $this->friendsWithMe;
  67 + }
  68 +}
21 tests/Doctrine/Tests/Models/CustomType/CustomTypeUpperCase.php
... ... @@ -0,0 +1,21 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\Models\CustomType;
  4 +
  5 +/**
  6 + * @Entity
  7 + * @Table(name="customtype_uppercases")
  8 + */
  9 +class CustomTypeUpperCase
  10 +{
  11 + /**
  12 + * @Id @Column(type="integer")
  13 + * @GeneratedValue(strategy="AUTO")
  14 + */
  15 + public $id;
  16 +
  17 + /**
  18 + * @Column(type="upper_case_string")
  19 + */
  20 + public $lowerCaseString;
  21 +}
105 tests/Doctrine/Tests/ORM/Functional/TypeValueSqlTest.php
... ... @@ -0,0 +1,105 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\ORM\Functional;
  4 +
  5 +use Doctrine\Tests\Models\CustomType\CustomTypeChild;
  6 +use Doctrine\Tests\Models\CustomType\CustomTypeParent;
  7 +use Doctrine\Tests\Models\CustomType\CustomTypeUpperCase;
  8 +use Doctrine\DBAL\Types\Type as DBALType;
  9 +
  10 +require_once __DIR__ . '/../../TestInit.php';
  11 +
  12 +class TypeValueSqlTest extends \Doctrine\Tests\OrmFunctionalTestCase
  13 +{
  14 + protected function setUp()
  15 + {
  16 + if (DBALType::hasType('upper_case_string')) {
  17 + DBALType::overrideType('upper_case_string', '\Doctrine\Tests\DbalTypes\UpperCaseStringType');
  18 + } else {
  19 + DBALType::addType('upper_case_string', '\Doctrine\Tests\DbalTypes\UpperCaseStringType');
  20 + }
  21 +
  22 + if (DBALType::hasType('negative_to_positive')) {
  23 + DBALType::overrideType('negative_to_positive', '\Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  24 + } else {
  25 + DBALType::addType('negative_to_positive', '\Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  26 + }
  27 +
  28 + $this->useModelSet('customtype');
  29 + parent::setUp();
  30 + }
  31 +
  32 + public function testUpperCaseStringType()
  33 + {
  34 + $entity = new CustomTypeUpperCase();
  35 + $entity->lowerCaseString = 'foo';
  36 +
  37 + $this->_em->persist($entity);
  38 + $this->_em->flush();
  39 +
  40 + $id = $entity->id;
  41 +
  42 + $this->_em->clear();
  43 +
  44 + $entity = $this->_em->find('\Doctrine\Tests\Models\CustomType\CustomTypeUpperCase', $id);
  45 +
  46 + $this->assertEquals('foo', $entity->lowerCaseString, 'Entity holds lowercase string');
  47 + $this->assertEquals('FOO', $this->_em->getConnection()->fetchColumn("select lowerCaseString from customtype_uppercases where id=".$entity->id.""), 'Database holds uppercase string');
  48 + }
  49 +
  50 + public function testTypeValueSqlWithAssociations()
  51 + {
  52 + $parent = new CustomTypeParent();
  53 + $parent->customInteger = -1;
  54 + $parent->child = new CustomTypeChild();
  55 +
  56 + $friend1 = new CustomTypeParent();
  57 + $friend2 = new CustomTypeParent();
  58 +
  59 + $parent->addMyFriend($friend1);
  60 + $parent->addMyFriend($friend2);
  61 +
  62 + $this->_em->persist($parent);
  63 + $this->_em->persist($friend1);
  64 + $this->_em->persist($friend2);
  65 + $this->_em->flush();
  66 +
  67 + $parentId = $parent->id;
  68 +
  69 + $this->_em->clear();
  70 +
  71 + $entity = $this->_em->find('Doctrine\Tests\Models\CustomType\CustomTypeParent', $parentId);
  72 +
  73 + $this->assertTrue($entity->customInteger < 0, 'Fetched customInteger negative');
  74 + $this->assertEquals(1, $this->_em->getConnection()->fetchColumn("select customInteger from customtype_parents where id=".$entity->id.""), 'Database has stored customInteger positive');
  75 +
  76 + $this->assertNotNull($parent->child, 'Child attached');
  77 + $this->assertCount(2, $entity->getMyFriends(), '2 friends attached');
  78 + }
  79 +
  80 + public function testSelectDQL()
  81 + {
  82 + $parent = new CustomTypeParent();
  83 + $parent->customInteger = -1;
  84 + $parent->child = new CustomTypeChild();
  85 +
  86 + $this->_em->persist($parent);
  87 + $this->_em->flush();
  88 +
  89 + $parentId = $parent->id;
  90 +
  91 + $this->_em->clear();
  92 +
  93 + $query = $this->_em->createQuery("SELECT p, p.customInteger, c from Doctrine\Tests\Models\CustomType\CustomTypeParent p JOIN p.child c where p.id = " . $parentId);
  94 +
  95 + $result = $query->getResult();
  96 +
  97 + $this->assertEquals(1, count($result));
  98 + $this->assertInstanceOf('Doctrine\Tests\Models\CustomType\CustomTypeParent', $result[0][0]);
  99 + $this->assertEquals(-1, $result[0][0]->customInteger);
  100 +
  101 + $this->assertEquals(-1, $result[0]['customInteger']);
  102 +
  103 + $this->assertEquals('foo', $result[0][0]->child->lowerCaseString);
  104 + }
  105 +}
79 tests/Doctrine/Tests/ORM/Persisters/BasicEntityPersisterTypeValueSqlTest.php
... ... @@ -0,0 +1,79 @@
  1 +<?php
  2 +
  3 +namespace Doctrine\Tests\ORM\Functional;
  4 +
  5 +use Doctrine\DBAL\Types\Type as DBALType;
  6 +use Doctrine\ORM\Persisters\BasicEntityPersister;
  7 +use Doctrine\Tests\Models\CustomType\CustomTypeParent;
  8 +use Doctrine\Tests\Models\CustomType\CustomTypeChild;
  9 +use Doctrine\Tests\Models\CustomType\CustomTypeFriend;
  10 +
  11 +require_once __DIR__ . '/../../TestInit.php';
  12 +
  13 +class BasicEntityPersisterTypeValueSqlTest extends \Doctrine\Tests\OrmTestCase
  14 +{
  15 + protected $_persister;
  16 + protected $_em;
  17 +
  18 + protected function setUp()
  19 + {
  20 + parent::setUp();
  21 +
  22 + if (DBALType::hasType('negative_to_positive')) {
  23 + DBALType::overrideType('negative_to_positive', '\Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  24 + } else {
  25 + DBALType::addType('negative_to_positive', '\Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  26 + }
  27 +
  28 + if (DBALType::hasType('upper_case_string')) {
  29 + DBALType::overrideType('upper_case_string', '\Doctrine\Tests\DbalTypes\UpperCaseStringType');
  30 + } else {
  31 + DBALType::addType('upper_case_string', '\Doctrine\Tests\DbalTypes\UpperCaseStringType');
  32 + }
  33 +
  34 + $this->_em = $this->_getTestEntityManager();
  35 +
  36 + $this->_persister = new BasicEntityPersister($this->_em, $this->_em->getClassMetadata("Doctrine\Tests\Models\CustomType\CustomTypeParent"));
  37 + }
  38 +
  39 + public function testGetInsertSQLUsesTypeValuesSQL()
  40 + {
  41 + $method = new \ReflectionMethod($this->_persister, '_getInsertSQL');
  42 + $method->setAccessible(true);
  43 +
  44 + $sql = $method->invoke($this->_persister);
  45 +
  46 + $this->assertEquals('INSERT INTO customtype_parents (customInteger, child_id) VALUES (ABS(?), ?)', $sql);
  47 + }
  48 +
  49 + public function testUpdateUsesTypeValuesSQL()
  50 + {
  51 + $child = new CustomTypeChild();
  52 +
  53 + $parent = new CustomTypeParent();
  54 + $parent->customInteger = 1;
  55 + $parent->child = $child;
  56 +
  57 + $this->_em->getUnitOfWork()->registerManaged($parent, array('id' => 1), array('customInteger' => 0, 'child' => null));
  58 + $this->_em->getUnitOfWork()->registerManaged($child, array('id' => 1), array());
  59 +
  60 + $this->_em->getUnitOfWork()->propertyChanged($parent, 'customInteger', 0, 1);
  61 + $this->_em->getUnitOfWork()->propertyChanged($parent, 'child', null, $child);
  62 +
  63 + $this->_persister->update($parent);
  64 +
  65 + $executeUpdates = $this->_em->getConnection()->getExecuteUpdates();
  66 +
  67 + $this->assertEquals('UPDATE customtype_parents SET customInteger = ABS(?), child_id = ? WHERE id = ?', $executeUpdates[0]['query']);
  68 + }
  69 +
  70 + public function testGetSelectConditionSQLUsesTypeValuesSQL()
  71 + {
  72 + $method = new \ReflectionMethod($this->_persister, '_getSelectConditionSQL');
  73 + $method->setAccessible(true);
  74 +
  75 + $sql = $method->invoke($this->_persister, array('customInteger' => 1, 'child' => 1));
  76 +
  77 + $this->assertEquals('t0.customInteger = ABS(?) AND t0.child_id = ?', $sql);
  78 + }
  79 +}
57 tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
@@ -2,6 +2,7 @@
2 2
3 3 namespace Doctrine\Tests\ORM\Query;
4 4
  5 +use Doctrine\DBAL\Types\Type as DBALType;
5 6 use Doctrine\ORM\Query;
6 7
7 8 require_once __DIR__ . '/../../TestInit.php';
@@ -1333,6 +1334,62 @@ public function testGroupByAllFieldsWhenObjectHasForeignKeys()
1333 1334 'SELECT c0_.id AS id0, c0_.name AS name1 FROM cms_employees c0_ GROUP BY c0_.id, c0_.name, c0_.spouse_id'
1334 1335 );
1335 1336 }
  1337 +
  1338 + public function testCustomTypeValueSql()
  1339 + {
  1340 + if (DBALType::hasType('negative_to_positive')) {
  1341 + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1342 + } else {
  1343 + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1344 + }
  1345 +
  1346 + $this->assertSqlGeneration(
  1347 + 'SELECT p.customInteger FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p WHERE p.id = 1',
  1348 + 'SELECT -(c0_.customInteger) AS customInteger0 FROM customtype_parents c0_ WHERE c0_.id = 1'
  1349 + );
  1350 + }
  1351 +
  1352 + public function testCustomTypeValueSqlIgnoresIdentifierColumn()
  1353 + {
  1354 + if (DBALType::hasType('negative_to_positive')) {
  1355 + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1356 + } else {
  1357 + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1358 + }
  1359 +
  1360 + $this->assertSqlGeneration(
  1361 + 'SELECT p.id FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p WHERE p.id = 1',
  1362 + 'SELECT c0_.id AS id0 FROM customtype_parents c0_ WHERE c0_.id = 1'
  1363 + );
  1364 + }
  1365 +
  1366 + public function testCustomTypeValueSqlForAllFields()
  1367 + {
  1368 + if (DBALType::hasType('negative_to_positive')) {
  1369 + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1370 + } else {
  1371 + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1372 + }
  1373 +
  1374 + $this->assertSqlGeneration(
  1375 + 'SELECT p FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p',
  1376 + 'SELECT c0_.id AS id0, -(c0_.customInteger) AS customInteger1 FROM customtype_parents c0_'
  1377 + );
  1378 + }
  1379 +
  1380 + public function testCustomTypeValueSqlForPartialObject()
  1381 + {
  1382 + if (DBALType::hasType('negative_to_positive')) {
  1383 + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1384 + } else {
  1385 + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  1386 + }
  1387 +
  1388 + $this->assertSqlGeneration(
  1389 + 'SELECT partial p.{id, customInteger} FROM Doctrine\Tests\Models\CustomType\CustomTypeParent p',
  1390 + 'SELECT c0_.id AS id0, -(c0_.customInteger) AS customInteger1 FROM customtype_parents c0_'
  1391 + );
  1392 + }
1336 1393 }
1337 1394
1338 1395
16 tests/Doctrine/Tests/ORM/Query/UpdateSqlGenerationTest.php
@@ -21,6 +21,8 @@
21 21
22 22 namespace Doctrine\Tests\ORM\Query;
23 23
  24 +use Doctrine\DBAL\Types\Type as DBALType;
  25 +
24 26 require_once __DIR__ . '/../../TestInit.php';
25 27
26 28 /**
@@ -42,6 +44,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
42 44 private $_em;
43 45
44 46 protected function setUp() {
  47 + if (DBALType::hasType('negative_to_positive')) {
  48 + DBALType::overrideType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  49 + } else {
  50 + DBALType::addType('negative_to_positive', 'Doctrine\Tests\DbalTypes\NegativeToPositiveType');
  51 + }
  52 +
45 53 $this->_em = $this->_getTestEntityManager();
46 54 }
47 55
@@ -186,4 +194,12 @@ public function testSubselectTableAliasReferencing()
186 194 "UPDATE cms_users SET status = 'inactive' WHERE (SELECT COUNT(*) FROM cms_users_groups c0_ WHERE c0_.user_id = cms_users.id) = 10"
187 195 );
188 196 }
  197 +
  198 + public function testCustomTypeValueSqlCompletelyIgnoredInUpdateStatements()
  199 + {
  200 + $this->assertSqlGeneration(
  201 + 'UPDATE Doctrine\Tests\Models\CustomType\CustomTypeParent p SET p.customInteger = 1 WHERE p.id = 1',
  202 + 'UPDATE customtype_parents SET customInteger = 1 WHERE id = 1'
  203 + );
  204 + }
189 205 }
12 tests/Doctrine/Tests/OrmFunctionalTestCase.php
@@ -112,6 +112,11 @@
112 112 'Doctrine\Tests\Models\Legacy\LegacyArticle',
113 113 'Doctrine\Tests\Models\Legacy\LegacyCar',
114 114 ),
  115 + 'customtype' => array(
  116 + 'Doctrine\Tests\Models\CustomType\CustomTypeChild',
  117 + 'Doctrine\Tests\Models\CustomType\CustomTypeParent',
  118 + 'Doctrine\Tests\Models\CustomType\CustomTypeUpperCase',
  119 + ),
115 120 );
116 121
117 122 protected function useModelSet($setName)
@@ -219,6 +224,13 @@ protected function tearDown()
219 224 $conn->executeUpdate('DELETE FROM legacy_users');
220 225 }
221 226
  227 + if (isset($this->_usedModelSets['customtype'])) {
  228 + $conn->executeUpdate('DELETE FROM customtype_parent_friends');
  229 + $conn->executeUpdate('DELETE FROM customtype_parents');
  230 + $conn->executeUpdate('DELETE FROM customtype_children');
  231 + $conn->executeUpdate('DELETE FROM customtype_uppercases');
  232 + }
  233 +
222 234 $this->_em->clear();
223 235 }
224 236

0 comments on commit be4eb63

Please sign in to comment.
Something went wrong with that request. Please try again.