Commit 023f06a4 authored by Jonathan H. Wage's avatar Jonathan H. Wage

Merge remote branch 'upstream/master'

parents aa70e642 841008c4
...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations; ...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -53,13 +54,28 @@ class Annotation ...@@ -53,13 +54,28 @@ class Annotation
} }
} }
/**
* Error handler for unknown property accessor in Annotation class.
*
* @param string $name Unknown property name
*/
public function __get($name) public function __get($name)
{ {
throw new \BadMethodCallException("Unknown annotation property '$name' on annotation '".get_class($this)."'."); throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
} }
/**
* Error handler for unknown property mutator in Annotation class.
*
* @param string $name Unkown property name
* @param mixed $value Property value
*/
public function __set($name, $value) public function __set($name, $value)
{ {
throw new \BadMethodCallException("Unknown annotation property '$name' on annotation '".get_class($this)."'."); throw new \BadMethodCallException(
sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this))
);
} }
} }
\ No newline at end of file
...@@ -27,19 +27,31 @@ namespace Doctrine\Common\Annotations; ...@@ -27,19 +27,31 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
*/ */
class AnnotationException extends \Doctrine\Common\CommonException class AnnotationException extends \Exception
{ {
/**
* Creates a new AnnotationException describing a Syntax error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function syntaxError($message) public static function syntaxError($message)
{ {
return new self('[Syntax Error] ' . $message); return new self('[Syntax Error] ' . $message);
} }
/**
* Creates a new AnnotationException describing a Semantical error.
*
* @param string $message Exception message
* @return AnnotationException
*/
public static function semanticalError($message) public static function semanticalError($message)
{ {
return new self('[Semantical Error] ' . $message); return new self('[Semantical Error] ' . $message);
......
...@@ -32,7 +32,7 @@ use \ReflectionClass, ...@@ -32,7 +32,7 @@ use \ReflectionClass,
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
...@@ -46,7 +46,7 @@ class AnnotationReader ...@@ -46,7 +46,7 @@ class AnnotationReader
* @var string * @var string
* @static * @static
*/ */
private static $CACHE_SALT = "@<Annot>"; private static $CACHE_SALT = '@<Annot>';
/** /**
* Annotations Parser * Annotations Parser
...@@ -56,15 +56,14 @@ class AnnotationReader ...@@ -56,15 +56,14 @@ class AnnotationReader
private $_parser; private $_parser;
/** /**
* Cache machanism to store processed Annotations * Cache mechanism to store processed Annotations
* *
* @var Doctrine\Common\Cache\Cache * @var Doctrine\Common\Cache\Cache
*/ */
private $_cache; private $_cache;
/** /**
* Constructor. Initializes a new AnnotationReader that uses the given * Constructor. Initializes a new AnnotationReader that uses the given Cache provider.
* Cache provider.
* *
* @param Cache $cache The cache provider to use. If none is provided, ArrayCache is used. * @param Cache $cache The cache provider to use. If none is provided, ArrayCache is used.
*/ */
...@@ -112,7 +111,7 @@ class AnnotationReader ...@@ -112,7 +111,7 @@ class AnnotationReader
return $data; return $data;
} }
$annotations = $this->_parser->parse($class->getDocComment(), "class ".$class->getName()); $annotations = $this->_parser->parse($class->getDocComment(), 'class ' . $class->getName());
$this->_cache->save($cacheKey, $annotations, null); $this->_cache->save($cacheKey, $annotations, null);
return $annotations; return $annotations;
...@@ -128,6 +127,7 @@ class AnnotationReader ...@@ -128,6 +127,7 @@ class AnnotationReader
public function getClassAnnotation(ReflectionClass $class, $annotation) public function getClassAnnotation(ReflectionClass $class, $annotation)
{ {
$annotations = $this->getClassAnnotations($class); $annotations = $this->getClassAnnotations($class);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null; return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
} }
...@@ -148,7 +148,7 @@ class AnnotationReader ...@@ -148,7 +148,7 @@ class AnnotationReader
return $data; return $data;
} }
$context = "property ".$property->getDeclaringClass()->getName()."::\$".$property->getName(); $context = 'property ' . $property->getDeclaringClass()->getName() . "::\$" . $property->getName();
$annotations = $this->_parser->parse($property->getDocComment(), $context); $annotations = $this->_parser->parse($property->getDocComment(), $context);
$this->_cache->save($cacheKey, $annotations, null); $this->_cache->save($cacheKey, $annotations, null);
...@@ -165,6 +165,7 @@ class AnnotationReader ...@@ -165,6 +165,7 @@ class AnnotationReader
public function getPropertyAnnotation(ReflectionProperty $property, $annotation) public function getPropertyAnnotation(ReflectionProperty $property, $annotation)
{ {
$annotations = $this->getPropertyAnnotations($property); $annotations = $this->getPropertyAnnotations($property);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null; return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
} }
...@@ -185,7 +186,7 @@ class AnnotationReader ...@@ -185,7 +186,7 @@ class AnnotationReader
return $data; return $data;
} }
$context = "method ".$method->getDeclaringClass()->getName()."::".$method->getName()."()"; $context = 'method ' . $method->getDeclaringClass()->getName() . '::' . $method->getName() . '()';
$annotations = $this->_parser->parse($method->getDocComment(), $context); $annotations = $this->_parser->parse($method->getDocComment(), $context);
$this->_cache->save($cacheKey, $annotations, null); $this->_cache->save($cacheKey, $annotations, null);
...@@ -202,6 +203,7 @@ class AnnotationReader ...@@ -202,6 +203,7 @@ class AnnotationReader
public function getMethodAnnotation(ReflectionMethod $method, $annotation) public function getMethodAnnotation(ReflectionMethod $method, $annotation)
{ {
$annotations = $this->getMethodAnnotations($method); $annotations = $this->getMethodAnnotations($method);
return isset($annotations[$annotation]) ? $annotations[$annotation] : null; return isset($annotations[$annotation]) ? $annotations[$annotation] : null;
} }
} }
\ No newline at end of file
...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations; ...@@ -27,7 +27,8 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -80,7 +81,7 @@ class Lexer extends \Doctrine\Common\Lexer ...@@ -80,7 +81,7 @@ class Lexer extends \Doctrine\Common\Lexer
$newVal = $this->_getNumeric($value); $newVal = $this->_getNumeric($value);
// Checking numeric value // Checking numeric value
if ($newVal !== false){ if ($newVal !== false) {
$value = $newVal; $value = $newVal;
return (strpos($value, '.') !== false || stripos($value, 'e') !== false) return (strpos($value, '.') !== false || stripos($value, 'e') !== false)
...@@ -93,16 +94,34 @@ class Lexer extends \Doctrine\Common\Lexer ...@@ -93,16 +94,34 @@ class Lexer extends \Doctrine\Common\Lexer
return self::T_STRING; return self::T_STRING;
} else { } else {
switch (strtolower($value)) { switch (strtolower($value)) {
case '@': return self::T_AT; case '@':
case ',': return self::T_COMMA; return self::T_AT;
case '(': return self::T_OPEN_PARENTHESIS;
case ')': return self::T_CLOSE_PARENTHESIS; case ',':
case '{': return self::T_OPEN_CURLY_BRACES; return self::T_COMMA;
case '(':
return self::T_OPEN_PARENTHESIS;
case ')':
return self::T_CLOSE_PARENTHESIS;
case '{':
return self::T_OPEN_CURLY_BRACES;
case '}': return self::T_CLOSE_CURLY_BRACES; case '}': return self::T_CLOSE_CURLY_BRACES;
case '=': return self::T_EQUALS; case '=':
case '\\': return self::T_NAMESPACE_SEPARATOR; return self::T_EQUALS;
case 'true': return self::T_TRUE;
case 'false': return self::T_FALSE; case '\\':
return self::T_NAMESPACE_SEPARATOR;
case 'true':
return self::T_TRUE;
case 'false':
return self::T_FALSE;
default: default:
if (ctype_alpha($value[0]) || $value[0] === '_') { if (ctype_alpha($value[0]) || $value[0] === '_') {
return self::T_IDENTIFIER; return self::T_IDENTIFIER;
...@@ -126,6 +145,7 @@ class Lexer extends \Doctrine\Common\Lexer ...@@ -126,6 +145,7 @@ class Lexer extends \Doctrine\Common\Lexer
if ( ! is_scalar($value)) { if ( ! is_scalar($value)) {
return false; return false;
} }
// Checking for valid numeric numbers: 1.234, -1.234e-2 // Checking for valid numeric numbers: 1.234, -1.234e-2
if (is_numeric($value)) { if (is_numeric($value)) {
return $value; return $value;
......
...@@ -27,11 +27,11 @@ namespace Doctrine\Common\Annotations; ...@@ -27,11 +27,11 @@ namespace Doctrine\Common\Annotations;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org * @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $ * @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/ */
class Parser class Parser
{ {
...@@ -173,9 +173,10 @@ class Parser ...@@ -173,9 +173,10 @@ class Parser
$message .= "'{$token['value']}' at position {$token['position']}"; $message .= "'{$token['value']}' at position {$token['position']}";
} }
if(strlen($this->_context)) { if (strlen($this->_context)) {
$message .= ' in '.$this->_context; $message .= ' in ' . $this->_context;
} }
$message .= '.'; $message .= '.';
throw AnnotationException::syntaxError($message); throw AnnotationException::syntaxError($message);
...@@ -411,6 +412,7 @@ class Parser ...@@ -411,6 +412,7 @@ class Parser
foreach ($values as $value) { foreach ($values as $value) {
list ($key, $val) = $value; list ($key, $val) = $value;
if ($key !== null) { if ($key !== null) {
$array[$key] = $val; $array[$key] = $val;
} else { } else {
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -21,15 +19,12 @@ ...@@ -21,15 +19,12 @@
namespace Doctrine\DBAL; namespace Doctrine\DBAL;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Logging\SQLLogger;
/** /**
* Configuration container for the Doctrine DBAL. * Configuration container for the Doctrine DBAL.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -46,22 +41,12 @@ class Configuration ...@@ -46,22 +41,12 @@ class Configuration
*/ */
protected $_attributes = array(); protected $_attributes = array();
/**
* Creates a new DBAL configuration instance.
*/
public function __construct()
{
$this->_attributes = array(
'sqlLogger' => null
);
}
/** /**
* Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled. * Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled.
* *
* @param SQLLogger $logger * @param SQLLogger $logger
*/ */
public function setSQLLogger($logger) public function setSQLLogger(SQLLogger $logger)
{ {
$this->_attributes['sqlLogger'] = $logger; $this->_attributes['sqlLogger'] = $logger;
} }
...@@ -73,6 +58,7 @@ class Configuration ...@@ -73,6 +58,7 @@ class Configuration
*/ */
public function getSQLLogger() public function getSQLLogger()
{ {
return $this->_attributes['sqlLogger']; return isset($this->_attributes['sqlLogger']) ?
$this->_attributes['sqlLogger'] : null;
} }
} }
\ No newline at end of file
...@@ -78,7 +78,7 @@ EOT ...@@ -78,7 +78,7 @@ EOT
if (preg_match('/^select/i', $sql)) { if (preg_match('/^select/i', $sql)) {
$resultSet = $conn->fetchAll($sql); $resultSet = $conn->fetchAll($sql);
} else { } else {
$resultSet = $em->getConnection()->executeUpdate($sql); $resultSet = $conn->executeUpdate($sql);
} }
\Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth); \Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth);
......
...@@ -27,8 +27,7 @@ use Doctrine\Common\Cache\Cache, ...@@ -27,8 +27,7 @@ use Doctrine\Common\Cache\Cache,
* It combines all configuration options from DBAL & ORM. * It combines all configuration options from DBAL & ORM.
* *
* @since 2.0 * @since 2.0
* @internal When adding a new configuration option just write a getter/setter * @internal When adding a new configuration option just write a getter/setter pair.
* pair and add the option to the _attributes array with a proper default value.
* @author Benjamin Eberlei <kontakt@beberlei.de> * @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
...@@ -36,24 +35,6 @@ use Doctrine\Common\Cache\Cache, ...@@ -36,24 +35,6 @@ use Doctrine\Common\Cache\Cache,
*/ */
class Configuration extends \Doctrine\DBAL\Configuration class Configuration extends \Doctrine\DBAL\Configuration
{ {
/**
* Creates a new configuration that can be used for Doctrine.
*/
public function __construct()
{
parent::__construct();
$this->_attributes = array_merge($this->_attributes, array(
'resultCacheImpl' => null,
'queryCacheImpl' => null,
'metadataCacheImpl' => null,
'metadataDriverImpl' => null,
'proxyDir' => null,
'useCExtension' => false,
'autoGenerateProxyClasses' => true,
'proxyNamespace' => null
));
}
/** /**
* Sets the directory where Doctrine generates any necessary proxy class files. * Sets the directory where Doctrine generates any necessary proxy class files.
* *
...@@ -71,7 +52,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -71,7 +52,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getProxyDir() public function getProxyDir()
{ {
return $this->_attributes['proxyDir']; return isset($this->_attributes['proxyDir']) ?
$this->_attributes['proxyDir'] : null;
} }
/** /**
...@@ -82,7 +64,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -82,7 +64,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getAutoGenerateProxyClasses() public function getAutoGenerateProxyClasses()
{ {
return $this->_attributes['autoGenerateProxyClasses']; return isset($this->_attributes['autoGenerateProxyClasses']) ?
$this->_attributes['autoGenerateProxyClasses'] : true;
} }
/** /**
...@@ -103,7 +86,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -103,7 +86,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getProxyNamespace() public function getProxyNamespace()
{ {
return $this->_attributes['proxyNamespace']; return isset($this->_attributes['proxyNamespace']) ?
$this->_attributes['proxyNamespace'] : null;
} }
/** /**
...@@ -188,7 +172,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -188,7 +172,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getMetadataDriverImpl() public function getMetadataDriverImpl()
{ {
return $this->_attributes['metadataDriverImpl']; return isset($this->_attributes['metadataDriverImpl']) ?
$this->_attributes['metadataDriverImpl'] : null;
} }
/** /**
...@@ -198,7 +183,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -198,7 +183,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getResultCacheImpl() public function getResultCacheImpl()
{ {
return $this->_attributes['resultCacheImpl']; return isset($this->_attributes['resultCacheImpl']) ?
$this->_attributes['resultCacheImpl'] : null;
} }
/** /**
...@@ -218,7 +204,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -218,7 +204,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getQueryCacheImpl() public function getQueryCacheImpl()
{ {
return $this->_attributes['queryCacheImpl']; return isset($this->_attributes['queryCacheImpl']) ?
$this->_attributes['queryCacheImpl'] : null;
} }
/** /**
...@@ -238,7 +225,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -238,7 +225,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getMetadataCacheImpl() public function getMetadataCacheImpl()
{ {
return $this->_attributes['metadataCacheImpl']; return isset($this->_attributes['metadataCacheImpl']) ?
$this->_attributes['metadataCacheImpl'] : null;
} }
/** /**
...@@ -259,7 +247,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -259,7 +247,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getUseCExtension() public function getUseCExtension()
{ {
return $this->_attributes['useCExtension']; return isset($this->_attributes['useCExtension']) ?
$this->_attributes['useCExtension'] : false;
} }
/** /**
...@@ -350,6 +339,8 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -350,6 +339,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
* Such a function can then be used in any DQL statement in any place where string * Such a function can then be used in any DQL statement in any place where string
* functions are allowed. * functions are allowed.
* *
* DQL function names are case-insensitive.
*
* @param string $name * @param string $name
* @param string $className * @param string $className
*/ */
...@@ -366,15 +357,33 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -366,15 +357,33 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getCustomStringFunction($name) public function getCustomStringFunction($name)
{ {
$name = strtolower($name);
return isset($this->_attributes['customStringFunctions'][$name]) ? return isset($this->_attributes['customStringFunctions'][$name]) ?
$this->_attributes['customStringFunctions'][$name] : null; $this->_attributes['customStringFunctions'][$name] : null;
} }
/**
* Sets a map of custom DQL string functions.
*
* Keys must be function names and values the FQCN of the implementing class.
* The function names will be case-insensitive in DQL.
*
* Any previously added string functions are discarded.
*
* @param array $functions The map of custom DQL string functions.
*/
public function setCustomStringFunctions(array $functions)
{
$this->_attributes['customStringFunctions'] = array_change_key_case($functions);
}
/** /**
* Registers a custom DQL function that produces a numeric value. * Registers a custom DQL function that produces a numeric value.
* Such a function can then be used in any DQL statement in any place where numeric * Such a function can then be used in any DQL statement in any place where numeric
* functions are allowed. * functions are allowed.
* *
* DQL function names are case-insensitive.
*
* @param string $name * @param string $name
* @param string $className * @param string $className
*/ */
...@@ -391,15 +400,33 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -391,15 +400,33 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getCustomNumericFunction($name) public function getCustomNumericFunction($name)
{ {
$name = strtolower($name);
return isset($this->_attributes['customNumericFunctions'][$name]) ? return isset($this->_attributes['customNumericFunctions'][$name]) ?
$this->_attributes['customNumericFunctions'][$name] : null; $this->_attributes['customNumericFunctions'][$name] : null;
} }
/**
* Sets a map of custom DQL numeric functions.
*
* Keys must be function names and values the FQCN of the implementing class.
* The function names will be case-insensitive in DQL.
*
* Any previously added numeric functions are discarded.
*
* @param array $functions The map of custom DQL numeric functions.
*/
public function setCustomNumericFunctions(array $functions)
{
$this->_attributes['customNumericFunctions'] = array_change_key_case($functions);
}
/** /**
* Registers a custom DQL function that produces a date/time value. * Registers a custom DQL function that produces a date/time value.
* Such a function can then be used in any DQL statement in any place where date/time * Such a function can then be used in any DQL statement in any place where date/time
* functions are allowed. * functions are allowed.
* *
* DQL function names are case-insensitive.
*
* @param string $name * @param string $name
* @param string $className * @param string $className
*/ */
...@@ -416,7 +443,23 @@ class Configuration extends \Doctrine\DBAL\Configuration ...@@ -416,7 +443,23 @@ class Configuration extends \Doctrine\DBAL\Configuration
*/ */
public function getCustomDatetimeFunction($name) public function getCustomDatetimeFunction($name)
{ {
$name = strtolower($name);
return isset($this->_attributes['customDatetimeFunctions'][$name]) ? return isset($this->_attributes['customDatetimeFunctions'][$name]) ?
$this->_attributes['customDatetimeFunctions'][$name] : null; $this->_attributes['customDatetimeFunctions'][$name] : null;
} }
/**
* Sets a map of custom DQL date/time functions.
*
* Keys must be function names and values the FQCN of the implementing class.
* The function names will be case-insensitive in DQL.
*
* Any previously added date/time functions are discarded.
*
* @param array $functions The map of custom DQL date/time functions.
*/
public function setCustomDatetimeFunctions(array $functions)
{
$this->_attributes['customDatetimeFunctions'] = array_change_key_case($functions);
}
} }
\ No newline at end of file
...@@ -440,7 +440,8 @@ class EntityManager ...@@ -440,7 +440,8 @@ class EntityManager
* *
* @param object $entity The entity to copy. * @param object $entity The entity to copy.
* @return object The new entity. * @return object The new entity.
* @todo Implementation or remove. * @todo Implementation need. This is necessary since $e2 = clone $e1; throws an E_FATAL when access anything on $e:
* Fatal error: Maximum function nesting level of '100' reached, aborting!
*/ */
public function copy($entity, $deep = false) public function copy($entity, $deep = false)
{ {
......
...@@ -43,6 +43,7 @@ class SingleScalarHydrator extends AbstractHydrator ...@@ -43,6 +43,7 @@ class SingleScalarHydrator extends AbstractHydrator
} else if ($num > 1 || count($result[key($result)]) > 1) { } else if ($num > 1 || count($result[key($result)]) > 1) {
throw new \Doctrine\ORM\NonUniqueResultException; throw new \Doctrine\ORM\NonUniqueResultException;
} }
$result = $this->_gatherScalarRowData($result[key($result)], $cache); $result = $this->_gatherScalarRowData($result[key($result)], $cache);
return array_shift($result); return array_shift($result);
......
...@@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping\ClassMetadata; ...@@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping\ClassMetadata;
* SINGLE_TABLE strategy. * SINGLE_TABLE strategy.
* *
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @since 2.0 * @since 2.0
* @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html * @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html
*/ */
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -31,10 +29,7 @@ namespace Doctrine\ORM\Query\AST; ...@@ -31,10 +29,7 @@ namespace Doctrine\ORM\Query\AST;
* SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField * SimpleStateFieldPathExpression ::= IdentificationVariable "." StateField
* SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField * SimpleStateFieldAssociationPathExpression ::= SingleValuedAssociationPathExpression "." StateField
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -27,10 +25,7 @@ use Doctrine\ORM\Query; ...@@ -27,10 +25,7 @@ use Doctrine\ORM\Query;
* An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language. * An LL(*) recursive-descent parser for the context-free grammar of the Doctrine Query Language.
* Parses a DQL query, reports any errors in it, and generates an AST. * Parses a DQL query, reports any errors in it, and generates an AST.
* *
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0 * @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com> * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com> * @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org> * @author Roman Borschel <roman@code-factory.org>
...@@ -208,12 +203,15 @@ class Parser ...@@ -208,12 +203,15 @@ class Parser
// Process any deferred validations of some nodes in the AST. // Process any deferred validations of some nodes in the AST.
// This also allows post-processing of the AST for modification purposes. // This also allows post-processing of the AST for modification purposes.
$this->_processDeferredIdentificationVariables(); $this->_processDeferredIdentificationVariables();
if ($this->_deferredPartialObjectExpressions) { if ($this->_deferredPartialObjectExpressions) {
$this->_processDeferredPartialObjectExpressions(); $this->_processDeferredPartialObjectExpressions();
} }
if ($this->_deferredPathExpressions) { if ($this->_deferredPathExpressions) {
$this->_processDeferredPathExpressions($AST); $this->_processDeferredPathExpressions($AST);
} }
if ($this->_deferredResultVariables) { if ($this->_deferredResultVariables) {
$this->_processDeferredResultVariables(); $this->_processDeferredResultVariables();
} }
...@@ -557,11 +555,16 @@ class Parser ...@@ -557,11 +555,16 @@ class Parser
{ {
foreach ($this->_deferredPathExpressions as $deferredItem) { foreach ($this->_deferredPathExpressions as $deferredItem) {
$pathExpression = $deferredItem['expression']; $pathExpression = $deferredItem['expression'];
$parts = $pathExpression->parts;
$numParts = count($parts);
$qComp = $this->_queryComponents[$pathExpression->identificationVariable]; $qComp = $this->_queryComponents[$pathExpression->identificationVariable];
$numParts = count($pathExpression->parts);
if ($numParts == 0) {
$pathExpression->parts = array($qComp['metadata']->identifier[0]);
$numParts++;
}
$parts = $pathExpression->parts;
$aliasIdentificationVariable = $pathExpression->identificationVariable; $aliasIdentificationVariable = $pathExpression->identificationVariable;
$parentField = $pathExpression->identificationVariable; $parentField = $pathExpression->identificationVariable;
$class = $qComp['metadata']; $class = $qComp['metadata'];
...@@ -625,6 +628,7 @@ class Parser ...@@ -625,6 +628,7 @@ class Parser
), ),
null null
); );
$AST->fromClause->identificationVariableDeclarations[0]->joinVariableDeclarations[] = $joinVariableDeclaration; $AST->fromClause->identificationVariableDeclarations[0]->joinVariableDeclarations[] = $joinVariableDeclaration;
$this->_queryComponents[$aliasIdentificationVariable . '.' . $field] = $joinQueryComponent; $this->_queryComponents[$aliasIdentificationVariable . '.' . $field] = $joinQueryComponent;
...@@ -915,12 +919,12 @@ class Parser ...@@ -915,12 +919,12 @@ class Parser
$identVariable = $this->IdentificationVariable(); $identVariable = $this->IdentificationVariable();
$parts = array(); $parts = array();
do { while ($this->_lexer->isNextToken(Lexer::T_DOT)) {
$this->match(Lexer::T_DOT); $this->match(Lexer::T_DOT);
$this->match(Lexer::T_IDENTIFIER); $this->match(Lexer::T_IDENTIFIER);
$parts[] = $this->_lexer->token['value']; $parts[] = $this->_lexer->token['value'];
} while ($this->_lexer->isNextToken(Lexer::T_DOT)); }
// Creating AST node // Creating AST node
$pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $parts); $pathExpr = new AST\PathExpression($expectedTypes, $identVariable, $parts);
...@@ -2168,7 +2172,7 @@ class Parser ...@@ -2168,7 +2172,7 @@ class Parser
return $this->SingleValuedPathExpression(); return $this->SingleValuedPathExpression();
} }
return $this->IdentificationVariable(); return $this->SimpleStateFieldPathExpression();
case Lexer::T_INPUT_PARAMETER: case Lexer::T_INPUT_PARAMETER:
return $this->InputParameter(); return $this->InputParameter();
...@@ -2619,9 +2623,10 @@ class Parser ...@@ -2619,9 +2623,10 @@ class Parser
public function CustomFunctionsReturningNumerics() public function CustomFunctionsReturningNumerics()
{ {
$funcNameLower = strtolower($this->_lexer->lookahead['value']); $funcName = strtolower($this->_lexer->lookahead['value']);
$funcClass = $this->_em->getConfiguration()->getCustomNumericFunction($funcNameLower); // getCustomNumericFunction is case-insensitive
$function = new $funcClass($funcNameLower); $funcClass = $this->_em->getConfiguration()->getCustomNumericFunction($funcName);
$function = new $funcClass($funcName);
$function->parse($this); $function->parse($this);
return $function; return $function;
...@@ -2642,9 +2647,10 @@ class Parser ...@@ -2642,9 +2647,10 @@ class Parser
public function CustomFunctionsReturningDatetime() public function CustomFunctionsReturningDatetime()
{ {
$funcNameLower = strtolower($this->_lexer->lookahead['value']); $funcName = $this->_lexer->lookahead['value'];
$funcClass = $this->_em->getConfiguration()->getCustomDatetimeFunction($funcNameLower); // getCustomDatetimeFunction is case-insensitive
$function = new $funcClass($funcNameLower); $funcClass = $this->_em->getConfiguration()->getCustomDatetimeFunction($funcName);
$function = new $funcClass($funcName);
$function->parse($this); $function->parse($this);
return $function; return $function;
...@@ -2670,9 +2676,10 @@ class Parser ...@@ -2670,9 +2676,10 @@ class Parser
public function CustomFunctionsReturningStrings() public function CustomFunctionsReturningStrings()
{ {
$funcNameLower = strtolower($this->_lexer->lookahead['value']); $funcName = $this->_lexer->lookahead['value'];
$funcClass = $this->_em->getConfiguration()->getCustomStringFunction($funcNameLower); // getCustomStringFunction is case-insensitive
$function = new $funcClass($funcNameLower); $funcClass = $this->_em->getConfiguration()->getCustomStringFunction($funcName);
$function = new $funcClass($funcName);
$function->parse($this); $function->parse($this);
return $function; return $function;
......
<?php <?php
/* /*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
...@@ -240,16 +238,17 @@ class SqlWalker implements TreeWalker ...@@ -240,16 +238,17 @@ class SqlWalker implements TreeWalker
{ {
$sql = ''; $sql = '';
$baseTableAlias = $this->getSqlTableAlias($class->table['name'], $dqlAlias); $baseTableAlias = $this->getSQLTableAlias($class->table['name'], $dqlAlias);
// INNER JOIN parent class tables // INNER JOIN parent class tables
foreach ($class->parentClasses as $parentClassName) { foreach ($class->parentClasses as $parentClassName) {
$parentClass = $this->_em->getClassMetadata($parentClassName); $parentClass = $this->_em->getClassMetadata($parentClassName);
$tableAlias = $this->getSqlTableAlias($parentClass->table['name'], $dqlAlias); $tableAlias = $this->getSQLTableAlias($parentClass->table['name'], $dqlAlias);
$sql .= ' INNER JOIN ' . $parentClass->getQuotedTableName($this->_platform) // If this is a joined association we must use left joins to preserve the correct result.
$sql .= isset($this->_queryComponents[$dqlAlias]['relation']) ? ' LEFT ' : ' INNER ';
$sql .= 'JOIN ' . $parentClass->getQuotedTableName($this->_platform)
. ' ' . $tableAlias . ' ON '; . ' ' . $tableAlias . ' ON ';
$first = true; $first = true;
foreach ($class->identifier as $idField) { foreach ($class->identifier as $idField) {
if ($first) $first = false; else $sql .= ' AND '; if ($first) $first = false; else $sql .= ' AND ';
...@@ -260,14 +259,13 @@ class SqlWalker implements TreeWalker ...@@ -260,14 +259,13 @@ class SqlWalker implements TreeWalker
} }
} }
// LEFT JOIN subclass tables, if partial objects disallowed // LEFT JOIN subclass tables, if partial objects disallowed.
if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) { if ( ! $this->_query->getHint(Query::HINT_FORCE_PARTIAL_LOAD)) {
foreach ($class->subClasses as $subClassName) { foreach ($class->subClasses as $subClassName) {
$subClass = $this->_em->getClassMetadata($subClassName); $subClass = $this->_em->getClassMetadata($subClassName);
$tableAlias = $this->getSqlTableAlias($subClass->table['name'], $dqlAlias); $tableAlias = $this->getSQLTableAlias($subClass->table['name'], $dqlAlias);
$sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform) $sql .= ' LEFT JOIN ' . $subClass->getQuotedTableName($this->_platform)
. ' ' . $tableAlias . ' ON '; . ' ' . $tableAlias . ' ON ';
$first = true; $first = true;
foreach ($class->identifier as $idField) { foreach ($class->identifier as $idField) {
if ($first) $first = false; else $sql .= ' AND '; if ($first) $first = false; else $sql .= ' AND ';
...@@ -458,6 +456,7 @@ class SqlWalker implements TreeWalker ...@@ -458,6 +456,7 @@ class SqlWalker implements TreeWalker
$sql .= $class->getQuotedColumnName($fieldName, $this->_platform); $sql .= $class->getQuotedColumnName($fieldName, $this->_platform);
break; break;
case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION: case AST\PathExpression::TYPE_SINGLE_VALUED_ASSOCIATION:
// 1- the owning side: // 1- the owning side:
// Just use the foreign key, i.e. u.group_id // Just use the foreign key, i.e. u.group_id
...@@ -477,13 +476,18 @@ class SqlWalker implements TreeWalker ...@@ -477,13 +476,18 @@ class SqlWalker implements TreeWalker
if (count($assoc->sourceToTargetKeyColumns) > 1) { if (count($assoc->sourceToTargetKeyColumns) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported(); throw QueryException::associationPathCompositeKeyNotSupported();
} }
$sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.'
. reset($assoc->targetToSourceKeyColumns); if ($this->_useSqlTableAliases) {
$sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.';
}
$sql .= reset($assoc->targetToSourceKeyColumns);
} else { } else {
// 2- Inverse side: NOT (YET?) SUPPORTED // 2- Inverse side: NOT (YET?) SUPPORTED
throw QueryException::associationPathInverseSideNotSupported(); throw QueryException::associationPathInverseSideNotSupported();
} }
break; break;
default: default:
throw QueryException::invalidPathExpression($pathExpr); throw QueryException::invalidPathExpression($pathExpr);
} }
......
...@@ -6,9 +6,9 @@ namespace Doctrine\Tests\Models\Company; ...@@ -6,9 +6,9 @@ namespace Doctrine\Tests\Models\Company;
* @Entity @Table(name="company_events") * @Entity @Table(name="company_events")
* @InheritanceType("JOINED") * @InheritanceType("JOINED")
* @DiscriminatorColumn(name="event_type", type="string") * @DiscriminatorColumn(name="event_type", type="string")
* @DiscriminatorMap({"auction" = "CompanyAuction", "raffle" = "CompanyRaffle"}) * @DiscriminatorMap({"auction"="CompanyAuction", "raffle"="CompanyRaffle"})
*/ */
class CompanyEvent { abstract class CompanyEvent {
/** /**
* @Id @Column(type="integer") * @Id @Column(type="integer")
* @GeneratedValue * @GeneratedValue
......
...@@ -294,5 +294,4 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase ...@@ -294,5 +294,4 @@ class ClassTableInheritanceTest extends \Doctrine\Tests\OrmFunctionalTestCase
->getResult()) > 0); ->getResult()) > 0);
} }
} }
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;
require_once __DIR__ . '/../../../TestInit.php';
class DDC512Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp()
{
parent::setUp();
$this->_schemaTool->createSchema(array(
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512Customer'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512OfferItem'),
$this->_em->getClassMetadata(__NAMESPACE__ . '\DDC512Item'),
));
}
public function testIssue()
{
$customer1 = new DDC512Customer();
$item = new DDC512OfferItem();
$customer1->item = $item;
$this->_em->persist($customer1);
$customer2 = new DDC512Customer();
$this->_em->persist($customer2);
$this->_em->flush();
$this->_em->clear();
$q = $this->_em->createQuery("select u,i from ".__NAMESPACE__."\\DDC512Customer u left join u.item i");
$result = $q->getResult();
$this->assertEquals(2, count($result));
$this->assertTrue($result[0] instanceof DDC512Customer);
$this->assertTrue($result[1] instanceof DDC512Customer);
if ($result[0]->id == $customer1->id) {
$this->assertTrue($result[0]->item instanceof DDC512OfferItem);
$this->assertEquals($item->id, $result[0]->item->id);
$this->assertNull($result[1]->item);
} else {
$this->assertTrue($result[1]->item instanceof DDC512OfferItem);
$this->assertNull($result[0]->item);
}
}
}
/**
* @Entity
*/
class DDC512Customer {
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
/**
* NOTE that we can currently not name the join column the same as the field
* (item = item), this currently confuses Doctrine.
*
* @OneToOne(targetEntity="DDC512OfferItem", cascade={"remove","persist"})
* @JoinColumn(name="item_id", referencedColumnName="id")
*/
public $item;
}
/**
* @Entity
*/
class DDC512OfferItem extends DDC512Item
{
}
/**
* @Entity
* @InheritanceType("JOINED")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"item" = "DDC512Item", "offerItem" = "DDC512OfferItem"})
*/
class DDC512Item
{
/**
* @Id
* @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
public $id;
}
...@@ -21,6 +21,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -21,6 +21,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$query = $this->_em->createQuery($dqlToBeTested); $query = $this->_em->createQuery($dqlToBeTested);
$query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true) $query->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
->useQueryCache(false); ->useQueryCache(false);
parent::assertEquals($sqlToBeConfirmed, $query->getSql()); parent::assertEquals($sqlToBeConfirmed, $query->getSql());
$query->free(); $query->free();
} catch (\Exception $e) { } catch (\Exception $e) {
...@@ -385,7 +386,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -385,7 +386,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
$this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_TIMESTAMP', $q->getSql()); $this->assertEquals('SELECT d0_.id AS id0 FROM date_time_model d0_ WHERE d0_.col_datetime > CURRENT_TIMESTAMP', $q->getSql());
} }
/*public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition() public function testExistsExpressionInWhereCorrelatedSubqueryAssocCondition()
{ {
$this->assertSqlGeneration( $this->assertSqlGeneration(
// DQL // DQL
...@@ -402,7 +403,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -402,7 +403,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
. ')' . ')'
); );
}*/ }
public function testLimitFromQueryClass() public function testLimitFromQueryClass()
{ {
...@@ -584,4 +585,62 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -584,4 +585,62 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
"SELECT c0_.name AS name0, (SELECT COUNT(c1_.phonenumber) AS dctrn__1 FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = 1234) AS sclr1 FROM cms_users c0_ WHERE c0_.name = 'jon'" "SELECT c0_.name AS name0, (SELECT COUNT(c1_.phonenumber) AS dctrn__1 FROM cms_phonenumbers c1_ WHERE c1_.phonenumber = 1234) AS sclr1 FROM cms_users c0_ WHERE c0_.name = 'jon'"
); );
} }
/**
* DDC-430
*/
public function testSupportSelectWithMoreThan10InputParameters()
{
$this->assertSqlGeneration(
"SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u WHERE u.id = ?1 OR u.id = ?2 OR u.id = ?3 OR u.id = ?4 OR u.id = ?5 OR u.id = ?6 OR u.id = ?7 OR u.id = ?8 OR u.id = ?9 OR u.id = ?10 OR u.id = ?11",
"SELECT c0_.id AS id0, c0_.status AS status1, c0_.username AS username2, c0_.name AS name3 FROM cms_users c0_ WHERE c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ? OR c0_.id = ?"
);
}
/**
* DDC-431
*/
public function testSupportToCustomDQLFunctions()
{
$config = $this->_em->getConfiguration();
$config->addCustomNumericFunction('MYABS', 'Doctrine\Tests\ORM\Query\MyAbsFunction');
$this->assertSqlGeneration(
'SELECT MYABS(p.phonenumber) FROM Doctrine\Tests\Models\CMS\CmsPhonenumber p',
'SELECT ABS(c0_.phonenumber) AS sclr0 FROM cms_phonenumbers c0_'
);
$config->setCustomNumericFunctions(array());
}
}
class MyAbsFunction extends \Doctrine\ORM\Query\AST\Functions\FunctionNode
{
public $simpleArithmeticExpression;
/**
* @override
*/
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return 'ABS(' . $sqlWalker->walkSimpleArithmeticExpression(
$this->simpleArithmeticExpression
) . ')';
}
/**
* @override
*/
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$lexer = $parser->getLexer();
$parser->match(\Doctrine\ORM\Query\Lexer::T_IDENTIFIER);
$parser->match(\Doctrine\ORM\Query\Lexer::T_OPEN_PARENTHESIS);
$this->simpleArithmeticExpression = $parser->SimpleArithmeticExpression();
$parser->match(\Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS);
}
} }
\ No newline at end of file
...@@ -159,4 +159,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase ...@@ -159,4 +159,12 @@ class UpdateSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
'UPDATE cms_users SET status = ? WHERE id BETWEEN ? AND ?' 'UPDATE cms_users SET status = ? WHERE id BETWEEN ? AND ?'
); );
} }
public function testSingleValuedAssociationFieldInWhere()
{
$this->assertSqlGeneration(
"UPDATE Doctrine\Tests\Models\CMS\CmsPhonenumber p SET p.phonenumber = 1234 WHERE p.user = ?1",
"UPDATE cms_phonenumbers SET phonenumber = 1234 WHERE user_id = ?"
);
}
} }
...@@ -15,7 +15,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -15,7 +15,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
private static $_queryCacheImpl = null; private static $_queryCacheImpl = null;
/* Shared connection when a TestCase is run alone (outside of it's functional suite) */ /* Shared connection when a TestCase is run alone (outside of it's functional suite) */
private static $_sharedConn; protected static $_sharedConn;
/** /**
* @var \Doctrine\ORM\EntityManager * @var \Doctrine\ORM\EntityManager
...@@ -33,13 +33,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -33,13 +33,13 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
protected $_sqlLoggerStack; protected $_sqlLoggerStack;
/** The names of the model sets used in this testcase. */ /** The names of the model sets used in this testcase. */
private $_usedModelSets = array(); protected $_usedModelSets = array();
/** Whether the database schema has already been created. */ /** Whether the database schema has already been created. */
private static $_tablesCreated = array(); protected static $_tablesCreated = array();
/** List of model sets and their classes. */ /** List of model sets and their classes. */
private static $_modelSets = array( protected static $_modelSets = array(
'cms' => array( 'cms' => array(
'Doctrine\Tests\Models\CMS\CmsUser', 'Doctrine\Tests\Models\CMS\CmsUser',
'Doctrine\Tests\Models\CMS\CmsPhonenumber', 'Doctrine\Tests\Models\CMS\CmsPhonenumber',
...@@ -170,11 +170,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -170,11 +170,11 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$forceCreateTables = false; $forceCreateTables = false;
if ( ! isset($this->sharedFixture['conn'])) { if ( ! isset($this->sharedFixture['conn'])) {
if ( ! isset(self::$_sharedConn)) { if ( ! isset(static::$_sharedConn)) {
self::$_sharedConn = TestUtil::getConnection(); static::$_sharedConn = TestUtil::getConnection();
} }
$this->sharedFixture['conn'] = self::$_sharedConn; $this->sharedFixture['conn'] = static::$_sharedConn;
if ($this->sharedFixture['conn']->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { if ($this->sharedFixture['conn']->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) {
$forceCreateTables = true; $forceCreateTables = true;
...@@ -189,12 +189,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase ...@@ -189,12 +189,12 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$classes = array(); $classes = array();
foreach ($this->_usedModelSets as $setName => $bool) { foreach ($this->_usedModelSets as $setName => $bool) {
if ( ! isset(self::$_tablesCreated[$setName])/* || $forceCreateTables*/) { if ( ! isset(static::$_tablesCreated[$setName])/* || $forceCreateTables*/) {
foreach (self::$_modelSets[$setName] as $className) { foreach (static::$_modelSets[$setName] as $className) {
$classes[] = $this->_em->getClassMetadata($className); $classes[] = $this->_em->getClassMetadata($className);
} }
self::$_tablesCreated[$setName] = true; static::$_tablesCreated[$setName] = true;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment