diff --git a/lib/Doctrine/Common/DoctrineException.php b/lib/Doctrine/Common/DoctrineException.php index 8252b2a9a..0c36f720f 100644 --- a/lib/Doctrine/Common/DoctrineException.php +++ b/lib/Doctrine/Common/DoctrineException.php @@ -31,8 +31,8 @@ class DoctrineException extends \Exception unset($arguments[count($arguments) - 1]); } - if (isset(self::$_messages[$method])) { - $message = sprintf(self::$_messages[$method], $arguments); + if ($message = self::getExceptionMessage($method)) { + $message = sprintf($message, $arguments); } else { $message = strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $method)); $message = ucfirst(str_replace('_', ' ', $message)); @@ -42,6 +42,23 @@ class DoctrineException extends \Exception } $message .= ' (' . implode(', ', $args) . ')'; } - return new self($message); + $class = get_called_class(); + return new $class($message); + } + + public static function getExceptionMessage($method) + { + if ( ! self::$_messages) { + self::$_messages = array( + 'partialObjectsAreDangerous' => + "Loading partial objects is dangerous. Fetch full objects or consider " . + "using a different fetch mode. If you really want partial objects, " . + "set the doctrine.forcePartialLoad query hint to TRUE." + ); + } + if (isset(self::$_messages[$method])) { + return self::$_messages[$method]; + } + return false; } } \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 2d9c8ad7b..855e5c7cc 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -1293,6 +1293,7 @@ abstract class AbstractPlatform } /** + * Gets the SQL snippet that declares a 4 byte integer column. * * @param $name * @param $field @@ -1300,33 +1301,19 @@ abstract class AbstractPlatform abstract public function getIntegerTypeDeclarationSql(array $columnDef); /** - * Gets the SQL snippet that declares a BIGINT column. + * Gets the SQL snippet that declares an 8 byte integer column. * * @return string */ abstract public function getBigIntTypeDeclarationSql(array $columnDef); /** - * Gets the SQL snippet that declares a TINYINT column. - * - * @return string - */ - //abstract public function getTinyIntTypeDeclarationSql(array $columnDef); - - /** - * Gets the SQL snippet that declares a SMALLINT column. + * Gets the SQL snippet that declares a 2 byte integer column. * * @return string */ abstract public function getSmallIntTypeDeclarationSql(array $columnDef); - /** - * Gets the SQL snippet that declares a MEDIUMINT column. - * - * @return string - */ - //abstract public function getMediumIntTypeDeclarationSql(array $columnDef); - /** * Gets the SQL snippet that declares common properties of an integer column. * diff --git a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index e41f0c380..649cbe5fb 100644 --- a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -21,6 +21,8 @@ namespace Doctrine\DBAL\Platforms; +use Doctrine\Common\DoctrineException; + /** * The MySqlPlatform provides the behavior, features and SQL dialect of the * MySQL database platform. @@ -29,90 +31,7 @@ namespace Doctrine\DBAL\Platforms; * @author Roman Borschel */ class MySqlPlatform extends AbstractPlatform -{ - /** - * MySql reserved words. - * - * @var array - * @todo Needed? What about lazy initialization? - */ - /*protected static $_reservedKeywords = array( - 'ADD', 'ALL', 'ALTER', - 'ANALYZE', 'AND', 'AS', - 'ASC', 'ASENSITIVE', 'BEFORE', - 'BETWEEN', 'BIGINT', 'BINARY', - 'BLOB', 'BOTH', 'BY', - 'CALL', 'CASCADE', 'CASE', - 'CHANGE', 'CHAR', 'CHARACTER', - 'CHECK', 'COLLATE', 'COLUMN', - 'CONDITION', 'CONNECTION', 'CONSTRAINT', - 'CONTINUE', 'CONVERT', 'CREATE', - 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', - 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', - 'DATABASE', 'DATABASES', 'DAY_HOUR', - 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', - 'DEC', 'DECIMAL', 'DECLARE', - 'DEFAULT', 'DELAYED', 'DELETE', - 'DESC', 'DESCRIBE', 'DETERMINISTIC', - 'DISTINCT', 'DISTINCTROW', 'DIV', - 'DOUBLE', 'DROP', 'DUAL', - 'EACH', 'ELSE', 'ELSEIF', - 'ENCLOSED', 'ESCAPED', 'EXISTS', - 'EXIT', 'EXPLAIN', 'FALSE', - 'FETCH', 'FLOAT', 'FLOAT4', - 'FLOAT8', 'FOR', 'FORCE', - 'FOREIGN', 'FROM', 'FULLTEXT', - 'GRANT', 'GROUP', 'HAVING', - 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', - 'HOUR_SECOND', 'IF', 'IGNORE', - 'IN', 'INDEX', 'INFILE', - 'INNER', 'INOUT', 'INSENSITIVE', - 'INSERT', 'INT', 'INT1', - 'INT2', 'INT3', 'INT4', - 'INT8', 'INTEGER', 'INTERVAL', - 'INTO', 'IS', 'ITERATE', - 'JOIN', 'KEY', 'KEYS', - 'KILL', 'LEADING', 'LEAVE', - 'LEFT', 'LIKE', 'LIMIT', - 'LINES', 'LOAD', 'LOCALTIME', - 'LOCALTIMESTAMP', 'LOCK', 'LONG', - 'LONGBLOB', 'LONGTEXT', 'LOOP', - 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', - 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', - 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', - 'MODIFIES', 'NATURAL', 'NOT', - 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', - 'ON', 'OPTIMIZE', 'OPTION', - 'OPTIONALLY', 'OR', 'ORDER', - 'OUT', 'OUTER', 'OUTFILE', - 'PRECISION', 'PRIMARY', 'PROCEDURE', - 'PURGE', 'RAID0', 'READ', - 'READS', 'REAL', 'REFERENCES', - 'REGEXP', 'RELEASE', 'RENAME', - 'REPEAT', 'REPLACE', 'REQUIRE', - 'RESTRICT', 'RETURN', 'REVOKE', - 'RIGHT', 'RLIKE', 'SCHEMA', - 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', - 'SENSITIVE', 'SEPARATOR', 'SET', - 'SHOW', 'SMALLINT', 'SONAME', - 'SPATIAL', 'SPECIFIC', 'SQL', - 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', - 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', - 'SSL', 'STARTING', 'STRAIGHT_JOIN', - 'TABLE', 'TERMINATED', 'THEN', - 'TINYBLOB', 'TINYINT', 'TINYTEXT', - 'TO', 'TRAILING', 'TRIGGER', - 'TRUE', 'UNDO', 'UNION', - 'UNIQUE', 'UNLOCK', 'UNSIGNED', - 'UPDATE', 'USAGE', 'USE', - 'USING', 'UTC_DATE', 'UTC_TIME', - 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', - 'VARCHAR', 'VARCHARACTER', 'VARYING', - 'WHEN', 'WHERE', 'WHILE', - 'WITH', 'WRITE', 'X509', - 'XOR', 'YEAR_MONTH', 'ZEROFILL' - );*/ - +{ /** * Creates a new MySqlPlatform instance. */ @@ -1080,7 +999,6 @@ class MySqlPlatform extends AbstractPlatform } /** - * getDefaultDeclaration * Obtain DBMS specific SQL code portion needed to set a default value * declaration to be used in statements like CREATE TABLE. * @@ -1095,25 +1013,7 @@ class MySqlPlatform extends AbstractPlatform if (isset($field['default']) && ( ! isset($field['length']) || $field['length'] <= 255)) { if ($field['default'] === '') { $field['default'] = null; - /*if ( ! empty($field['notnull']) && array_key_exists($field['type'], $this->valid_default_values)) { - $field['default'] = $this->valid_default_values[$field['type']]; - } - if ($field['default'] === '' - && ($this->_conn->getAttribute(Doctrine::ATTR_PORTABILITY) & Doctrine::PORTABILITY_EMPTY_TO_NULL) - ) { - $field['default'] = ' '; - }*/ } - - /*if ($field['type'] == 'enum' && $this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)) { - $fieldType = 'varchar'; - } else { - if ($field['type'] === 'boolean') { - $fields['default'] = $this->convertBooleans($field['default']); - } - $fieldType = $field['type']; - }*/ - $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']); } return $default; @@ -1139,12 +1039,12 @@ class MySqlPlatform extends AbstractPlatform $type = strtoupper($definition['type']) . ' '; break; default: - throw \Doctrine\Common\DoctrineException::updateMe('Unknown index type ' . $definition['type']); + throw DoctrineException::updateMe('Unknown index type ' . $definition['type']); } } if ( ! isset($definition['fields'])) { - throw \Doctrine\Common\DoctrineException::updateMe('No index columns given.'); + throw DoctrineException::updateMe('No index columns given.'); } if ( ! is_array($definition['fields'])) { $definition['fields'] = array($definition['fields']); @@ -1185,7 +1085,7 @@ class MySqlPlatform extends AbstractPlatform $fieldString .= ' ' . $sort; break; default: - throw \Doctrine\Common\DoctrineException::updateMe('Unknown index sorting option given.'); + throw DoctrineException::updateMe('Unknown index sorting option given.'); } } } else { diff --git a/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php index fe8300ba6..9d7a0a08f 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ArrayHydrator.php @@ -27,8 +27,15 @@ class ArrayHydrator extends AbstractHydrator protected function _prepare($parserResult) { parent::_prepare($parserResult); - reset($this->_queryComponents); - $this->_rootAlias = key($this->_queryComponents); + //reset($this->_queryComponents); + //$this->_rootAlias = key($this->_queryComponents); + $this->_rootAlias = $parserResult->getDefaultQueryComponentAlias(); + $this->_rootEntityName = $this->_queryComponents[$this->_rootAlias]['metadata']->getClassName(); + if (isset($this->_queryComponents['dctrn'])) { + $this->_isSimpleQuery = count($this->_queryComponents) <= 2; + } else { + $this->_isSimpleQuery = count($this->_queryComponents) <= 1; + } $this->_rootEntityName = $this->_queryComponents[$this->_rootAlias]['metadata']->getClassName(); $this->_isSimpleQuery = count($this->_queryComponents) <= 1; $this->_identifierMap = array(); diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index 6b12add6f..132b14f8d 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -48,10 +48,15 @@ class ObjectHydrator extends AbstractHydrator protected function _prepare($parserResult) { parent::_prepare($parserResult); - reset($this->_queryComponents); - $this->_rootAlias = key($this->_queryComponents); + //reset($this->_queryComponents); + //$this->_rootAlias = key($this->_queryComponents); + $this->_rootAlias = $parserResult->getDefaultQueryComponentAlias(); $this->_rootEntityName = $this->_queryComponents[$this->_rootAlias]['metadata']->getClassName(); - $this->_isSimpleQuery = count($this->_queryComponents) <= 1; + if (isset($this->_queryComponents['dctrn'])) { + $this->_isSimpleQuery = count($this->_queryComponents) <= 2; + } else { + $this->_isSimpleQuery = count($this->_queryComponents) <= 1; + } $this->_identifierMap = array(); $this->_resultPointers = array(); $this->_idTemplate = array(); diff --git a/lib/Doctrine/ORM/Query.php b/lib/Doctrine/ORM/Query.php index 1f559e6fb..0982ace80 100644 --- a/lib/Doctrine/ORM/Query.php +++ b/lib/Doctrine/ORM/Query.php @@ -22,11 +22,10 @@ namespace Doctrine\ORM; use Doctrine\ORM\Query\Parser; +use Doctrine\ORM\Query\QueryException; /** - * A Doctrine_ORM_Query object represents a DQL query. It is used to query databases for - * data in an object-oriented fashion. A DQL query understands relations and inheritance - * and is to a large degree dbms independant. + * A Query object represents a DQL query. * * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.doctrine-project.org @@ -304,7 +303,7 @@ class Query extends AbstractQuery $params = $this->_prepareParams($params); // Executing the query and returning statement - return $executor->execute($this->_conn, $params); + return $executor->execute($this->_em->getConnection(), $params); } /** @@ -313,7 +312,7 @@ class Query extends AbstractQuery protected function _prepareParams(array $params) { // Convert boolean params - $params = $this->_em->getConnection()->convertBooleans($params); + $params = $this->_em->getConnection()->getDatabasePlatform()->convertBooleans($params); // Convert enum params return $this->convertEnums($params); diff --git a/lib/Doctrine/ORM/Query/AbstractResult.php b/lib/Doctrine/ORM/Query/AbstractResult.php index 2ff4c17d8..33f1aa3b0 100644 --- a/lib/Doctrine/ORM/Query/AbstractResult.php +++ b/lib/Doctrine/ORM/Query/AbstractResult.php @@ -21,6 +21,8 @@ namespace Doctrine\ORM\Query; +use Doctrine\Common\DoctrineException; + /** * Doctrine_ORM_Query_AbstractResult * @@ -61,8 +63,16 @@ abstract class AbstractResult */ protected $_enumParams; + /** + * @var string + */ protected $_defaultQueryComponentAlias; + /** + * @var boolean + */ + protected $_isMixedQuery = false; + /** * Cannot be called directly, factory methods handle this job. * @@ -138,7 +148,7 @@ abstract class AbstractResult public function getQueryComponent($componentAlias) { if ( ! isset($this->_queryComponents[$componentAlias])) { - throw new \Doctrine\Common\DoctrineException('Unknown query component ' . $componentAlias); + throw new DoctrineException('Unknown query component ' . $componentAlias); } return $this->_queryComponents[$componentAlias]; @@ -206,7 +216,7 @@ abstract class AbstractResult public function getTableAlias($tableAlias) { if ( ! isset($this->_tableAliasMap[$tableAlias])) { - throw \Doctrine\Common\DoctrineException::updateMe('Unknown table alias ' . $tableAlias); + throw DoctrineException::updateMe('Unknown table alias ' . $tableAlias); } return $this->_tableAliasMap[$tableAlias]; @@ -234,6 +244,26 @@ abstract class AbstractResult return (isset($this->_tableAliasMap[$tableAlias])); } + /** + * Gets whether the parsed query selects objects/arrays and scalar values + * at the same time. + * + * @return boolean + */ + public function isMixedQuery() + { + return $this->_isMixedQuery; + } + + /** + * Sets whether the parsed query selects objects/arrays and scalar values + * at the same time. + */ + public function setMixedQuery($bool) + { + $this->_isMixedQuery = $bool; + } + /** * Returns the enum parameters. * diff --git a/lib/Doctrine/ORM/Query/Parser.php b/lib/Doctrine/ORM/Query/Parser.php index c7db39e46..25ea919ae 100644 --- a/lib/Doctrine/ORM/Query/Parser.php +++ b/lib/Doctrine/ORM/Query/Parser.php @@ -612,9 +612,14 @@ class Parser $this->match(Lexer::T_FROM); $identificationVariableDeclarations = array(); $identificationVariableDeclarations[] = $this->_IdentificationVariableDeclaration(); - $this->_parserResult->setDefaultQueryComponentAlias( - $identificationVariableDeclarations[0]->getRangeVariableDeclaration()->getAbstractSchemaName() - ); + + $firstRangeDecl = $identificationVariableDeclarations[0]->getRangeVariableDeclaration(); + if ($firstRangeDecl->getAliasIdentificationVariable()) { + $this->_parserResult->setDefaultQueryComponentAlias($firstRangeDecl->getAliasIdentificationVariable()); + } else { + $this->_parserResult->setDefaultQueryComponentAlias($firstRangeDecl->getAbstractSchemaName()); + } + while ($this->_lexer->isNextToken(',')) { $this->match(','); $identificationVariableDeclarations[] = $this->_IdentificationVariableDeclaration(); @@ -1294,19 +1299,7 @@ class Parser $rightExpr = $this->_StringExpression(); } } - } - /*else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) { - $leftExpr = $this->_StringExpression(); - $operator = $this->_ComparisonOperator(); - if ($this->_lexer->lookahead['type'] === Lexer::T_ALL || - $this->_lexer->lookahead['type'] === Lexer::T_ANY || - $this->_lexer->lookahead['type'] === Lexer::T_SOME) { - $rightExpr = $this->_QuantifiedExpression(); - } else { - $rightExpr = $this->_StringExpression(); - } - }*/ - else { + } else { $leftExpr = $this->_ArithmeticExpression(); $operator = $this->_ComparisonOperator(); if ($this->_lexer->lookahead['type'] === Lexer::T_ALL || @@ -1321,6 +1314,9 @@ class Parser return new AST\ComparisonExpression($leftExpr, $operator, $rightExpr); } + /** + * Function ::= FunctionsReturningStrings | FunctionsReturningNumerics | FunctionsReturningDatetime + */ public function _Function() { $funcName = $this->_lexer->lookahead['value']; @@ -1335,21 +1331,36 @@ class Parser } } + /** + * Checks whether the function with the given name is a string function + * (a function that returns strings). + */ public function _isStringFunction($funcName) { return isset(self::$_STRING_FUNCTIONS[strtolower($funcName)]); } + /** + * Checks whether the function with the given name is a numeric function + * (a function that returns numerics). + */ public function _isNumericFunction($funcName) { return isset(self::$_NUMERIC_FUNCTIONS[strtolower($funcName)]); } + /** + * Checks whether the function with the given name is a datetime function + * (a function that returns date/time values). + */ public function _isDatetimeFunction($funcName) { return isset(self::$_DATETIME_FUNCTIONS[strtolower($funcName)]); } + /** + * Peeks beyond the specified token and returns the first token after that one. + */ private function _peekBeyond($token) { $peek = $this->_lexer->peek(); @@ -1361,6 +1372,9 @@ class Parser return $peek; } + /** + * Checks whether the given token is a comparison operator. + */ public function _isComparisonOperator($token) { $value = $token['value']; diff --git a/lib/Doctrine/ORM/Query/ParserResult.php b/lib/Doctrine/ORM/Query/ParserResult.php index e4141920b..edbf80feb 100644 --- a/lib/Doctrine/ORM/Query/ParserResult.php +++ b/lib/Doctrine/ORM/Query/ParserResult.php @@ -123,7 +123,7 @@ class ParserResult extends AbstractResult public function getQueryField($fieldAlias) { if ( ! isset($this->_queryFields[$fieldAlias])) { - throw \Doctrine\Common\DoctrineException::updateMe('Unknown query field ' . $fieldAlias); + throw DoctrineException::updateMe('Unknown query field ' . $fieldAlias); } return $this->_queryFields[$fieldAlias]; diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index a6b47e0aa..25899c39a 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -21,6 +21,7 @@ namespace Doctrine\ORM; +use Doctrine\Common\DoctrineException; use Doctrine\ORM\Internal\CommitOrderCalculator; use Doctrine\ORM\Internal\CommitOrderNode; use Doctrine\ORM\PersistentCollection; @@ -424,7 +425,7 @@ class UnitOfWork } if ( ! $assoc->isCascadeSave()) { - echo "NOT CASCADING INTO " . $assoc->getSourceFieldName() . PHP_EOL; + //echo "NOT CASCADING INTO " . $assoc->getSourceFieldName() . PHP_EOL; return; // "Persistence by reachability" only if save cascade specified } @@ -470,7 +471,7 @@ class UnitOfWork $this->_entityChangeSets[$oid] = $changeSet; $this->_originalEntityData[$oid] = $data; } else if ($state == self::STATE_DELETED) { - \Doctrine\Common\DoctrineException::updateMe("Deleted entity in collection detected during flush."); + throw DoctrineException::updateMe("Deleted entity in collection detected during flush."); } // MANAGED associated entities are already taken into account // during changeset calculation anyway, since they are in the identity map. @@ -605,13 +606,13 @@ class UnitOfWork $oid = spl_object_hash($entity); if (isset($this->_entityUpdates[$oid])) { - \Doctrine\Common\DoctrineException::updateMe("Dirty object can't be registered as new."); + throw DoctrineException::updateMe("Dirty object can't be registered as new."); } if (isset($this->_entityDeletions[$oid])) { - \Doctrine\Common\DoctrineException::updateMe("Removed object can't be registered as new."); + throw DoctrineException::updateMe("Removed object can't be registered as new."); } if (isset($this->_entityInsertions[$oid])) { - \Doctrine\Common\DoctrineException::updateMe("Object already registered as new. Can't register twice."); + throw DoctrineException::updateMe("Object already registered as new. Can't register twice."); } $this->_entityInsertions[$oid] = $entity; @@ -642,11 +643,11 @@ class UnitOfWork { $oid = spl_object_hash($entity); if ( ! isset($this->_entityIdentifiers[$oid])) { - \Doctrine\Common\DoctrineException::updateMe("Entity without identity " + throw DoctrineException::updateMe("Entity without identity " . "can't be registered as dirty."); } if (isset($this->_entityDeletions[$oid])) { - \Doctrine\Common\DoctrineException::updateMe("Removed object can't be registered as dirty."); + throw DoctrineException::updateMe("Removed object can't be registered as dirty."); } if ( ! isset($this->_entityUpdates[$oid]) && ! isset($this->_entityInsertions[$oid])) { @@ -784,7 +785,7 @@ class UnitOfWork $classMetadata = $this->_em->getClassMetadata(get_class($entity)); $idHash = $this->getIdentifierHash($this->_entityIdentifiers[spl_object_hash($entity)]); if ($idHash === '') { - \Doctrine\Common\DoctrineException::updateMe("Entity with oid '" . spl_object_hash($entity) + throw DoctrineException::updateMe("Entity with oid '" . spl_object_hash($entity) . "' has no identity and therefore can't be added to the identity map."); } $className = $classMetadata->getRootClassName(); diff --git a/tests/Doctrine/Tests/ORM/Functional/BasicCRUDTest.php b/tests/Doctrine/Tests/ORM/Functional/BasicCRUDTest.php index 7f3013dd0..130c150a1 100644 --- a/tests/Doctrine/Tests/ORM/Functional/BasicCRUDTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/BasicCRUDTest.php @@ -12,12 +12,19 @@ require_once __DIR__ . '/../../TestInit.php'; class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase { + protected function tearDown() + { + $conn = $this->_em->getConnection(); + $conn->exec('DELETE FROM cms_users_groups'); + $conn->exec('DELETE FROM cms_groups'); + $conn->exec('DELETE FROM cms_addresses'); + $conn->exec('DELETE FROM cms_phonenumbers'); + $conn->exec('DELETE FROM cms_users'); + } + public function testBasicUnitsOfWorkWithOneToManyAssociation() { - $em = $this->_em; - - $exporter = new ClassExporter($this->_em); - $exporter->exportClasses(array( + $this->_exporter->exportClasses(array( $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsUser'), $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsPhonenumber'), $this->_em->getClassMetadata('Doctrine\Tests\Models\CMS\CmsAddress'), @@ -29,44 +36,44 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase $user->name = 'Roman'; $user->username = 'romanb'; $user->status = 'developer'; - $em->save($user); + $this->_em->save($user); $this->assertTrue(is_numeric($user->id)); - $this->assertTrue($em->contains($user)); + $this->assertTrue($this->_em->contains($user)); // Read - $user2 = $em->find('Doctrine\Tests\Models\CMS\CmsUser', $user->id); + $user2 = $this->_em->find('Doctrine\Tests\Models\CMS\CmsUser', $user->id); $this->assertTrue($user === $user2); // Add a phonenumber $ph = new CmsPhonenumber; $ph->phonenumber = "12345"; $user->addPhonenumber($ph); - $em->flush(); - $this->assertTrue($em->contains($ph)); - $this->assertTrue($em->contains($user)); + $this->_em->flush(); + $this->assertTrue($this->_em->contains($ph)); + $this->assertTrue($this->_em->contains($user)); //$this->assertTrue($user->phonenumbers instanceof \Doctrine\ORM\PersistentCollection); // Update name $user->name = 'guilherme'; - $em->flush(); + $this->_em->flush(); $this->assertEquals('guilherme', $user->name); // Add another phonenumber $ph2 = new CmsPhonenumber; $ph2->phonenumber = "6789"; $user->addPhonenumber($ph2); - $em->flush(); - $this->assertTrue($em->contains($ph2)); + $this->_em->flush(); + $this->assertTrue($this->_em->contains($ph2)); // Delete - $em->delete($user); - $this->assertTrue($em->getUnitOfWork()->isRegisteredRemoved($user)); - $this->assertTrue($em->getUnitOfWork()->isRegisteredRemoved($ph)); - $this->assertTrue($em->getUnitOfWork()->isRegisteredRemoved($ph2)); - $em->flush(); - $this->assertFalse($em->getUnitOfWork()->isRegisteredRemoved($user)); - $this->assertFalse($em->getUnitOfWork()->isRegisteredRemoved($ph)); - $this->assertFalse($em->getUnitOfWork()->isRegisteredRemoved($ph2)); + $this->_em->delete($user); + $this->assertTrue($this->_em->getUnitOfWork()->isRegisteredRemoved($user)); + $this->assertTrue($this->_em->getUnitOfWork()->isRegisteredRemoved($ph)); + $this->assertTrue($this->_em->getUnitOfWork()->isRegisteredRemoved($ph2)); + $this->_em->flush(); + $this->assertFalse($this->_em->getUnitOfWork()->isRegisteredRemoved($user)); + $this->assertFalse($this->_em->getUnitOfWork()->isRegisteredRemoved($ph)); + $this->assertFalse($this->_em->getUnitOfWork()->isRegisteredRemoved($ph2)); } public function testOneToManyAssociationModification() @@ -188,4 +195,63 @@ class BasicCRUDTest extends \Doctrine\Tests\OrmFunctionalTestCase array())->fetchColumn(); $this->assertEquals(0, $count); } + + public function testBasicQuery() + { + $user = new CmsUser; + $user->name = 'Guilherme'; + $user->username = 'gblanco'; + $user->status = 'developer'; + $this->_em->save($user); + $this->_em->flush(); + + $query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u"); + + $users = $query->getResultList(); + + $this->assertEquals(1, $users->count()); + $this->assertEquals('Guilherme', $users[0]->name); + $this->assertEquals('gblanco', $users[0]->username); + $this->assertEquals('developer', $users[0]->status); + $this->assertNull($users[0]->phonenumbers); + $this->assertNull($users[0]->articles); + } + + public function testBasicInnerJoin() + { + $user = new CmsUser; + $user->name = 'Guilherme'; + $user->username = 'gblanco'; + $user->status = 'developer'; + $this->_em->save($user); + $this->_em->flush(); + + $query = $this->_em->createQuery("select u from Doctrine\Tests\Models\CMS\CmsUser u join u.phonenumbers p"); + + $users = $query->getResultList(); + + $this->assertEquals(0, $users->count()); + } + + public function testBasicLeftJoin() + { + $user = new CmsUser; + $user->name = 'Guilherme'; + $user->username = 'gblanco'; + $user->status = 'developer'; + $this->_em->save($user); + $this->_em->flush(); + + $query = $this->_em->createQuery("select u,p from Doctrine\Tests\Models\CMS\CmsUser u left join u.phonenumbers p"); + + $users = $query->getResultList(); + + $this->assertEquals(1, $users->count()); + $this->assertEquals('Guilherme', $users[0]->name); + $this->assertEquals('gblanco', $users[0]->username); + $this->assertEquals('developer', $users[0]->status); + $this->assertTrue($users[0]->phonenumbers instanceof \Doctrine\ORM\PersistentCollection); + $this->assertEquals(0, $users[0]->phonenumbers->count()); + $this->assertNull($users[0]->articles); + } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Hydration/HydrationTest.php b/tests/Doctrine/Tests/ORM/Hydration/HydrationTest.php index 520b979d3..0ed9226bf 100644 --- a/tests/Doctrine/Tests/ORM/Hydration/HydrationTest.php +++ b/tests/Doctrine/Tests/ORM/Hydration/HydrationTest.php @@ -4,6 +4,9 @@ namespace Doctrine\Tests\ORM\Hydration; require_once __DIR__ . '/../../TestInit.php'; +use Doctrine\ORM\Query\ParserResult; +use Doctrine\ORM\Query\Parser; + class HydrationTest extends \Doctrine\Tests\OrmTestCase { protected $_em; @@ -17,9 +20,16 @@ class HydrationTest extends \Doctrine\Tests\OrmTestCase /** Helper method */ protected function _createParserResult($queryComponents, $tableToClassAliasMap, $isMixedQuery = false) { - $parserResult = new \Doctrine\ORM\Query\ParserResultDummy(); + $parserResult = new ParserResult( + '', + array(/*queryComponent*/), + array(/*tableAliasMap*/) + ); + + //$parserResult = new \Doctrine\ORM\Query\ParserResult(); $parserResult->setQueryComponents($queryComponents); - $parserResult->setTableToClassAliasMap($tableToClassAliasMap); + $parserResult->setDefaultQueryComponentAlias(key($queryComponents)); + $parserResult->setTableAliasMap($tableToClassAliasMap); $parserResult->setMixedQuery($isMixedQuery); return $parserResult; } diff --git a/tests/Doctrine/Tests/OrmFunctionalTestCase.php b/tests/Doctrine/Tests/OrmFunctionalTestCase.php index 487951c5d..5bda8472f 100644 --- a/tests/Doctrine/Tests/OrmFunctionalTestCase.php +++ b/tests/Doctrine/Tests/OrmFunctionalTestCase.php @@ -15,6 +15,9 @@ class OrmFunctionalTestCase extends OrmTestCase /** The EntityManager for this testcase. */ protected $_em; + /** The ClassExporter for this testcase. */ + protected $_exporter; + /** * The currently loaded model names of the fixtures for the testcase. */ @@ -121,6 +124,7 @@ class OrmFunctionalTestCase extends OrmTestCase } if ( ! $this->_em) { $this->_em = $this->_getEntityManager(); + $this->_exporter = new \Doctrine\ORM\Export\ClassExporter($this->_em); } }