[2.0] Introduced SQL logging facilities. Made Type constructor private to prevent instantiation and force use of the factory method getType().
This commit is contained in:
parent
0ed8e7a34b
commit
a758b56551
23 changed files with 1318 additions and 1260 deletions
|
@ -47,9 +47,30 @@ class Configuration
|
|||
public function __construct()
|
||||
{
|
||||
$this->_attributes = array(
|
||||
'quoteIdentifiers' => false
|
||||
'quoteIdentifiers' => false,
|
||||
'sqlLogger' => null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled.
|
||||
*
|
||||
* @param SqlLogger $logger
|
||||
*/
|
||||
public function setSqlLogger($logger)
|
||||
{
|
||||
$this->_attributes['sqlLogger'] = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL logger that is used.
|
||||
*
|
||||
* @return SqlLogger
|
||||
*/
|
||||
public function getSqlLogger()
|
||||
{
|
||||
return $this->_attributes['sqlLogger'];
|
||||
}
|
||||
|
||||
public function getQuoteIdentifiers()
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
20
lib/Doctrine/DBAL/Logging/EchoSqlLogger.php
Normal file
20
lib/Doctrine/DBAL/Logging/EchoSqlLogger.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Doctrine\DBAL\Logging;
|
||||
|
||||
/**
|
||||
* A SQL logger that logs to the standard output using echo/var_dump.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
class EchoSqlLogger implements SqlLogger
|
||||
{
|
||||
public function logSql($sql, array $params = null)
|
||||
{
|
||||
echo $sql . PHP_EOL;
|
||||
if ($params) {
|
||||
var_dump($params);
|
||||
}
|
||||
}
|
||||
}
|
14
lib/Doctrine/DBAL/Logging/SqlLogger.php
Normal file
14
lib/Doctrine/DBAL/Logging/SqlLogger.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Doctrine\DBAL\Logging;
|
||||
|
||||
/**
|
||||
* Interface for SQL loggers.
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
interface SqlLogger
|
||||
{
|
||||
public function logSql($sql, array $params = null);
|
||||
}
|
|
@ -37,6 +37,9 @@ abstract class Type
|
|||
'double' => 'Doctrine\DBAL\Types\DoubleType'
|
||||
);
|
||||
|
||||
/* Prevent instantiation and force use of the factory method. */
|
||||
private function __construct() {}
|
||||
|
||||
public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
|
||||
{
|
||||
return $value;
|
||||
|
|
|
@ -170,11 +170,11 @@ class EntityManager
|
|||
}
|
||||
|
||||
/**
|
||||
* Starts a transaction on the underlying connection.
|
||||
* Starts a transaction on the underlying database connection.
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
return $this->_conn->beginTransaction();
|
||||
$this->_conn->beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,15 +182,23 @@ class EntityManager
|
|||
*
|
||||
* This causes a flush() of the EntityManager if the flush mode is set to
|
||||
* AUTO or COMMIT.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
if ($this->_flushMode == self::FLUSHMODE_AUTO || $this->_flushMode == self::FLUSHMODE_COMMIT) {
|
||||
$this->flush();
|
||||
}
|
||||
return $this->_conn->commitTransaction();
|
||||
$this->_conn->commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a rollback on the underlying database connection and closes the
|
||||
* EntityManager as it may now be in a corrupted state.
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->_conn->rollback();
|
||||
$this->close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,6 +409,7 @@ class EntityManager
|
|||
*/
|
||||
public function refresh($entity)
|
||||
{
|
||||
$this->_errorIfClosed();
|
||||
throw DoctrineException::notImplemented();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Doctrine\ORM;
|
|||
*
|
||||
* This class cannot be instantiated.
|
||||
*
|
||||
* @author robo
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
final class Events
|
||||
|
@ -35,6 +35,9 @@ final class Events
|
|||
|
||||
const preDelete = 'preDelete';
|
||||
const postDelete = 'postDelete';
|
||||
const preSave = 'preSave';
|
||||
const postSave = 'postSave';
|
||||
const preInsert = 'preSave';
|
||||
const postInsert = 'postSave';
|
||||
const preUpdate = 'preUpdate';
|
||||
const postUpdate = 'postUpdate';
|
||||
const load = 'load';
|
||||
}
|
|
@ -185,7 +185,7 @@ abstract class AbstractHydrator
|
|||
$classMetadata = $this->_lookupDeclaringClass($classMetadata, $fieldName);
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['isScalar'] = false;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->getTypeOfField($fieldName));
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
} else {
|
||||
|
|
|
@ -55,17 +55,12 @@ class ArrayHydrator extends AbstractHydrator
|
|||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
{
|
||||
$s = microtime(true);
|
||||
|
||||
$result = array();
|
||||
$cache = array();
|
||||
while ($data = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_hydrateRow($data, $cache, $result);
|
||||
}
|
||||
|
||||
$e = microtime(true);
|
||||
echo 'Hydration took: ' . ($e - $s) . PHP_EOL;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,8 +113,6 @@ class ObjectHydrator extends AbstractHydrator
|
|||
*/
|
||||
protected function _hydrateAll()
|
||||
{
|
||||
$s = microtime(true);
|
||||
|
||||
$result = $this->_rsm->isMixed ? array() : new Collection;
|
||||
|
||||
$cache = array();
|
||||
|
@ -132,10 +130,6 @@ class ObjectHydrator extends AbstractHydrator
|
|||
$this->_collections = array();
|
||||
$this->_initializedRelations = array();
|
||||
|
||||
$e = microtime(true);
|
||||
|
||||
echo 'Hydration took: ' . ($e - $s) . ' for '.count($result).' records' . PHP_EOL;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -279,10 +273,10 @@ class ObjectHydrator extends AbstractHydrator
|
|||
*/
|
||||
private function setRelatedElement($entity1, $property, $entity2)
|
||||
{
|
||||
$classMetadata1 = $this->_ce[get_class($entity1)];
|
||||
$classMetadata1->reflFields[$property]->setValue($entity1, $entity2);
|
||||
$class = $this->_ce[get_class($entity1)];
|
||||
$class->reflFields[$property]->setValue($entity1, $entity2);
|
||||
$this->_uow->setOriginalEntityProperty(spl_object_hash($entity1), $property, $entity2);
|
||||
$relation = $classMetadata1->associationMappings[$property];
|
||||
$relation = $class->associationMappings[$property];
|
||||
if ($relation->isOneToOne()) {
|
||||
$targetClass = $this->_ce[$relation->targetEntityName];
|
||||
if ($relation->isOwningSide) {
|
||||
|
@ -290,7 +284,7 @@ class ObjectHydrator extends AbstractHydrator
|
|||
if (isset($targetClass->inverseMappings[$property])) {
|
||||
$sourceProp = $targetClass->inverseMappings[$property]->sourceFieldName;
|
||||
$targetClass->reflFields[$sourceProp]->setValue($entity2, $entity1);
|
||||
} else if ($classMetadata1 === $targetClass) {
|
||||
} else if ($class === $targetClass) {
|
||||
// Special case: self-referencing one-one on the same class
|
||||
$targetClass->reflFields[$property]->setValue($entity2, $entity1);
|
||||
}
|
||||
|
|
|
@ -253,15 +253,6 @@ final class ClassMetadata
|
|||
* @var array
|
||||
*/
|
||||
public $columnNames = array();
|
||||
|
||||
/**
|
||||
* Map that maps lowercased column names (keys) to field names (values).
|
||||
* Mainly used during hydration because Doctrine enforces PDO_CASE_LOWER
|
||||
* for portability.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $lcColumnToFieldNames = array();
|
||||
|
||||
/**
|
||||
* Whether to automatically OUTER JOIN subtypes when a basetype is queried.
|
||||
|
@ -724,29 +715,6 @@ final class ClassMetadata
|
|||
$this->fieldNames[$columnName] : $columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field name for a completely lowercased column name.
|
||||
* Mainly used during hydration.
|
||||
*
|
||||
* @param string $lcColumnName The all-lowercase column name.
|
||||
* @return string The field name.
|
||||
*/
|
||||
public function getFieldNameForLowerColumnName($lcColumnName)
|
||||
{
|
||||
return $this->lcColumnToFieldNames[$lcColumnName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a specified column name (all lowercase) exists in this class.
|
||||
*
|
||||
* @param string $lcColumnName
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasLowerColumn($lcColumnName)
|
||||
{
|
||||
return isset($this->lcColumnToFieldNames[$lcColumnName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates & completes the given field mapping.
|
||||
*
|
||||
|
@ -767,11 +735,9 @@ final class ClassMetadata
|
|||
if ( ! isset($mapping['columnName'])) {
|
||||
$mapping['columnName'] = $mapping['fieldName'];
|
||||
}
|
||||
$lcColumnName = strtolower($mapping['columnName']);
|
||||
|
||||
$this->columnNames[$mapping['fieldName']] = $mapping['columnName'];
|
||||
$this->fieldNames[$mapping['columnName']] = $mapping['fieldName'];
|
||||
$this->lcColumnToFieldNames[$lcColumnName] = $mapping['fieldName'];
|
||||
|
||||
// Complete id mapping
|
||||
if (isset($mapping['id']) && $mapping['id'] === true) {
|
||||
|
|
|
@ -246,6 +246,7 @@ class ClassMetadataFactory
|
|||
// Generate INSERT SQL
|
||||
$columns = $values = array();
|
||||
if ($class->inheritanceType == ClassMetadata::INHERITANCE_TYPE_JOINED) {
|
||||
// Generate INSERT SQL for inheritance type JOINED
|
||||
foreach ($class->reflFields as $name => $field) {
|
||||
if (isset($class->fieldMappings[$name]['inherited']) && ! isset($class->fieldMappings[$name]['id'])
|
||||
|| isset($class->inheritedAssociationFields[$name])) {
|
||||
|
@ -266,6 +267,7 @@ class ClassMetadataFactory
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// Generate INSERT SQL for inheritance types NONE, SINGLE_TABLE, TABLE_PER_CLASS
|
||||
foreach ($class->reflFields as $name => $field) {
|
||||
if (isset($class->associationMappings[$name])) {
|
||||
$assoc = $class->associationMappings[$name];
|
||||
|
@ -281,6 +283,8 @@ class ClassMetadataFactory
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add discriminator column to the INSERT SQL if necessary
|
||||
if ($class->isInheritanceTypeSingleTable() || $class->isInheritanceTypeJoined() && $class->name == $class->rootEntityName) {
|
||||
$columns[] = $class->discriminatorColumn['name'];
|
||||
$values[] = '?';
|
||||
|
|
|
@ -53,6 +53,7 @@ final class DoctrineColumn extends \Addendum\Annotation {
|
|||
public $length;
|
||||
public $unique = false;
|
||||
public $nullable = false;
|
||||
public $quote = false;
|
||||
}
|
||||
final class DoctrineOneToOne extends \Addendum\Annotation {
|
||||
public $targetEntity;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
|
@ -36,227 +36,252 @@ use Doctrine\Common\DoctrineException;
|
|||
*/
|
||||
class JoinedSubclassPersister extends StandardEntityPersister
|
||||
{
|
||||
/** Map that maps column names to the table names that own them.
|
||||
* This is mainly a temporary cache, used during a single request.
|
||||
*/
|
||||
private $_owningTableMap = array();
|
||||
/** Map that maps column names to the table names that own them.
|
||||
* This is mainly a temporary cache, used during a single request.
|
||||
*/
|
||||
private $_owningTableMap = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||
{
|
||||
parent::_prepareData($entity, $result, $isInsert);
|
||||
// Populate the discriminator column
|
||||
if ($isInsert) {
|
||||
$discColumn = $this->_class->discriminatorColumn;
|
||||
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
|
||||
$result[$rootClass->primaryTable['name']][$discColumn['name']] =
|
||||
$this->_class->discriminatorValue;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||
{
|
||||
parent::_prepareData($entity, $result, $isInsert);
|
||||
// Populate the discriminator column
|
||||
if ($isInsert) {
|
||||
$discColumn = $this->_class->discriminatorColumn;
|
||||
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
|
||||
$result[$rootClass->primaryTable['name']][$discColumn['name']] =
|
||||
$this->_class->discriminatorValue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function getOwningTable($fieldName)
|
||||
{
|
||||
if ( ! isset($this->_owningTableMap[$fieldName])) {
|
||||
if (isset($this->_class->associationMappings[$fieldName])) {
|
||||
if (isset($this->_class->inheritedAssociationFields[$fieldName])) {
|
||||
$this->_owningTableMap[$fieldName] = $this->_em->getClassMetadata(
|
||||
$this->_class->inheritedAssociationFields[$fieldName])->primaryTable['name'];
|
||||
} else {
|
||||
$this->_owningTableMap[$fieldName] = $this->_class->primaryTable['name'];
|
||||
}
|
||||
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
|
||||
$this->_owningTableMap[$fieldName] = $this->_em->getClassMetadata(
|
||||
$this->_class->fieldMappings[$fieldName]['inherited'])->primaryTable['name'];
|
||||
} else {
|
||||
$this->_owningTableMap[$fieldName] = $this->_class->primaryTable['name'];
|
||||
}
|
||||
}
|
||||
return $this->_owningTableMap[$fieldName];
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function getOwningTable($fieldName)
|
||||
{
|
||||
if ( ! isset($this->_owningTableMap[$fieldName])) {
|
||||
if (isset($this->_class->associationMappings[$fieldName])) {
|
||||
if (isset($this->_class->inheritedAssociationFields[$fieldName])) {
|
||||
$this->_owningTableMap[$fieldName] = $this->_em->getClassMetadata(
|
||||
$this->_class->inheritedAssociationFields[$fieldName])->primaryTable['name'];
|
||||
} else {
|
||||
$this->_owningTableMap[$fieldName] = $this->_class->primaryTable['name'];
|
||||
}
|
||||
} else if (isset($this->_class->fieldMappings[$fieldName]['inherited'])) {
|
||||
$this->_owningTableMap[$fieldName] = $this->_em->getClassMetadata(
|
||||
$this->_class->fieldMappings[$fieldName]['inherited'])->primaryTable['name'];
|
||||
} else {
|
||||
$this->_owningTableMap[$fieldName] = $this->_class->primaryTable['name'];
|
||||
}
|
||||
}
|
||||
return $this->_owningTableMap[$fieldName];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function executeInserts()
|
||||
{
|
||||
if ( ! $this->_queuedInserts) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
public function executeInserts()
|
||||
{
|
||||
if ( ! $this->_queuedInserts) {
|
||||
return;
|
||||
}
|
||||
|
||||
$postInsertIds = array();
|
||||
$idGen = $this->_class->idGenerator;
|
||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||
$postInsertIds = array();
|
||||
$idGen = $this->_class->idGenerator;
|
||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||
$sqlLogger = $this->_conn->getConfiguration()->getSqlLogger();
|
||||
|
||||
// Prepare statements for all tables
|
||||
$stmts = $classes = array();
|
||||
$stmts[$this->_class->primaryTable['name']] = $this->_conn->prepare($this->_class->insertSql);
|
||||
$classes[$this->_class->name] = $this->_class;
|
||||
foreach ($this->_class->parentClasses as $parentClass) {
|
||||
$classes[$parentClass] = $this->_em->getClassMetadata($parentClass);
|
||||
$stmts[$classes[$parentClass]->primaryTable['name']] = $this->_conn->prepare($classes[$parentClass]->insertSql);
|
||||
}
|
||||
$rootTableName = $classes[$this->_class->rootEntityName]->primaryTable['name'];
|
||||
// Prepare statements for all tables
|
||||
$stmts = $classes = array();
|
||||
$stmts[$this->_class->primaryTable['name']] = $this->_conn->prepare($this->_class->insertSql);
|
||||
$sql[$this->_class->primaryTable['name']] = $this->_class->insertSql;
|
||||
foreach ($this->_class->parentClasses as $parentClass) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClass);
|
||||
$sql[$parentClass->primaryTable['name']] = $parentClass->insertSql;
|
||||
$stmts[$parentClass->primaryTable['name']] = $this->_conn->prepare($parentClass->insertSql);
|
||||
}
|
||||
$rootTableName = $this->_em->getClassMetadata($this->_class->rootEntityName)->primaryTable['name'];
|
||||
|
||||
foreach ($this->_queuedInserts as $entity) {
|
||||
$insertData = array();
|
||||
$this->_prepareData($entity, $insertData, true);
|
||||
|
||||
// Execute insert on root table
|
||||
$paramIndex = 1;
|
||||
$stmt = $stmts[$rootTableName];
|
||||
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
||||
$stmt->bindValue($paramIndex++, $value/*, TODO: TYPE*/);
|
||||
}
|
||||
$stmt->execute();
|
||||
unset($insertData[$rootTableName]);
|
||||
foreach ($this->_queuedInserts as $entity) {
|
||||
$insertData = array();
|
||||
$this->_prepareData($entity, $insertData, true);
|
||||
|
||||
if ($isPostInsertId) {
|
||||
$id = $idGen->generate($this->_em, $entity);
|
||||
$postInsertIds[$id] = $entity;
|
||||
} else {
|
||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
||||
}
|
||||
// Execute insert on root table
|
||||
$stmt = $stmts[$rootTableName];
|
||||
$paramIndex = 1;
|
||||
if ($sqlLogger) {
|
||||
$params = array();
|
||||
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
||||
$params[$paramIndex] = $value;
|
||||
$stmt->bindValue($paramIndex++, $value/*, TODO: TYPE*/);
|
||||
}
|
||||
$sqlLogger->logSql($sql[$rootTableName], $params);
|
||||
} else {
|
||||
foreach ($insertData[$rootTableName] as $columnName => $value) {
|
||||
$stmt->bindValue($paramIndex++, $value/*, TODO: TYPE*/);
|
||||
}
|
||||
}
|
||||
$stmt->execute();
|
||||
unset($insertData[$rootTableName]);
|
||||
|
||||
// Execute inserts on subtables
|
||||
foreach ($insertData as $tableName => $data) {
|
||||
$stmt = $stmts[$tableName];
|
||||
$paramIndex = 1;
|
||||
foreach ((array)$id as $idVal) {
|
||||
$stmt->bindValue($paramIndex++, $idVal/*, TODO: TYPE*/);
|
||||
}
|
||||
foreach ($data as $columnName => $value) {
|
||||
$stmt->bindValue($paramIndex++, $value/*, TODO: TYPE*/);
|
||||
}
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
if ($isPostInsertId) {
|
||||
$id = $idGen->generate($this->_em, $entity);
|
||||
$postInsertIds[$id] = $entity;
|
||||
} else {
|
||||
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($entity);
|
||||
}
|
||||
|
||||
foreach ($stmts as $stmt)
|
||||
$stmt->closeCursor();
|
||||
// Execute inserts on subtables
|
||||
foreach ($insertData as $tableName => $data) {
|
||||
$stmt = $stmts[$tableName];
|
||||
$paramIndex = 1;
|
||||
if ($sqlLogger) {
|
||||
//TODO: Log type
|
||||
$params = array();
|
||||
foreach ((array)$id as $idVal) {
|
||||
$params[$paramIndex] = $idVal;
|
||||
$stmt->bindValue($paramIndex++, $idVal/*, TODO: TYPE*/);
|
||||
}
|
||||
foreach ($data as $columnName => $value) {
|
||||
$params[$paramIndex] = $value;
|
||||
$stmt->bindValue($paramIndex++, $value/*, TODO: TYPE*/);
|
||||
}
|
||||
$sqlLogger->logSql($sql[$tableName], $params);
|
||||
} else {
|
||||
foreach ((array)$id as $idVal) {
|
||||
$stmt->bindValue($paramIndex++, $idVal/*, TODO: TYPE*/);
|
||||
}
|
||||
foreach ($data as $columnName => $value) {
|
||||
$stmt->bindValue($paramIndex++, $value/*, TODO: TYPE*/);
|
||||
}
|
||||
}
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$this->_queuedInserts = array();
|
||||
foreach ($stmts as $stmt)
|
||||
$stmt->closeCursor();
|
||||
|
||||
return $postInsertIds;
|
||||
}
|
||||
$this->_queuedInserts = array();
|
||||
|
||||
/**
|
||||
* Updates an entity.
|
||||
*
|
||||
* @param object $entity The entity to update.
|
||||
* @override
|
||||
*/
|
||||
public function update($entity)
|
||||
{
|
||||
$updateData = array();
|
||||
$this->_prepareData($entity, $updateData);
|
||||
return $postInsertIds;
|
||||
}
|
||||
|
||||
$id = array_combine(
|
||||
$this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||
);
|
||||
/**
|
||||
* Updates an entity.
|
||||
*
|
||||
* @param object $entity The entity to update.
|
||||
* @override
|
||||
*/
|
||||
public function update($entity)
|
||||
{
|
||||
$updateData = array();
|
||||
$this->_prepareData($entity, $updateData);
|
||||
|
||||
foreach ($updateData as $tableName => $data) {
|
||||
$this->_conn->update($tableName, $updateData[$tableName], $id);
|
||||
}
|
||||
}
|
||||
$id = array_combine(
|
||||
$this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||
);
|
||||
|
||||
/**
|
||||
* Deletes an entity.
|
||||
*
|
||||
* @param object $entity The entity to delete.
|
||||
* @override
|
||||
*/
|
||||
public function delete($entity)
|
||||
{
|
||||
$id = array_combine(
|
||||
$this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||
);
|
||||
foreach ($updateData as $tableName => $data) {
|
||||
$this->_conn->update($tableName, $updateData[$tableName], $id);
|
||||
}
|
||||
}
|
||||
|
||||
// If the database platform supports FKs, just
|
||||
// delete the row from the root table. Cascades do the rest.
|
||||
if ($this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$this->_conn->delete($this->_em->getClassMetadata($this->_class->rootEntityName)
|
||||
->primaryTable['name'], $id);
|
||||
} else {
|
||||
// Delete the parent tables, starting from this class' table up to the root table
|
||||
$this->_conn->delete($this->_class->primaryTable['name'], $id);
|
||||
foreach ($this->_class->parentClasses as $parentClass) {
|
||||
$this->_conn->delete($this->_em->getClassMetadata($parentClass)->primaryTable['name'], $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SELECT SQL to select a single entity by a set of field criteria.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @return string The SQL.
|
||||
* @todo Quote identifier.
|
||||
* @override
|
||||
*/
|
||||
protected function _getSelectSingleEntitySql(array $criteria)
|
||||
{
|
||||
$tableAliases = array();
|
||||
$aliasIndex = 1;
|
||||
$idColumns = $this->_class->getIdentifierColumnNames();
|
||||
$baseTableAlias = 't0';
|
||||
|
||||
foreach (array_merge($this->_class->subClasses, $this->_class->parentClasses) as $className) {
|
||||
$tableAliases[$className] = 't' . $aliasIndex++;
|
||||
}
|
||||
|
||||
$columnList = '';
|
||||
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
||||
$tableAlias = isset($mapping['inherited']) ?
|
||||
$tableAliases[$mapping['inherited']] : $baseTableAlias;
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $tableAlias . '.' . $this->_class->columnNames[$fieldName];
|
||||
}
|
||||
|
||||
$sql = 'SELECT ' . $columnList . ' FROM ' . $this->_class->primaryTable['name']. ' ' . $baseTableAlias;
|
||||
|
||||
// INNER JOIN parent tables
|
||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||
$tableAlias = $tableAliases[$parentClassName];
|
||||
$sql .= ' INNER JOIN ' . $parentClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||
}
|
||||
}
|
||||
|
||||
// OUTER JOIN sub tables
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$tableAlias = $tableAliases[$subClassName];
|
||||
$sql .= ' LEFT JOIN ' . $subClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||
}
|
||||
}
|
||||
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
$conditionSql .= $baseTableAlias . '.' . $this->_class->columnNames[$field] . ' = ?';
|
||||
}
|
||||
|
||||
return $sql . ' WHERE ' . $conditionSql;
|
||||
}
|
||||
/**
|
||||
* Deletes an entity.
|
||||
*
|
||||
* @param object $entity The entity to delete.
|
||||
* @override
|
||||
*/
|
||||
public function delete($entity)
|
||||
{
|
||||
$id = array_combine(
|
||||
$this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||
);
|
||||
|
||||
// If the database platform supports FKs, just
|
||||
// delete the row from the root table. Cascades do the rest.
|
||||
if ($this->_conn->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$this->_conn->delete($this->_em->getClassMetadata($this->_class->rootEntityName)
|
||||
->primaryTable['name'], $id);
|
||||
} else {
|
||||
// Delete the parent tables, starting from this class' table up to the root table
|
||||
$this->_conn->delete($this->_class->primaryTable['name'], $id);
|
||||
foreach ($this->_class->parentClasses as $parentClass) {
|
||||
$this->_conn->delete($this->_em->getClassMetadata($parentClass)->primaryTable['name'], $id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SELECT SQL to select a single entity by a set of field criteria.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @return string The SQL.
|
||||
* @todo Quote identifier.
|
||||
* @override
|
||||
*/
|
||||
protected function _getSelectSingleEntitySql(array $criteria)
|
||||
{
|
||||
$tableAliases = array();
|
||||
$aliasIndex = 1;
|
||||
$idColumns = $this->_class->getIdentifierColumnNames();
|
||||
$baseTableAlias = 't0';
|
||||
|
||||
foreach (array_merge($this->_class->subClasses, $this->_class->parentClasses) as $className) {
|
||||
$tableAliases[$className] = 't' . $aliasIndex++;
|
||||
}
|
||||
|
||||
$columnList = '';
|
||||
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
|
||||
$tableAlias = isset($mapping['inherited']) ?
|
||||
$tableAliases[$mapping['inherited']] : $baseTableAlias;
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $tableAlias . '.' . $this->_class->columnNames[$fieldName];
|
||||
}
|
||||
|
||||
$sql = 'SELECT ' . $columnList . ' FROM ' . $this->_class->primaryTable['name']. ' ' . $baseTableAlias;
|
||||
|
||||
// INNER JOIN parent tables
|
||||
foreach ($this->_class->parentClasses as $parentClassName) {
|
||||
$parentClass = $this->_em->getClassMetadata($parentClassName);
|
||||
$tableAlias = $tableAliases[$parentClassName];
|
||||
$sql .= ' INNER JOIN ' . $parentClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||
}
|
||||
}
|
||||
|
||||
// OUTER JOIN sub tables
|
||||
foreach ($this->_class->subClasses as $subClassName) {
|
||||
$subClass = $this->_em->getClassMetadata($subClassName);
|
||||
$tableAlias = $tableAliases[$subClassName];
|
||||
$sql .= ' LEFT JOIN ' . $subClass->primaryTable['name'] . ' ' . $tableAlias . ' ON ';
|
||||
$first = true;
|
||||
foreach ($idColumns as $idColumn) {
|
||||
if ($first) $first = false; else $sql .= ' AND ';
|
||||
$sql .= $baseTableAlias . '.' . $idColumn . ' = ' . $tableAlias . '.' . $idColumn;
|
||||
}
|
||||
}
|
||||
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
$conditionSql .= $baseTableAlias . '.' . $this->_class->columnNames[$field] . ' = ?';
|
||||
}
|
||||
|
||||
return $sql . ' WHERE ' . $conditionSql;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<?php
|
||||
<?php
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
|
@ -37,336 +37,349 @@ use Doctrine\ORM\Mapping\ClassMetadata;
|
|||
* @since 2.0
|
||||
*/
|
||||
class StandardEntityPersister
|
||||
{
|
||||
/**
|
||||
* Metadata object that describes the mapping of the mapped entity class.
|
||||
*
|
||||
* @var Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
protected $_class;
|
||||
{
|
||||
/**
|
||||
* Metadata object that describes the mapping of the mapped entity class.
|
||||
*
|
||||
* @var Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
protected $_class;
|
||||
|
||||
/**
|
||||
* The name of the entity the persister is used for.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_entityName;
|
||||
|
||||
/**
|
||||
* The Connection instance.
|
||||
*
|
||||
* @var Doctrine\DBAL\Connection $conn
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* The EntityManager instance.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* Queued inserts.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_queuedInserts = array();
|
||||
|
||||
/**
|
||||
* Initializes a new instance of a class derived from AbstractEntityPersister
|
||||
* that uses the given EntityManager and persists instances of the class described
|
||||
* by the given class metadata descriptor.
|
||||
*/
|
||||
public function __construct(EntityManager $em, ClassMetadata $class)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_entityName = $class->name;
|
||||
$this->_conn = $em->getConnection();
|
||||
$this->_class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entity to the queued inserts.
|
||||
*
|
||||
* @param object $entity
|
||||
*/
|
||||
public function addInsert($entity)
|
||||
{
|
||||
$this->_queuedInserts[spl_object_hash($entity)] = $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all queued inserts.
|
||||
*
|
||||
* @return array An array of any generated post-insert IDs.
|
||||
*/
|
||||
public function executeInserts()
|
||||
{
|
||||
if ( ! $this->_queuedInserts) {
|
||||
return;
|
||||
}
|
||||
|
||||
$postInsertIds = array();
|
||||
$idGen = $this->_class->idGenerator;
|
||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||
|
||||
$stmt = $this->_conn->prepare($this->_class->insertSql);
|
||||
$primaryTableName = $this->_class->primaryTable['name'];
|
||||
$sqlLogger = $this->_conn->getConfiguration()->getSqlLogger();
|
||||
|
||||
foreach ($this->_queuedInserts as $entity) {
|
||||
$insertData = array();
|
||||
$this->_prepareData($entity, $insertData, true);
|
||||
|
||||
/**
|
||||
* The name of the entity the persister is used for.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_entityName;
|
||||
$paramIndex = 1;
|
||||
if ($sqlLogger) {
|
||||
//TODO: Log type
|
||||
$params = array();
|
||||
foreach ($insertData[$primaryTableName] as $value) {
|
||||
$params[$paramIndex] = $value;
|
||||
$stmt->bindValue($paramIndex++, $value/*, Type::getType()*/);
|
||||
}
|
||||
$sqlLogger->logSql($this->_class->insertSql, $params);
|
||||
} else {
|
||||
foreach ($insertData[$primaryTableName] as $value) {
|
||||
$stmt->bindValue($paramIndex++, $value/*, Type::getType()*/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Connection instance.
|
||||
*
|
||||
* @var Doctrine\DBAL\Connection $conn
|
||||
*/
|
||||
protected $_conn;
|
||||
|
||||
/**
|
||||
* The EntityManager instance.
|
||||
*
|
||||
* @var Doctrine\ORM\EntityManager
|
||||
*/
|
||||
protected $_em;
|
||||
$stmt->execute();
|
||||
|
||||
/**
|
||||
* Queued inserts.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_queuedInserts = array();
|
||||
if ($isPostInsertId) {
|
||||
$postInsertIds[$idGen->generate($this->_em, $entity)] = $entity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of a class derived from AbstractEntityPersister
|
||||
* that uses the given EntityManager and persists instances of the class described
|
||||
* by the given class metadata descriptor.
|
||||
*/
|
||||
public function __construct(EntityManager $em, ClassMetadata $class)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_entityName = $class->name;
|
||||
$this->_conn = $em->getConnection();
|
||||
$this->_class = $class;
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
$this->_queuedInserts = array();
|
||||
|
||||
/**
|
||||
* Adds an entity to the queued inserts.
|
||||
*
|
||||
* @param object $entity
|
||||
*/
|
||||
public function addInsert($entity)
|
||||
{
|
||||
$this->_queuedInserts[spl_object_hash($entity)] = $entity;
|
||||
}
|
||||
return $postInsertIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all queued inserts.
|
||||
*
|
||||
* @return array An array of any generated post-insert IDs.
|
||||
*/
|
||||
public function executeInserts()
|
||||
{
|
||||
if ( ! $this->_queuedInserts) {
|
||||
return;
|
||||
}
|
||||
|
||||
$postInsertIds = array();
|
||||
$idGen = $this->_class->idGenerator;
|
||||
$isPostInsertId = $idGen->isPostInsertGenerator();
|
||||
/**
|
||||
* Updates an entity.
|
||||
*
|
||||
* @param object $entity The entity to update.
|
||||
*/
|
||||
public function update($entity)
|
||||
{
|
||||
$updateData = array();
|
||||
$this->_prepareData($entity, $updateData);
|
||||
$id = array_combine($this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity));
|
||||
$tableName = $this->_class->primaryTable['name'];
|
||||
$this->_conn->update($tableName, $updateData[$tableName], $id);
|
||||
}
|
||||
|
||||
$stmt = $this->_conn->prepare($this->_class->insertSql);
|
||||
$primaryTableName = $this->_class->primaryTable['name'];
|
||||
foreach ($this->_queuedInserts as $entity) {
|
||||
$insertData = array();
|
||||
$this->_prepareData($entity, $insertData, true);
|
||||
/**
|
||||
* Deletes an entity.
|
||||
*
|
||||
* @param object $entity The entity to delete.
|
||||
*/
|
||||
public function delete($entity)
|
||||
{
|
||||
$id = array_combine(
|
||||
$this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||
);
|
||||
$this->_conn->delete($this->_class->primaryTable['name'], $id);
|
||||
}
|
||||
|
||||
$paramIndex = 1;
|
||||
foreach ($insertData[$primaryTableName] as $value) {
|
||||
$stmt->bindValue($paramIndex++, $value/*, Type::getType()*/);
|
||||
}
|
||||
$stmt->execute();
|
||||
/**
|
||||
* Adds an entity to delete.
|
||||
*
|
||||
* @param object $entity
|
||||
*/
|
||||
public function addDelete($entity)
|
||||
{
|
||||
|
||||
if ($isPostInsertId) {
|
||||
$postInsertIds[$idGen->generate($this->_em, $entity)] = $entity;
|
||||
}
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
$this->_queuedInserts = array();
|
||||
}
|
||||
|
||||
return $postInsertIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an entity.
|
||||
*
|
||||
* @param object $entity The entity to update.
|
||||
*/
|
||||
public function update($entity)
|
||||
{
|
||||
$updateData = array();
|
||||
$this->_prepareData($entity, $updateData);
|
||||
$id = array_combine($this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity));
|
||||
$tableName = $this->_class->primaryTable['name'];
|
||||
$this->_conn->update($tableName, $updateData[$tableName], $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an entity.
|
||||
*
|
||||
* @param object $entity The entity to delete.
|
||||
*/
|
||||
public function delete($entity)
|
||||
{
|
||||
$id = array_combine(
|
||||
$this->_class->getIdentifierFieldNames(),
|
||||
$this->_em->getUnitOfWork()->getEntityIdentifier($entity)
|
||||
);
|
||||
$this->_conn->delete($this->_class->primaryTable['name'], $id);
|
||||
}
|
||||
/**
|
||||
* Executes all pending entity deletions.
|
||||
*
|
||||
* @see addDelete()
|
||||
*/
|
||||
public function executeDeletions()
|
||||
{
|
||||
|
||||
/**
|
||||
* Adds an entity to delete.
|
||||
*
|
||||
* @param object $entity
|
||||
*/
|
||||
public function addDelete($entity)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes all pending entity deletions.
|
||||
*
|
||||
* @see addDelete()
|
||||
*/
|
||||
public function executeDeletions()
|
||||
{
|
||||
|
||||
}
|
||||
/**
|
||||
* Gets the ClassMetadata instance of the entity class this persister is used for.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
public function getClassMetadata()
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ClassMetadata instance of the entity class this persister is used for.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
public function getClassMetadata()
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
/**
|
||||
* Gets the table name to use for temporary identifier tables.
|
||||
*/
|
||||
public function getTemporaryIdTableName()
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the table name to use for temporary identifier tables.
|
||||
*/
|
||||
public function getTemporaryIdTableName()
|
||||
{
|
||||
//...
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the data changeset of an entity for database insertion.
|
||||
* The array that is passed as the second parameter is filled with
|
||||
* <columnName> => <value> pairs, grouped by table name, during this preparation.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* array(
|
||||
* 'foo_table' => array('column1' => 'value1', 'column2' => 'value2', ...),
|
||||
* 'bar_table' => array('columnX' => 'valueX', 'columnY' => 'valueY', ...),
|
||||
* ...
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* Notes to inheritors: Be sure to call <code>parent::_prepareData($entity, $result, $isInsert);</code>
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $result The reference to the data array.
|
||||
* @param boolean $isInsert
|
||||
*/
|
||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||
{
|
||||
$platform = $this->_conn->getDatabasePlatform();
|
||||
$uow = $this->_em->getUnitOfWork();
|
||||
|
||||
foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
|
||||
$oldVal = $change[0];
|
||||
$newVal = $change[1];
|
||||
/**
|
||||
* Prepares the data changeset of an entity for database insertion.
|
||||
* The array that is passed as the second parameter is filled with
|
||||
* <columnName> => <value> pairs, grouped by table name, during this preparation.
|
||||
*
|
||||
* Example:
|
||||
* <code>
|
||||
* array(
|
||||
* 'foo_table' => array('column1' => 'value1', 'column2' => 'value2', ...),
|
||||
* 'bar_table' => array('columnX' => 'valueX', 'columnY' => 'valueY', ...),
|
||||
* ...
|
||||
* )
|
||||
* </code>
|
||||
*
|
||||
* Notes to inheritors: Be sure to call <code>parent::_prepareData($entity, $result, $isInsert);</code>
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $result The reference to the data array.
|
||||
* @param boolean $isInsert
|
||||
*/
|
||||
protected function _prepareData($entity, array &$result, $isInsert = false)
|
||||
{
|
||||
$platform = $this->_conn->getDatabasePlatform();
|
||||
$uow = $this->_em->getUnitOfWork();
|
||||
|
||||
$columnName = $this->_class->getColumnName($field);
|
||||
foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
|
||||
$oldVal = $change[0];
|
||||
$newVal = $change[1];
|
||||
|
||||
if (isset($this->_class->associationMappings[$field])) {
|
||||
$assocMapping = $this->_class->associationMappings[$field];
|
||||
// Only owning side of x-1 associations can have a FK column.
|
||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special case: One-one self-referencing of the same class.
|
||||
if ($newVal !== null && $assocMapping->sourceEntityName == $assocMapping->targetEntityName) {
|
||||
$oid = spl_object_hash($newVal);
|
||||
$isScheduledForInsert = $uow->isRegisteredNew($newVal);
|
||||
if (isset($this->_queuedInserts[$oid]) || $isScheduledForInsert) {
|
||||
// The associated entity $newVal is not yet persisted, so we must
|
||||
// set $newVal = null, in order to insert a null value and update later.
|
||||
$newVal = null;
|
||||
} else if ($isInsert && ! $isScheduledForInsert && $uow->getEntityState($newVal) == UnitOfWork::STATE_MANAGED) {
|
||||
// $newVal is already fully persisted
|
||||
// Clear changeset of $newVal, so that only the identifier is updated.
|
||||
// Not sure this is really rock-solid here but it seems to work.
|
||||
$uow->clearEntityChangeSet($oid);
|
||||
$uow->propertyChanged($newVal, $field, $entity, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($assocMapping->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
$otherClass = $this->_em->getClassMetadata($assocMapping->targetEntityName);
|
||||
if ($newVal === null) {
|
||||
$result[$this->getOwningTable($field)][$sourceColumn] = null;
|
||||
} else {
|
||||
$result[$this->getOwningTable($field)][$sourceColumn] =
|
||||
$otherClass->reflFields[$otherClass->fieldNames[$targetColumn]]
|
||||
->getValue($newVal);
|
||||
}
|
||||
}
|
||||
} else if ($newVal === null) {
|
||||
$result[$this->getOwningTable($field)][$columnName] = null;
|
||||
} else {
|
||||
$result[$this->getOwningTable($field)][$columnName] = Type::getType(
|
||||
$this->_class->fieldMappings[$field]['type'])
|
||||
->convertToDatabaseValue($newVal, $platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
$columnName = $this->_class->getColumnName($field);
|
||||
|
||||
/**
|
||||
* Gets the name of the table that owns the column the given field is mapped to.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
*/
|
||||
public function getOwningTable($fieldName)
|
||||
{
|
||||
return $this->_class->primaryTable['name'];
|
||||
}
|
||||
if (isset($this->_class->associationMappings[$field])) {
|
||||
$assocMapping = $this->_class->associationMappings[$field];
|
||||
// Only owning side of x-1 associations can have a FK column.
|
||||
if ( ! $assocMapping->isOneToOne() || $assocMapping->isInverseSide()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an entity by a list of field criteria.
|
||||
*
|
||||
* @param array $criteria The criteria by which to load the entity.
|
||||
* @param object $entity The entity to load the data into. If not specified,
|
||||
* a new entity is created.
|
||||
*/
|
||||
public function load(array $criteria, $entity = null)
|
||||
{
|
||||
$stmt = $this->_conn->prepare($this->_getSelectSingleEntitySql($criteria));
|
||||
$stmt->execute(array_values($criteria));
|
||||
$data = array();
|
||||
foreach ($stmt->fetch(\PDO::FETCH_ASSOC) as $column => $value) {
|
||||
$fieldName = $this->_class->fieldNames[$column];
|
||||
$data[$fieldName] = Type::getType($this->_class->getTypeOfField($fieldName))
|
||||
->convertToPHPValue($value);
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
// Special case: One-one self-referencing of the same class.
|
||||
if ($newVal !== null && $assocMapping->sourceEntityName == $assocMapping->targetEntityName) {
|
||||
$oid = spl_object_hash($newVal);
|
||||
$isScheduledForInsert = $uow->isRegisteredNew($newVal);
|
||||
if (isset($this->_queuedInserts[$oid]) || $isScheduledForInsert) {
|
||||
// The associated entity $newVal is not yet persisted, so we must
|
||||
// set $newVal = null, in order to insert a null value and update later.
|
||||
$newVal = null;
|
||||
} else if ($isInsert && ! $isScheduledForInsert && $uow->getEntityState($newVal) == UnitOfWork::STATE_MANAGED) {
|
||||
// $newVal is already fully persisted
|
||||
// Clear changeset of $newVal, so that only the identifier is updated.
|
||||
// Not sure this is really rock-solid here but it seems to work.
|
||||
$uow->clearEntityChangeSet($oid);
|
||||
$uow->propertyChanged($newVal, $field, $entity, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity === null) {
|
||||
$entity = $this->_em->getUnitOfWork()->createEntity($this->_entityName, $data);
|
||||
} else {
|
||||
foreach ($data as $field => $value) {
|
||||
$this->_class->reflFields[$field]->setValue($entity, $value);
|
||||
}
|
||||
$id = array();
|
||||
if ($this->_class->isIdentifierComposite) {
|
||||
foreach ($this->_class->identifier as $fieldName) {
|
||||
$id[] = $data[$fieldName];
|
||||
}
|
||||
} else {
|
||||
$id = array($data[$this->_class->getSingleIdentifierFieldName()]);
|
||||
}
|
||||
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
|
||||
}
|
||||
foreach ($assocMapping->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
|
||||
$otherClass = $this->_em->getClassMetadata($assocMapping->targetEntityName);
|
||||
if ($newVal === null) {
|
||||
$result[$this->getOwningTable($field)][$sourceColumn] = null;
|
||||
} else {
|
||||
$result[$this->getOwningTable($field)][$sourceColumn] =
|
||||
$otherClass->reflFields[$otherClass->fieldNames[$targetColumn]]->getValue($newVal);
|
||||
}
|
||||
}
|
||||
} else if ($newVal === null) {
|
||||
$result[$this->getOwningTable($field)][$columnName] = null;
|
||||
} else {
|
||||
$result[$this->getOwningTable($field)][$columnName] = Type::getType(
|
||||
$this->_class->fieldMappings[$field]['type'])
|
||||
->convertToDatabaseValue($newVal, $platform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $this->_em->getConfiguration()->getAllowPartialObjects()) {
|
||||
foreach ($this->_class->associationMappings as $field => $assoc) {
|
||||
if ($assoc->isOneToOne()) {
|
||||
if ($assoc->isLazilyFetched()) {
|
||||
// Inject proxy
|
||||
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($entity, $assoc);
|
||||
$this->_class->reflFields[$field]->setValue($entity, $proxy);
|
||||
} else {
|
||||
//TODO: Eager fetch?
|
||||
}
|
||||
} else {
|
||||
// Inject collection
|
||||
$this->_class->reflFields[$field]->setValue(
|
||||
$entity, new PersistentCollection($this->_em,
|
||||
$this->_em->getClassMetadata($assoc->targetEntityName)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets the name of the table that owns the column the given field is mapped to.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return string
|
||||
*/
|
||||
public function getOwningTable($fieldName)
|
||||
{
|
||||
return $this->_class->primaryTable['name'];
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
/**
|
||||
* Loads an entity by a list of field criteria.
|
||||
*
|
||||
* @param array $criteria The criteria by which to load the entity.
|
||||
* @param object $entity The entity to load the data into. If not specified,
|
||||
* a new entity is created.
|
||||
*/
|
||||
public function load(array $criteria, $entity = null)
|
||||
{
|
||||
$stmt = $this->_conn->prepare($this->_getSelectSingleEntitySql($criteria));
|
||||
$stmt->execute(array_values($criteria));
|
||||
$data = array();
|
||||
foreach ($stmt->fetch(\PDO::FETCH_ASSOC) as $column => $value) {
|
||||
$fieldName = $this->_class->fieldNames[$column];
|
||||
$data[$fieldName] = Type::getType($this->_class->getTypeOfField($fieldName))
|
||||
->convertToPHPValue($value);
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
|
||||
/**
|
||||
* Gets the SELECT SQL to select a single entity by a set of field criteria.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @return string The SQL.
|
||||
* @todo Quote identifier.
|
||||
*/
|
||||
protected function _getSelectSingleEntitySql(array $criteria)
|
||||
{
|
||||
$columnList = '';
|
||||
foreach ($this->_class->columnNames as $column) {
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $column;
|
||||
}
|
||||
if ($entity === null) {
|
||||
$entity = $this->_em->getUnitOfWork()->createEntity($this->_entityName, $data);
|
||||
} else {
|
||||
foreach ($data as $field => $value) {
|
||||
$this->_class->reflFields[$field]->setValue($entity, $value);
|
||||
}
|
||||
$id = array();
|
||||
if ($this->_class->isIdentifierComposite) {
|
||||
foreach ($this->_class->identifier as $fieldName) {
|
||||
$id[] = $data[$fieldName];
|
||||
}
|
||||
} else {
|
||||
$id = array($data[$this->_class->getSingleIdentifierFieldName()]);
|
||||
}
|
||||
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
|
||||
}
|
||||
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
$conditionSql .= $this->_class->columnNames[$field] . ' = ?';
|
||||
}
|
||||
if ( ! $this->_em->getConfiguration()->getAllowPartialObjects()) {
|
||||
foreach ($this->_class->associationMappings as $field => $assoc) {
|
||||
if ($assoc->isOneToOne()) {
|
||||
if ($assoc->isLazilyFetched) {
|
||||
// Inject proxy
|
||||
$proxy = $this->_em->getProxyGenerator()->getAssociationProxy($entity, $assoc);
|
||||
$this->_class->reflFields[$field]->setValue($entity, $proxy);
|
||||
} else {
|
||||
//TODO: Eager fetch?
|
||||
}
|
||||
} else {
|
||||
// Inject collection
|
||||
$this->_class->reflFields[$field]->setValue(
|
||||
$entity, new PersistentCollection($this->_em,
|
||||
$this->_em->getClassMetadata($assoc->targetEntityName)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 'SELECT ' . $columnList . ' FROM ' . $this->_class->getTableName()
|
||||
. ' WHERE ' . $conditionSql;
|
||||
}
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SELECT SQL to select a single entity by a set of field criteria.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @return string The SQL.
|
||||
* @todo Quote identifier.
|
||||
*/
|
||||
protected function _getSelectSingleEntitySql(array $criteria)
|
||||
{
|
||||
$columnList = '';
|
||||
foreach ($this->_class->columnNames as $column) {
|
||||
if ($columnList != '') $columnList .= ', ';
|
||||
$columnList .= $column;
|
||||
}
|
||||
|
||||
$conditionSql = '';
|
||||
foreach ($criteria as $field => $value) {
|
||||
if ($conditionSql != '') $conditionSql .= ' AND ';
|
||||
$conditionSql .= $this->_class->columnNames[$field] . ' = ?';
|
||||
}
|
||||
|
||||
return 'SELECT ' . $columnList . ' FROM ' . $this->_class->getTableName()
|
||||
. ' WHERE ' . $conditionSql;
|
||||
}
|
||||
}
|
|
@ -56,9 +56,8 @@ class ResultSetMapping
|
|||
|
||||
/**
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $alias The alias for this class. The alias must be unique within this ResultSetMapping.
|
||||
* @param <type> $discriminatorColumn
|
||||
* @param string $class The class name.
|
||||
* @param string $alias The alias for this class. The alias must be unique within this ResultSetMapping.
|
||||
*/
|
||||
public function addEntityResult($class, $alias)
|
||||
{
|
||||
|
@ -67,9 +66,8 @@ class ResultSetMapping
|
|||
|
||||
/**
|
||||
*
|
||||
* @param <type> $className
|
||||
* @param <type> $alias
|
||||
* @param <type> $discrColumn
|
||||
* @param string $alias
|
||||
* @param string $discrColumn
|
||||
*/
|
||||
public function setDiscriminatorColumn($alias, $discrColumn)
|
||||
{
|
||||
|
@ -130,9 +128,9 @@ class ResultSetMapping
|
|||
|
||||
/**
|
||||
*
|
||||
* @param <type> $alias
|
||||
* @param <type> $columnName
|
||||
* @param <type> $fieldName
|
||||
* @param string $alias
|
||||
* @param string $columnName
|
||||
* @param string $fieldName
|
||||
*/
|
||||
public function addFieldResult($alias, $columnName, $fieldName)
|
||||
{
|
||||
|
@ -145,10 +143,10 @@ class ResultSetMapping
|
|||
|
||||
/**
|
||||
*
|
||||
* @param <type> $class
|
||||
* @param <type> $alias
|
||||
* @param <type> $parentAlias
|
||||
* @param <type> $relation
|
||||
* @param string $class
|
||||
* @param string $alias
|
||||
* @param string $parentAlias
|
||||
* @param object $relation
|
||||
*/
|
||||
public function addJoinedEntityResult($class, $alias, $parentAlias, $relation)
|
||||
{
|
||||
|
@ -156,12 +154,12 @@ class ResultSetMapping
|
|||
$this->parentAliasMap[$alias] = $parentAlias;
|
||||
$this->relationMap[$alias] = $relation;
|
||||
}
|
||||
|
||||
/*public function isDiscriminatorColumn($columnName)
|
||||
{
|
||||
return isset($this->_discriminatorMap[$columnName]);
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $columnName
|
||||
* @param string $alias
|
||||
*/
|
||||
public function addScalarResult($columnName, $alias)
|
||||
{
|
||||
$this->scalarMappings[$columnName] = $alias;
|
||||
|
|
|
@ -483,7 +483,6 @@ class UnitOfWork implements PropertyChangedListener
|
|||
}
|
||||
|
||||
if ( ! $assoc->isCascadeSave) {
|
||||
//echo "NOT CASCADING INTO " . $assoc->getSourceFieldName() . PHP_EOL;
|
||||
return; // "Persistence by reachability" only if save cascade specified
|
||||
}
|
||||
|
||||
|
@ -498,7 +497,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||
$oid = spl_object_hash($entry);
|
||||
if ($state == self::STATE_NEW) {
|
||||
// Get identifier, if possible (not post-insert)
|
||||
$idGen = $targetClass->getIdGenerator();
|
||||
$idGen = $targetClass->idGenerator;
|
||||
if ( ! $idGen->isPostInsertGenerator()) {
|
||||
$idValue = $idGen->generate($this->_em, $entry);
|
||||
$this->_entityStates[$oid] = self::STATE_MANAGED;
|
||||
|
@ -803,35 +802,6 @@ class UnitOfWork implements PropertyChangedListener
|
|||
isset($this->_entityDeletions[$oid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches all currently managed entities.
|
||||
* Alternatively, if an entity class name is given, all entities of that type
|
||||
* (or subtypes) are detached. Don't forget that entities are registered in
|
||||
* the identity map with the name of the root entity class. So calling detachAll()
|
||||
* with a class name that is not the name of a root entity has no effect.
|
||||
*
|
||||
* @return integer The number of detached entities.
|
||||
*/
|
||||
public function detachAll($entityName = null)
|
||||
{
|
||||
$numDetached = 0;
|
||||
if ($entityName !== null && isset($this->_identityMap[$entityName])) {
|
||||
$numDetached = count($this->_identityMap[$entityName]);
|
||||
foreach ($this->_identityMap[$entityName] as $entity) {
|
||||
$this->detach($entity);
|
||||
}
|
||||
$this->_identityMap[$entityName] = array();
|
||||
} else {
|
||||
$numDetached = count($this->_identityMap);
|
||||
$this->_identityMap = array();
|
||||
$this->_entityInsertions = array();
|
||||
$this->_entityUpdates = array();
|
||||
$this->_entityDeletions = array();
|
||||
}
|
||||
|
||||
return $numDetached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an entity in the identity map.
|
||||
* Note that entities in a hierarchy are registered with the class name of
|
||||
|
@ -960,8 +930,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||
|
||||
return isset($this->_identityMap
|
||||
[$classMetadata->rootEntityName]
|
||||
[$idHash]
|
||||
);
|
||||
[$idHash]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1174,6 +1143,10 @@ class UnitOfWork implements PropertyChangedListener
|
|||
|
||||
/**
|
||||
* Cascades a merge operation to associated entities.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param object $managedCopy
|
||||
* @param array $visited
|
||||
*/
|
||||
private function _cascadeMerge($entity, $managedCopy, array &$visited)
|
||||
{
|
||||
|
@ -1199,6 +1172,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||
*
|
||||
* @param object $entity
|
||||
* @param array $visited
|
||||
* @param array $insertNow
|
||||
*/
|
||||
private function _cascadeSave($entity, array &$visited, array &$insertNow)
|
||||
{
|
||||
|
@ -1223,6 +1197,7 @@ class UnitOfWork implements PropertyChangedListener
|
|||
* Cascades the delete operation to associated entities.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param array $visited
|
||||
*/
|
||||
private function _cascadeDelete($entity, array &$visited)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Doctrine\Tests\DBAL\Functional\Schema;
|
|||
|
||||
use Doctrine\Tests\TestUtil;
|
||||
use Doctrine\DBAL\Schema;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
|
@ -59,13 +60,13 @@ class MysqlSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -86,13 +87,13 @@ class MysqlSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -114,13 +115,13 @@ class MysqlSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -158,13 +159,13 @@ class MysqlSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -197,13 +198,13 @@ class MysqlSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -245,7 +246,7 @@ class MysqlSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
$this->_sm->createView('test_create_view', 'SELECT * from mysql.user');
|
||||
$views = $this->_sm->listViews();
|
||||
|
||||
$this->assertEquals($views[0]['name'], 'test_create_view');
|
||||
$this->assertEquals($views[0]['sql'], '/* ALGORITHM=UNDEFINED */ select `mysql`.`user`.`Host` AS `Host`,`mysql`.`user`.`User` AS `User`,`mysql`.`user`.`Password` AS `Password`,`mysql`.`user`.`Select_priv` AS `Select_priv`,`mysql`.`user`.`Insert_priv` AS `Insert_priv`,`mysql`.`user`.`Update_priv` AS `Update_priv`,`mysql`.`user`.`Delete_priv` AS `Delete_priv`,`mysql`.`user`.`Create_priv` AS `Create_priv`,`mysql`.`user`.`Drop_priv` AS `Drop_priv`,`mysql`.`user`.`Reload_priv` AS `Reload_priv`,`mysql`.`user`.`Shutdown_priv` AS `Shutdown_priv`,`mysql`.`user`.`Process_priv` AS `Process_priv`,`mysql`.`user`.`File_priv` AS `File_priv`,`mysql`.`user`.`Grant_priv` AS `Grant_priv`,`mysql`.`user`.`References_priv` AS `References_priv`,`mysql`.`user`.`Index_priv` AS `Index_priv`,`mysql`.`user`.`Alter_priv` AS `Alter_priv`,`mysql`.`user`.`Show_db_priv` AS `Show_db_priv`,`mysql`.`user`.`Super_priv` AS `Super_priv`,`mysql`.`user`.`Create_tmp_table_priv` AS `Create_tmp_table_priv`,`mysql`.`user`.`Lock_tables_priv` AS `Lock_tables_priv`,`mysql`.`user`.`Execute_priv` AS `Execute_priv`,`mysql`.`user`.`Repl_slave_priv` AS `Repl_slave_priv`,`mysql`.`user`.`Repl_client_priv` AS `Repl_client_priv`,`mysql`.`user`.`Create_view_priv` AS `Create_view_priv`,`mysql`.`user`.`Show_view_priv` AS `Show_view_priv`,`mysql`.`user`.`Create_routine_priv` AS `Create_routine_priv`,`mysql`.`user`.`Alter_routine_priv` AS `Alter_routine_priv`,`mysql`.`user`.`Create_user_priv` AS `Create_user_priv`,`mysql`.`user`.`ssl_type` AS `ssl_type`,`mysql`.`user`.`ssl_cipher` AS `ssl_cipher`,`mysql`.`user`.`x509_issuer` AS `x509_issuer`,`mysql`.`user`.`x509_subject` AS `x509_subject`,`mysql`.`user`.`max_questions` AS `max_questions`,`mysql`.`user`.`max_updates` AS `max_updates`,`mysql`.`user`.`max_connections` AS `max_connections`,`mysql`.`user`.`max_user_connections` AS `max_user_connections` from `mysql`.`user`');
|
||||
$this->assertEquals('test_create_view', $views[0]['name']);
|
||||
$this->assertEquals('/* ALGORITHM=UNDEFINED */ select `mysql`.`user`.`Host` AS `Host`,`mysql`.`user`.`User` AS `User`,`mysql`.`user`.`Password` AS `Password`,`mysql`.`user`.`Select_priv` AS `Select_priv`,`mysql`.`user`.`Insert_priv` AS `Insert_priv`,`mysql`.`user`.`Update_priv` AS `Update_priv`,`mysql`.`user`.`Delete_priv` AS `Delete_priv`,`mysql`.`user`.`Create_priv` AS `Create_priv`,`mysql`.`user`.`Drop_priv` AS `Drop_priv`,`mysql`.`user`.`Reload_priv` AS `Reload_priv`,`mysql`.`user`.`Shutdown_priv` AS `Shutdown_priv`,`mysql`.`user`.`Process_priv` AS `Process_priv`,`mysql`.`user`.`File_priv` AS `File_priv`,`mysql`.`user`.`Grant_priv` AS `Grant_priv`,`mysql`.`user`.`References_priv` AS `References_priv`,`mysql`.`user`.`Index_priv` AS `Index_priv`,`mysql`.`user`.`Alter_priv` AS `Alter_priv`,`mysql`.`user`.`Show_db_priv` AS `Show_db_priv`,`mysql`.`user`.`Super_priv` AS `Super_priv`,`mysql`.`user`.`Create_tmp_table_priv` AS `Create_tmp_table_priv`,`mysql`.`user`.`Lock_tables_priv` AS `Lock_tables_priv`,`mysql`.`user`.`Execute_priv` AS `Execute_priv`,`mysql`.`user`.`Repl_slave_priv` AS `Repl_slave_priv`,`mysql`.`user`.`Repl_client_priv` AS `Repl_client_priv`,`mysql`.`user`.`Create_view_priv` AS `Create_view_priv`,`mysql`.`user`.`Show_view_priv` AS `Show_view_priv`,`mysql`.`user`.`Create_routine_priv` AS `Create_routine_priv`,`mysql`.`user`.`Alter_routine_priv` AS `Alter_routine_priv`,`mysql`.`user`.`Create_user_priv` AS `Create_user_priv`,`mysql`.`user`.`ssl_type` AS `ssl_type`,`mysql`.`user`.`ssl_cipher` AS `ssl_cipher`,`mysql`.`user`.`x509_issuer` AS `x509_issuer`,`mysql`.`user`.`x509_subject` AS `x509_subject`,`mysql`.`user`.`max_questions` AS `max_questions`,`mysql`.`user`.`max_updates` AS `max_updates`,`mysql`.`user`.`max_connections` AS `max_connections`,`mysql`.`user`.`max_user_connections` AS `max_user_connections` from `mysql`.`user`', $views[0]['sql']);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ namespace Doctrine\Tests\DBAL\Functional\Schema;
|
|||
|
||||
use Doctrine\Tests\TestUtil;
|
||||
use Doctrine\DBAL\Schema;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
|
@ -58,13 +59,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -91,13 +92,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -131,13 +132,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -164,13 +165,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -198,13 +199,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -250,13 +251,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
@ -314,13 +315,13 @@ class SqliteSchemaManagerTest extends \Doctrine\Tests\DbalFunctionalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Doctrine\Tests\DBAL\Platforms;
|
||||
|
||||
use Doctrine\DBAL\Platforms\SqlitePlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
|
||||
require_once __DIR__ . '/../../TestInit.php';
|
||||
|
||||
|
@ -19,13 +20,13 @@ class SqlitePlatformTest extends \Doctrine\Tests\DbalTestCase
|
|||
{
|
||||
$columns = array(
|
||||
'id' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\IntegerType,
|
||||
'type' => Type::getType('integer'),
|
||||
'autoincrement' => true,
|
||||
'primary' => true,
|
||||
'notnull' => true
|
||||
),
|
||||
'test' => array(
|
||||
'type' => new \Doctrine\DBAL\Types\StringType,
|
||||
'type' => Type::getType('string'),
|
||||
'length' => 255
|
||||
)
|
||||
);
|
||||
|
|
|
@ -23,4 +23,20 @@ class ForumUser
|
|||
* @DoctrineJoinColumn(name="avatar_id", referencedColumnName="id")
|
||||
*/
|
||||
public $avatar;
|
||||
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getUsername() {
|
||||
return $this->username;
|
||||
}
|
||||
|
||||
public function getAvatar() {
|
||||
return $this->avatar;
|
||||
}
|
||||
|
||||
public function setAvatar(CmsAvatar $avatar) {
|
||||
$this->avatar = $avatar;
|
||||
}
|
||||
}
|
|
@ -150,8 +150,6 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
|
||||
public function testManyToManyCollectionClearing()
|
||||
{
|
||||
echo PHP_EOL . "MANY-MANY" . PHP_EOL;
|
||||
|
||||
$user = new CmsUser;
|
||||
$user->name = 'Guilherme';
|
||||
$user->username = 'gblanco';
|
||||
|
@ -176,7 +174,6 @@ class BasicFunctionalTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||
//$user->groups->clear();
|
||||
unset($user->groups);
|
||||
|
||||
echo PHP_EOL . "FINAL FLUSH" . PHP_EOL;
|
||||
$this->_em->flush();
|
||||
|
||||
// Check that the links in the association table have been deleted
|
||||
|
|
|
@ -24,7 +24,7 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
|||
*
|
||||
* MAXIMUM TIME: 3 seconds
|
||||
*/
|
||||
public function testNewHydrationSimpleQueryArrayHydrationPerformance()
|
||||
public function testSimpleQueryArrayHydrationPerformance()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
|
@ -69,7 +69,10 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
|||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$this->setMaxRunningTime(3);
|
||||
$s = microtime(true);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$e = microtime(true);
|
||||
echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,7 +82,7 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
|||
*
|
||||
* MAXIMUM TIME: 4 seconds
|
||||
*/
|
||||
public function testNewHydrationMixedQueryFetchJoinArrayHydrationPerformance()
|
||||
public function testMixedQueryFetchJoinArrayHydrationPerformance()
|
||||
{
|
||||
$rsm = new ResultSetMapping;
|
||||
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
|
||||
|
@ -140,7 +143,10 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
|||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ArrayHydrator($this->_em);
|
||||
|
||||
$this->setMaxRunningTime(4);
|
||||
$s = microtime(true);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$e = microtime(true);
|
||||
echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,8 +199,10 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
|||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
|
||||
$this->setMaxRunningTime(5);
|
||||
$s = microtime(true);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
echo count($result);
|
||||
$e = microtime(true);
|
||||
echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,7 +271,10 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
|
|||
$hydrator = new \Doctrine\ORM\Internal\Hydration\ObjectHydrator($this->_em);
|
||||
|
||||
$this->setMaxRunningTime(4);
|
||||
$s = microtime(true);
|
||||
$result = $hydrator->hydrateAll($stmt, $rsm);
|
||||
$e = microtime(true);
|
||||
echo __FUNCTION__ . " - " . ($e - $s) . " seconds" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue