From f033d6eadf7c9685695d9f5bd814fc65de2ea6c9 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 29 Jun 2021 10:29:23 +0200 Subject: [PATCH] [jOOQ/jOOQ#8917] INSERT .. RETURNING emulation doesn't work on SQL Server when returning expressions or aliases This includes: - [jOOQ/jOOQ#12071] Add an internal means of ad-hoc table mapping --- .../java/org/jooq/impl/AbstractDMLQuery.java | 38 +++++++++- .../jooq/impl/AbstractQualifiedRecord.java | 26 +++---- .../java/org/jooq/impl/AbstractRoutine.java | 2 +- .../main/java/org/jooq/impl/CatalogImpl.java | 3 +- .../java/org/jooq/impl/DefaultBinding.java | 15 ++-- .../java/org/jooq/impl/DefaultDSLContext.java | 6 +- .../org/jooq/impl/DefaultExecuteContext.java | 34 +++------ .../jooq/impl/QualifiedRecordConstant.java | 3 +- .../main/java/org/jooq/impl/SchemaImpl.java | 12 ++-- .../java/org/jooq/impl/SelectQueryImpl.java | 3 +- .../main/java/org/jooq/impl/SequenceImpl.java | 3 +- .../main/java/org/jooq/impl/TableImpl.java | 6 +- jOOQ/src/main/java/org/jooq/impl/Tools.java | 70 +++++++++++++++---- jOOQ/src/main/java/org/jooq/impl/UDTImpl.java | 4 +- 14 files changed, 141 insertions(+), 84 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java index 5b449c2455..7bc6c4f0a5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractDMLQuery.java @@ -87,14 +87,13 @@ import static org.jooq.impl.Keywords.K_ROWCOUNT; import static org.jooq.impl.Keywords.K_SELECT; import static org.jooq.impl.Keywords.K_SQL; import static org.jooq.impl.Keywords.K_TABLE; -import static org.jooq.impl.ScopeMarker.TOP_LEVEL_CTE; import static org.jooq.impl.Tools.EMPTY_FIELD; import static org.jooq.impl.Tools.EMPTY_STRING; import static org.jooq.impl.Tools.anyMatch; +import static org.jooq.impl.Tools.autoAlias; import static org.jooq.impl.Tools.findAny; import static org.jooq.impl.Tools.flattenCollection; import static org.jooq.impl.Tools.map; -import static org.jooq.impl.Tools.qualify; import static org.jooq.impl.Tools.BooleanDataKey.DATA_EMULATE_BULK_INSERT_RETURNING; import static org.jooq.impl.Tools.BooleanDataKey.DATA_UNALIAS_ALIASED_EXPRESSIONS; import static org.jooq.impl.Tools.DataKey.DATA_DML_TARGET_TABLE; @@ -120,6 +119,8 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; +import java.util.regex.Pattern; import org.jooq.Asterisk; import org.jooq.Binding; @@ -143,13 +144,18 @@ import org.jooq.Record; import org.jooq.Result; import org.jooq.Row; import org.jooq.SQLDialect; +import org.jooq.SchemaMapping; import org.jooq.Scope; import org.jooq.Select; import org.jooq.SelectFieldOrAsterisk; import org.jooq.Table; +import org.jooq.TableField; import org.jooq.UniqueKey; import org.jooq.Update; import org.jooq.conf.ExecuteWithoutWhere; +import org.jooq.conf.MappedSchema; +import org.jooq.conf.MappedTable; +import org.jooq.conf.RenderMapping; import org.jooq.conf.RenderNameCase; import org.jooq.conf.SettingsTools; import org.jooq.exception.DataAccessException; @@ -590,6 +596,23 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery + + + + + + + + + + + + + + + + + @@ -772,6 +795,17 @@ abstract class AbstractDMLQuery extends AbstractRowCountQuery + + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java index 7fc610cfab..1eb45276a6 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java @@ -37,24 +37,21 @@ */ package org.jooq.impl; -import static org.jooq.impl.DefaultExecuteContext.localConfiguration; -import static org.jooq.impl.DefaultExecuteContext.localData; +import static org.jooq.impl.DefaultExecuteContext.localScope; import static org.jooq.impl.Tools.fieldsArray; +import static org.jooq.impl.Tools.getMappedUDTName; import static org.jooq.impl.Tools.row0; import java.sql.SQLException; import java.sql.SQLInput; import java.sql.SQLOutput; -import java.util.Map; -import org.jooq.Configuration; import org.jooq.Converter; import org.jooq.Field; import org.jooq.QualifiedRecord; -import org.jooq.Record; import org.jooq.RecordQualifier; import org.jooq.Row; -import org.jooq.UDT; +import org.jooq.Scope; /** * @author Lukas Eder @@ -115,20 +112,18 @@ abstract class AbstractQualifiedRecord> extends Abs // [#1693] This needs to return the fully qualified SQL type name, in // case the connected user is not the owner of the UDT - Configuration configuration = localConfiguration(); - return Tools.getMappedUDTName(configuration, this); + return getMappedUDTName(localScope(), this); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public final void readSQL(SQLInput stream, String typeName) throws SQLException { - Configuration configuration = localConfiguration(); - Map data = localData(); + Scope scope = localScope(); Field[] f = getQualifier().fields(); for (int i = 0; i < f.length; i++) { Field field = f[i]; - DefaultBindingGetSQLInputContext out = new DefaultBindingGetSQLInputContext(configuration, data, stream); + DefaultBindingGetSQLInputContext out = new DefaultBindingGetSQLInputContext(scope.configuration(), scope.data(), stream); field.getBinding().get(out); set(i, field, out.value()); } @@ -137,13 +132,10 @@ abstract class AbstractQualifiedRecord> extends Abs @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public final void writeSQL(SQLOutput stream) throws SQLException { - Configuration configuration = localConfiguration(); - Map data = localData(); + Scope scope = localScope(); Field[] f = getQualifier().fields(); - for (int i = 0; i < f.length; i++) { - Field field = f[i]; - field.getBinding().set(new DefaultBindingSetSQLOutputContext(configuration, data, stream, get(i))); - } + for (int i = 0; i < f.length; i++) + f[i].getBinding().set(new DefaultBindingSetSQLOutputContext(scope.configuration(), scope.data(), stream, get(i))); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 54ac477b37..a5825c51b0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -1175,7 +1175,7 @@ public abstract class AbstractRoutine extends AbstractNamed implements Routin List list = new ArrayList<>(); if (ctx.qualify()) { - Schema mapped = Tools.getMappedSchema(ctx.configuration(), getSchema()); + Schema mapped = Tools.getMappedSchema(ctx, getSchema()); if (mapped != null && !"".equals(mapped.getName())) list.addAll(asList(mapped.getQualifiedName().parts())); diff --git a/jOOQ/src/main/java/org/jooq/impl/CatalogImpl.java b/jOOQ/src/main/java/org/jooq/impl/CatalogImpl.java index 8ae89d55ba..559073de3d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CatalogImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CatalogImpl.java @@ -39,6 +39,7 @@ package org.jooq.impl; import static org.jooq.Clause.CATALOG; import static org.jooq.Clause.CATALOG_REFERENCE; +import static org.jooq.impl.Tools.getMappedCatalog; import java.util.Collections; import java.util.List; @@ -82,7 +83,7 @@ public class CatalogImpl extends AbstractNamed implements Catalog { @Override public final void accept(Context ctx) { - Catalog mappedCatalog = Tools.getMappedCatalog(ctx.configuration(), this); + Catalog mappedCatalog = getMappedCatalog(ctx, this); ctx.visit(mappedCatalog != null ? mappedCatalog.getUnqualifiedName() : getUnqualifiedName()); } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 31385f714e..da919e4abc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -128,6 +128,7 @@ import static org.jooq.impl.Tools.convertBytesToHex; import static org.jooq.impl.Tools.emulateMultiset; import static org.jooq.impl.Tools.enums; import static org.jooq.impl.Tools.findAny; +// ... import static org.jooq.impl.Tools.getMappedUDTName; import static org.jooq.impl.Tools.map; import static org.jooq.impl.Tools.needsBackslashEscaping; @@ -511,19 +512,19 @@ public class DefaultBinding implements Binding { return theBinding; } - static final Map> typeMap(Class type, Configuration configuration) { - return typeMap(type, configuration, new HashMap<>()); + static final Map> typeMap(Class type, Scope scope) { + return typeMap(type, scope, new HashMap<>()); } @SuppressWarnings("unchecked") - static final Map> typeMap(Class type, Configuration configuration, Map> result) { + static final Map> typeMap(Class type, Scope scope, Map> result) { try { if (QualifiedRecord.class.isAssignableFrom(type)) { Class> t = (Class>) type; - result.put(getMappedUDTName(configuration, t), t); + result.put(getMappedUDTName(scope, t), t); QualifiedRecord r = t.getDeclaredConstructor().newInstance(); for (Field field : r.getQualifier().fields()) - typeMap(field.getType(), configuration, result); + typeMap(field.getType(), scope, result); } @@ -3561,7 +3562,7 @@ public class DefaultBinding implements Binding { return pgNewRecord(dataType.getType(), null, ctx.resultSet().getObject(ctx.index())); default: - return (Record) ctx.resultSet().getObject(ctx.index(), typeMap(dataType.getType(), ctx.configuration())); + return (Record) ctx.resultSet().getObject(ctx.index(), typeMap(dataType.getType(), ctx)); } } @@ -3574,7 +3575,7 @@ public class DefaultBinding implements Binding { return pgNewRecord(dataType.getType(), null, ctx.statement().getObject(ctx.index())); default: - return (Record) ctx.statement().getObject(ctx.index(), typeMap(dataType.getType(), ctx.configuration())); + return (Record) ctx.statement().getObject(ctx.index(), typeMap(dataType.getType(), ctx)); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java index 540543c829..c12b9812f8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDSLContext.java @@ -61,6 +61,8 @@ import static org.jooq.impl.Tools.EMPTY_TABLE; import static org.jooq.impl.Tools.EMPTY_TABLE_RECORD; import static org.jooq.impl.Tools.EMPTY_UPDATABLE_RECORD; import static org.jooq.impl.Tools.blocking; +import static org.jooq.impl.Tools.getMappedSchema; +import static org.jooq.impl.Tools.getMappedTable; import static org.jooq.impl.Tools.list; import java.io.ByteArrayInputStream; @@ -350,12 +352,12 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri @Override public Schema map(Schema schema) { - return Tools.getMappedSchema(configuration(), schema); + return getMappedSchema(this, schema); } @Override public Table map(Table table) { - return Tools.getMappedTable(configuration(), table); + return getMappedTable(this, table); } // ------------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java index 7f26f45211..14debeba98 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java @@ -42,8 +42,6 @@ import static org.jooq.impl.Tools.EMPTY_INT; import static org.jooq.impl.Tools.EMPTY_QUERY; import static org.jooq.impl.Tools.EMPTY_STRING; -import java.io.Closeable; -import java.io.IOException; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; @@ -69,13 +67,13 @@ import org.jooq.ExecuteContext; import org.jooq.ExecuteType; import org.jooq.Insert; import org.jooq.Merge; -// ... import org.jooq.Query; import org.jooq.Record; import org.jooq.Result; import org.jooq.ResultQuery; import org.jooq.Routine; import org.jooq.SQLDialect; +import org.jooq.Scope; import org.jooq.Update; import org.jooq.conf.Settings; import org.jooq.tools.JooqLogger; @@ -83,8 +81,6 @@ import org.jooq.tools.jdbc.JDBCUtils; import org.jetbrains.annotations.NotNull; -// ... - /** * A default implementation for the {@link ExecuteContext}. * @@ -171,8 +167,7 @@ class DefaultExecuteContext implements ExecuteContext { RESOURCES.remove(); } - LOCAL_CONFIGURATION.remove(); - LOCAL_DATA.remove(); + LOCAL_SCOPE.remove(); LOCAL_CONNECTION.remove(); } @@ -222,29 +217,17 @@ class DefaultExecuteContext implements ExecuteContext { // XXX: Static utility methods for handling Configuration lifecycle // ------------------------------------------------------------------------ - private static final ThreadLocal LOCAL_CONFIGURATION = new ThreadLocal<>(); - private static final ThreadLocal> LOCAL_DATA = new ThreadLocal<>(); + private static final ThreadLocal LOCAL_SCOPE = new ThreadLocal<>(); /** - * Get the registered configuration. + * Get the registered scope. *

* It can be safely assumed that such a configuration is available once the * {@link ExecuteContext} has been established, until the statement is * closed. */ - static final Configuration localConfiguration() { - return LOCAL_CONFIGURATION.get(); - } - - /** - * Get the registered data. - *

- * It can be safely assumed that such a configuration is available once the - * {@link ExecuteContext} has been established, until the statement is - * closed. - */ - static final Map localData() { - return LOCAL_DATA.get(); + static final Scope localScope() { + return LOCAL_SCOPE.get(); } // ------------------------------------------------------------------------ @@ -272,7 +255,7 @@ class DefaultExecuteContext implements ExecuteContext { * {@link ExecuteContext} has been established, until the statement is * closed. */ - static final Connection localTargetConnection(Configuration configuration) { + static final Connection localTargetConnection(Scope scope) { Connection result = localConnection(); @@ -360,8 +343,7 @@ class DefaultExecuteContext implements ExecuteContext { } clean(); - LOCAL_CONFIGURATION.set(configuration); - LOCAL_DATA.set(this.data); + LOCAL_SCOPE.set(this); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java b/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java index a662175989..99da267512 100644 --- a/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java +++ b/jOOQ/src/main/java/org/jooq/impl/QualifiedRecordConstant.java @@ -41,6 +41,7 @@ package org.jooq.impl; import static org.jooq.conf.ParamType.INLINED; import static org.jooq.impl.DSL.val; import static org.jooq.impl.Keywords.K_ROW; +import static org.jooq.impl.Tools.getMappedUDTName; import org.jooq.BindContext; import org.jooq.Context; @@ -160,7 +161,7 @@ final class QualifiedRecordConstant> extends Abstra return "ROW"; default: - return Tools.getMappedUDTName(ctx.configuration(), value); + return getMappedUDTName(ctx, value); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/SchemaImpl.java b/jOOQ/src/main/java/org/jooq/impl/SchemaImpl.java index 5e0c33a858..ddaf1bf854 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SchemaImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SchemaImpl.java @@ -42,6 +42,8 @@ import static org.jooq.Clause.SCHEMA; import static org.jooq.Clause.SCHEMA_REFERENCE; import static org.jooq.impl.CatalogImpl.DEFAULT_CATALOG; import static org.jooq.impl.Tools.flatMap; +import static org.jooq.impl.Tools.getMappedCatalog; +import static org.jooq.impl.Tools.getMappedSchema; import static org.jooq.tools.StringUtils.defaultIfNull; import java.util.ArrayList; @@ -118,15 +120,13 @@ public class SchemaImpl extends AbstractNamed implements Schema { @Override public final void accept(Context ctx) { if (ctx.qualifyCatalog()) { - Catalog mappedCatalog = Tools.getMappedCatalog(ctx.configuration(), getCatalog()); + Catalog mappedCatalog = getMappedCatalog(ctx, getCatalog()); - if (mappedCatalog != null && !"".equals(mappedCatalog.getName())) { - ctx.visit(mappedCatalog); - ctx.sql('.'); - } + if (mappedCatalog != null && !"".equals(mappedCatalog.getName())) + ctx.visit(mappedCatalog).sql('.'); } - Schema mappedSchema = Tools.getMappedSchema(ctx.configuration(), this); + Schema mappedSchema = getMappedSchema(ctx, this); ctx.visit(mappedSchema != null ? mappedSchema.getUnqualifiedName() : getUnqualifiedName()); } diff --git a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index 616517db1a..9bdafb2876 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -185,6 +185,7 @@ import static org.jooq.impl.Tools.EMPTY_SORTFIELD; import static org.jooq.impl.Tools.aliased; import static org.jooq.impl.Tools.aliasedFields; import static org.jooq.impl.Tools.anyMatch; +import static org.jooq.impl.Tools.autoAlias; import static org.jooq.impl.Tools.camelCase; import static org.jooq.impl.Tools.fieldArray; import static org.jooq.impl.Tools.findAny; @@ -666,7 +667,7 @@ final class SelectQueryImpl extends AbstractResultQuery imp public final Table asTable() { // Its usually better to alias nested selects that are used in // the FROM clause of a query - return new DerivedTable<>(this).as("alias_" + Tools.hash(this)); + return new DerivedTable<>(this).as(autoAlias(this)); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java b/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java index 6293651ca2..5256320b48 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SequenceImpl.java @@ -58,6 +58,7 @@ import static org.jooq.impl.Names.N_CURRVAL; import static org.jooq.impl.Names.N_GENERATE_SERIES; import static org.jooq.impl.Names.N_GEN_ID; import static org.jooq.impl.Names.N_NEXTVAL; +import static org.jooq.impl.Tools.getMappedSchema; import org.jooq.Catalog; import org.jooq.Clause; @@ -328,7 +329,7 @@ public class SequenceImpl extends AbstractTypedNamed implem - Schema mappedSchema = Tools.getMappedSchema(ctx.configuration(), schema); + Schema mappedSchema = getMappedSchema(ctx, schema); if (mappedSchema != null && !"".equals(mappedSchema.getName()) && ctx.family() != CUBRID) ctx.visit(mappedSchema) diff --git a/jOOQ/src/main/java/org/jooq/impl/TableImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableImpl.java index 09b0858182..295bee0a48 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableImpl.java @@ -308,7 +308,7 @@ public class TableImpl extends AbstractTable implements Sco // [#4834] Generate alias only if allowed to do so if (ctx.declareAliases()) ctx.sql(' ') - .visit(Tools.getMappedTable(ctx.configuration(), this).getUnqualifiedName()); + .visit(getMappedTable(ctx, this).getUnqualifiedName()); } else accept0(ctx); @@ -330,7 +330,7 @@ public class TableImpl extends AbstractTable implements Sco )) { - Schema mappedSchema = Tools.getMappedSchema(ctx.configuration(), getSchema()); + Schema mappedSchema = Tools.getMappedSchema(ctx, getSchema()); if (mappedSchema != null && !"".equals(mappedSchema.getName())) { ctx.visit(mappedSchema); @@ -338,7 +338,7 @@ public class TableImpl extends AbstractTable implements Sco } } - ctx.visit(getMappedTable(ctx.configuration(), this).getUnqualifiedName()); + ctx.visit(getMappedTable(ctx, this).getUnqualifiedName()); if (parameters != null && ctx.declareTables()) { diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 0b992fd3fc..e963d12def 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -277,6 +277,7 @@ import org.jooq.Results; import org.jooq.Row; import org.jooq.SQLDialect; import org.jooq.Schema; +import org.jooq.SchemaMapping; import org.jooq.Scope; import org.jooq.Select; import org.jooq.SelectFieldOrAsterisk; @@ -316,6 +317,8 @@ import org.jooq.types.UInteger; import org.jooq.types.ULong; import org.jooq.types.UShort; +import org.jetbrains.annotations.Nullable; + /** * General internal jOOQ utilities * @@ -634,7 +637,13 @@ final class Tools { * [#10540] Aliases to be applied to the current SELECT * statement. */ - DATA_SELECT_ALIASES + DATA_SELECT_ALIASES, + + /** + * [#8917] An internal schema mapping that overrides any user-defined + * schema mappings. + */ + DATA_SCHEMA_MAPPING, } /** @@ -2995,9 +3004,12 @@ final class Tools { /** * Map a {@link Catalog} according to the configured {@link org.jooq.SchemaMapping} */ - static final Catalog getMappedCatalog(Configuration configuration, Catalog catalog) { - if (configuration != null) { - org.jooq.SchemaMapping mapping = configuration.schemaMapping(); + static final Catalog getMappedCatalog(Scope scope, Catalog catalog) { + if (scope != null) { + org.jooq.SchemaMapping mapping = (SchemaMapping) scope.data(DataKey.DATA_SCHEMA_MAPPING); + + if (mapping == null) + mapping = scope.configuration().schemaMapping(); if (mapping != null) return mapping.map(catalog); @@ -3009,9 +3021,12 @@ final class Tools { /** * Map a {@link Schema} according to the configured {@link org.jooq.SchemaMapping} */ - static final Schema getMappedSchema(Configuration configuration, Schema schema) { - if (configuration != null) { - org.jooq.SchemaMapping mapping = configuration.schemaMapping(); + static final Schema getMappedSchema(Scope scope, Schema schema) { + if (scope != null) { + org.jooq.SchemaMapping mapping = (SchemaMapping) scope.data(DataKey.DATA_SCHEMA_MAPPING); + + if (mapping == null) + mapping = scope.configuration().schemaMapping(); if (mapping != null) return mapping.map(schema); @@ -3023,9 +3038,12 @@ final class Tools { /** * Map a {@link Table} according to the configured {@link org.jooq.SchemaMapping} */ - static final Table getMappedTable(Configuration configuration, Table table) { - if (configuration != null) { - org.jooq.SchemaMapping mapping = configuration.schemaMapping(); + static final Table getMappedTable(Scope scope, Table table) { + if (scope != null) { + org.jooq.SchemaMapping mapping = (SchemaMapping) scope.data(DataKey.DATA_SCHEMA_MAPPING); + + if (mapping == null) + mapping = scope.configuration().schemaMapping(); if (mapping != null) return mapping.map(table); @@ -3039,17 +3057,17 @@ final class Tools { * {@link org.jooq.SchemaMapping} */ @SuppressWarnings("unchecked") - static final String getMappedUDTName(Configuration configuration, Class> type) { - return getMappedUDTName(configuration, Tools.newRecord(false, (Class>) type).operate(null)); + static final String getMappedUDTName(Scope scope, Class> type) { + return getMappedUDTName(scope, Tools.newRecord(false, (Class>) type).operate(null)); } /** * Map an {@link QualifiedRecord} according to the configured * {@link org.jooq.SchemaMapping} */ - static final String getMappedUDTName(Configuration configuration, QualifiedRecord record) { + static final String getMappedUDTName(Scope scope, QualifiedRecord record) { RecordQualifier udt = record.getQualifier(); - Schema mapped = getMappedSchema(configuration, udt.getSchema()); + Schema mapped = getMappedSchema(scope, udt.getSchema()); StringBuilder sb = new StringBuilder(); if (mapped != null && !"".equals(mapped.getName())) @@ -3121,7 +3139,29 @@ final class Tools { - static final DSLContext CTX = DSL.using(new DefaultConfiguration()); + static final DSLContext CTX = DSL.using(new DefaultConfiguration()); + + /** + * A possibly inefficient but stable way to generate an alias for any + * {@link QueryPart}. + *

+ * Stability is important to profit from execution plan caching. Equal query + * parts must produce the same alias every time. + */ + static final String autoAlias(QueryPart part) { + return "alias_" + hash(part); + } + + /** + * A possibly inefficient but stable way to generate an alias for any + * {@link QueryPart}. + *

+ * Stability is important to profit from execution plan caching. Equal query + * parts must produce the same alias every time. + */ + static final Name autoAliasName(QueryPart part) { + return DSL.name(autoAlias(part)); + } /** * Return a non-negative hash code for a {@link QueryPart}, taking into diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTImpl.java b/jOOQ/src/main/java/org/jooq/impl/UDTImpl.java index c35af26f1d..e31af24717 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UDTImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/UDTImpl.java @@ -37,6 +37,8 @@ */ package org.jooq.impl; +import static org.jooq.impl.Tools.getMappedSchema; + import java.util.stream.Stream; import org.jooq.Binding; @@ -151,7 +153,7 @@ public class UDTImpl> extends AbstractNamed implements UD @Override public final void accept(Context ctx) { - Schema mappedSchema = Tools.getMappedSchema(ctx.configuration(), getSchema()); + Schema mappedSchema = getMappedSchema(ctx, getSchema()); if (mappedSchema != null && !"".equals(mappedSchema.getName())) ctx.visit(mappedSchema).sql('.');