You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Markus Fuchs (JIRA)" <ji...@apache.org> on 2007/07/10 23:47:04 UTC

[jira] Updated: (OPENJPA-235) SQL reordering to avoid non-nullable foreign key constraint violations

     [ https://issues.apache.org/jira/browse/OPENJPA-235?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Markus Fuchs updated OPENJPA-235:
---------------------------------

    Attachment: openjpa-235-break-nullable.patch

This patch guarantees that circular dependencies are always broken at nullable foreign keys. Its successfully tested by new tests and running the JPA TCK. The changes are:

ConstraintUpdateManager.java:
=============================
- analyzeForeignKeys, analyzeAgainstInserts:
the direction of edges in the dependency graph has been reversed. 
A node has edges to other nodes it depends on
- flushGraph:
Handles circular constraints
  - if deleted row A has a ciricular fk to deleted row B, 
  then use an update statement to null A's fk to B before flushing, 
  and then flush
  - if inserted row A has a circular fk to updated/inserted row B,
  then null the fk in the B row object, then flush,
  and after flushing, use an update to set the fk back to A
Depending on where circular dependencies are broken, the  
topological order of the graph nodes has to be re-calculated;
The Lists deleteUpdates and insertUpdates are always initialized, 
since they are passed to resolceCycles 
- addDeleteUpdate, addInsertUpdate:
refactored the code nulifying foreign keys into separate methods
- findBreakableLink:
finds a nullable foreign key by walking the dependency cycle.
- recalculateDFA:
Re-calculates the DepthFirstSearch analysis of the graph 
after some of the edges have been removed. Assertions ensure
that the graph is cycle free.
- resolveCycles:
Resolves cycles by identifying a nullable foreign key, and 
then calling either addDeleteUpdate or addInsertUpdate depending 
on the operation causing the dependency

ForeignKey.java:
================
- hasNotNullColumns:
checks for non-nullable local columns
 
kernel/localizer.properties:
============================
- added messages used in ConstraintUpdateManager.

DepthFirstAnalysis.java:
========================
- added localizer for messages
- visit:
a) takes a list of graph edges traversed while walking the graph in DFS; 
list is initially empty; 
always contains the edges walked to reach currently visited node
b) the cycle is calculated for back- and forward edges;
The cycle always exists for back edges part: of path + back edge;
The cycle might exist for forward edges: Reasons for forward edges
i) The graph is disconnected or ii) Threre's a cycle. 
- buildCycle:
Constructs the cycle for back edges: part of DFS path + back edge
- cycleForBackEdge:
calculates the cycle for a back edge
- cycleForForwardEdge:
Once a forward edge is found, the graph is walked to find a path from
the end of the forward edge back to it's beginning node
- findNodeInPath:
Finds the position of the edge starting from a node in a continuous 
list of edges.
- NodeInfoComparator.compare
Since the edge direction is reversed, node are sorted by finished order

Edge.java:
==========
- List cycle holds the cycle for back- and forward edges
- cycle field is re-set in clearTraversal

util/localizer.properties:
==========================
- added messages used in DepthFirstAnalysis.

TestDepthFirstAnalysis.java:
============================
- refactored test data set up
- adjusted testNodeSorting for reversed edge direction
- added new graph resembling the commit dependencies in 
TestNoForeignKeyViolation#testComplexCycle to test cycle detection

EntityB.java, EntityC.java:
===========================
- reintroduced "non optional" property removed in last commit

EntityD.java:
=============
- added two optional relationships to EntityA and EntityB. Both
relationships may cause a circular dependency

EntityE.java:
=============
- added class, has a nullable relationship to EntityB. This
relationship doesn't cause a circular dependency

TestNoForeignKeyViolation.java:
===============================
- refactored test data set up
- testSimpleCycle
Dependency graph has exactly one cycle. 
The nodes on the cycle don't have any edges which are not on the cycle
- testComplexCycle
Like above. One node on the cycle has an edge which is not on the cycle
- testComplexTwoCycles
Dependency graph has two cycles. Otherwise like above.


> SQL reordering to avoid non-nullable foreign key constraint violations
> ----------------------------------------------------------------------
>
>                 Key: OPENJPA-235
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-235
>             Project: OpenJPA
>          Issue Type: Improvement
>          Components: kernel
>            Reporter: Reece Garrett
>            Assignee: Patrick Linskey
>             Fix For: 0.9.8
>
>         Attachments: merge-detached.patch, merge-testcases.patch, openjpa-235-break-nullable.patch, openjpa-235-test.jar, openjpa-235-test1.jar, openjpa-235-test2.zip, sqlreorder.patch, sqlReorder2.patch, sqlReorderTests.patch
>
>
> OpenJPA does not do any SQL statement re-ordering in order to resolve foreign key constraints. Instead, objects are always inserted in the order in which the user persists the instances.  When you persist in an order that would violate foreign key constraints, OpenJPA attempts to insert null and then update the foreign key value in a separate statement. If you use non-nullable constraints, though, you must persist your objects in the correct order.
> This improvement re-orders SQL statements as follows:
> 1. First, all insert statements execute. Inserts which have foreign keys with non-nullable constraints execute AFTER the foreign keys which they depend on have been inserted since no deferred update is possible.
> 2. Next, all update statements execute. No reordering is necessary.
> 3.  Finally, all delete statements execute. Like inserts, deletes execute in an order which does not violate non-nullable foreign key constraints.
> If a circular foreign key reference is found during the re-ordering process then re-ordering halts and the remaining unordered statements are left as is. There is nothing that can be done about the circular reference (other than fixing the schema) and the resulting SQL statements will not succeed.
> The net effect is that users do not need to worry about the persistence order of their objects regardless of non-nullable foreign key constraints. The only class modified was org.apache.openjpa.jdbc.kernel.OperationOrderUpdateManager. I have included a patch which includes my modifications to OperationOrderUpdateManager and test cases. The test cases I have provided fail on the current trunk but pass with my modifications. I have also verified that I did not break anything by using maven to run all test cases with my modifications in place.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.