[#3592] Add Setting to enable Oracle scalar subquery caching for stored function calls
This commit is contained in:
parent
754328b80b
commit
e46450c793
@ -58,6 +58,7 @@ import java.util.Arrays;
|
||||
|
||||
// ...
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.InsertQuery;
|
||||
import org.jooq.Record;
|
||||
@ -67,6 +68,7 @@ import org.jooq.Record3;
|
||||
import org.jooq.Record6;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.Select;
|
||||
import org.jooq.SelectQuery;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.TableRecord;
|
||||
@ -79,6 +81,8 @@ import org.jooq.test.jOOQAbstractTest;
|
||||
import org.jooq.tools.reflect.Reflect;
|
||||
import org.jooq.tools.reflect.ReflectException;
|
||||
|
||||
import org.junit.Assume;
|
||||
|
||||
public class RoutineAndUDTTests<
|
||||
A extends UpdatableRecord<A> & Record6<Integer, String, String, Date, Integer, ?>,
|
||||
AP,
|
||||
@ -270,11 +274,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
}
|
||||
|
||||
public void testStoredFunctions() throws Exception {
|
||||
if (cRoutines() == null) {
|
||||
log.info("SKIPPING", "functions test");
|
||||
return;
|
||||
}
|
||||
|
||||
Assume.assumeNotNull(cRoutines());
|
||||
jOOQAbstractTest.reset = false;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -379,11 +379,22 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
assertEquals(Integer.valueOf(2), result2.getValue(1, 2));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testScalarSubqueryCaching() throws Exception {
|
||||
Assume.assumeNotNull(cRoutines());
|
||||
|
||||
DSLContext create = create(create().settings().withRenderScalarSubqueriesForStoredFunctions(true));
|
||||
|
||||
Field<Number> f = (Field<Number>) FOneField();
|
||||
Select<Record1<Number>> select = create.select(f).where(f.eq(f));
|
||||
|
||||
assertEquals(FOneField().getDataType().convert(1), create.fetchValue(select));
|
||||
assertTrue(create.render(select).contains("select (select"));
|
||||
assertTrue(create.render(select).contains("= (select"));
|
||||
}
|
||||
|
||||
public void testStoredFunctionsWithNoSchema() throws Exception {
|
||||
if (cRoutines() == null) {
|
||||
log.info("SKIPPING", "functions test with no schema");
|
||||
return;
|
||||
}
|
||||
Assume.assumeNotNull(cRoutines());
|
||||
|
||||
/* [pro] xx
|
||||
xx xxx xxxxx xxx xx xxxxx xxxxxxxxxxx xxxxxxxx xxxxxx xxxx xx xxx xxxxx xxxxxx
|
||||
@ -398,8 +409,7 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
.fetchOne(0, Integer.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public void testARRAYType() throws Exception {
|
||||
if (TArrays() == null) {
|
||||
log.info("SKIPPING", "ARRAY type test");
|
||||
|
||||
@ -2542,6 +2542,11 @@ public abstract class jOOQAbstractTest<
|
||||
new RoutineAndUDTTests(this).testStoredFunctions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScalarSubqueryCaching() throws Exception {
|
||||
new RoutineAndUDTTests(this).testScalarSubqueryCaching();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoredFunctionsWithNoSchema() throws Exception {
|
||||
new RoutineAndUDTTests(this).testStoredFunctionsWithNoSchema();
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static org.jooq.Clause.FIELD;
|
||||
import static org.jooq.Clause.FIELD_FUNCTION;
|
||||
// ...
|
||||
@ -51,6 +52,7 @@ import static org.jooq.impl.DSL.using;
|
||||
import static org.jooq.impl.DSL.val;
|
||||
import static org.jooq.impl.Utils.consumeExceptions;
|
||||
import static org.jooq.impl.Utils.consumeWarnings;
|
||||
import static org.jooq.impl.Utils.settings;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
@ -763,7 +765,7 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
|
||||
/**
|
||||
* The {@link Field} representation of this {@link Routine}
|
||||
*/
|
||||
private class RoutineField extends AbstractFunction<T> {
|
||||
private class RoutineField extends AbstractField<T> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
@ -776,8 +778,8 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
|
||||
}
|
||||
|
||||
@Override
|
||||
final Field<T> getFunction0(Configuration c) {
|
||||
RenderContext local = create(c).renderContext();
|
||||
public void accept(Context<?> ctx) {
|
||||
RenderContext local = create(ctx).renderContext();
|
||||
toSQLQualifiedName(local);
|
||||
|
||||
Field<?>[] array = new Field<?>[getInParameters().size()];
|
||||
@ -786,7 +788,7 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
|
||||
for (Parameter<?> p : getInParameters()) {
|
||||
|
||||
// Disambiguate overloaded function signatures
|
||||
if (POSTGRES == c.dialect() && isOverloaded()) {
|
||||
if (POSTGRES == ctx.dialect() && isOverloaded()) {
|
||||
array[i] = getInValues().get(p).cast(p.getType());
|
||||
}
|
||||
else {
|
||||
@ -796,7 +798,14 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
|
||||
i++;
|
||||
}
|
||||
|
||||
return function(local.render(), getDataType(), array);
|
||||
Field<T> result = function(local.render(), getDataType(), array);
|
||||
|
||||
// [#3592] Decrease SQL -> PL/SQL context switches with Oracle Scalar Subquery Caching
|
||||
if (TRUE.equals(settings(ctx.configuration()).isRenderScalarSubqueriesForStoredFunctions())) {
|
||||
result = DSL.select(result).asField();
|
||||
}
|
||||
|
||||
ctx.visit(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,11 @@
|
||||
<!-- Whether rendered SQL should be pretty-printed -->
|
||||
<element name="renderFormatted" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
|
||||
|
||||
<!-- Whether stored function calls should be wrapped in scalar subqueries.
|
||||
Oracle 11g (and potentially, other databases too) implements scalar subquery caching. With this flag
|
||||
set to true, users can automatically profit from this feature in all SQL statements. -->
|
||||
<element name="renderScalarSubqueriesForStoredFunctions" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
|
||||
|
||||
<!-- Whether rendered bind values should be rendered as:
|
||||
|
||||
- question marks
|
||||
|
||||
Loading…
Reference in New Issue
Block a user