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
4f5b332d
Commit
4f5b332d
authored
May 19, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] Adding insert performance tests.
parent
c07416ac
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
214 additions
and
70 deletions
+214
-70
Connection.php
lib/Doctrine/DBAL/Connection.php
+3
-3
EntityManager.php
lib/Doctrine/ORM/EntityManager.php
+1
-1
ClassMetadata.php
lib/Doctrine/ORM/Mapping/ClassMetadata.php
+49
-2
ClassMetadataFactory.php
lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
+4
-2
StandardEntityPersister.php
lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
+28
-11
UnitOfWork.php
lib/Doctrine/ORM/UnitOfWork.php
+46
-39
EntityPersisterMock.php
tests/Doctrine/Tests/Mocks/EntityPersisterMock.php
+22
-2
AllTests.php
tests/Doctrine/Tests/ORM/AllTests.php
+1
-1
AllTests.php
tests/Doctrine/Tests/ORM/Performance/AllTests.php
+1
-0
InsertPerformanceTest.php
.../Doctrine/Tests/ORM/Performance/InsertPerformanceTest.php
+55
-0
UnitOfWorkTest.php
tests/Doctrine/Tests/ORM/UnitOfWorkTest.php
+3
-0
OrmPerformanceTestCase.php
tests/Doctrine/Tests/OrmPerformanceTestCase.php
+1
-9
No files found.
lib/Doctrine/DBAL/Connection.php
View file @
4f5b332d
...
...
@@ -515,7 +515,7 @@ class Connection
{
$this
->
connect
();
try
{
echo
"DBAL:"
.
$query
.
PHP_EOL
;
//
echo "DBAL:" . $query . PHP_EOL;
if
(
!
empty
(
$params
))
{
$stmt
=
$this
->
prepare
(
$query
);
$stmt
->
execute
(
$params
);
...
...
@@ -542,9 +542,9 @@ class Connection
public
function
exec
(
$query
,
array
$params
=
array
())
{
$this
->
connect
();
try
{
echo
$query
.
PHP_EOL
;
//
echo $query . PHP_EOL;
if
(
!
empty
(
$params
))
{
var_dump
(
$params
);
//
var_dump($params);
$stmt
=
$this
->
prepare
(
$query
);
$stmt
->
execute
(
$params
);
return
$stmt
->
rowCount
();
...
...
lib/Doctrine/ORM/EntityManager.php
View file @
4f5b332d
...
...
@@ -346,7 +346,7 @@ class EntityManager
public
function
clear
(
$entityName
=
null
)
{
if
(
$entityName
===
null
)
{
$this
->
_unitOfWork
->
detachAll
();
$this
->
_unitOfWork
->
clear
();
}
else
{
//TODO
throw
DoctrineException
::
notImplemented
();
...
...
lib/Doctrine/ORM/Mapping/ClassMetadata.php
View file @
4f5b332d
...
...
@@ -360,8 +360,6 @@ final class ClassMetadata
*/
public
$reflFields
;
//private $_insertSql;
/**
* The ID generator used for generating IDs for this class.
*
...
...
@@ -392,6 +390,13 @@ final class ClassMetadata
*/
public
$changeTrackingPolicy
=
self
::
CHANGETRACKING_DEFERRED_IMPLICIT
;
/**
* The SQL INSERT string for entities of this class.
*
* @var string
*/
public
$insertSql
;
/**
* Initializes a new ClassMetadata instance that will hold the object-relational mapping
* metadata of the class with the given name.
...
...
@@ -1373,6 +1378,8 @@ final class ClassMetadata
public
function
addFieldMapping
(
array
$fieldMapping
)
{
$this
->
fieldMappings
[
$fieldMapping
[
'fieldName'
]]
=
$fieldMapping
;
$this
->
columnNames
[
$fieldMapping
[
'fieldName'
]]
=
$fieldMapping
[
'columnName'
];
$this
->
fieldNames
[
$fieldMapping
[
'columnName'
]]
=
$fieldMapping
[
'fieldName'
];
}
/**
...
...
@@ -1754,6 +1761,46 @@ final class ClassMetadata
$this
->
sequenceGeneratorDefinition
=
$definition
;
}
/**
* INTERNAL: Called by ClassMetadataFactory.
*
* Tells this class descriptor to finish the mapping definition, making any
* final adjustments, i.e. generating some SQL strings.
*/
public
function
finishMapping
()
{
$columns
=
$values
=
array
();
if
(
$this
->
inheritanceType
==
self
::
INHERITANCE_TYPE_JOINED
)
{
//TODO
}
else
{
foreach
(
$this
->
reflFields
as
$name
=>
$field
)
{
if
(
isset
(
$this
->
associationMappings
[
$name
]))
{
$assoc
=
$this
->
associationMappings
[
$name
];
if
(
$assoc
->
isOwningSide
&&
$assoc
->
isOneToOne
())
{
foreach
(
$assoc
->
targetToSourceKeyColumns
as
$sourceCol
)
{
$columns
[]
=
$sourceCol
;
$values
[]
=
'?'
;
}
}
}
else
if
(
$this
->
generatorType
!=
self
::
GENERATOR_TYPE_IDENTITY
||
$this
->
identifier
[
0
]
!=
$name
)
{
$columns
[]
=
$this
->
columnNames
[
$name
];
$values
[]
=
'?'
;
}
}
}
if
(
$this
->
discriminatorColumn
)
{
$columns
[]
=
$this
->
discriminatorColumn
[
'name'
];
$values
[]
=
'?'
;
}
$this
->
insertSql
=
'INSERT INTO '
.
$this
->
primaryTable
[
'name'
]
.
' ('
.
implode
(
', '
,
$columns
)
.
') '
.
'VALUES ('
.
implode
(
', '
,
$values
)
.
')'
;
}
/**
* Creates a string representation of this instance.
*
...
...
lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
View file @
4f5b332d
...
...
@@ -136,7 +136,6 @@ class ClassMetadataFactory
$class
=
$this
->
_newClassMetadataInstance
(
$className
);
if
(
$parent
)
{
$class
->
setInheritanceType
(
$parent
->
inheritanceType
);
//$class->setDiscriminatorMap($parent->getDiscriminatorMap());
$class
->
setDiscriminatorColumn
(
$parent
->
discriminatorColumn
);
$class
->
setIdGeneratorType
(
$parent
->
generatorType
);
$this
->
_addInheritedFields
(
$class
,
$parent
);
...
...
@@ -166,10 +165,13 @@ class ClassMetadataFactory
if
(
$parent
&&
$parent
->
isInheritanceTypeSingleTable
())
{
$class
->
setTableName
(
$parent
->
getTableName
());
}
$class
->
setParentClasses
(
$visited
);
$class
->
finishMapping
();
$this
->
_loadedMetadata
[
$className
]
=
$class
;
$parent
=
$class
;
$class
->
setParentClasses
(
$visited
);
array_unshift
(
$visited
,
$className
);
}
}
...
...
lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
View file @
4f5b332d
...
...
@@ -96,7 +96,11 @@ class StandardEntityPersister
{
$insertData
=
array
();
$this
->
_prepareData
(
$entity
,
$insertData
,
true
);
$this
->
_conn
->
insert
(
$this
->
_class
->
getTableName
(),
$insertData
);
$stmt
=
$this
->
_conn
->
prepare
(
$this
->
_class
->
insertSql
);
$stmt
->
execute
(
array_values
(
$insertData
));
$stmt
->
closeCursor
();
$idGen
=
$this
->
_class
->
getIdGenerator
();
if
(
$idGen
->
isPostInsertGenerator
())
{
return
$idGen
->
generate
(
$this
->
_em
,
$entity
);
...
...
@@ -111,9 +115,7 @@ class StandardEntityPersister
*/
public
function
addInsert
(
$entity
)
{
$insertData
=
array
();
$this
->
_prepareData
(
$entity
,
$insertData
,
true
);
$this
->
_queuedInserts
[]
=
$insertData
;
$this
->
_queuedInserts
[]
=
$entity
;
}
/**
...
...
@@ -121,12 +123,27 @@ class StandardEntityPersister
*/
public
function
executeInserts
()
{
//$tableName = $this->_class->getTableName();
$stmt
=
$this
->
_conn
->
prepare
(
$this
->
_class
->
getInsertSql
());
foreach
(
$this
->
_queuedInserts
as
$insertData
)
{
if
(
!
$this
->
_queuedInserts
)
{
return
;
}
$postInsertIds
=
array
();
$idGen
=
$this
->
_class
->
getIdGenerator
();
$isPostInsertId
=
$idGen
->
isPostInsertGenerator
();
$stmt
=
$this
->
_conn
->
prepare
(
$this
->
_class
->
insertSql
);
foreach
(
$this
->
_queuedInserts
as
$entity
)
{
$insertData
=
array
();
$this
->
_prepareData
(
$entity
,
$insertData
,
true
);
$stmt
->
execute
(
array_values
(
$insertData
));
if
(
$isPostInsertId
)
{
$postInsertIds
[
$idGen
->
generate
(
$this
->
_em
,
$entity
)]
=
$entity
;
}
}
$stmt
->
closeCursor
();
$this
->
_queuedInserts
=
array
();
return
$postInsertIds
;
}
/**
...
...
@@ -226,13 +243,13 @@ class StandardEntityPersister
$columnName
=
$this
->
_class
->
getColumnName
(
$field
);
if
(
$this
->
_class
->
hasAssociation
(
$field
))
{
$assocMapping
=
$this
->
_class
->
getAssociationMapping
(
$field
)
;
if
(
isset
(
$this
->
_class
->
associationMappings
[
$field
]
))
{
$assocMapping
=
$this
->
_class
->
associationMappings
[
$field
]
;
if
(
!
$assocMapping
->
isOneToOne
()
||
$assocMapping
->
isInverseSide
())
{
continue
;
}
foreach
(
$assocMapping
->
getSourceToTargetKeyColumns
()
as
$sourceColumn
=>
$targetColumn
)
{
$otherClass
=
$this
->
_em
->
getClassMetadata
(
$assocMapping
->
getTargetEntityName
()
);
foreach
(
$assocMapping
->
sourceToTargetKeyColumns
as
$sourceColumn
=>
$targetColumn
)
{
$otherClass
=
$this
->
_em
->
getClassMetadata
(
$assocMapping
->
targetEntityName
);
if
(
$newVal
===
null
)
{
$result
[
$sourceColumn
]
=
null
;
}
else
{
...
...
lib/Doctrine/ORM/UnitOfWork.php
View file @
4f5b332d
...
...
@@ -235,30 +235,38 @@ class UnitOfWork implements PropertyChangedListener
// Now we need a commit order to maintain referential integrity
$commitOrder
=
$this
->
_getCommitOrder
();
//TODO: begin transaction here?
$conn
=
$this
->
_em
->
getConnection
();
try
{
$conn
->
beginTransaction
();
foreach
(
$commitOrder
as
$class
)
{
$this
->
_executeInserts
(
$class
);
}
foreach
(
$commitOrder
as
$class
)
{
$this
->
_executeUpdates
(
$class
);
}
// Collection deletions (deletions of complete collections)
foreach
(
$this
->
_collectionDeletions
as
$collectionToDelete
)
{
$this
->
getCollectionPersister
(
$collectionToDelete
->
getMapping
())
->
delete
(
$collectionToDelete
);
}
// Collection updates (deleteRows, updateRows, insertRows)
foreach
(
$this
->
_collectionUpdates
as
$collectionToUpdate
)
{
$this
->
getCollectionPersister
(
$collectionToUpdate
->
getMapping
())
->
update
(
$collectionToUpdate
);
}
//TODO: collection recreations (insertions of complete collections)
foreach
(
$commitOrder
as
$class
)
{
$this
->
_executeInserts
(
$class
);
}
foreach
(
$commitOrder
as
$class
)
{
$this
->
_executeUpdates
(
$class
);
}
// Entity deletions come last and need to be in reverse commit order
for
(
$count
=
count
(
$commitOrder
),
$i
=
$count
-
1
;
$i
>=
0
;
--
$i
)
{
$this
->
_executeDeletions
(
$commitOrder
[
$i
]);
// Collection deletions (deletions of complete collections)
foreach
(
$this
->
_collectionDeletions
as
$collectionToDelete
)
{
$this
->
getCollectionPersister
(
$collectionToDelete
->
getMapping
())
->
delete
(
$collectionToDelete
);
}
// Collection updates (deleteRows, updateRows, insertRows)
foreach
(
$this
->
_collectionUpdates
as
$collectionToUpdate
)
{
$this
->
getCollectionPersister
(
$collectionToUpdate
->
getMapping
())
->
update
(
$collectionToUpdate
);
}
//TODO: collection recreations (insertions of complete collections)
// Entity deletions come last and need to be in reverse commit order
for
(
$count
=
count
(
$commitOrder
),
$i
=
$count
-
1
;
$i
>=
0
;
--
$i
)
{
$this
->
_executeDeletions
(
$commitOrder
[
$i
]);
}
$conn
->
commit
();
}
catch
(
\Exception
$e
)
{
$conn
->
rollback
();
throw
$e
;
}
//TODO: commit transaction here?
...
...
@@ -401,7 +409,7 @@ class UnitOfWork implements PropertyChangedListener
$assoc
=
$class
->
getAssociationMapping
(
$name
);
//echo PHP_EOL . "INJECTING PCOLL into $name" . PHP_EOL;
// Inject PersistentCollection
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$this
->
_em
->
getClassMetadata
(
$assoc
->
getTargetEntityName
()
),
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$this
->
_em
->
getClassMetadata
(
$assoc
->
targetEntityName
),
$actualData
[
$name
]
?
$actualData
[
$name
]
:
array
());
$coll
->
setOwner
(
$entity
,
$assoc
);
if
(
!
$coll
->
isEmpty
())
{
...
...
@@ -438,7 +446,7 @@ class UnitOfWork implements PropertyChangedListener
if
(
isset
(
$changeSet
[
$propName
]))
{
if
(
$class
->
hasAssociation
(
$propName
))
{
$assoc
=
$class
->
getAssociationMapping
(
$propName
);
if
(
$assoc
->
isOneToOne
()
&&
$assoc
->
isOwningSide
()
)
{
if
(
$assoc
->
isOneToOne
()
&&
$assoc
->
isOwningSide
)
{
$entityIsDirty
=
true
;
}
else
if
(
$orgValue
instanceof
PersistentCollection
)
{
// A PersistentCollection was de-referenced, so delete it.
...
...
@@ -538,25 +546,24 @@ class UnitOfWork implements PropertyChangedListener
*/
private
function
_executeInserts
(
$class
)
{
//TODO: Maybe $persister->addInsert($entity) in the loop and
// $persister->executeInserts() at the end to allow easy prepared
// statement reuse and maybe bulk operations in the persister.
// Same for update/delete.
$className
=
$class
->
name
;
$persister
=
$this
->
getEntityPersister
(
$className
);
foreach
(
$this
->
_entityInsertions
as
$entity
)
{
if
(
get_class
(
$entity
)
==
$className
)
{
$returnVal
=
$persister
->
insert
(
$entity
);
if
(
$returnVal
!==
null
)
{
// Persister returned a post-insert ID
$oid
=
spl_object_hash
(
$entity
);
$idField
=
$class
->
getSingleIdentifierFieldName
();
$class
->
reflFields
[
$idField
]
->
setValue
(
$entity
,
$returnVal
);
$this
->
_entityIdentifiers
[
$oid
]
=
array
(
$returnVal
);
$this
->
_entityStates
[
$oid
]
=
self
::
STATE_MANAGED
;
$this
->
_originalEntityData
[
$oid
][
$idField
]
=
$returnVal
;
$this
->
addToIdentityMap
(
$entity
);
}
$persister
->
addInsert
(
$entity
);
}
}
$postInsertIds
=
$persister
->
executeInserts
();
if
(
$postInsertIds
)
{
foreach
(
$postInsertIds
as
$id
=>
$entity
)
{
// Persister returned a post-insert ID
$oid
=
spl_object_hash
(
$entity
);
$idField
=
$class
->
identifier
[
0
];
$class
->
reflFields
[
$idField
]
->
setValue
(
$entity
,
$id
);
$this
->
_entityIdentifiers
[
$oid
]
=
array
(
$id
);
$this
->
_entityStates
[
$oid
]
=
self
::
STATE_MANAGED
;
$this
->
_originalEntityData
[
$oid
][
$idField
]
=
$id
;
$this
->
addToIdentityMap
(
$entity
);
}
}
}
...
...
tests/Doctrine/Tests/Mocks/EntityPersisterMock.php
View file @
4f5b332d
...
...
@@ -12,6 +12,7 @@ class EntityPersisterMock extends \Doctrine\ORM\Persisters\StandardEntityPersist
private
$_deletes
=
array
();
private
$_identityColumnValueCounter
=
0
;
private
$_mockIdGeneratorType
;
private
$_postInsertIds
=
array
();
/**
* @param <type> $entity
...
...
@@ -22,12 +23,31 @@ class EntityPersisterMock extends \Doctrine\ORM\Persisters\StandardEntityPersist
{
$this
->
_inserts
[]
=
$entity
;
if
(
!
is_null
(
$this
->
_mockIdGeneratorType
)
&&
$this
->
_mockIdGeneratorType
==
\Doctrine\ORM\Mapping\ClassMetadata
::
GENERATOR_TYPE_IDENTITY
||
$this
->
_classMetadata
->
isIdGeneratorIdentity
())
{
return
$this
->
_identityColumnValueCounter
++
;
||
$this
->
_class
->
isIdGeneratorIdentity
())
{
$id
=
$this
->
_identityColumnValueCounter
++
;
$this
->
_postInsertIds
[
$id
]
=
$entity
;
return
$id
;
}
return
null
;
}
public
function
addInsert
(
$entity
)
{
$this
->
_inserts
[]
=
$entity
;
if
(
!
is_null
(
$this
->
_mockIdGeneratorType
)
&&
$this
->
_mockIdGeneratorType
==
\Doctrine\ORM\Mapping\ClassMetadata
::
GENERATOR_TYPE_IDENTITY
||
$this
->
_class
->
isIdGeneratorIdentity
())
{
$id
=
$this
->
_identityColumnValueCounter
++
;
$this
->
_postInsertIds
[
$id
]
=
$entity
;
return
$id
;
}
return
null
;
}
public
function
executeInserts
()
{
return
$this
->
_postInsertIds
;
}
public
function
setMockIdGeneratorType
(
$genType
)
{
$this
->
_mockIdGeneratorType
=
$genType
;
...
...
tests/Doctrine/Tests/ORM/AllTests.php
View file @
4f5b332d
...
...
@@ -30,7 +30,7 @@ class AllTests
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\UnitOfWorkTest'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\EntityManagerTest'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\EntityPersisterTest'
);
//
$suite->addTestSuite('Doctrine\Tests\ORM\EntityPersisterTest');
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\CommitOrderCalculatorTest'
);
$suite
->
addTest
(
Query\AllTests
::
suite
());
...
...
tests/Doctrine/Tests/ORM/Performance/AllTests.php
View file @
4f5b332d
...
...
@@ -21,6 +21,7 @@ class AllTests
$suite
=
new
\Doctrine\Tests\DoctrineTestSuite
(
'Doctrine Orm Performance'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\Performance\HydrationPerformanceTest'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\Performance\InsertPerformanceTest'
);
return
$suite
;
}
...
...
tests/Doctrine/Tests/ORM/Performance/InsertPerformanceTest.php
0 → 100644
View file @
4f5b332d
<?php
namespace
Doctrine\Tests\ORM\Performance
;
require_once
__DIR__
.
'/../../TestInit.php'
;
use
Doctrine\Tests\Models\CMS\CmsUser
;
/**
* Description of InsertPerformanceTest
*
* @author robo
*/
class
InsertPerformanceTest
extends
\Doctrine\Tests\OrmPerformanceTestCase
{
protected
function
setUp
()
{
$this
->
useModelSet
(
'cms'
);
parent
::
setUp
();
}
/**
* [romanb: 10000 objects in ~8 seconds]
*/
public
function
testInsertPerformance
()
{
$s
=
microtime
(
true
);
$conn
=
$this
->
_em
->
getConnection
();
$this
->
setMaxRunningTime
(
10
);
//$mem = memory_get_usage();
//echo "Memory usage before: " . ($mem / 1024) . " KB" . PHP_EOL;
for
(
$i
=
0
;
$i
<
10000
;
++
$i
)
{
$user
=
new
CmsUser
;
$user
->
status
=
'user'
;
$user
->
username
=
'user'
.
$i
;
$user
->
name
=
'Mr.Smith-'
.
$i
;
$this
->
_em
->
save
(
$user
);
if
((
$i
%
20
)
==
0
)
{
$this
->
_em
->
flush
();
$this
->
_em
->
clear
();
}
}
//$memAfter = memory_get_usage();
//echo "Memory usage after: " . ($memAfter / 1024) . " KB" . PHP_EOL;
$e
=
microtime
(
true
);
echo
' Inserted 10000 records in '
.
(
$e
-
$s
)
.
' seconds'
.
PHP_EOL
;
}
}
tests/Doctrine/Tests/ORM/UnitOfWorkTest.php
View file @
4f5b332d
...
...
@@ -125,6 +125,9 @@ class UnitOfWorkTest extends \Doctrine\Tests\OrmTestCase
public
function
testChangeTrackingNotify
()
{
$persister
=
new
EntityPersisterMock
(
$this
->
_emMock
,
$this
->
_emMock
->
getClassMetadata
(
"Doctrine\Tests\ORM\NotifyChangedEntity"
));
$this
->
_unitOfWork
->
setEntityPersister
(
'Doctrine\Tests\ORM\NotifyChangedEntity'
,
$persister
);
$entity
=
new
NotifyChangedEntity
;
$entity
->
setData
(
'thedata'
);
$this
->
_unitOfWork
->
save
(
$entity
);
...
...
tests/Doctrine/Tests/OrmPerformanceTestCase.php
View file @
4f5b332d
...
...
@@ -7,16 +7,8 @@ namespace Doctrine\Tests;
*
* @author robo
*/
class
OrmPerformanceTestCase
extends
OrmTestCase
class
OrmPerformanceTestCase
extends
Orm
Functional
TestCase
{
protected
$_em
;
protected
function
setUp
()
{
parent
::
setUp
();
$this
->
_em
=
$this
->
_getTestEntityManager
();
}
/**
* @var integer
*/
...
...
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