Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
49434b03
Commit
49434b03
authored
Jul 21, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] Further cleanups. Started eager loading support.
parent
b3d110ba
Changes
25
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
294 additions
and
403 deletions
+294
-403
AbstractQuery.php
lib/Doctrine/ORM/AbstractQuery.php
+8
-7
AbstractHydrator.php
lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
+5
-1
ObjectHydrator.php
lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
+23
-11
DoctrineAnnotations.php
lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
+2
-2
OneToOneMapping.php
lib/Doctrine/ORM/Mapping/OneToOneMapping.php
+10
-7
StandardEntityPersister.php
lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
+10
-3
Query.php
lib/Doctrine/ORM/Query.php
+27
-2
AbstractResult.php
lib/Doctrine/ORM/Query/AbstractResult.php
+0
-58
CacheHandler.php
lib/Doctrine/ORM/Query/CacheHandler.php
+0
-146
AbstractExecutor.php
lib/Doctrine/ORM/Query/Exec/AbstractExecutor.php
+0
-112
AbstractSqlExecutor.php
lib/Doctrine/ORM/Query/Exec/AbstractSqlExecutor.php
+18
-11
MultiTableDeleteExecutor.php
lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php
+1
-1
MultiTableUpdateExecutor.php
lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php
+1
-1
SingleSelectExecutor.php
lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php
+1
-2
SingleTableDeleteUpdateExecutor.php
...ctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php
+1
-2
Parser.php
lib/Doctrine/ORM/Query/Parser.php
+1
-1
ParserResult.php
lib/Doctrine/ORM/Query/ParserResult.php
+1
-1
SqlWalker.php
lib/Doctrine/ORM/Query/SqlWalker.php
+69
-31
TreeWalker.php
lib/Doctrine/ORM/Query/TreeWalker.php
+26
-0
TreeWalkerAdapter.php
lib/Doctrine/ORM/Query/TreeWalkerAdapter.php
+19
-0
UnitOfWork.php
lib/Doctrine/ORM/UnitOfWork.php
+1
-2
MockTreeWalker.php
tests/Doctrine/Tests/Mocks/MockTreeWalker.php
+9
-1
OneToOneBidirectionalAssociationTest.php
...s/ORM/Functional/OneToOneBidirectionalAssociationTest.php
+1
-0
HydrationPerformanceTest.php
...ctrine/Tests/ORM/Performance/HydrationPerformanceTest.php
+58
-0
LanguageRecognitionTest.php
tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php
+2
-1
No files found.
lib/Doctrine/ORM/AbstractQuery.php
View file @
49434b03
...
...
@@ -423,6 +423,8 @@ abstract class AbstractQuery
*/
public
function
execute
(
$params
=
array
(),
$hydrationMode
=
null
)
{
// If there are still pending insertions in the UnitOfWork we need to flush
// in order to guarantee a correct result.
if
(
$this
->
_em
->
getUnitOfWork
()
->
hasPendingInsertions
())
{
$this
->
_em
->
flush
();
}
...
...
@@ -442,25 +444,24 @@ abstract class AbstractQuery
if
(
$cached
===
false
)
{
// Cache miss.
$result
=
$this
->
_doExecute
(
$params
);
$queryResult
=
CacheHandler
::
fromResultSet
(
$this
,
$result
);
$cacheDriver
->
save
(
$hash
,
$queryResult
->
toCachedForm
(),
$this
->
_resultCacheTTL
);
$cacheDriver
->
save
(
$hash
,
serialize
(
$result
),
$this
->
_resultCacheTTL
);
return
$result
;
}
else
{
// Cache hit.
$queryResult
=
CacheHandler
::
fromCachedResult
(
$this
,
$cached
);
return
$queryResult
->
getResultSet
();
return
unserialize
(
$cached
);
}
}
$stmt
=
$this
->
_doExecute
(
$params
);
if
(
is_
integer
(
$stmt
))
{
if
(
is_
numeric
(
$stmt
))
{
return
$stmt
;
}
return
$this
->
_em
->
getHydrator
(
$this
->
_hydrationMode
)
->
hydrateAll
(
$stmt
,
$this
->
_resultSetMapping
);
return
$this
->
_em
->
getHydrator
(
$this
->
_hydrationMode
)
->
hydrateAll
(
$stmt
,
$this
->
_resultSetMapping
,
$this
->
_hints
);
}
/**
...
...
lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php
View file @
49434b03
...
...
@@ -56,6 +56,9 @@ abstract class AbstractHydrator
/** @var Statement The statement that provides the data to hydrate. */
protected
$_stmt
;
/** @var array The query hints. */
protected
$_hints
;
/**
* Initializes a new instance of a class derived from <tt>AbstractHydrator</tt>.
*
...
...
@@ -90,10 +93,11 @@ abstract class AbstractHydrator
* @param object $resultSetMapping
* @return mixed
*/
public
function
hydrateAll
(
$stmt
,
$resultSetMapping
)
public
function
hydrateAll
(
$stmt
,
$resultSetMapping
,
array
$hints
=
array
()
)
{
$this
->
_stmt
=
$stmt
;
$this
->
_rsm
=
$resultSetMapping
;
$this
->
_hints
=
$hints
;
$this
->
_prepare
();
$result
=
$this
->
_hydrateAll
();
$this
->
_cleanup
();
...
...
lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
View file @
49434b03
...
...
@@ -23,6 +23,7 @@ namespace Doctrine\ORM\Internal\Hydration;
use
Doctrine\DBAL\Connection
;
use
Doctrine\ORM\PersistentCollection
;
use
Doctrine\ORM\Query
;
use
Doctrine\Common\Collections\Collection
;
/**
...
...
@@ -39,7 +40,6 @@ class ObjectHydrator extends AbstractHydrator
/* Class entries */
private
$_ce
=
array
();
private
$_discriminatorMap
=
array
();
/*
* The following parts are reinitialized on every hydration run.
*/
...
...
@@ -61,7 +61,8 @@ class ObjectHydrator extends AbstractHydrator
protected
function
_prepare
()
{
$this
->
_isSimpleQuery
=
count
(
$this
->
_rsm
->
aliasMap
)
<=
1
;
$this
->
_allowPartialObjects
=
$this
->
_em
->
getConfiguration
()
->
getAllowPartialObjects
();
$this
->
_allowPartialObjects
=
$this
->
_em
->
getConfiguration
()
->
getAllowPartialObjects
()
||
isset
(
$this
->
_hints
[
Query
::
HINT_FORCE_PARTIAL_LOAD
]);
$this
->
_identifierMap
=
array
();
$this
->
_resultPointers
=
array
();
$this
->
_idTemplate
=
array
();
...
...
@@ -226,6 +227,13 @@ class ObjectHydrator extends AbstractHydrator
}
}
/**
* Gets an entity instance.
*
* @param $data The instance data.
* @param $dqlAlias The DQL alias of the entity's class.
* @return object The entity.
*/
private
function
getEntity
(
array
$data
,
$dqlAlias
)
{
$className
=
$this
->
_rsm
->
aliasMap
[
$dqlAlias
];
...
...
@@ -234,25 +242,28 @@ class ObjectHydrator extends AbstractHydrator
$className
=
$this
->
_discriminatorMap
[
$className
][
$data
[
$discrColumn
]];
unset
(
$data
[
$discrColumn
]);
}
$entity
=
$this
->
_uow
->
createEntity
(
$className
,
$data
);
$entity
=
$this
->
_uow
->
createEntity
(
$className
,
$data
,
$this
->
_hints
);
// Properly initialize any unfetched associations, if partial objects are not allowed.
if
(
!
$this
->
_allowPartialObjects
)
{
foreach
(
$this
->
_ce
[
$className
]
->
associationMappings
as
$field
=>
$assoc
)
{
if
(
!
isset
(
$this
->
_fetchedAssociations
[
$className
][
$field
]))
{
if
(
$assoc
->
isOneToOne
())
{
if
(
$assoc
->
isLazilyFetched
())
{
$joinColumnsValues
=
array
();
$joinColumns
=
array
();
foreach
(
$assoc
->
targetToSourceKeyColumns
as
$srcColumn
)
{
$joinColumnsValue
s
[
$srcColumn
]
=
$data
[
$assoc
->
joinColumnFieldNames
[
$srcColumn
]];
$joinColumn
s
[
$srcColumn
]
=
$data
[
$assoc
->
joinColumnFieldNames
[
$srcColumn
]];
}
if
(
$assoc
->
isLazilyFetched
())
{
// Inject proxy
$
proxy
=
$this
->
_em
->
getProxyFactory
()
->
getAssociationProxy
(
$entity
,
$assoc
,
$joinColumnsValues
);
$this
->
_ce
[
$className
]
->
reflFields
[
$field
]
->
setValue
(
$entity
,
$proxy
);
$
this
->
_ce
[
$className
]
->
reflFields
[
$field
]
->
setValue
(
$entity
,
$this
->
_em
->
getProxyFactory
()
->
getAssociationProxy
(
$entity
,
$assoc
,
$joinColumns
)
);
}
else
{
//TODO: Schedule for eager fetching
// Eager load
//TODO: Allow more efficient and configurable batching of these loads
$assoc
->
load
(
$entity
,
new
$className
,
$this
->
_em
,
$joinColumns
);
}
}
else
{
//TODO: Eager load
// Inject collection
$this
->
_ce
[
$className
]
->
reflFields
[
$field
]
->
setValue
(
$entity
,
new
PersistentCollection
(
...
...
@@ -280,6 +291,7 @@ class ObjectHydrator extends AbstractHydrator
$class
->
reflFields
[
$property
]
->
setValue
(
$entity1
,
$entity2
);
$this
->
_uow
->
setOriginalEntityProperty
(
spl_object_hash
(
$entity1
),
$property
,
$entity2
);
$relation
=
$class
->
associationMappings
[
$property
];
if
(
$relation
->
isOneToOne
())
{
$targetClass
=
$this
->
_ce
[
$relation
->
targetEntityName
];
if
(
$relation
->
isOwningSide
)
{
...
...
lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
View file @
49434b03
...
...
@@ -29,7 +29,7 @@ final class Entity extends \Doctrine\Common\Annotations\Annotation {
final
class
InheritanceType
extends
\Doctrine\Common\Annotations\Annotation
{}
final
class
DiscriminatorColumn
extends
\Doctrine\Common\Annotations\Annotation
{
public
$name
;
//
public $fieldName; // field name used in non-object hydration (array/scalar)
public
$fieldName
;
// field name used in non-object hydration (array/scalar)
public
$type
;
public
$length
;
}
...
...
@@ -43,7 +43,7 @@ final class GeneratedValue extends \Doctrine\Common\Annotations\Annotation {
final
class
Version
extends
\Doctrine\Common\Annotations\Annotation
{}
final
class
JoinColumn
extends
\Doctrine\Common\Annotations\Annotation
{
public
$name
;
//
public $fieldName; // field name used in non-object hydration (array/scalar)
public
$fieldName
;
// field name used in non-object hydration (array/scalar)
public
$referencedColumnName
;
public
$unique
=
false
;
public
$nullable
=
true
;
...
...
lib/Doctrine/ORM/Mapping/OneToOneMapping.php
View file @
49434b03
...
...
@@ -179,10 +179,12 @@ class OneToOneMapping extends AssociationMapping
$conditions
[
$targetKeyColumn
]
=
$joinColumnValues
[
$sourceKeyColumn
];
}
}
if
(
$targetClass
->
hasInverseAssociationMapping
(
$this
->
sourceFieldName
))
{
$targetClass
->
setFieldValue
(
$targetEntity
,
$targetClass
->
inverseMappings
[
$this
->
sourceFieldName
]
->
getSourceFieldName
(),
$targetEntity
=
$em
->
getUnitOfWork
()
->
getEntityPersister
(
$this
->
targetEntityName
)
->
load
(
$conditions
,
$targetEntity
);
if
(
$targetEntity
!==
null
&&
$targetClass
->
hasInverseAssociationMapping
(
$this
->
sourceFieldName
))
{
$targetClass
->
setFieldValue
(
$targetEntity
,
$targetClass
->
inverseMappings
[
$this
->
sourceFieldName
]
->
sourceFieldName
,
$sourceEntity
);
}
}
else
{
...
...
@@ -195,10 +197,11 @@ class OneToOneMapping extends AssociationMapping
$conditions
[
$sourceKeyColumn
]
=
$joinColumnValues
[
$targetKeyColumn
];
}
}
$targetEntity
=
$em
->
getUnitOfWork
()
->
getEntityPersister
(
$this
->
targetEntityName
)
->
load
(
$conditions
,
$targetEntity
);
$targetClass
->
setFieldValue
(
$targetEntity
,
$this
->
mappedByFieldName
,
$sourceEntity
);
}
$em
->
getUnitOfWork
()
->
getEntityPersister
(
$this
->
targetEntityName
)
->
load
(
$conditions
,
$targetEntity
);
}
protected
function
_getPrivateValue
(
ClassMetadata
$class
,
$entity
,
$column
)
...
...
lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
View file @
49434b03
...
...
@@ -406,6 +406,7 @@ class StandardEntityPersister
* @param array $criteria The criteria by which to load the entity.
* @param object $entity The entity to load the data into. If not specified,
* a new entity is created.
* @return The loaded entity instance or NULL if the entity/the data can not be found.
*/
public
function
load
(
array
$criteria
,
$entity
=
null
)
{
...
...
@@ -413,7 +414,14 @@ class StandardEntityPersister
$stmt
->
execute
(
array_values
(
$criteria
));
$data
=
array
();
$joinColumnValues
=
array
();
foreach
(
$stmt
->
fetch
(
Connection
::
FETCH_ASSOC
)
as
$column
=>
$value
)
{
$result
=
$stmt
->
fetch
(
Connection
::
FETCH_ASSOC
);
$stmt
->
closeCursor
();
if
(
$result
===
false
)
{
return
null
;
}
foreach
(
$result
as
$column
=>
$value
)
{
if
(
isset
(
$this
->
_class
->
fieldNames
[
$column
]))
{
$fieldName
=
$this
->
_class
->
fieldNames
[
$column
];
$data
[
$fieldName
]
=
Type
::
getType
(
$this
->
_class
->
getTypeOfField
(
$fieldName
))
...
...
@@ -422,7 +430,6 @@ class StandardEntityPersister
$joinColumnValues
[
$column
]
=
$value
;
}
}
$stmt
->
closeCursor
();
if
(
$entity
===
null
)
{
$entity
=
$this
->
_em
->
getUnitOfWork
()
->
createEntity
(
$this
->
_entityName
,
$data
);
...
...
lib/Doctrine/ORM/Query.php
View file @
49434b03
...
...
@@ -21,7 +21,6 @@
namespace
Doctrine\ORM
;
use
Doctrine\ORM\Query\CacheHandler
;
use
Doctrine\ORM\Query\Parser
;
use
Doctrine\ORM\Query\QueryException
;
...
...
@@ -38,11 +37,11 @@ use Doctrine\ORM\Query\QueryException;
*/
final
class
Query
extends
AbstractQuery
{
/* Query STATES */
/**
* A query object is in CLEAN state when it has NO unparsed/unprocessed DQL parts.
*/
const
STATE_CLEAN
=
1
;
/**
* A query object is in state DIRTY when it has DQL parts that have not yet been
* parsed/processed. This is automatically defined as DIRTY when addDqlQueryPart
...
...
@@ -50,6 +49,32 @@ final class Query extends AbstractQuery
*/
const
STATE_DIRTY
=
2
;
/* Query HINTS */
/**
* The refresh hint turns any query into a refresh query with the result that
* any local changes in entities are overridden with the fetched values.
*
* @var string
*/
const
HINT_REFRESH
=
'doctrine.refresh'
;
/**
* The forcePartialLoad query hint forces a particular query to return
* partial objects when partial objects in general are disallowed in the
* configuration.
*
* @var string
*/
const
HINT_FORCE_PARTIAL_LOAD
=
'doctrine.forcePartialLoad'
;
/**
* The includeMetaColumns query hint causes meta columns like foreign keys and
* discriminator columns to be selected and returned as part of the query result.
*
* This hint does only apply to non-object queries.
*
* @var string
*/
const
HINT_INCLUDE_META_COLUMNS
=
'doctrine.includeMetaColumns'
;
/**
* @var integer $_state The current state of this query.
*/
...
...
lib/Doctrine/ORM/Query/AbstractResult.php
deleted
100644 → 0
View file @
b3d110ba
<?php
/*
* $Id$
*
* 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\Query
;
use
Doctrine\Common\DoctrineException
;
/**
* Doctrine_ORM_Query_AbstractResult
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @version $Revision: 1393 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
*/
abstract
class
AbstractResult
{
/**
* @var mixed $_data The actual data to be stored. Can be an array, a string or an integer.
*/
protected
$_data
;
/**
* Returns this object in serialized format, revertable using fromCached*.
*
* @return string Serialized cached item.
*/
public
function
toCachedForm
()
{
return
serialize
(
array
(
$this
->
_data
,
$this
->
getQueryComponents
(),
$this
->
getTableAliasMap
(),
$this
->
getEnumParams
()
));
}
}
\ No newline at end of file
lib/Doctrine/ORM/Query/CacheHandler.php
deleted
100644 → 0
View file @
b3d110ba
<?php
/*
* $Id: Cache.php 3938 2008-03-06 19:36:50Z romanb $
*
* 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\Query
;
/**
* Doctrine\ORM\Query\CacheHandler
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @version $Revision: 1393 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
*
* @todo Re-document this class
*/
abstract
class
CacheHandler
{
/**
* Static factory method. Receives a Doctrine_ORM_Query object and generates
* the object after processing queryComponents. Table aliases are retrieved
* directly from Doctrine_ORM_Query_Parser.
*
* @param mixed $result Data to be stored.
* @param Doctrine_ORM_Query_ParserResult $parserResult Parser results that enables to have important data retrieved.
*/
public
static
function
fromResultSet
(
$result
,
$parserResult
)
{
$queryComponents
=
array
();
foreach
(
$parserResult
->
getQueryComponents
()
as
$alias
=>
$components
)
{
if
(
!
isset
(
$components
[
'parent'
]))
{
$queryComponents
[
$alias
][]
=
$components
[
'mapper'
]
->
getComponentName
();
//$queryComponents[$alias][] = $components['mapper']->getComponentName();
}
else
{
$queryComponents
[
$alias
][]
=
$components
[
'parent'
]
.
'.'
.
$components
[
'relation'
]
->
getAlias
();
}
if
(
isset
(
$components
[
'agg'
]))
{
$queryComponents
[
$alias
][]
=
$components
[
'agg'
];
}
if
(
isset
(
$components
[
'map'
]))
{
$queryComponents
[
$alias
][]
=
$components
[
'map'
];
}
}
return
new
QueryResult
(
$result
,
$queryComponents
,
$parserResult
->
getTableAliasMap
(),
$parserResult
->
getEnumParams
()
);
}
/**
* Static factory method. Receives a Doctrine_ORM_Query object and a cached data.
* It handles the cache and generates the object after processing queryComponents.
* Table aliases are retrieved from cache.
*
* @param Doctrine_ORM_Query $query Doctrine_ORM_Query_Object related to this cache item.
* @param mixed $cached Cached data.
*/
public
static
function
fromCachedResult
(
$query
,
$cached
=
false
)
{
$cached
=
unserialize
(
$cached
);
return
new
QueryResult
(
$cached
[
0
],
self
::
_getQueryComponents
(
$cached
[
1
]),
$cached
[
2
],
$cached
[
3
]
);
}
/**
* Static factory method. Receives a Doctrine_ORM_Query object and a cached data.
* It handles the cache and generates the object after processing queryComponents.
* Table aliases are retrieved from cache.
*
* @param Doctrine_ORM_Query $query Doctrine_ORM_Query_Object related to this cache item.
* @param mixed $cached Cached data.
*/
public
static
function
fromCachedQuery
(
$query
,
$cached
=
false
)
{
$cached
=
unserialize
(
$cached
);
return
new
ParserResult
(
$cached
[
0
],
self
::
_getQueryComponents
(
$cached
[
1
]),
$cached
[
2
],
$cached
[
3
]
);
}
/**
* @nodoc
*/
protected
static
function
_getQueryComponents
(
$query
,
$cachedQueryComponents
)
{
$queryComponents
=
array
();
foreach
(
$cachedQueryComponents
as
$alias
=>
$components
)
{
$e
=
explode
(
'.'
,
$components
[
0
]);
if
(
count
(
$e
)
===
1
)
{
$queryComponents
[
$alias
][
'mapper'
]
=
$query
->
getConnection
()
->
getMapper
(
$e
[
0
]);
$queryComponents
[
$alias
][
'table'
]
=
$queryComponents
[
$alias
][
'mapper'
]
->
getTable
();
}
else
{
$queryComponents
[
$alias
][
'parent'
]
=
$e
[
0
];
$queryComponents
[
$alias
][
'relation'
]
=
$queryComponents
[
$e
[
0
]][
'table'
]
->
getAssociation
(
$e
[
1
]);
$queryComponents
[
$alias
][
'mapper'
]
=
$query
->
getConnection
()
->
getMapper
(
$queryComponents
[
$alias
][
'relation'
]
->
getTargetEntityName
());
$queryComponents
[
$alias
][
'table'
]
=
$queryComponents
[
$alias
][
'mapper'
]
->
getTable
();
}
if
(
isset
(
$v
[
1
]))
{
$queryComponents
[
$alias
][
'agg'
]
=
$components
[
1
];
}
if
(
isset
(
$v
[
2
]))
{
$queryComponents
[
$alias
][
'map'
]
=
$components
[
2
];
}
}
return
$queryComponents
;
}
}
\ No newline at end of file
lib/Doctrine/ORM/Query/Exec/AbstractExecutor.php
deleted
100644 → 0
View file @
b3d110ba
<?php
/*
* $Id$
*
* 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.phpdoctrine.org>.
*/
namespace
Doctrine\ORM\Query\Exec
;
/**
* Base class for SQL statement executors.
*
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link http://www.phpdoctrine.org
* @since 2.0
* @version $Revision$
*/
abstract
class
AbstractExecutor
implements
\Serializable
{
protected
$_sqlStatements
;
public
function
__construct
(
\Doctrine\ORM\Query\AST\Node
$AST
,
$sqlWalker
)
{
}
/**
* Gets the SQL statements that are executed by the executor.
*
* @return array All the SQL update statements.
*/
public
function
getSqlStatements
()
{
return
$this
->
_sqlStatements
;
}
/**
* Executes all sql statements.
*
* @param Doctrine_Connection $conn The database connection that is used to execute the queries.
* @param array $params The parameters.
*/
abstract
public
function
execute
(
\Doctrine\DBAL\Connection
$conn
,
array
$params
);
/**
* Factory method.
* Creates an appropriate sql executor for the given AST.
*
* @param Doctrine_ORM_Query_AST $AST The root node of the AST.
* @return Doctrine_ORM_Query_SqlExecutor_Abstract The executor that is suitable for the given AST.
*/
public
static
function
create
(
\Doctrine\ORM\Query\AST\Node
$AST
,
$sqlWalker
)
{
$isDeleteStatement
=
$AST
instanceof
\Doctrine\ORM\Query\AST\DeleteStatement
;
$isUpdateStatement
=
$AST
instanceof
\Doctrine\ORM\Query\AST\UpdateStatement
;
if
(
$isDeleteStatement
)
{
$primaryClass
=
$sqlWalker
->
getEntityManager
()
->
getClassMetadata
(
$AST
->
getDeleteClause
()
->
getAbstractSchemaName
()
);
if
(
$primaryClass
->
isInheritanceTypeJoined
())
{
return
new
MultiTableDeleteExecutor
(
$AST
,
$sqlWalker
);
}
else
{
return
new
SingleTableDeleteUpdateExecutor
(
$AST
,
$sqlWalker
);
}
}
else
if
(
$isUpdateStatement
)
{
$primaryClass
=
$sqlWalker
->
getEntityManager
()
->
getClassMetadata
(
$AST
->
getUpdateClause
()
->
getAbstractSchemaName
()
);
if
(
$primaryClass
->
isInheritanceTypeJoined
())
{
return
new
MultiTableUpdateExecutor
(
$AST
,
$sqlWalker
);
}
else
{
return
new
SingleTableDeleteUpdateExecutor
(
$AST
,
$sqlWalker
);
}
}
else
{
return
new
SingleSelectExecutor
(
$AST
,
$sqlWalker
);
}
}
/**
* Serializes the sql statements of the executor.
*
* @return string
*/
public
function
serialize
()
{
return
serialize
(
$this
->
_sqlStatements
);
}
/**
* Reconstructs the executor with it's sql statements.
*/
public
function
unserialize
(
$serialized
)
{
$this
->
_sqlStatements
=
unserialize
(
$serialized
);
}
}
\ No newline at end of file
lib/Doctrine/ORM/Query/
QueryResult
.php
→
lib/Doctrine/ORM/Query/
Exec/AbstractSqlExecutor
.php
View file @
49434b03
...
...
@@ -19,29 +19,36 @@
* <http://www.doctrine-project.org>.
*/
namespace
Doctrine\ORM\Query
;
namespace
Doctrine\ORM\Query
\Exec
;
/**
*
Doctrine_ORM_Query_QueryResult
*
Base class for SQL statement executors.
*
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Janne Vanhala <jpvanhal@cc.hut.fi>
* @author Roman Borschel <roman@code-factory.org>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link http://www.doctrine-project.org
* @since 2.0
* @version $Revision$
*/
class
QueryResult
extends
AbstractResult
abstract
class
AbstractSqlExecutor
{
protected
$_data
;
protected
$_sqlStatements
;
/**
*
Returns cached resultset
.
*
Gets the SQL statements that are executed by the executor
.
*
* @return array
Resultset
.
* @return array
All the SQL update statements
.
*/
public
function
get
ResultSet
()
public
function
get
SqlStatements
()
{
return
$this
->
_
data
;
return
$this
->
_
sqlStatements
;
}
/**
* Executes all sql statements.
*
* @param Doctrine_Connection $conn The database connection that is used to execute the queries.
* @param array $params The parameters.
*/
abstract
public
function
execute
(
\Doctrine\DBAL\Connection
$conn
,
array
$params
);
}
\ No newline at end of file
lib/Doctrine/ORM/Query/Exec/MultiTableDeleteExecutor.php
View file @
49434b03
...
...
@@ -33,7 +33,7 @@ use Doctrine\ORM\Query\AST;
* @since 2.0
* @version $Revision$
*/
class
MultiTableDeleteExecutor
extends
AbstractExecutor
class
MultiTableDeleteExecutor
extends
Abstract
Sql
Executor
{
private
$_createTempTableSql
;
private
$_dropTempTableSql
;
...
...
lib/Doctrine/ORM/Query/Exec/MultiTableUpdateExecutor.php
View file @
49434b03
...
...
@@ -33,7 +33,7 @@ use Doctrine\ORM\Query\AST;
* @since 2.0
* @version $Revision$
*/
class
MultiTableUpdateExecutor
extends
AbstractExecutor
class
MultiTableUpdateExecutor
extends
Abstract
Sql
Executor
{
private
$_createTempTableSql
;
private
$_dropTempTableSql
;
...
...
lib/Doctrine/ORM/Query/Exec/SingleSelectExecutor.php
View file @
49434b03
...
...
@@ -30,11 +30,10 @@ namespace Doctrine\ORM\Query\Exec;
* @link www.doctrine-project.org
* @since 2.0
*/
class
SingleSelectExecutor
extends
AbstractExecutor
class
SingleSelectExecutor
extends
Abstract
Sql
Executor
{
public
function
__construct
(
\Doctrine\ORM\Query\AST\SelectStatement
$AST
,
$sqlWalker
)
{
parent
::
__construct
(
$AST
,
$sqlWalker
);
$this
->
_sqlStatements
=
$sqlWalker
->
walkSelectStatement
(
$AST
);
}
...
...
lib/Doctrine/ORM/Query/Exec/SingleTableDeleteUpdateExecutor.php
View file @
49434b03
...
...
@@ -34,11 +34,10 @@ use Doctrine\ORM\Query\AST;
* @since 2.0
* @todo This is exactly the same as SingleSelectExecutor. Unify in SingleStatementExecutor.
*/
class
SingleTableDeleteUpdateExecutor
extends
AbstractExecutor
class
SingleTableDeleteUpdateExecutor
extends
Abstract
Sql
Executor
{
public
function
__construct
(
AST\Node
$AST
,
$sqlWalker
)
{
parent
::
__construct
(
$AST
,
$sqlWalker
);
if
(
$AST
instanceof
AST\UpdateStatement
)
{
$this
->
_sqlStatements
=
$sqlWalker
->
walkUpdateStatement
(
$AST
);
}
else
if
(
$AST
instanceof
AST\DeleteStatement
)
{
...
...
lib/Doctrine/ORM/Query/Parser.php
View file @
49434b03
...
...
@@ -189,7 +189,7 @@ class Parser
);
// Assign an SQL executor to the parser result
$this
->
_parserResult
->
setSqlExecutor
(
Exec\AbstractExecutor
::
create
(
$AST
,
$sqlWalker
));
$this
->
_parserResult
->
setSqlExecutor
(
$sqlWalker
->
getExecutor
(
$AST
));
return
$this
->
_parserResult
;
}
...
...
lib/Doctrine/ORM/Query/ParserResult.php
View file @
49434b03
...
...
@@ -77,7 +77,7 @@ class ParserResult
*
* @param AbstractExecutor $executor
*/
public
function
setSqlExecutor
(
\Doctrine\ORM\Query\Exec\AbstractExecutor
$executor
)
public
function
setSqlExecutor
(
$executor
)
{
$this
->
_sqlExecutor
=
$executor
;
}
...
...
lib/Doctrine/ORM/Query/SqlWalker.php
View file @
49434b03
This diff is collapsed.
Click to expand it.
lib/Doctrine/ORM/Query/TreeWalker.php
View file @
49434b03
<?php
/*
* $Id$
*
* 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\Query
;
...
...
@@ -333,4 +352,11 @@ interface TreeWalker
* @return string The SQL.
*/
function
walkPathExpression
(
$pathExpr
);
/**
* Gets an executor that can be used to execute the result of this walker.
*
* @return AbstractExecutor
*/
function
getExecutor
(
$AST
);
}
\ No newline at end of file
lib/Doctrine/ORM/Query/TreeWalkerAdapter.php
View file @
49434b03
<?php
/*
* $Id$
*
* 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\Query
;
...
...
lib/Doctrine/ORM/UnitOfWork.php
View file @
49434b03
...
...
@@ -1476,8 +1476,7 @@ class UnitOfWork implements PropertyChangedListener
if
(
isset
(
$this
->
_identityMap
[
$class
->
rootEntityName
][
$idHash
]))
{
$entity
=
$this
->
_identityMap
[
$class
->
rootEntityName
][
$idHash
];
$oid
=
spl_object_hash
(
$entity
);
$overrideLocalChanges
=
false
;
//$overrideLocalChanges = isset($hints['doctrine.refresh']) && $hints['doctrine.refresh'] === true;
$overrideLocalChanges
=
isset
(
$hints
[
Query
::
HINT_REFRESH
]);
}
else
{
$entity
=
new
$className
;
$oid
=
spl_object_hash
(
$entity
);
...
...
tests/Doctrine/Tests/Mocks/MockTreeWalker.php
View file @
49434b03
...
...
@@ -4,6 +4,14 @@ namespace Doctrine\Tests\Mocks;
class
MockTreeWalker
extends
\Doctrine\ORM\Query\TreeWalkerAdapter
{
/**
* Gets an executor that can be used to execute the result of this walker.
*
* @return AbstractExecutor
*/
public
function
getExecutor
(
$AST
)
{
return
null
;
}
}
tests/Doctrine/Tests/ORM/Functional/OneToOneBidirectionalAssociationTest.php
View file @
49434b03
...
...
@@ -89,6 +89,7 @@ class OneToOneBidirectionalAssociationTest extends \Doctrine\Tests\OrmFunctional
$result
=
$query
->
getResultList
();
$customer
=
$result
[
0
];
$this
->
assertNull
(
$customer
->
getMentor
());
$this
->
assertTrue
(
$customer
->
getCart
()
instanceof
ECommerceCart
);
$this
->
assertEquals
(
'paypal'
,
$customer
->
getCart
()
->
getPayment
());
}
...
...
tests/Doctrine/Tests/ORM/Performance/HydrationPerformanceTest.php
View file @
49434b03
...
...
@@ -276,5 +276,63 @@ class HydrationPerformanceTest extends \Doctrine\Tests\OrmPerformanceTestCase
$e
=
microtime
(
true
);
echo
__FUNCTION__
.
" - "
.
(
$e
-
$s
)
.
" seconds"
.
PHP_EOL
;
}
/**
* Times for comparison:
*
* [romanb: 10000 rows => 0.7 seconds]
*
* MAXIMUM TIME: 1 second
*/
public
function
testSimpleQueryScalarHydrationPerformance
()
{
$rsm
=
new
ResultSetMapping
;
$rsm
->
addEntityResult
(
'Doctrine\Tests\Models\CMS\CmsUser'
,
'u'
);
$rsm
->
addFieldResult
(
'u'
,
'u__id'
,
'id'
);
$rsm
->
addFieldResult
(
'u'
,
'u__status'
,
'status'
);
$rsm
->
addFieldResult
(
'u'
,
'u__username'
,
'username'
);
$rsm
->
addFieldResult
(
'u'
,
'u__name'
,
'name'
);
// Faked result set
$resultSet
=
array
(
//row1
array
(
'u__id'
=>
'1'
,
'u__status'
=>
'developer'
,
'u__username'
=>
'romanb'
,
'u__name'
=>
'Roman'
,
),
array
(
'u__id'
=>
'1'
,
'u__status'
=>
'developer'
,
'u__username'
=>
'romanb'
,
'u__name'
=>
'Roman'
,
),
array
(
'u__id'
=>
'2'
,
'u__status'
=>
'developer'
,
'u__username'
=>
'romanb'
,
'u__name'
=>
'Roman'
,
)
);
for
(
$i
=
4
;
$i
<
10000
;
++
$i
)
{
$resultSet
[]
=
array
(
'u__id'
=>
$i
,
'u__status'
=>
'developer'
,
'u__username'
=>
'jwage'
,
'u__name'
=>
'Jonathan'
,
);
}
$stmt
=
new
HydratorMockStatement
(
$resultSet
);
$hydrator
=
new
\Doctrine\ORM\Internal\Hydration\ScalarHydrator
(
$this
->
_em
);
$this
->
setMaxRunningTime
(
1
);
$s
=
microtime
(
true
);
$result
=
$hydrator
->
hydrateAll
(
$stmt
,
$rsm
);
$e
=
microtime
(
true
);
echo
__FUNCTION__
.
" - "
.
(
$e
-
$s
)
.
" seconds"
.
PHP_EOL
;
}
}
tests/Doctrine/Tests/ORM/Query/LanguageRecognitionTest.php
View file @
49434b03
...
...
@@ -47,7 +47,8 @@ class LanguageRecognitionTest extends \Doctrine\Tests\OrmTestCase
}
$parser
=
new
\Doctrine\ORM\Query\Parser
(
$query
);
//$parser->setSqlTreeWalker(new \Doctrine\Tests\Mocks\MockTreeWalker);
// We do NOT test SQL construction here. That only unnecessarily slows down the tests!
$parser
->
setSqlTreeWalker
(
new
\Doctrine\Tests\Mocks\MockTreeWalker
);
return
$parser
->
parse
();
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment