Permalink
Browse files

Initial implementation of Doctrine\DBAL\Types\Type::convertToDatabase…

…ValueSQL() and Doctrine\DBAL\Types\Type::convertToPHPValueSQL() integration
  • Loading branch information...
1 parent 43b1e79 commit 6f356799115b1edf17309f826345da82b16ce7f2 @jsor jsor committed Nov 18, 2011
@@ -65,6 +65,11 @@ protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r
$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;
}
@@ -338,10 +338,19 @@ public function update($entity)
$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 @@ protected function _getInsertSQL()
);
} 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 @@ protected function _getInsertColumnList()
}
} 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 @@ protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r
$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,13 +1285,20 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
foreach ($criteria as $field => $value) {
$conditionSql .= $conditionSql ? ' AND ' : '';
+
+ $placeholder = '?';
if (isset($this->_class->columnNames[$field])) {
$className = (isset($this->_class->fieldMappings[$field]['inherited']))
? $this->_class->fieldMappings[$field]['inherited']
: $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 @@ protected function _getSelectConditionSQL(array $criteria, $assoc = null)
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;
}
@@ -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 @@ public function walkSelectStatement(AST\SelectStatement $AST)
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 @@ public function walkPathExpression($pathExpr)
$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 @@ public function walkSelectExpression($selectExpression)
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
- $columnAlias = $this->getSQLColumnAlias($columnName);
+ $columnAlias = $this->getSQLColumnAlias($columnName);
+
+ $col = $sqlTableAlias . '.' . $columnName;
+
+ if (!$class->isIdentifier($fieldName)) {
+ $type = Type::getType($class->getTypeOfField($fieldName));
+ $col = $type->convertToPHPValueSQL($col, $this->_conn->getDatabasePlatform());
+ }
- $sql .= $sqlTableAlias . '.' . $columnName . ' AS ' . $columnAlias;
+ $sql .= $col . ' AS ' . $columnAlias;
if ( ! $hidden) {
$this->_rsm->addScalarResult($columnAlias, $resultAlias);
@@ -1086,7 +1115,14 @@ public function walkSelectExpression($selectExpression)
$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 @@ public function walkSelectExpression($selectExpression)
$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 @@ public function walkUpdateItem($updateItem)
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 @@ public function walkLiteral($literal)
{
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;
}
/**
@@ -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)';
+ }
+}
@@ -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 $_lastInsertId = 0;
private $_inserts = array();
+ private $_executeUpdates = array();
public function __construct(array $params, $driver, $config = null, $eventManager = null)
{
@@ -35,6 +36,14 @@ public function insert($tableName, array $data, array $types = array())
$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
*/
@@ -84,6 +93,11 @@ public function getInserts()
return $this->_inserts;
}
+ public function getExecuteUpdates()
+ {
+ return $this->_executeUpdates;
+ }
+
public function reset()
{
$this->_inserts = array();
@@ -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';
+}
Oops, something went wrong.

0 comments on commit 6f35679

Please sign in to comment.