diff --git a/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php
index dbcc8c813..a095c2a7d 100644
--- a/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php
+++ b/lib/Doctrine/ORM/Internal/Hydration/SingleScalarHydrator.php
@@ -36,7 +36,11 @@ class SingleScalarHydrator extends AbstractHydrator
{
$cache = array();
$result = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC);
- if (count($result) > 1 || count($result[key($result)]) > 1) {
+ $num = count($result);
+
+ if ($num == 0) {
+ throw new \Doctrine\ORM\NoResultException;
+ } else if ($num > 1 || count($result[key($result)]) > 1) {
throw new \Doctrine\ORM\NonUniqueResultException;
}
$result = $this->_gatherScalarRowData($result[key($result)], $cache);
diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php
index 7ae8857fa..6ac796adc 100644
--- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php
+++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php
@@ -243,10 +243,10 @@ class ClassMetadata extends ClassMetadataInfo
// Store ReflectionProperty of mapped field
$sourceFieldName = $assocMapping->sourceFieldName;
-
- $refProp = $this->reflClass->getProperty($sourceFieldName);
- $refProp->setAccessible(true);
- $this->reflFields[$sourceFieldName] = $refProp;
+
+ $refProp = $this->reflClass->getProperty($sourceFieldName);
+ $refProp->setAccessible(true);
+ $this->reflFields[$sourceFieldName] = $refProp;
}
/**
diff --git a/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php
index 29dedf3e1..637971cb5 100644
--- a/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php
+++ b/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php
@@ -155,7 +155,7 @@ abstract class AbstractFileDriver implements Driver
if ($this->_paths) {
foreach ((array) $this->_paths as $path) {
if ( ! is_dir($path)) {
- throw MappingException::driverRequiresConfiguredDirectoryPath();
+ throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath();
}
$iterator = new \RecursiveIteratorIterator(
diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php
index 49d13d38d..15296395b 100644
--- a/lib/Doctrine/ORM/Query/SqlWalker.php
+++ b/lib/Doctrine/ORM/Query/SqlWalker.php
@@ -465,6 +465,11 @@ class SqlWalker implements TreeWalker
$fieldName = array_pop($parts);
$dqlAlias = $pathExpr->identificationVariable;
$class = $this->_queryComponents[$dqlAlias]['metadata'];
+
+ if (isset($class->inheritedAssociationFields[$fieldName])) {
+ $class = $this->_em->getClassMetadata($class->inheritedAssociationFields[$fieldName]);
+ }
+
$assoc = $class->associationMappings[$fieldName];
if ($assoc->isOwningSide) {
@@ -472,8 +477,8 @@ class SqlWalker implements TreeWalker
if (count($assoc->sourceToTargetKeyColumns) > 1) {
throw QueryException::associationPathCompositeKeyNotSupported();
}
- $sql .= $this->walkIdentificationVariable($dqlAlias) . '.'
- . reset($assoc->targetToSourceKeyColumns);
+ $sql .= $this->getSqlTableAlias($class->table['name'], $dqlAlias) . '.'
+ . reset($assoc->targetToSourceKeyColumns);
} else {
// 2- Inverse side: NOT (YET?) SUPPORTED
throw QueryException::associationPathInverseSideNotSupported();
@@ -683,23 +688,15 @@ class SqlWalker implements TreeWalker
$joinAssocPathExpr = $join->joinAssociationPathExpression;
$joinedDqlAlias = $join->aliasIdentificationVariable;
- $targetQComp = $this->_queryComponents[$joinedDqlAlias];
- $targetClass = $targetQComp['metadata'];
- $relation = $targetQComp['relation'];
- $sourceClass = $this->_queryComponents[$joinAssocPathExpr->identificationVariable]['metadata'];
-
+ $relation = $this->_queryComponents[$joinedDqlAlias]['relation'];
+ $targetClass = $this->_em->getClassMetadata($relation->targetEntityName);
+ $sourceClass = $this->_em->getClassMetadata($relation->sourceEntityName);
$targetTableName = $targetClass->getQuotedTableName($this->_platform);
- $targetTableAlias = $this->getSqlTableAlias($targetClass->getTableName(), $joinedDqlAlias);
- $sourceTableAlias = $this->getSqlTableAlias(
- $sourceClass->getTableName(), $joinAssocPathExpr->identificationVariable
- );
+ $targetTableAlias = $this->getSqlTableAlias($targetClass->table['name'], $joinedDqlAlias);
+ $sourceTableAlias = $this->getSqlTableAlias($sourceClass->table['name'], $joinAssocPathExpr->identificationVariable);
// Ensure we got the owning side, since it has all mapping info
- if ( ! $relation->isOwningSide) {
- $assoc = $targetClass->associationMappings[$relation->mappedBy];
- } else {
- $assoc = $relation;
- }
+ $assoc = ( ! $relation->isOwningSide) ? $targetClass->associationMappings[$relation->mappedBy] : $relation;
if ($this->_query->getHint(Query::HINT_INTERNAL_ITERATION) == true) {
if ($relation->isOneToMany() || $relation->isManyToMany()) {
@@ -713,7 +710,7 @@ class SqlWalker implements TreeWalker
foreach ($assoc->sourceToTargetKeyColumns as $sourceColumn => $targetColumn) {
if ( ! $first) $sql .= ' AND '; else $first = false;
-
+
if ($relation->isOwningSide) {
$quotedTargetColumn = $targetClass->getQuotedColumnName($targetClass->fieldNames[$targetColumn], $this->_platform);
$sql .= $sourceTableAlias . '.' . $sourceColumn
diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
index 947cac9fb..9bd82c36c 100644
--- a/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
+++ b/lib/Doctrine/ORM/Tools/Console/Command/ClearCache/ResultCommand.php
@@ -95,9 +95,9 @@ EOT
$deleted = $cacheDriver->delete($id);
if (is_array($deleted)) {
- $this->_printDeleted($deleted);
+ $this->_printDeleted($output, $deleted);
} else if (is_bool($deleted) && $deleted) {
- $this->_printDeleted(array($id));
+ $this->_printDeleted($output, array($id));
}
$outputed = true;
@@ -105,12 +105,12 @@ EOT
}
// Removing based on --regex
- if (($regex = $input->getOption('regex')) !== null && $regexps) {
+ if (($regexps = $input->getOption('regex')) !== null && $regexps) {
foreach($regexps as $regex) {
$output->write($outputed ? PHP_EOL : '');
$output->write(sprintf('Clearing Result cache entries that match the regular expression "%s"', $regex) . PHP_EOL);
- $this->_printDeleted($cacheDriver->deleteByRegex('/' . $regex. '/'));
+ $this->_printDeleted($output, $cacheDriver->deleteByRegex('/' . $regex. '/'));
$outputed = true;
}
@@ -122,7 +122,7 @@ EOT
$output->write($outputed ? PHP_EOL : '');
$output->write(sprintf('Clearing Result cache entries that have the prefix "%s"', $prefix) . PHP_EOL);
- $this->_printDeleted($cacheDriver->deleteByPrefix($prefix));
+ $this->_printDeleted($output, $cacheDriver->deleteByPrefix($prefix));
$outputed = true;
}
@@ -134,7 +134,7 @@ EOT
$output->write($outputed ? PHP_EOL : '');
$output->write(sprintf('Clearing Result cache entries that have the suffix "%s"', $suffix) . PHP_EOL);
- $this->_printDeleted($cacheDriver->deleteBySuffix($suffix));
+ $this->_printDeleted($output, $cacheDriver->deleteBySuffix($suffix));
$outputed = true;
}
@@ -143,9 +143,9 @@ EOT
// Removing ALL entries
if ( ! $ids && ! $regexps && ! $prefixes && ! $suffixes) {
$output->write($outputed ? PHP_EOL : '');
- $output->write('Clearing ALL Result cache entries');
+ $output->write('Clearing ALL Result cache entries' . PHP_EOL);
- $this->_printDeleted($cacheDriver->deleteAll());
+ $this->_printDeleted($output, $cacheDriver->deleteAll());
$outputed = true;
}
diff --git a/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php
index 48e6f3eb2..89a6a55d5 100644
--- a/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php
+++ b/lib/Doctrine/ORM/Tools/Console/Command/ConvertMappingCommand.php
@@ -61,8 +61,8 @@ class ConvertMappingCommand extends Console\Command\Command
'dest-path', InputArgument::REQUIRED,
'The path to generate your entities classes.'
),
- new InputArgument(
- 'from-database', InputArgument::OPTIONAL, 'The path of mapping information.'
+ new InputOption(
+ 'from-database', null, null, 'Whether or not to convert mapping information from existing database.'
),
new InputOption(
'extend', null, InputOption::PARAMETER_OPTIONAL,
@@ -86,10 +86,7 @@ EOT
{
$em = $this->getHelper('em')->getEntityManager();
- $metadatas = $em->getMetadataFactory()->getAllMetadata();
- $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter'));
-
- if ($input->getArgument('from-database') === true) {
+ if ($input->getOption('from-database') === true) {
$em->getConfiguration()->setMetadataDriverImpl(
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
@@ -97,8 +94,14 @@ EOT
);
}
+ $metadatas = $em->getMetadataFactory()->getAllMetadata();
+ $metadatas = MetadataFilter::filter($metadatas, $input->getOption('filter'));
+
// Process destination directory
- $destPath = realpath($input->getArgument('dest-path'));
+ if ( ! is_dir($destPath = $input->getArgument('dest-path'))) {
+ mkdir($destPath, 0777, true);
+ }
+ $destPath = realpath($destPath);
if ( ! file_exists($destPath)) {
throw new \InvalidArgumentException(
diff --git a/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php
index 44cdd5688..7c33174f5 100644
--- a/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php
+++ b/lib/Doctrine/ORM/Tools/Console/Command/EnsureProductionSettingsCommand.php
@@ -65,12 +65,21 @@ EOT
protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
{
$em = $this->getHelper('em')->getEntityManager();
- $em->getConfiguration()->ensureProductionSettings();
- if ($input->getOption('complete') !== null) {
- $em->getConnection()->connect();
+ $error = false;
+ try {
+ $em->getConfiguration()->ensureProductionSettings();
+
+ if ($input->getOption('complete') !== null) {
+ $em->getConnection()->connect();
+ }
+ } catch (\Exception $e) {
+ $error = true;
+ $output->writeln('' . $e->getMessage() . '');
}
- $output->write('Environment is correctly configured for production.');
+ if ($error === false) {
+ $output->write('Environment is correctly configured for production.' . PHP_EOL);
+ }
}
}
\ No newline at end of file
diff --git a/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php b/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php
index 5f71125d0..412cf869b 100644
--- a/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php
+++ b/lib/Doctrine/ORM/Tools/Console/Command/GenerateProxiesCommand.php
@@ -79,6 +79,10 @@ EOT
$destPath = $em->getConfiguration()->getProxyDir();
}
+ if ( ! is_dir($destPath)) {
+ mkdir($destPath, 0777, true);
+ }
+
$destPath = realpath($destPath);
if ( ! file_exists($destPath)) {
diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php
index 9dcc27d4b..c8957041a 100644
--- a/lib/Doctrine/ORM/Tools/EntityGenerator.php
+++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php
@@ -933,6 +933,9 @@ public function ()
case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY:
return 'IDENTITY';
+ case ClassMetadataInfo::GENERATOR_TYPE_NONE:
+ return 'NONE';
+
default:
throw new \InvalidArgumentException('Invalid provided IdGeneratorType: ' . $type);
}
diff --git a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php
index 4a13b0b7a..b1074cbc5 100644
--- a/tests/Doctrine/Tests/ORM/Functional/QueryTest.php
+++ b/tests/Doctrine/Tests/ORM/Functional/QueryTest.php
@@ -224,7 +224,47 @@ class QueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testGetSingleResultThrowsExceptionOnNoResult()
{
$this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a")
- ->getSingleResult();
+ ->getSingleResult();
+ }
+
+ /**
+ * @expectedException Doctrine\ORM\NoResultException
+ */
+ public function testGetSingleScalarResultThrowsExceptionOnNoResult()
+ {
+ $this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a")
+ ->getSingleScalarResult();
+ }
+
+ /**
+ * @expectedException Doctrine\ORM\NonUniqueResultException
+ */
+ public function testGetSingleScalarResultThrowsExceptionOnNonUniqueResult()
+ {
+ $user = new CmsUser;
+ $user->name = 'Guilherme';
+ $user->username = 'gblanco';
+ $user->status = 'developer';
+
+ $article1 = new CmsArticle;
+ $article1->topic = "Doctrine 2";
+ $article1->text = "This is an introduction to Doctrine 2.";
+ $user->addArticle($article1);
+
+ $article2 = new CmsArticle;
+ $article2->topic = "Symfony 2";
+ $article2->text = "This is an introduction to Symfony 2.";
+ $user->addArticle($article2);
+
+ $this->_em->persist($user);
+ $this->_em->persist($article1);
+ $this->_em->persist($article2);
+
+ $this->_em->flush();
+ $this->_em->clear();
+
+ $this->_em->createQuery("select a from Doctrine\Tests\Models\CMS\CmsArticle a")
+ ->getSingleScalarResult();
}
public function testSupportsQueriesWithEntityNamespaces()
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
new file mode 100644
index 000000000..91c9e129e
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC448Test.php
@@ -0,0 +1,71 @@
+_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448MainTable'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448ConnectedClass'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC448SubTable'),
+ ));
+ }
+
+ public function testIssue()
+ {
+ $q = $this->_em->createQuery("select b from ".__NAMESPACE__."\\DDC448SubTable b where b.connectedClassId = ?1");
+ $this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.connectedClassId AS connectedClassId2 FROM SubTable s1_ INNER JOIN DDC448MainTable d0_ ON s1_.id = d0_.id WHERE d0_.connectedClassId = ?', $q->getSQL());
+ }
+}
+
+/**
+ * @Entity
+ * @InheritanceType("JOINED")
+ * @DiscriminatorColumn(name="discr", type="smallint")
+ * @DiscriminatorMap({
+ * "0" = "DDC448MainTable",
+ * "1" = "DDC448SubTable"
+ * })
+ */
+class DDC448MainTable
+{
+ /**
+ * @Id
+ * @Column(name="id", type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ private $id;
+
+ /**
+ * @ManyToOne(targetEntity="DDC448ConnectedClass", cascade={"all"}, fetch="EAGER")
+ * @JoinColumn(name="connectedClassId", referencedColumnName="id", onDelete="CASCADE", onUpdate="CASCADE", nullable=true)
+ */
+ private $connectedClassId;
+}
+
+/**
+ * @Entity
+ * @Table(name="connectedClass")
+ * @HasLifecycleCallbacks
+ */
+class DDC448ConnectedClass
+{
+ /**
+ * @Id
+ * @Column(name="id", type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ protected $id; // connected with DDC448MainTable
+}
+
+/**
+ * @Entity
+ * @Table(name="SubTable")
+ */
+class DDC448SubTable extends DDC448MainTable
+{
+}
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
new file mode 100644
index 000000000..5503d033e
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC493Test.php
@@ -0,0 +1,69 @@
+_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Customer'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Distributor'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC493Contact')
+ ));
+ }
+
+ public function testIssue()
+ {
+ $q = $this->_em->createQuery("select u, u.contact.data from ".__NAMESPACE__."\\DDC493Distributor u");
+ $this->assertEquals('SELECT d0_.id AS id0, d1_.data AS data1, d0_.discr AS discr2, d0_.contact AS contact3 FROM DDC493Distributor d2_ INNER JOIN DDC493Customer d0_ ON d2_.id = d0_.id INNER JOIN DDC493Contact d1_ ON d0_.contact = d1_.id', $q->getSQL());
+ }
+}
+
+/**
+ * @Entity
+ * @InheritanceType("JOINED")
+ * @DiscriminatorColumn(name="discr", type="string")
+ * @DiscriminatorMap({"distributor" = "DDC493Distributor", "customer" = "DDC493Customer"})
+ */
+class DDC493Customer {
+ /**
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ public $id;
+ /**
+ * @OneToOne(targetEntity="DDC493Contact", cascade={"remove","persist"})
+ * @JoinColumn(name="contact", referencedColumnName="id")
+ */
+ public $contact;
+
+}
+
+/**
+ * @Entity
+ */
+class DDC493Distributor extends DDC493Customer {
+}
+
+/**
+ * @Entity
+ */
+class DDC493Contact
+{
+ /**
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ public $id;
+ /** @Column(type="string") */
+ public $data;
+}
+
+
+
+
diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
new file mode 100644
index 000000000..125f297db
--- /dev/null
+++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC513Test.php
@@ -0,0 +1,71 @@
+_schemaTool->createSchema(array(
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513OfferItem'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513Item'),
+ $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC513Price'),
+ ));
+ }
+
+ public function testIssue()
+ {
+ $q = $this->_em->createQuery("select u from ".__NAMESPACE__."\\DDC513OfferItem u left join u.price p");
+ $this->assertEquals('SELECT d0_.id AS id0, d0_.discr AS discr1, d0_.price AS price2 FROM DDC513OfferItem d1_ INNER JOIN DDC513Item d0_ ON d1_.id = d0_.id LEFT JOIN DDC513Price d2_ ON d0_.price = d2_.id', $q->getSQL());
+ }
+}
+
+/**
+ * @Entity
+ */
+class DDC513OfferItem extends DDC513Item
+{
+}
+
+/**
+ * @Entity
+ * @InheritanceType("JOINED")
+ * @DiscriminatorColumn(name="discr", type="string")
+ * @DiscriminatorMap({"item" = "DDC513Item", "offerItem" = "DDC513OfferItem"})
+ */
+class DDC513Item
+{
+ /**
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ public $id;
+
+ /**
+ * @OneToOne(targetEntity="DDC513Price", cascade={"remove","persist"})
+ * @JoinColumn(name="price", referencedColumnName="id")
+ */
+ public $price;
+}
+
+/**
+ * @Entity
+ */
+class DDC513Price {
+ /**
+ * @Id
+ * @Column(type="integer")
+ * @GeneratedValue(strategy="AUTO")
+ */
+ public $id;
+
+ /** @Column(type="string") */
+ public $data;
+}
+
+
+
+
diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.CTI.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.CTI.dcm.xml
index 9c8c8f98e..472c16558 100644
--- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.CTI.dcm.xml
+++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.ORM.Mapping.CTI.dcm.xml
@@ -3,7 +3,7 @@
xsi="http://www.w3.org/2001/XMLSchema-instance"
schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
-
+