UpgradeSkipLockedTest, PessimisticReadSkipLockedTest and OracleFollowOnLockingTest fail with Oracle12c

Description

org.hibernate.test.locking.UpgradeSkipLockedTest.testOracleSkipLocked
org.hibernate.test.locking.PessimisticReadSkipLockedTest.testOracleSkipLocked
org.hibernate.test.dialect.functional.OracleFollowOnLockingTest.testPessimisticLockWithMaxResultsThenNoFollowOnLocking

These tests pass with older versions of Oracle databases, but fail with Oracle12. It looks like that Oracle12c doesn't support FOR UPDATE together with FETCH FIRST ....

Oracle11gR2 (with Oracle10gDialect) uses different query

Difference with Oracle12cDialect is LimitHandler

It's probably only test issue, but I'm not sure.

Activity

Jon BakeNovember 21, 2018 at 8:35 PM

Guillaume SmetOctober 22, 2018 at 4:10 PM

it seems very fragile and I don't think it will work, especially once we integrate https://github.com/hibernate/hibernate-orm/pull/2465 .

We will need to pass the additional information to the LimitHandler. Hopefully, it's available somewhere and we can pass it (this needs to be checked).

We would need a default method defaulting to the current one to ensure compatibility.

Could you create a JIRA issue so we can track it?

We will release 5.4.0 in a couple of weeks, it could be a great addition if you think you can work on it.

Jon BakeOctober 19, 2018 at 2:05 PM

@Guillaume Smet Couldn't we do something similar to the `LimitHandler` defined in `Oracle8iDialect`, which calls: `sql.trim().toLowerCase(Locale.ROOT).endsWith( " for update" )`: https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/Oracle8iDialect.java#L77.

Maybe something like this?:
```
class Oracle12cLimitHandler extends AbstractLimitHandler {
private static final LimitHandler LEGACY_LIMIT_HANDLER = new Oracle10gDialect().getLimitHandler();

@Override
public boolean supportsLimit () {
return true;
}

@Override
public String processSql (String sql, RowSelection selection) {
LimitHandler limitHandler;
if (sql.trim().toLowerCase(Locale.ROOT).endsWith( " for update" )) {
limitHandler = LEGACY_LIMIT_HANDLER;
} else {
limitHandler = SQL2008StandardLimitHandler.INSTANCE;
}
return limitHandler.processSql(sql, selection);
}
}
```

Guillaume SmetOctober 19, 2018 at 11:31 AM

sure, we are always interested in contributions.

I think the difficulty will be to pass the necessary information to the LimitHandler so that it can know if the statement is a FOR UPDATE statement.

Happy to discuss it further once you have taken a closer look to the code.

Jon BakeOctober 18, 2018 at 9:43 PM

There are huge performance gains in Oracle 12c by using fetch first and offset (SQL2008StandardLimitHandler syntax) over rownum for limit handling. Would it make more sense to use the SQL2008StandardLimitHandler for everything besides FOR UPDATE statements? I can submit a PR if you are open to the suggestion.

Fixed

Details

Assignee

Reporter

Labels

Components

Fix versions

Affects versions

Priority

Created July 23, 2018 at 12:11 PM
Updated March 21, 2022 at 2:35 PM
Resolved August 1, 2018 at 9:46 AM