Initial implementation of Doctrine\DBAL\Types\Type::convertToDatabaseValueSQL() and Doctrine\DBAL\Types\Type::convertToPHPValueSQL() integration
This commit is contained in:
parent
43b1e79ec4
commit
6f35679911
@ -65,6 +65,11 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
|
|||||||
$columnAlias = $this->getSQLColumnAlias($columnName);
|
$columnAlias = $this->getSQLColumnAlias($columnName);
|
||||||
$this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
|
$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;
|
return $sql . ' AS ' . $columnAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,10 +338,19 @@ class BasicEntityPersister
|
|||||||
$set = $params = $types = array();
|
$set = $params = $types = array();
|
||||||
|
|
||||||
foreach ($updateData as $columnName => $value) {
|
foreach ($updateData as $columnName => $value) {
|
||||||
$set[] = (isset($this->_class->fieldNames[$columnName]))
|
$column = $columnName;
|
||||||
? $this->_class->getQuotedColumnName($this->_class->fieldNames[$columnName], $this->_platform) . ' = ?'
|
$placeholder = '?';
|
||||||
: $columnName . ' = ?';
|
|
||||||
|
|
||||||
|
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;
|
$params[] = $value;
|
||||||
$types[] = $this->_columnTypes[$columnName];
|
$types[] = $this->_columnTypes[$columnName];
|
||||||
}
|
}
|
||||||
@ -1117,7 +1126,18 @@ class BasicEntityPersister
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
$columns = array_unique($columns);
|
$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)
|
$insertSql = 'INSERT INTO ' . $this->_class->getQuotedTableName($this->_platform)
|
||||||
. ' (' . implode(', ', $columns) . ') VALUES (' . implode(', ', $values) . ')';
|
. ' (' . 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) {
|
} else if ($this->_class->generatorType != ClassMetadata::GENERATOR_TYPE_IDENTITY || $this->_class->identifier[0] != $name) {
|
||||||
$columns[] = $this->_class->getQuotedColumnName($name, $this->_platform);
|
$columns[] = $this->_class->getQuotedColumnName($name, $this->_platform);
|
||||||
|
$this->_columnTypes[$name] = $this->_class->fieldMappings[$name]['type'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1178,6 +1199,11 @@ class BasicEntityPersister
|
|||||||
|
|
||||||
$this->_rsm->addFieldResult($alias, $columnAlias, $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;
|
return $sql . ' AS ' . $columnAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1260,12 +1286,19 @@ class BasicEntityPersister
|
|||||||
foreach ($criteria as $field => $value) {
|
foreach ($criteria as $field => $value) {
|
||||||
$conditionSql .= $conditionSql ? ' AND ' : '';
|
$conditionSql .= $conditionSql ? ' AND ' : '';
|
||||||
|
|
||||||
|
$placeholder = '?';
|
||||||
|
|
||||||
if (isset($this->_class->columnNames[$field])) {
|
if (isset($this->_class->columnNames[$field])) {
|
||||||
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
|
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
|
||||||
? $this->_class->fieldMappings[$field]['inherited']
|
? $this->_class->fieldMappings[$field]['inherited']
|
||||||
: $this->_class->name;
|
: $this->_class->name;
|
||||||
|
|
||||||
$conditionSql .= $this->_getSQLTableAlias($className) . '.' . $this->_class->getQuotedColumnName($field, $this->_platform);
|
$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])) {
|
} else if (isset($this->_class->associationMappings[$field])) {
|
||||||
if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
|
if ( ! $this->_class->associationMappings[$field]['isOwningSide']) {
|
||||||
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
|
throw ORMException::invalidFindByInverseAssociation($this->_class->name, $field);
|
||||||
@ -1286,7 +1319,7 @@ class BasicEntityPersister
|
|||||||
throw ORMException::unrecognizedField($field);
|
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;
|
return $conditionSql;
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
namespace Doctrine\ORM\Query;
|
namespace Doctrine\ORM\Query;
|
||||||
|
|
||||||
use Doctrine\DBAL\LockMode,
|
use Doctrine\DBAL\LockMode,
|
||||||
|
Doctrine\DBAL\Types\Type,
|
||||||
Doctrine\ORM\Mapping\ClassMetadata,
|
Doctrine\ORM\Mapping\ClassMetadata,
|
||||||
Doctrine\ORM\Query,
|
Doctrine\ORM\Query,
|
||||||
Doctrine\ORM\Query\QueryException,
|
Doctrine\ORM\Query\QueryException,
|
||||||
@ -97,6 +98,17 @@ class SqlWalker implements TreeWalker
|
|||||||
*/
|
*/
|
||||||
private $_useSqlTableAliases = true;
|
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.
|
* The database platform abstraction.
|
||||||
*
|
*
|
||||||
@ -409,6 +421,7 @@ class SqlWalker implements TreeWalker
|
|||||||
public function walkUpdateStatement(AST\UpdateStatement $AST)
|
public function walkUpdateStatement(AST\UpdateStatement $AST)
|
||||||
{
|
{
|
||||||
$this->_useSqlTableAliases = false;
|
$this->_useSqlTableAliases = false;
|
||||||
|
$this->_useDbalTypeValueSql = false;
|
||||||
|
|
||||||
return $this->walkUpdateClause($AST->updateClause) . $this->walkWhereClause($AST->whereClause);
|
return $this->walkUpdateClause($AST->updateClause) . $this->walkWhereClause($AST->whereClause);
|
||||||
}
|
}
|
||||||
@ -464,11 +477,20 @@ class SqlWalker implements TreeWalker
|
|||||||
$dqlAlias = $pathExpr->identificationVariable;
|
$dqlAlias = $pathExpr->identificationVariable;
|
||||||
$class = $this->_queryComponents[$dqlAlias]['metadata'];
|
$class = $this->_queryComponents[$dqlAlias]['metadata'];
|
||||||
|
|
||||||
|
$column = '';
|
||||||
|
|
||||||
if ($this->_useSqlTableAliases) {
|
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;
|
break;
|
||||||
|
|
||||||
case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION:
|
case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION:
|
||||||
@ -1004,7 +1026,14 @@ class SqlWalker implements TreeWalker
|
|||||||
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
|
$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) {
|
if ( ! $hidden) {
|
||||||
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
|
||||||
@ -1086,7 +1115,14 @@ class SqlWalker implements TreeWalker
|
|||||||
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
||||||
$quotedColumnName = $class->getQuotedColumnName($fieldName, $this->_platform);
|
$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);
|
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $class->name);
|
||||||
}
|
}
|
||||||
@ -1108,7 +1144,14 @@ class SqlWalker implements TreeWalker
|
|||||||
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
$columnAlias = $this->getSQLColumnAlias($mapping['columnName']);
|
||||||
$quotedColumnName = $subClass->getQuotedColumnName($fieldName, $this->_platform);
|
$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);
|
$this->_rsm->addFieldResult($dqlAlias, $columnAlias, $fieldName, $subClassName);
|
||||||
}
|
}
|
||||||
@ -1386,7 +1429,18 @@ class SqlWalker implements TreeWalker
|
|||||||
|
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case ($newValue instanceof AST\Node):
|
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);
|
$sql .= $newValue->dispatch($this);
|
||||||
|
$this->_currentColumnType = $currentColumnTypeBefore;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ($newValue === null):
|
case ($newValue === null):
|
||||||
@ -1759,20 +1813,30 @@ class SqlWalker implements TreeWalker
|
|||||||
{
|
{
|
||||||
switch ($literal->type) {
|
switch ($literal->type) {
|
||||||
case AST\Literal::STRING:
|
case AST\Literal::STRING:
|
||||||
return $this->_conn->quote($literal->value);
|
$value = $this->_conn->quote($literal->value);
|
||||||
|
break;
|
||||||
|
|
||||||
case AST\Literal::BOOLEAN:
|
case AST\Literal::BOOLEAN:
|
||||||
$bool = strtolower($literal->value) == 'true' ? true : false;
|
$bool = strtolower($literal->value) == 'true' ? true : false;
|
||||||
$boolVal = $this->_conn->getDatabasePlatform()->convertBooleans($bool);
|
$boolVal = $this->_conn->getDatabasePlatform()->convertBooleans($bool);
|
||||||
|
|
||||||
return $boolVal;
|
$value = $boolVal;
|
||||||
|
break;
|
||||||
|
|
||||||
case AST\Literal::NUMERIC:
|
case AST\Literal::NUMERIC:
|
||||||
return $literal->value;
|
$value = $literal->value;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw QueryException::invalidLiteral($literal);
|
throw QueryException::invalidLiteral($literal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->_currentColumnType !== null) {
|
||||||
|
$type = Type::getType($this->_currentColumnType);
|
||||||
|
$value = $type->convertToDatabaseValueSQL($value, $this->_conn->getDatabasePlatform());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
34
tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php
Normal file
34
tests/Doctrine/Tests/DbalTypes/NegativeToPositiveType.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\DbalTypes;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
|
||||||
|
class NegativeToPositiveType extends Type
|
||||||
|
{
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'negative_to_positive';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canRequireSQLConversion()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
return 'ABS(' . $sqlExpr . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToPHPValueSQL($sqlExpr, $platform)
|
||||||
|
{
|
||||||
|
return '((' . $sqlExpr . ') * -1)';
|
||||||
|
}
|
||||||
|
}
|
29
tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php
Normal file
29
tests/Doctrine/Tests/DbalTypes/UpperCaseStringType.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\DbalTypes;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\StringType;
|
||||||
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
|
||||||
|
class UpperCaseStringType extends StringType
|
||||||
|
{
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return 'upper_case_string';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canRequireSQLConversion()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
return 'UPPER(' . $sqlExpr . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToPHPValueSQL($sqlExpr, $platform)
|
||||||
|
{
|
||||||
|
return 'LOWER(' . $sqlExpr . ')';
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
|||||||
private $_platformMock;
|
private $_platformMock;
|
||||||
private $_lastInsertId = 0;
|
private $_lastInsertId = 0;
|
||||||
private $_inserts = array();
|
private $_inserts = array();
|
||||||
|
private $_executeUpdates = array();
|
||||||
|
|
||||||
public function __construct(array $params, $driver, $config = null, $eventManager = null)
|
public function __construct(array $params, $driver, $config = null, $eventManager = null)
|
||||||
{
|
{
|
||||||
@ -35,6 +36,14 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
|||||||
$this->_inserts[$tableName][] = $data;
|
$this->_inserts[$tableName][] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @override
|
||||||
|
*/
|
||||||
|
public function executeUpdate($query, array $params = array(), array $types = array())
|
||||||
|
{
|
||||||
|
$this->_executeUpdates[] = array('query' => $query, 'params' => $params, 'types' => $types);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
@ -84,6 +93,11 @@ class ConnectionMock extends \Doctrine\DBAL\Connection
|
|||||||
return $this->_inserts;
|
return $this->_inserts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getExecuteUpdates()
|
||||||
|
{
|
||||||
|
return $this->_executeUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
public function reset()
|
public function reset()
|
||||||
{
|
{
|
||||||
$this->_inserts = array();
|
$this->_inserts = array();
|
||||||
|
21
tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php
Normal file
21
tests/Doctrine/Tests/Models/CustomType/CustomTypeChild.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\CustomType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="customtype_children")
|
||||||
|
*/
|
||||||
|
class CustomTypeChild
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id @Column(type="negative_to_positive")
|
||||||
|
* @GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(type="upper_case_string")
|
||||||
|
*/
|
||||||
|
public $lowerCaseString = 'foo';
|
||||||
|
}
|
68
tests/Doctrine/Tests/Models/CustomType/CustomTypeParent.php
Normal file
68
tests/Doctrine/Tests/Models/CustomType/CustomTypeParent.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\CustomType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="customtype_parents")
|
||||||
|
*/
|
||||||
|
class CustomTypeParent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id @Column(type="negative_to_positive")
|
||||||
|
* @GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(type="negative_to_positive", nullable=true)
|
||||||
|
*/
|
||||||
|
public $customInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OneToOne(targetEntity="Doctrine\Tests\Models\CustomType\CustomTypeChild", cascade={"persist", "remove"})
|
||||||
|
*/
|
||||||
|
public $child;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToMany(targetEntity="Doctrine\Tests\Models\CustomType\CustomTypeParent", mappedBy="myFriends")
|
||||||
|
*/
|
||||||
|
private $friendsWithMe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ManyToMany(targetEntity="Doctrine\Tests\Models\CustomType\CustomTypeParent", inversedBy="friendsWithMe")
|
||||||
|
* @JoinTable(
|
||||||
|
* name="customtype_parent_friends",
|
||||||
|
* joinColumns={@JoinColumn(name="customtypeparent_id", referencedColumnName="id")},
|
||||||
|
* inverseJoinColumns={@JoinColumn(name="friend_customtypeparent_id", referencedColumnName="id")}
|
||||||
|
* )
|
||||||
|
*/
|
||||||
|
private $myFriends;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\CustomType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table(name="customtype_uppercases")
|
||||||
|
*/
|
||||||
|
class CustomTypeUpperCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id @Column(type="integer")
|
||||||
|
* @GeneratedValue(strategy="AUTO")
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(type="upper_case_string")
|
||||||
|
*/
|
||||||
|
public $lowerCaseString;
|
||||||
|
}
|
104
tests/Doctrine/Tests/ORM/Functional/TypeValueSqlTest.php
Normal file
104
tests/Doctrine/Tests/ORM/Functional/TypeValueSqlTest.php
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
|
use Doctrine\Tests\Models\CustomType\CustomTypeChild;
|
||||||
|
use Doctrine\Tests\Models\CustomType\CustomTypeParent;
|
||||||
|
use Doctrine\Tests\Models\CustomType\CustomTypeUpperCase;
|
||||||
|
use Doctrine\DBAL\Types\Type as DBALType;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
|
class TypeValueSqlTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||||
|
{
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
if (DBALType::hasType('upper_case_string')) {
|
||||||
|
DBALType::overrideType('upper_case_string', '\Doctrine\Tests\DbalTypes\UpperCaseStringType');
|
||||||
|
} else {
|
||||||
|
DBALType::addType('upper_case_string', '\Doctrine\Tests\DbalTypes\UpperCaseStringType');
|
||||||
|
}
|
||||||
|
|
||||||
|
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->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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type as DBALType;
|
||||||
|
use Doctrine\ORM\Persisters\BasicEntityPersister;
|
||||||
|
use Doctrine\Tests\Models\CustomType\CustomTypeParent;
|
||||||
|
use Doctrine\Tests\Models\CustomType\CustomTypeChild;
|
||||||
|
use Doctrine\Tests\Models\CustomType\CustomTypeFriend;
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
|
class BasicEntityPersisterTypeValueSqlTest extends \Doctrine\Tests\OrmTestCase
|
||||||
|
{
|
||||||
|
protected $_persister;
|
||||||
|
protected $_em;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->_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);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Doctrine\Tests\ORM\Query;
|
namespace Doctrine\Tests\ORM\Query;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type as DBALType;
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
|
|
||||||
require_once __DIR__ . '/../../TestInit.php';
|
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'
|
'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_'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
namespace Doctrine\Tests\ORM\Query;
|
namespace Doctrine\Tests\ORM\Query;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Types\Type as DBALType;
|
||||||
|
|
||||||
require_once __DIR__ . '/../../TestInit.php';
|
require_once __DIR__ . '/../../TestInit.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,6 +44,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
|||||||
private $_em;
|
private $_em;
|
||||||
|
|
||||||
protected function setUp() {
|
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();
|
$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"
|
"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'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
'Doctrine\Tests\Models\Legacy\LegacyArticle',
|
'Doctrine\Tests\Models\Legacy\LegacyArticle',
|
||||||
'Doctrine\Tests\Models\Legacy\LegacyCar',
|
'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)
|
protected function useModelSet($setName)
|
||||||
@ -219,6 +224,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
$conn->executeUpdate('DELETE FROM legacy_users');
|
$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();
|
$this->_em->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user