Project

General

Profile

Bug #7047

Problem with AdaptiveQuery and ScrollableResults

Added by Igor Skornyakov over 1 year ago. Updated about 1 year ago.

Status:
New
Priority:
Normal
Assignee:
-
Target version:
-
Start date:
Due date:
% Done:

0%

billable:
No
vendor_id:
GCD
case_num:

fill.p Magnifier - test program (498 Bytes) Igor Skornyakov, 01/18/2023 04:05 AM

ttsrc.df - table definition (457 Bytes) Igor Skornyakov, 01/18/2023 04:06 AM

ttsrc.d - table contents (268 Bytes) Igor Skornyakov, 01/18/2023 04:06 AM


Related issues

Related to Database - Feature #7061: Enable the use of lazy result sets in H2 Closed

History

#1 Updated by Igor Skornyakov over 1 year ago

It looks like we have problems either with AdaptiveQuery or ScrollingResults (or both).
Consider the attached program fill.p. It uses permanent table ttsrc (see attached definition and contents). Please note that the table has no index.

The test runs OK with H2 and MariaDB but with PostgreSQL, it fails will the exception:

org.postgresql.util.PSQLException: Operation requires a scrollable ResultSet, but this ResultSet is FORWARD_ONLY.
        at org.postgresql.jdbc.PgResultSet.checkScrollable(PgResultSet.java:280)
        at org.postgresql.jdbc.PgResultSet.first(PgResultSet.java:355)
        at com.mchange.v2.c3p0.impl.NewProxyResultSet.first(NewProxyResultSet.java:815)
        at com.goldencode.p2j.persist.orm.ScrollableResults.execute(ScrollableResults.java:434)
        at com.goldencode.p2j.persist.orm.ScrollableResults.first(ScrollableResults.java:139)
        at com.goldencode.p2j.persist.ScrollingResults.first(ScrollingResults.java:134)
        at com.goldencode.p2j.persist.ResultsAdapter.first(ResultsAdapter.java:131)
        at com.goldencode.p2j.persist.PreselectQuery.first(PreselectQuery.java:2457)
        at com.goldencode.p2j.persist.AdaptiveQuery.first(AdaptiveQuery.java:1228)
        at com.goldencode.p2j.persist.PreselectQuery.first(PreselectQuery.java:2424)
        at com.goldencode.p2j.persist.QueryWrapper.lambda$first$0(QueryWrapper.java:1892)
        at com.goldencode.p2j.persist.QueryWrapper.handleQueryOffEnd(QueryWrapper.java:6884)
        at com.goldencode.p2j.persist.QueryWrapper.first(QueryWrapper.java:1892)

I understand that the reason is the following:
The AdaptiveQuery.executeQuery() instead of creating ProgressiveResults which seems to be most appropriate here, calls PreselectQuery.executeQuery creating ScrollingResults because probablyRequiresResort() returns true.
In addition ScrollingResults.first() calls ResultSet.first() even if it is the first call after executeQuery. This is OK for H2 and MariaDB, but not for PostgreSQL.

If we add an explicit ordering to the query or an index to the ttsrc table the test runs with PostgreSQL as well

#2 Updated by Igor Skornyakov over 1 year ago

Added attachements

#3 Updated by Alexandru Lungu about 1 year ago

  • Related to Feature #7061: Enable the use of lazy result sets in H2 added

#4 Updated by Alexandru Lungu about 1 year ago

  • Start date deleted (01/18/2023)

As a side investigation which may help here:

AdaptiveQuery is not considering recid index as a sorting index. Therefore, probablyRequiresResort returns true for non-indexed queries, just like in #7047-1. This is something that should be fixed separately.
We always add a physical tree index for (multiplex, recid) pair, but our code just searches through the legacy indexes and thus a ScrollingResults is used. ProgressiveResults requires more result-sets, so the example in #7047-1 may be in luck - another query is used to retrieve the first record, so there is no actual ResultSet.first done which could have caused problems.

I can't say why PostgreSQL behaves differently, but logically all non-scrolling 4GL queries should be TYPE_SCROLL_INSENSITIVE. In 4GL non-scrolling doesn't mean one single way of iteration (FORWARD_ONLY), it means that we can't reposition, but we still have the ability to get back to some previous results: using GET PREVIOUS or GET FIRST. My point here is that we should use TYPE_SCROLL_INSENSITIVE for all AdaptiveQuery instances (and maybe PreselectQuery?). Anyways, a performance investigation for TYPE_SCROLL_INSENSITIVE vs FORWARD_ONLY will be done in #7061 anyways.

#5 Updated by Eric Faulhaber about 1 year ago

Alexandru Lungu wrote:

I can't say why PostgreSQL behaves differently, but logically all non-scrolling 4GL queries should be TYPE_SCROLL_INSENSITIVE. In 4GL non-scrolling doesn't mean one single way of iteration (FORWARD_ONLY), it means that we can't reposition, but we still have the ability to get back to some previous results: using GET PREVIOUS or GET FIRST. My point here is that we should use TYPE_SCROLL_INSENSITIVE for all AdaptiveQuery instances (and maybe PreselectQuery?). Anyways, a performance investigation for TYPE_SCROLL_INSENSITIVE vs FORWARD_ONLY will be done in #7061 anyways.

Be very careful about changing the scroll type. I intentionally biased it toward TYPE_FORWARD_ONLY as much as possible, to address OOME problems we were having early on in FWD development, with PostgreSQL on the back end. This may not be logically the best match for 4GL behavior, but not crashing the server JVM is a pretty important consideration ;)

When using PostgreSQL, TYPE_FORWARD_ONLY (along with a non-zero JDBC fetch size) lets us use a server-side database cursor to fetch the results. This is important when fetching large result sets, so we don't pull the entire result set into the JDBC driver's memory and cause OOME. We addressed this problem for PostgreSQL by setting fetch size > 0 (but not to a huge value). Note the comments in the Persistence.list API javadoc about preferring scroll to list in this regard. There probably should be similar warnings in the scroll methods' javadoc about the scroll type.

See also https://jdbc.postgresql.org/documentation/query/.

I don't know what other dialects do, in terms of the default JDBC driver behavior on this point, nor am I aware of the conditions needed for server-side cursors to be used in other databases. This is something we should understand, as the API currently is based on PostgreSQL's behavior in this area.

Also available in: Atom PDF