mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 15:02:22 +01:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e9438ba60 | ||
|
|
73483bf003 | ||
|
|
245c30a1a0 | ||
|
|
15dc64f2f9 | ||
|
|
66951f3c47 | ||
|
|
5f21f177e9 | ||
|
|
7af877d17e | ||
|
|
f628a7f609 | ||
|
|
64c222e4d3 | ||
|
|
13db27609c | ||
|
|
f039902a44 | ||
|
|
59d0c02aa9 | ||
|
|
63d1d847ac | ||
|
|
ce4aacaaee | ||
|
|
dadcc7e9fc | ||
|
|
cc9b96e259 | ||
|
|
006412bad9 | ||
|
|
ffbaaece93 | ||
|
|
c3fa29f298 | ||
|
|
aa82a75726 | ||
|
|
fba85d481f | ||
|
|
5bdfad9e0a | ||
|
|
d69a79c723 | ||
|
|
f51409b627 | ||
|
|
8c8deb9c9b | ||
|
|
79c8f42483 | ||
|
|
04ae8f2c64 | ||
|
|
ecb495d293 | ||
|
|
1418173870 | ||
|
|
26a6b69993 | ||
|
|
fa5ee57faf | ||
|
|
2a2f010788 | ||
|
|
e958085559 | ||
|
|
98ba0c1ab2 | ||
|
|
b574be5e3b | ||
|
|
79ad9068e1 | ||
|
|
af403d52fb |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "doctrine/orm",
|
||||
"type": "library","version":"2.2.1",
|
||||
"type": "library","version":"2.2.2",
|
||||
"description": "Object-Relational-Mapper for PHP",
|
||||
"keywords": ["orm", "database"],
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\DBAL\Types\Type,
|
||||
Doctrine\DBAL\Cache\QueryCacheProfile,
|
||||
Doctrine\ORM\Query\QueryException,
|
||||
Doctrine\DBAL\Cache\QueryCacheProfile;
|
||||
Doctrine\ORM\Internal\Hydration\CacheHydrator;
|
||||
|
||||
/**
|
||||
* Base contract for ORM queries. Base class for Query and NativeQuery.
|
||||
@@ -29,7 +30,6 @@ use Doctrine\DBAL\Types\Type,
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
@@ -101,6 +101,11 @@ abstract class AbstractQuery
|
||||
*/
|
||||
protected $_expireResultCache = false;
|
||||
|
||||
/**
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile
|
||||
*/
|
||||
protected $_hydrationCacheProfile;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of a class derived from <tt>AbstractQuery</tt>.
|
||||
*
|
||||
@@ -295,6 +300,68 @@ abstract class AbstractQuery
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cache profile for hydration caching.
|
||||
*
|
||||
* If no result cache driver is set in the QueryCacheProfile, the default
|
||||
* result cache driver is used from the configuration.
|
||||
*
|
||||
* Important: Hydration caching does NOT register entities in the
|
||||
* UnitOfWork when retrieved from the cache. Never use result cached
|
||||
* entities for requests that also flush the EntityManager. If you want
|
||||
* some form of caching with UnitOfWork registration you should use
|
||||
* {@see AbstractQuery::setResultCacheProfile()}.
|
||||
*
|
||||
* @example
|
||||
* $lifetime = 100;
|
||||
* $resultKey = "abc";
|
||||
* $query->setHydrationCacheProfile(new QueryCacheProfile());
|
||||
* $query->setHydrationCacheProfile(new QueryCacheProfile($lifetime, $resultKey));
|
||||
*
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setHydrationCacheProfile(QueryCacheProfile $profile = null)
|
||||
{
|
||||
if ( ! $profile->getResultCacheDriver()) {
|
||||
$resultCacheDriver = $this->_em->getConfiguration()->getHydrationCacheImpl();
|
||||
$profile = $profile->setResultCacheDriver($resultCacheDriver);
|
||||
}
|
||||
|
||||
$this->_hydrationCacheProfile = $profile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Doctrine\DBAL\Cache\QueryCacheProfile
|
||||
*/
|
||||
public function getHydrationCacheProfile()
|
||||
{
|
||||
return $this->_hydrationCacheProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cache profile for the result cache.
|
||||
*
|
||||
* If no result cache driver is set in the QueryCacheProfile, the default
|
||||
* result cache driver is used from the configuration.
|
||||
*
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setResultCacheProfile(QueryCacheProfile $profile = null)
|
||||
{
|
||||
if ( ! $profile->getResultCacheDriver()) {
|
||||
$resultCacheDriver = $this->_em->getConfiguration()->getResultCacheImpl();
|
||||
$profile = $profile->setResultCacheDriver($resultCacheDriver);
|
||||
}
|
||||
|
||||
$this->_queryCacheProfile = $profile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching result sets and implictly enables caching.
|
||||
*
|
||||
@@ -640,15 +707,68 @@ abstract class AbstractQuery
|
||||
$this->setParameters($params);
|
||||
}
|
||||
|
||||
$setCacheEntry = function() {};
|
||||
|
||||
if ($this->_hydrationCacheProfile !== null) {
|
||||
list($cacheKey, $realCacheKey) = $this->getHydrationCacheId();
|
||||
|
||||
$queryCacheProfile = $this->getHydrationCacheProfile();
|
||||
$cache = $queryCacheProfile->getResultCacheDriver();
|
||||
$result = $cache->fetch($cacheKey);
|
||||
|
||||
if (isset($result[$realCacheKey])) {
|
||||
return $result[$realCacheKey];
|
||||
}
|
||||
|
||||
if ( ! $result) {
|
||||
$result = array();
|
||||
}
|
||||
|
||||
$setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) {
|
||||
$result[$realCacheKey] = $data;
|
||||
$cache->save($cacheKey, $result, $queryCacheProfile->getLifetime());
|
||||
};
|
||||
}
|
||||
|
||||
$stmt = $this->_doExecute();
|
||||
|
||||
if (is_numeric($stmt)) {
|
||||
$setCacheEntry($stmt);
|
||||
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
return $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
|
||||
$data = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
|
||||
$stmt, $this->_resultSetMapping, $this->_hints
|
||||
);
|
||||
|
||||
$setCacheEntry($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result cache id to use to store the result set cache entry.
|
||||
* Will return the configured id if it exists otherwise a hash will be
|
||||
* automatically generated for you.
|
||||
*
|
||||
* @return array ($key, $hash)
|
||||
*/
|
||||
protected function getHydrationCacheId()
|
||||
{
|
||||
$params = $this->getParameters();
|
||||
|
||||
foreach ($params AS $key => $value) {
|
||||
$params[$key] = $this->processParameterValue($value);
|
||||
}
|
||||
|
||||
$sql = $this->getSQL();
|
||||
$queryCacheProfile = $this->getHydrationCacheProfile();
|
||||
$hints = $this->getHints();
|
||||
$hints['hydrationMode'] = $this->getHydrationMode();
|
||||
ksort($hints);
|
||||
|
||||
return $queryCacheProfile->generateCacheKeys($sql, $params, $hints);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -230,6 +230,28 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
$this->_attributes['queryCacheImpl'] = $cacheImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for the hydration cache (SQL cache).
|
||||
*
|
||||
* @return \Doctrine\Common\Cache\Cache
|
||||
*/
|
||||
public function getHydrationCacheImpl()
|
||||
{
|
||||
return isset($this->_attributes['hydrationCacheImpl'])
|
||||
? $this->_attributes['hydrationCacheImpl']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver implementation that is used for the hydration cache (SQL cache).
|
||||
*
|
||||
* @param \Doctrine\Common\Cache\Cache $cacheImpl
|
||||
*/
|
||||
public function setHydrationCacheImpl(Cache $cacheImpl)
|
||||
{
|
||||
$this->_attributes['hydrationCacheImpl'] = $cacheImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for metadata caching.
|
||||
*
|
||||
|
||||
@@ -1209,7 +1209,9 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
foreach ($mapping['joinColumns'] as $key => &$joinColumn) {
|
||||
if ($mapping['type'] === self::ONE_TO_ONE && ! $this->isInheritanceTypeSingleTable()) {
|
||||
if (count($mapping['joinColumns']) == 1) {
|
||||
$joinColumn['unique'] = true;
|
||||
if (! isset($mapping['id']) || ! $mapping['id']) {
|
||||
$joinColumn['unique'] = true;
|
||||
}
|
||||
} else {
|
||||
$uniqueContraintColumns[] = $joinColumn['name'];
|
||||
}
|
||||
@@ -1991,7 +1993,7 @@ class ClassMetadataInfo implements ClassMetadata
|
||||
if ( ! class_exists($className)) {
|
||||
throw MappingException::invalidClassInDiscriminatorMap($className, $this->name);
|
||||
}
|
||||
if (is_subclass_of($className, $this->name)) {
|
||||
if (is_subclass_of($className, $this->name) && ! in_array($className, $this->subClasses)) {
|
||||
$this->subClasses[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,13 @@ class DatabaseDriver implements Driver
|
||||
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
|
||||
}
|
||||
|
||||
if ( ! $table->hasPrimaryKey()) {
|
||||
throw new MappingException(
|
||||
"Table " . $table->getName() . " has no primary key. Doctrine does not ".
|
||||
"support reverse engineering from tables that don't have a primary key."
|
||||
);
|
||||
}
|
||||
|
||||
$pkColumns = $table->getPrimaryKey()->getColumns();
|
||||
sort($pkColumns);
|
||||
sort($allForeignKeyColumns);
|
||||
@@ -185,12 +192,13 @@ class DatabaseDriver implements Driver
|
||||
$fieldMappings = array();
|
||||
foreach ($columns as $column) {
|
||||
$fieldMapping = array();
|
||||
if ($primaryKeyColumns && in_array($column->getName(), $primaryKeyColumns)) {
|
||||
$fieldMapping['id'] = true;
|
||||
} else if (in_array($column->getName(), $allForeignKeyColumns)) {
|
||||
|
||||
if (in_array($column->getName(), $allForeignKeyColumns)) {
|
||||
continue;
|
||||
} else if ($primaryKeyColumns && in_array($column->getName(), $primaryKeyColumns)) {
|
||||
$fieldMapping['id'] = true;
|
||||
}
|
||||
|
||||
|
||||
$fieldMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $column->getName(), false);
|
||||
$fieldMapping['columnName'] = $column->getName();
|
||||
$fieldMapping['type'] = strtolower((string) $column->getType());
|
||||
@@ -291,13 +299,23 @@ class DatabaseDriver implements Driver
|
||||
$associationMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $localColumn, true);
|
||||
$associationMapping['targetEntity'] = $this->getClassNameForTable($foreignTable);
|
||||
|
||||
if ($primaryKeyColumns && in_array($localColumn, $primaryKeyColumns)) {
|
||||
$associationMapping['id'] = true;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($cols); $i++) {
|
||||
$associationMapping['joinColumns'][] = array(
|
||||
'name' => $cols[$i],
|
||||
'referencedColumnName' => $fkCols[$i],
|
||||
);
|
||||
}
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
|
||||
//Here we need to check if $cols are the same as $primaryKeyColums
|
||||
if (!array_diff($cols,$primaryKeyColumns)) {
|
||||
$metadata->mapOneToOne($associationMapping);
|
||||
} else {
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -402,9 +402,6 @@ class YamlDriver extends AbstractFileDriver
|
||||
if (isset($manyToManyElement['mappedBy'])) {
|
||||
$mapping['mappedBy'] = $manyToManyElement['mappedBy'];
|
||||
} else if (isset($manyToManyElement['joinTable'])) {
|
||||
if (isset($manyToManyElement['inversedBy'])) {
|
||||
$mapping['inversedBy'] = $manyToManyElement['inversedBy'];
|
||||
}
|
||||
|
||||
$joinTableElement = $manyToManyElement['joinTable'];
|
||||
$joinTable = array(
|
||||
@@ -434,6 +431,10 @@ class YamlDriver extends AbstractFileDriver
|
||||
$mapping['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['inversedBy'])) {
|
||||
$mapping['inversedBy'] = $manyToManyElement['inversedBy'];
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['cascade'])) {
|
||||
$mapping['cascade'] = $manyToManyElement['cascade'];
|
||||
}
|
||||
|
||||
@@ -1143,6 +1143,7 @@ class BasicEntityPersister
|
||||
$placeholder = '?';
|
||||
|
||||
if (isset($this->_columnTypes[$column]) &&
|
||||
isset($this->_class->fieldNames[$column]) &&
|
||||
isset($this->_class->fieldMappings[$this->_class->fieldNames[$column]]['requireSQLConversion'])) {
|
||||
$type = Type::getType($this->_columnTypes[$column]);
|
||||
$placeholder = $type->convertToDatabaseValueSQL('?', $this->_platform);
|
||||
|
||||
78
lib/Doctrine/ORM/Proxy/Autoloader.php
Normal file
78
lib/Doctrine/ORM/Proxy/Autoloader.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Proxy;
|
||||
|
||||
/**
|
||||
* Special Autoloader for Proxy classes because them not being PSR-0 compatible.
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class Autoloader
|
||||
{
|
||||
/**
|
||||
* Resolve proxy class name to a filename based on the following pattern.
|
||||
*
|
||||
* 1. Remove Proxy namespace from class name
|
||||
* 2. Remove namespace seperators from remaining class name.
|
||||
* 3. Return PHP filename from proxy-dir with the result from 2.
|
||||
*
|
||||
* @param string $proxyDir
|
||||
* @param string $proxyNamespace
|
||||
* @param string $className
|
||||
* @return string
|
||||
*/
|
||||
static public function resolveFile($proxyDir, $proxyNamespace, $className)
|
||||
{
|
||||
if (0 !== strpos($className, $proxyNamespace)) {
|
||||
throw ProxyException::notProxyClass($className, $proxyNamespace);
|
||||
}
|
||||
|
||||
$className = str_replace('\\', '', substr($className, strlen($proxyNamespace) +1));
|
||||
return $proxyDir . DIRECTORY_SEPARATOR . $className.'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register and return autoloader callback for the given proxy dir and
|
||||
* namespace.
|
||||
*
|
||||
* @param string $proxyDir
|
||||
* @param string $proxyNamespace
|
||||
* @param Closure $notFoundCallback Invoked when the proxy file is not found.
|
||||
* @return Closure
|
||||
*/
|
||||
static public function register($proxyDir, $proxyNamespace, \Closure $notFoundCallback = null)
|
||||
{
|
||||
$proxyNamespace = ltrim($proxyNamespace, "\\");
|
||||
$autoloader = function($className) use ($proxyDir, $proxyNamespace, $notFoundCallback) {
|
||||
if (0 === strpos($className, $proxyNamespace)) {
|
||||
$file = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className);
|
||||
|
||||
if ($notFoundCallback && ! file_exists($file)) {
|
||||
$notFoundCallback($proxyDir, $proxyNamespace, $className);
|
||||
}
|
||||
|
||||
require $file;
|
||||
}
|
||||
};
|
||||
spl_autoload_register($autoloader);
|
||||
return $autoloader;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,4 +40,12 @@ class ProxyException extends \Doctrine\ORM\ORMException {
|
||||
return new self("You must configure a proxy namespace. See docs for details");
|
||||
}
|
||||
|
||||
}
|
||||
public static function notProxyClass($className, $proxyNamespace)
|
||||
{
|
||||
return new self(sprintf(
|
||||
"The class %s is not part of the proxy namespace %s",
|
||||
$className, $proxyNamespace
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,22 +125,27 @@ class ProxyFactory
|
||||
* @param string $toDir The target directory of the proxy classes. If not specified, the
|
||||
* directory configured on the Configuration of the EntityManager used
|
||||
* by this factory is used.
|
||||
* @return int Number of generated proxies.
|
||||
*/
|
||||
public function generateProxyClasses(array $classes, $toDir = null)
|
||||
{
|
||||
$proxyDir = $toDir ?: $this->_proxyDir;
|
||||
$proxyDir = rtrim($proxyDir, DIRECTORY_SEPARATOR);
|
||||
$num = 0;
|
||||
|
||||
foreach ($classes as $class) {
|
||||
/* @var $class ClassMetadata */
|
||||
if ($class->isMappedSuperclass) {
|
||||
if ($class->isMappedSuperclass || $class->reflClass->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$proxyFileName = $this->getProxyFileName($class->name, $proxyDir);
|
||||
|
||||
$this->_generateProxyClass($class, $proxyFileName, self::$_proxyClassTemplate);
|
||||
$num++;
|
||||
}
|
||||
|
||||
return $num;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -562,6 +562,8 @@ class Expr
|
||||
{
|
||||
if (is_numeric($literal) && !is_string($literal)) {
|
||||
return (string) $literal;
|
||||
} else if (is_bool($literal)) {
|
||||
return $literal ? "true" : "false";
|
||||
} else {
|
||||
return "'" . str_replace("'", "''", $literal) . "'";
|
||||
}
|
||||
|
||||
@@ -440,13 +440,15 @@ class SqlWalker implements TreeWalker
|
||||
$sql .= ' ' . $this->_platform->getWriteLockSQL();
|
||||
break;
|
||||
|
||||
case LockMode::PESSIMISTIC_OPTIMISTIC:
|
||||
case LockMode::OPTIMISTIC:
|
||||
foreach ($this->_selectedClasses AS $selectedClass) {
|
||||
if ( ! $class->isVersioned) {
|
||||
if ( ! $selectedClass['class']->isVersioned) {
|
||||
throw \Doctrine\ORM\OptimisticLockException::lockFailed($selectedClass['class']->name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LockMode::NONE:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw \Doctrine\ORM\Query\QueryException::invalidLockMode();
|
||||
@@ -1101,7 +1103,7 @@ class SqlWalker implements TreeWalker
|
||||
|
||||
$sqlTableAlias = $this->getSQLTableAlias($tableName, $dqlAlias);
|
||||
$columnName = $class->getQuotedColumnName($fieldName, $this->_platform);
|
||||
$columnAlias = $this->getSQLColumnAlias($columnName);
|
||||
$columnAlias = $this->getSQLColumnAlias($class->fieldMappings[$fieldName]['columnName']);
|
||||
|
||||
$col = $sqlTableAlias . '.' . $columnName;
|
||||
|
||||
|
||||
@@ -862,6 +862,14 @@ public function <methodName>()
|
||||
|
||||
if ($this->_generateAnnotations) {
|
||||
$lines[] = $this->_spaces . ' *';
|
||||
|
||||
if (isset($associationMapping['id']) && $associationMapping['id']) {
|
||||
$lines[] = $this->_spaces . ' * @' . $this->_annotationsPrefix . 'Id';
|
||||
|
||||
if ($generatorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
|
||||
$lines[] = $this->_spaces . ' * @' . $this->_annotationsPrefix . 'GeneratedValue(strategy="' . $generatorType . '")';
|
||||
}
|
||||
}
|
||||
|
||||
$type = null;
|
||||
switch ($associationMapping['type']) {
|
||||
|
||||
@@ -36,7 +36,7 @@ class Version
|
||||
/**
|
||||
* Current Doctrine Version
|
||||
*/
|
||||
const VERSION = '2.2.1';
|
||||
const VERSION = '2.2.2';
|
||||
|
||||
/**
|
||||
* Compares a Doctrine version with the current one.
|
||||
|
||||
2
lib/vendor/doctrine-common
vendored
2
lib/vendor/doctrine-common
vendored
Submodule lib/vendor/doctrine-common updated: 6c7f9cfd46...14eb4d62b6
2
lib/vendor/doctrine-dbal
vendored
2
lib/vendor/doctrine-dbal
vendored
Submodule lib/vendor/doctrine-dbal updated: e01f7468d8...ee8f64111d
86
tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php
Normal file
86
tests/Doctrine/Tests/ORM/Functional/HydrationCacheTest.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
namespace Doctrine\Tests\ORM\Functional;
|
||||
|
||||
use Doctrine\Tests\OrmFunctionalTestCase;
|
||||
use Doctrine\Tests\Models\Cms\CmsUser;
|
||||
use Doctrine\DBAL\Cache\QueryCacheProfile;
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
|
||||
/**
|
||||
* @group DDC-1766
|
||||
*/
|
||||
class HydrationCacheTest extends OrmFunctionalTestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
$this->useModelSet('cms');
|
||||
parent::setUp();
|
||||
|
||||
$user = new CmsUser;
|
||||
$user->name = "Benjamin";
|
||||
$user->username = "beberlei";
|
||||
$user->status = 'active';
|
||||
|
||||
$this->_em->persist($user);
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
}
|
||||
|
||||
public function testHydrationCache()
|
||||
{
|
||||
$cache = new ArrayCache();
|
||||
$dql = "SELECT u FROM Doctrine\Tests\Models\Cms\CmsUser u";
|
||||
|
||||
$users = $this->_em->createQuery($dql)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache))
|
||||
->getResult();
|
||||
|
||||
$c = $this->getCurrentQueryCount();
|
||||
$users = $this->_em->createQuery($dql)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache))
|
||||
->getResult();
|
||||
|
||||
$this->assertEquals($c, $this->getCurrentQueryCount(), "Should not execute query. Its cached!");
|
||||
|
||||
$users = $this->_em->createQuery($dql)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache))
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertEquals($c + 1, $this->getCurrentQueryCount(), "Hydration is part of cache key.");
|
||||
|
||||
$users = $this->_em->createQuery($dql)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache))
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertEquals($c + 1, $this->getCurrentQueryCount(), "Hydration now cached");
|
||||
|
||||
$users = $this->_em->createQuery($dql)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, 'cachekey', $cache))
|
||||
->getArrayResult();
|
||||
|
||||
$this->assertTrue($cache->contains('cachekey'), 'Explicit cache key');
|
||||
|
||||
$users = $this->_em->createQuery($dql)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, 'cachekey', $cache))
|
||||
->getArrayResult();
|
||||
$this->assertEquals($c + 2, $this->getCurrentQueryCount(), "Hydration now cached");
|
||||
}
|
||||
|
||||
public function testHydrationParametersSerialization()
|
||||
{
|
||||
$cache = new ArrayCache();
|
||||
$user = new CmsUser();
|
||||
$user->id = 1;
|
||||
|
||||
$dql = "SELECT u FROM Doctrine\Tests\Models\Cms\CmsUser u WHERE u.id = ?1";
|
||||
$query = $this->_em->createQuery($dql)
|
||||
->setParameter(1, $user)
|
||||
->setHydrationCacheProfile(new QueryCacheProfile(null, null, $cache));
|
||||
|
||||
$query->getResult();
|
||||
$c = $this->getCurrentQueryCount();
|
||||
$query->getResult();
|
||||
$this->assertEquals($c, $this->getCurrentQueryCount(), "Should not execute query. Its cached!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ use Doctrine\Tests\Models\CMS\CmsArticle,
|
||||
|
||||
require_once __DIR__ . '/../../../TestInit.php';
|
||||
|
||||
/**
|
||||
* @group locking
|
||||
*/
|
||||
class LockTest extends \Doctrine\Tests\OrmFunctionalTestCase {
|
||||
protected function setUp() {
|
||||
$this->useModelSet('cms');
|
||||
@@ -139,7 +142,6 @@ class LockTest extends \Doctrine\Tests\OrmFunctionalTestCase {
|
||||
|
||||
/**
|
||||
* @group DDC-178
|
||||
* @group locking
|
||||
*/
|
||||
public function testLockPessimisticRead() {
|
||||
$readLockSql = $this->_em->getConnection()->getDatabasePlatform()->getReadLockSql();
|
||||
@@ -166,4 +168,17 @@ class LockTest extends \Doctrine\Tests\OrmFunctionalTestCase {
|
||||
$query = array_pop( $this->_sqlLoggerStack->queries );
|
||||
$this->assertContains($readLockSql, $query['sql']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1693
|
||||
*/
|
||||
public function testLockOptimisticNonVersionedThrowsExceptionInDQL()
|
||||
{
|
||||
$dql = "SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'";
|
||||
|
||||
$this->setExpectedException('Doctrine\ORM\OptimisticLockException', 'The optimistic lock on an entity failed.');
|
||||
$sql = $this->_em->createQuery($dql)->setHint(
|
||||
\Doctrine\ORM\Query::HINT_LOCK_MODE, \Doctrine\DBAL\LockMode::OPTIMISTIC
|
||||
)->getSQL();
|
||||
}
|
||||
}
|
||||
|
||||
158
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1695Test.php
Normal file
158
tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1695Test.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
namespace Doctrine\Tests\ORM\Functional\Ticket;
|
||||
|
||||
/**
|
||||
* @group DDC-1695
|
||||
*/
|
||||
class DDC1695Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
{
|
||||
public function testIssue()
|
||||
{
|
||||
if ($this->_em->getConnection()->getDatabasePlatform()->getName() != "sqlite") {
|
||||
$this->markTestSkipped("Only with sqlite");
|
||||
}
|
||||
$dql = "SELECT n.smallText, n.publishDate FROM " . __NAMESPACE__ . "\\DDC1695News n";
|
||||
$sql = $this->_em->createQuery($dql)->getSQL();
|
||||
|
||||
$this->assertEquals(
|
||||
'SELECT d0_."SmallText" AS SmallText0, d0_."PublishDate" AS PublishDate1 FROM "DDC1695News" d0_',
|
||||
$sql
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Table(name="`DDC1695News`")
|
||||
* @Entity
|
||||
*/
|
||||
class DDC1695News
|
||||
{
|
||||
/**
|
||||
* @var integer $idNews
|
||||
*
|
||||
* @Column(name="`IdNews`", type="integer", nullable=false)
|
||||
* @Id
|
||||
* @GeneratedValue
|
||||
*/
|
||||
private $idNews;
|
||||
|
||||
/**
|
||||
* @var bigint $iduser
|
||||
*
|
||||
* @Column(name="`IdUser`", type="bigint", nullable=false)
|
||||
*/
|
||||
private $idUser;
|
||||
|
||||
/**
|
||||
* @var integer $idLanguage
|
||||
*
|
||||
* @Column(name="`IdLanguage`", type="integer", nullable=false)
|
||||
*/
|
||||
private $idLanguage;
|
||||
|
||||
/**
|
||||
* @var integer $idCondition
|
||||
*
|
||||
* @Column(name="`IdCondition`", type="integer", nullable=true)
|
||||
*/
|
||||
private $idCondition;
|
||||
|
||||
/**
|
||||
* @var integer $idHealthProvider
|
||||
*
|
||||
* @Column(name="`IdHealthProvider`", type="integer", nullable=true)
|
||||
*/
|
||||
private $idHealthProvider;
|
||||
|
||||
/**
|
||||
* @var integer $idSpeciality
|
||||
*
|
||||
* @Column(name="`IdSpeciality`", type="integer", nullable=true)
|
||||
*/
|
||||
private $idSpeciality;
|
||||
|
||||
/**
|
||||
* @var integer $idMedicineType
|
||||
*
|
||||
* @Column(name="`IdMedicineType`", type="integer", nullable=true)
|
||||
*/
|
||||
private $idMedicineType;
|
||||
|
||||
/**
|
||||
* @var integer $idTreatment
|
||||
*
|
||||
* @Column(name="`IdTreatment`", type="integer", nullable=true)
|
||||
*/
|
||||
private $idTreatment;
|
||||
|
||||
/**
|
||||
* @var string $title
|
||||
*
|
||||
* @Column(name="`Title`", type="string", nullable=true)
|
||||
*/
|
||||
private $title;
|
||||
|
||||
/**
|
||||
* @var string $smallText
|
||||
*
|
||||
* @Column(name="`SmallText`", type="string", nullable=true)
|
||||
*/
|
||||
private $smallText;
|
||||
|
||||
/**
|
||||
* @var string $longText
|
||||
*
|
||||
* @Column(name="`LongText`", type="string", nullable=true)
|
||||
*/
|
||||
private $longText;
|
||||
|
||||
/**
|
||||
* @var datetimetz $publishDate
|
||||
*
|
||||
* @Column(name="`PublishDate`", type="datetimetz", nullable=true)
|
||||
*/
|
||||
private $publishDate;
|
||||
|
||||
/**
|
||||
* @var tsvector $idxNews
|
||||
*
|
||||
* @Column(name="`IdxNews`", type="tsvector", nullable=true)
|
||||
*/
|
||||
private $idxNews;
|
||||
|
||||
/**
|
||||
* @var boolean $highlight
|
||||
*
|
||||
* @Column(name="`Highlight`", type="boolean", nullable=false)
|
||||
*/
|
||||
private $highlight;
|
||||
|
||||
/**
|
||||
* @var integer $order
|
||||
*
|
||||
* @Column(name="`Order`", type="integer", nullable=false)
|
||||
*/
|
||||
private $order;
|
||||
|
||||
/**
|
||||
* @var boolean $deleted
|
||||
*
|
||||
* @Column(name="`Deleted`", type="boolean", nullable=false)
|
||||
*/
|
||||
private $deleted;
|
||||
|
||||
/**
|
||||
* @var boolean $active
|
||||
*
|
||||
* @Column(name="`Active`", type="boolean", nullable=false)
|
||||
*/
|
||||
private $active;
|
||||
|
||||
/**
|
||||
* @var boolean $updateToHighlighted
|
||||
*
|
||||
* @Column(name="`UpdateToHighlighted`", type="boolean", nullable=true)
|
||||
*/
|
||||
private $updateToHighlighted;
|
||||
}
|
||||
62
tests/Doctrine/Tests/ORM/Proxy/AutoloaderTest.php
Normal file
62
tests/Doctrine/Tests/ORM/Proxy/AutoloaderTest.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* This software consists of voluntary contributions made by many individuals
|
||||
* and is licensed under the LGPL. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\Tests\ORM\Proxy;
|
||||
|
||||
use Doctrine\Tests\OrmTestCase;
|
||||
use Doctrine\ORM\Proxy\Autoloader;
|
||||
|
||||
/**
|
||||
* @group DDC-1698
|
||||
*/
|
||||
class AutoloaderTest extends OrmTestCase
|
||||
{
|
||||
static public function dataResolveFile()
|
||||
{
|
||||
return array(
|
||||
array('/tmp', 'MyProxy', 'MyProxy\__CG__\RealClass', '/tmp/__CG__RealClass.php'),
|
||||
array('/tmp', 'MyProxy\Subdir', 'MyProxy\Subdir\__CG__\RealClass', '/tmp/__CG__RealClass.php'),
|
||||
array('/tmp', 'MyProxy', 'MyProxy\__CG__\Other\RealClass', '/tmp/__CG__OtherRealClass.php'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataResolveFile
|
||||
*/
|
||||
public function testResolveFile($proxyDir, $proxyNamespace, $className, $expectedProxyFile)
|
||||
{
|
||||
$actualProxyFile = Autoloader::resolveFile($proxyDir, $proxyNamespace, $className);
|
||||
$this->assertEquals($expectedProxyFile, $actualProxyFile);
|
||||
}
|
||||
|
||||
public function testAutoload()
|
||||
{
|
||||
if (file_exists(sys_get_temp_dir() ."/AutoloaderTestClass.php")) {
|
||||
unlink(sys_get_temp_dir() ."/AutoloaderTestClass.php");
|
||||
}
|
||||
|
||||
$autoloader = Autoloader::register(sys_get_temp_dir(), 'ProxyAutoloaderTest', function($proxyDir, $proxyNamespace, $className) {
|
||||
file_put_contents(sys_get_temp_dir() . "/AutoloaderTestClass.php", "<?php namespace ProxyAutoloaderTest; class AutoloaderTestClass {} ");
|
||||
});
|
||||
|
||||
$this->assertTrue(class_exists('ProxyAutoloaderTest\AutoloaderTestClass', true));
|
||||
unlink(sys_get_temp_dir() ."/AutoloaderTestClass.php");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +155,20 @@ class ProxyClassGeneratorTest extends \Doctrine\Tests\OrmTestCase
|
||||
$this->assertEquals(1, substr_count($classCode, 'function __sleep'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1771
|
||||
*/
|
||||
public function testSkipAbstractClassesOnGeneration()
|
||||
{
|
||||
$cm = new \Doctrine\ORM\Mapping\ClassMetadata(__NAMESPACE__ . '\\AbstractClass');
|
||||
$cm->initializeReflection(new \Doctrine\Common\Persistence\Mapping\RuntimeReflectionService);
|
||||
$this->assertNotNull($cm->reflClass);
|
||||
|
||||
$num = $this->_proxyFactory->generateProxyClasses(array($cm));
|
||||
|
||||
$this->assertEquals(0, $num, "No proxies generated.");
|
||||
}
|
||||
|
||||
public function testNoConfigDir_ThrowsException()
|
||||
{
|
||||
$this->setExpectedException('Doctrine\ORM\Proxy\ProxyException');
|
||||
@@ -183,3 +197,8 @@ class SleepClass
|
||||
return array('id');
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AbstractClass
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -336,4 +336,13 @@ class ExprTest extends \Doctrine\Tests\OrmTestCase
|
||||
$orExpr = $this->_expr->orx();
|
||||
$orExpr->add($this->_expr->quot(5, 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1683
|
||||
*/
|
||||
public function testBooleanLiteral()
|
||||
{
|
||||
$this->assertEquals('true', $this->_expr->literal(true));
|
||||
$this->assertEquals('false', $this->_expr->literal(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -893,6 +893,20 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-1693
|
||||
* @group locking
|
||||
*/
|
||||
public function testLockModeNoneQueryHint()
|
||||
{
|
||||
$this->assertSqlGeneration(
|
||||
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.username = 'gblanco'",
|
||||
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 ".
|
||||
"FROM cms_users c0_ WHERE c0_.username = 'gblanco'",
|
||||
array(Query::HINT_LOCK_MODE => \Doctrine\DBAL\LockMode::NONE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-430
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user