Bug #2219
problematic dynamic query test cases
100%
History
#1 Updated by Eric Faulhaber over 10 years ago
Originally reported by Stanislav in #2120:
Yet another minor bug. Testcase:
def temp-table tt field f1 as integer. def var h1 as handle. def var h2 as handle. def var q as handle. h1 = buffer book:handle. h2 = buffer tt:handle. create query q. q:set-buffers(h1, h2). q:query-prepare("for each book, each tt"). q:query-open. q:get-next.
Warning:
[11/14/2013 22:37:35 TMT] (com.goldencode.p2j.persist.Persistence$Context:WARNING) [00000001:00000007:syman-->local/p2j_test/primary] rolling back open transaction during context cleanup
#2 Updated by Eric Faulhaber over 10 years ago
Originally reported by Stanislav in #2120:
Variation of the bug above. Testcase:
def temp-table tt0 field f1 as integer. def temp-table tt field f1 as integer. def var h1 as handle. def var h2 as handle. def var q as handle. h1 = buffer tt0:handle. h2 = buffer tt:handle. create query q. q:set-buffers(h1, h2). q:query-prepare("for each tt0, each tt"). q:query-open. q:get-next.
Stacktrace:
[11/14/2013 23:04:29 TMT] (com.goldencode.p2j.persist.Persistence$Context:WARNING) [00000001:00000006:syman-->local/_temp/primary] rolling back open transaction during context cleanup [11/14/2013 23:04:29 TMT] (com.goldencode.p2j.persist.Persistence$Context:WARNING) [00000001:00000006:syman-->local/_temp/primary] rolling back orphaned transaction [11/14/2013 23:04:29 TMT] (com.goldencode.p2j.persist.Persistence$Context:SEVERE) Error closing Hibernate session during context cleanup com.goldencode.p2j.persist.PersistenceException: [00000001:00000006:syman-->local/_temp/primary] unable to rollback current transaction at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4615) at com.goldencode.p2j.persist.Persistence$Context.closeSession(Persistence.java:5095) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4613) at com.goldencode.p2j.persist.Persistence$Context.cleanup(Persistence.java:5341) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:618) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:616) at com.goldencode.p2j.security.ContextLocal$Wrapper.cleanup(ContextLocal.java:381) at com.goldencode.p2j.security.SecurityContext.cleanup(SecurityContext.java:498) at com.goldencode.p2j.security.SecurityManager.endContext(SecurityManager.java:6772) at com.goldencode.p2j.security.SecurityManager.popContextWorker(SecurityManager.java:6710) at com.goldencode.p2j.security.SecurityManager.popAndRestoreSecurityContext(SecurityManager.java:3933) at com.goldencode.p2j.net.RouterSessionManager.restoreContext(RouterSessionManager.java:1065) at com.goldencode.p2j.net.Conversation.run(Conversation.java:191) at java.lang.Thread.run(Thread.java:722) Caused by: org.hibernate.TransactionException: rollback failed at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:215) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4602) at com.goldencode.p2j.persist.Persistence$Context.closeSession(Persistence.java:5095) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4613) at com.goldencode.p2j.persist.Persistence$Context.cleanup(Persistence.java:5341) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:618) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:616) at com.goldencode.p2j.security.ContextLocal$Wrapper.cleanup(ContextLocal.java:381) at com.goldencode.p2j.security.SecurityContext.cleanup(SecurityContext.java:498) at com.goldencode.p2j.security.SecurityManager.endContext(SecurityManager.java:6772) at com.goldencode.p2j.security.SecurityManager.popContextWorker(SecurityManager.java:6710) at com.goldencode.p2j.security.SecurityManager.popAndRestoreSecurityContext(SecurityManager.java:3933) at com.goldencode.p2j.net.RouterSessionManager.restoreContext(RouterSessionManager.java:1065) at com.goldencode.p2j.net.Conversation.run(Conversation.java:191) at java.lang.Thread.run(Thread.java:722) Caused by: org.hibernate.TransactionException: unable to rollback against JDBC connection at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:167) at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4602) at com.goldencode.p2j.persist.Persistence$Context.closeSession(Persistence.java:5095) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4613) at com.goldencode.p2j.persist.Persistence$Context.cleanup(Persistence.java:5341) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:618) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:616) at com.goldencode.p2j.security.ContextLocal$Wrapper.cleanup(ContextLocal.java:381) at com.goldencode.p2j.security.SecurityContext.cleanup(SecurityContext.java:498) at com.goldencode.p2j.security.SecurityManager.endContext(SecurityManager.java:6772) at com.goldencode.p2j.security.SecurityManager.popContextWorker(SecurityManager.java:6710) at com.goldencode.p2j.security.SecurityManager.popAndRestoreSecurityContext(SecurityManager.java:3933) at com.goldencode.p2j.net.RouterSessionManager.restoreContext(RouterSessionManager.java:1065) at com.goldencode.p2j.net.Conversation.run(Conversation.java:191) at java.lang.Thread.run(Thread.java:722) Caused by: org.h2.jdbc.JdbcSQLException: The object is already closed [90007-169] at org.h2.message.DbException.getJdbcSQLException(DbException.java:329) at org.h2.message.DbException.get(DbException.java:169) at org.h2.message.DbException.get(DbException.java:146) at org.h2.message.DbException.get(DbException.java:135) at org.h2.jdbc.JdbcConnection.checkClosed(JdbcConnection.java:1386) at org.h2.jdbc.JdbcConnection.checkClosedForWrite(JdbcConnection.java:1374) at org.h2.jdbc.JdbcConnection.rollback(JdbcConnection.java:460) at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:163) at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4602) at com.goldencode.p2j.persist.Persistence$Context.closeSession(Persistence.java:5095) at com.goldencode.p2j.persist.Persistence$Context.rollback(Persistence.java:4613) at com.goldencode.p2j.persist.Persistence$Context.cleanup(Persistence.java:5341) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:618) at com.goldencode.p2j.persist.Persistence$1.cleanup(Persistence.java:616) at com.goldencode.p2j.security.ContextLocal$Wrapper.cleanup(ContextLocal.java:381) at com.goldencode.p2j.security.SecurityContext.cleanup(SecurityContext.java:498) at com.goldencode.p2j.security.SecurityManager.endContext(SecurityManager.java:6772) at com.goldencode.p2j.security.SecurityManager.popContextWorker(SecurityManager.java:6710) at com.goldencode.p2j.security.SecurityManager.popAndRestoreSecurityContext(SecurityManager.java:3933) at com.goldencode.p2j.net.RouterSessionManager.restoreContext(RouterSessionManager.java:1065) at com.goldencode.p2j.net.Conversation.run(Conversation.java:191) at java.lang.Thread.run(Thread.java:722)
#3 Updated by Eric Faulhaber about 10 years ago
- Assignee set to Stanislav Lomany
#4 Updated by Stanislav Lomany about 10 years ago
The issue is caused by an unclosed implicit transaction opened by a query. It doesn't cause an error for static queries because these queries are closed when they are deleted as static resources. For dynamic queries the query is closed when the external procedure in which it was opened finishes. IMO the best place to close the query is where static resources are deleted - in ProcedureManager.scopeFinished
.
#5 Updated by Constantin Asofiei about 10 years ago
Stanislav Lomany wrote:
The issue is caused by an unclosed implicit transaction opened by a query. It doesn't cause an error for static queries because these queries are closed when they are deleted as static resources. For dynamic queries the query is closed when the external procedure in which it was opened finishes. IMO the best place to close the query is where static resources are deleted - in
ProcedureManager.scopeFinished
.
The problem here is that a dynamic resource can survive a procedure ran persistent - please test what happens if you expose the query handle to the caller, and the code in note 2 is ran in a persistent procedure.
#6 Updated by Stanislav Lomany about 10 years ago
The problem here is that a dynamic resource can survive a procedure ran persistent - please test what happens if you expose the query handle to the caller, and the code in note 2 is ran in a persistent procedure.
Constantin, what did you mean by "can survive a procedure ran persistent"? Query is closed when the persistent procedure is deleted. Is that what you expected or you think that the query scope can be longer or shorter in some cases?
#7 Updated by Constantin Asofiei about 10 years ago
Stanislav Lomany wrote:
The problem here is that a dynamic resource can survive a procedure ran persistent - please test what happens if you expose the query handle to the caller, and the code in note 2 is ran in a persistent procedure.
Constantin, what did you mean by "can survive a procedure ran persistent"? Query is closed when the persistent procedure is deleted. Is that what you expected or you think that the query scope can be longer or shorter in some cases?
In previous note, you mentioned that you wanted to close the query when the procedure finishes, not when it gets deleted. The idea is that a dynamic resource can survive the persistent procedure which created (the INSTANTIATING-PROCEDURE), and it will survive until its INSTANTIATING-PROCEDURE (the creator) gets deleted.
The QueryWrapper.resourceDelete
code handles the resource deletion (which is called by ProcedureManager, when a persistent procedure gets deleted), but I think that it's missing a query close call (as you mentioned) - please check if QueryWrapper.resourceDelete
can help.
#8 Updated by Stanislav Lomany about 10 years ago
Guys, we have a problem with dynamic queries which are converted to AdaptiveQueries
. Consider testcase:
DEF TEMP-TABLE tt FIELD f1 AS INTEGER. CREATE tt. tt.f1 = 1. CREATE tt. tt.f1 = 2. DEF VAR q AS HANDLE. RUN proc. q:GET-NEXT. MESSAGE STRING(tt.f1). PROCEDURE proc: CREATE QUERY q. q:SET-BUFFERS(BUFFER tt:HANDLE). q:QUERY-PREPARE("FOR EACH tt"). q:QUERY-OPEN. q:GET-NEXT. MESSAGE STRING(tt.f1). END.
Output is "1,1". While equivalent testcase with the static query produces correct output "1,2":
DEF TEMP-TABLE tt FIELD f1 AS INTEGER. CREATE tt. tt.f1 = 1. CREATE tt. tt.f1 = 2. DEFINE QUERY q FOR tt. RUN proc. GET NEXT q. MESSAGE STRING(tt.f1). PROCEDURE proc: OPEN QUERY q FOR EACH tt. GET NEXT q. MESSAGE STRING(tt.f1). END.
Dynamic query has the following Progress-equivalent code:
OPEN QUERY inMemQuery1 FOR EACH tt.
Which is converted to
public class InMemP2jQuery1 { public TempRecord1.Buf tt = null; AdaptiveQuery query0; public void execute() { query0 = new AdaptiveQuery(tt, (String) null, null, "tt.id asc"); } public P2JQuery getQuery() { return query0; } }
While equivalent static conversion uses
QueryWrapper
:final QueryWrapper query0 = new QueryWrapper("inMemQ", false); public void execute() { externalProcedure(new Block() { public void body() { RecordBuffer.openScope(tt); query0.assign(new AdaptiveQuery(tt, (String) null, null, "tt.id asc")); query0.open(); } }); }
The difference between a pure AdaptiveQuery
and an AdaptiveQuery
assigned to a QueryWrapper
is that a QueryWrapper
sets standalone
flag to false
, while standalone queries perform cleanup and resets results when the current scope (not necessary top-level) ends (see PreselectQuery.registerCleaner
).
Do you think that we should convert a dynamic query using QueryWrapper
?
#9 Updated by Stanislav Lomany about 10 years ago
- File svl_upd20140502a.zip added
Update for review for the original issues (except the one noted in the previous note).
#10 Updated by Eric Faulhaber about 10 years ago
Stanislav Lomany wrote:
Do you think that we should convert a dynamic query using
QueryWrapper
?
Yes, assuming CREATE QUERY is semantically the dynamic equivalent of OPEN QUERY, since the semantics of a FOR EACH loop are different than an OPEN QUERY FOR EACH query.
#11 Updated by Constantin Asofiei about 10 years ago
Stanislav Lomany wrote:
The difference between a pure
AdaptiveQuery
and anAdaptiveQuery
assigned to aQueryWrapper
is that aQueryWrapper
setsstandalone
flag tofalse
, while standalone queries perform cleanup and resets results when the current scope (not necessary top-level) ends (seePreselectQuery.registerCleaner
).
Do you think that we should convert a dynamic query usingQueryWrapper
?
I think this might be a runtime problem, not a conversion problem: looking into the QueryWrapper.prepare
and QueryWrapper.assignImpl
, I think prepare
should have called the assignImpl
, and not just save the delegate
: calling assignImpl
should ensure that standalone
is set to false
for the query.
#12 Updated by Eric Faulhaber about 10 years ago
OK, please make the change.
#13 Updated by Stanislav Lomany about 10 years ago
- File svl_upd20140504a.zip added
Constantin, thank you for the idea!
#14 Updated by Eric Faulhaber almost 10 years ago
Code review 20140504a:
Update looks good. Please regression test and commit/distribute if it passes.
Does this fix both variants of the problem in notes 1 & 2?
#15 Updated by Stanislav Lomany almost 10 years ago
Does this fix both variants of the problem in notes 1 & 2?
Yes.
#16 Updated by Stanislav Lomany almost 10 years ago
- Status changed from New to WIP
#17 Updated by Stanislav Lomany almost 10 years ago
- Status changed from WIP to Review
#18 Updated by Eric Faulhaber almost 10 years ago
- % Done changed from 0 to 100
- Status changed from Review to Closed
#19 Updated by Greg Shah over 7 years ago
- Target version changed from Milestone 11 to Cleanup and Stablization for Server Features