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
96f4d511
Commit
96f4d511
authored
May 05, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] Improved changeset detection.
parent
a6d9236e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
128 additions
and
82 deletions
+128
-82
OraclePlatform.php
lib/Doctrine/DBAL/Platforms/OraclePlatform.php
+10
-0
UnitOfWork.php
lib/Doctrine/ORM/UnitOfWork.php
+118
-82
No files found.
lib/Doctrine/DBAL/Platforms/OraclePlatform.php
View file @
96f4d511
...
...
@@ -351,4 +351,14 @@ class OraclePlatform extends AbstractPlatform
return
parent
::
_getTransactionIsolationLevelSql
(
$level
);
}
}
/**
* Whether the platform prefers sequences for ID generation.
*
* @return boolean
*/
public
function
prefersSequences
()
{
return
true
;
}
}
\ No newline at end of file
lib/Doctrine/ORM/UnitOfWork.php
View file @
96f4d511
...
...
@@ -305,16 +305,23 @@ class UnitOfWork implements PropertyChangedListener
public
function
computeChangeSets
(
array
$entities
=
null
)
{
$entitySet
=
array
();
$newEntities
=
array
();
if
(
$entities
!==
null
)
{
foreach
(
$entities
as
$entity
)
{
$entitySet
[
get_class
(
$entity
)][]
=
$entity
;
}
$newEntities
=
$entities
;
}
else
{
$entitySet
=
$this
->
_identityMap
;
$newEntities
=
$this
->
_entityInsertions
;
}
//TODO: Compute changesets for NEW entities first here
// Compute changes for NEW entities first. This must always happen.
foreach
(
$newEntities
as
$entity
)
{
$this
->
_computeEntityChanges
(
$this
->
_em
->
getClassMetadata
(
get_class
(
$entity
)),
$entity
);
}
// Compute changes for MANAGED entities. Change tracking policies take effect here.
foreach
(
$entitySet
as
$className
=>
$entities
)
{
$class
=
$this
->
_em
->
getClassMetadata
(
$className
);
...
...
@@ -328,97 +335,126 @@ class UnitOfWork implements PropertyChangedListener
$this
->
_scheduledForDirtyCheck
[
$className
]
:
$entities
;
foreach
(
$entitiesToProcess
as
$entity
)
{
$oid
=
spl_object_hash
(
$entity
);
$state
=
$this
->
getEntityState
(
$entity
);
if
(
!
$class
->
isInheritanceTypeNone
())
{
$class
=
$this
->
_em
->
getClassMetadata
(
get_class
(
$entity
));
}
// Look for changes in the entity itself by comparing against the
// original data we have.
if
(
$state
==
self
::
STATE_MANAGED
||
$state
==
self
::
STATE_NEW
)
{
$actualData
=
array
();
foreach
(
$class
->
getReflectionProperties
()
as
$name
=>
$refProp
)
{
if
(
!
$class
->
isIdentifier
(
$name
)
||
!
$class
->
isIdGeneratorIdentity
())
{
$actualData
[
$name
]
=
$refProp
->
getValue
(
$entity
);
}
if
(
$class
->
isCollectionValuedAssociation
(
$name
)
&&
$actualData
[
$name
]
!==
null
&&
!
(
$actualData
[
$name
]
instanceof
PersistentCollection
))
{
//TODO: If $actualData[$name] is Collection then unwrap the array
$assoc
=
$class
->
getAssociationMapping
(
$name
);
echo
PHP_EOL
.
"INJECTING PCOLL into
$name
"
.
PHP_EOL
;
// Inject PersistentCollection
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$assoc
->
getTargetEntityName
(),
$actualData
[
$name
]
?
$actualData
[
$name
]
:
array
());
$coll
->
setOwner
(
$entity
,
$assoc
);
if
(
!
$coll
->
isEmpty
())
$coll
->
setDirty
(
true
);
$class
->
getReflectionProperty
(
$name
)
->
setValue
(
$entity
,
$coll
);
$actualData
[
$name
]
=
$coll
;
// Only MANAGED entities are processed here.
if
(
$this
->
getEntityState
(
$entity
)
==
self
::
STATE_MANAGED
)
{
$this
->
_computeEntityChanges
(
$class
,
$entity
);
// Look for changes in associations of the entity
foreach
(
$class
->
getAssociationMappings
()
as
$assoc
)
{
$val
=
$class
->
getReflectionProperty
(
$assoc
->
getSourceFieldName
())
->
getValue
(
$entity
);
if
(
$val
!==
null
)
{
$this
->
_computeAssociationChanges
(
$assoc
,
$val
);
}
}
}
}
}
}
if
(
!
isset
(
$this
->
_originalEntityData
[
$oid
]))
{
// Entity is either NEW or MANAGED but not yet fully persisted
// (only has an id). These result in an INSERT.
$this
->
_originalEntityData
[
$oid
]
=
$actualData
;
$this
->
_entityChangeSets
[
$oid
]
=
array_map
(
function
(
$e
)
{
return
array
(
null
,
$e
);
},
$actualData
);
}
else
{
// Entity is "fully" MANAGED: it was already fully persisted before
// and we have a copy of the original data
$originalData
=
$this
->
_originalEntityData
[
$oid
];
$changeSet
=
array
();
$entityIsDirty
=
false
;
foreach
(
$actualData
as
$propName
=>
$actualValue
)
{
$orgValue
=
isset
(
$originalData
[
$propName
])
?
$originalData
[
$propName
]
:
null
;
if
(
is_object
(
$orgValue
)
&&
$orgValue
!==
$actualValue
)
{
$changeSet
[
$propName
]
=
array
(
$orgValue
,
$actualValue
);
}
else
if
(
$orgValue
!=
$actualValue
||
(
$orgValue
===
null
xor
$actualValue
===
null
))
{
$changeSet
[
$propName
]
=
array
(
$orgValue
,
$actualValue
);
}
/**
* Computes the changes done to a single entity.
*
* Modifies/populates the following properties:
*
* {@link _originalEntityData}
* If the entity is NEW or MANAGED but not yet fully persisted (only has an id)
* then it was not fetched from the database and therefore we have no original
* entity data yet. All of the current entity data is stored as the original entity data.
*
* {@link _entityChangeSets}
* The changes detected on all properties of the entity are stored there.
* A change is a tuple array where the first entry is the old value and the second
* entry is the new value of the property. Changesets are used by persisters
* to INSERT/UPDATE the persistent entity state.
*
* {@link _entityUpdates}
* If the entity is already fully MANAGED (has been fetched from the database before)
* and any changes to its properties are detected, then a reference to the entity is stored
* there to mark it for an update.
*
* {@link _collectionDeletions}
* If a PersistentCollection has been de-referenced in a fully MANAGED entity,
* then this collection is marked for deletion.
*
* @param ClassMetadata $class The class descriptor of the entity.
* @param object $entity The entity for which to compute the changes.
*/
private
function
_computeEntityChanges
(
$class
,
$entity
)
{
$oid
=
spl_object_hash
(
$entity
);
if
(
!
$class
->
isInheritanceTypeNone
())
{
$class
=
$this
->
_em
->
getClassMetadata
(
get_class
(
$entity
));
}
$actualData
=
array
();
foreach
(
$class
->
getReflectionProperties
()
as
$name
=>
$refProp
)
{
if
(
!
$class
->
isIdentifier
(
$name
)
||
!
$class
->
isIdGeneratorIdentity
())
{
$actualData
[
$name
]
=
$refProp
->
getValue
(
$entity
);
}
if
(
isset
(
$changeSet
[
$propName
]))
{
if
(
$class
->
hasAssociation
(
$propName
))
{
$assoc
=
$class
->
getAssociationMapping
(
$propName
);
if
(
$assoc
->
isOneToOne
()
&&
$assoc
->
isOwningSide
())
{
$entityIsDirty
=
true
;
}
else
if
(
$orgValue
instanceof
PersistentCollection
)
{
// A PersistentCollection was de-referenced, so delete it.
if
(
!
in_array
(
$orgValue
,
$this
->
_collectionDeletions
,
true
))
{
$this
->
_collectionDeletions
[]
=
$orgValue
;
}
}
}
else
{
$entityIsDirty
=
true
;
}
}
}
if
(
$changeSet
)
{
if
(
$entityIsDirty
)
{
$this
->
_entityUpdates
[
$oid
]
=
$entity
;
}
$this
->
_entityChangeSets
[
$oid
]
=
$changeSet
;
$this
->
_originalEntityData
[
$oid
]
=
$actualData
;
}
}
if
(
$class
->
isCollectionValuedAssociation
(
$name
)
&&
$actualData
[
$name
]
!==
null
&&
!
(
$actualData
[
$name
]
instanceof
PersistentCollection
)
)
{
//TODO: If $actualData[$name] is Collection then unwrap the array
$assoc
=
$class
->
getAssociationMapping
(
$name
);
echo
PHP_EOL
.
"INJECTING PCOLL into
$name
"
.
PHP_EOL
;
// Inject PersistentCollection
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$assoc
->
getTargetEntityName
(),
$actualData
[
$name
]
?
$actualData
[
$name
]
:
array
());
$coll
->
setOwner
(
$entity
,
$assoc
);
if
(
!
$coll
->
isEmpty
())
$coll
->
setDirty
(
true
);
$class
->
getReflectionProperty
(
$name
)
->
setValue
(
$entity
,
$coll
);
$actualData
[
$name
]
=
$coll
;
}
}
// Look for changes in associations of the entity
if
(
$state
==
self
::
STATE_MANAGED
)
{
foreach
(
$class
->
getAssociationMappings
()
as
$assoc
)
{
$val
=
$actualData
[
$assoc
->
getSourceFieldName
()];
if
(
$val
!==
null
)
{
$this
->
_computeAssociationChanges
(
$assoc
,
$val
);
if
(
!
isset
(
$this
->
_originalEntityData
[
$oid
]))
{
// Entity is either NEW or MANAGED but not yet fully persisted
// (only has an id). These result in an INSERT.
$this
->
_originalEntityData
[
$oid
]
=
$actualData
;
$this
->
_entityChangeSets
[
$oid
]
=
array_map
(
function
(
$e
)
{
return
array
(
null
,
$e
);
},
$actualData
);
}
else
{
// Entity is "fully" MANAGED: it was already fully persisted before
// and we have a copy of the original data
$originalData
=
$this
->
_originalEntityData
[
$oid
];
$changeSet
=
array
();
$entityIsDirty
=
false
;
foreach
(
$actualData
as
$propName
=>
$actualValue
)
{
$orgValue
=
isset
(
$originalData
[
$propName
])
?
$originalData
[
$propName
]
:
null
;
if
(
is_object
(
$orgValue
)
&&
$orgValue
!==
$actualValue
)
{
$changeSet
[
$propName
]
=
array
(
$orgValue
,
$actualValue
);
}
else
if
(
$orgValue
!=
$actualValue
||
(
$orgValue
===
null
xor
$actualValue
===
null
))
{
$changeSet
[
$propName
]
=
array
(
$orgValue
,
$actualValue
);
}
if
(
isset
(
$changeSet
[
$propName
]))
{
if
(
$class
->
hasAssociation
(
$propName
))
{
$assoc
=
$class
->
getAssociationMapping
(
$propName
);
if
(
$assoc
->
isOneToOne
()
&&
$assoc
->
isOwningSide
())
{
$entityIsDirty
=
true
;
}
else
if
(
$orgValue
instanceof
PersistentCollection
)
{
// A PersistentCollection was de-referenced, so delete it.
if
(
!
in_array
(
$orgValue
,
$this
->
_collectionDeletions
,
true
))
{
$this
->
_collectionDeletions
[]
=
$orgValue
;
}
}
}
else
{
$entityIsDirty
=
true
;
}
}
}
if
(
$changeSet
)
{
if
(
$entityIsDirty
)
{
$this
->
_entityUpdates
[
$oid
]
=
$entity
;
}
$this
->
_entityChangeSets
[
$oid
]
=
$changeSet
;
$this
->
_originalEntityData
[
$oid
]
=
$actualData
;
}
}
}
...
...
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