diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 68362eaf2e..42ac25a3a7 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -845,7 +845,26 @@ public abstract class jOOQAbstractTest< assertEquals("O Alquimista", result.getValue(2, TBook_TITLE())); assertEquals("Brida", result.getValue(3, TBook_TITLE())); + // [#995] Schema mapping in stored functions + // ----------------------------------------- + Field f1 = FOneField().cast(Integer.class); + Field f2 = FNumberField(42).cast(Integer.class); + + q = + create(mapping).select(f1, f2); + + // Assure that schema is replaced + assertTrue(create(mapping).render(q).contains(TAuthor().getSchema().getName() + "2")); + assertTrue(q.getSQL().contains(TAuthor().getSchema().getName() + "2")); + assertEquals(create(mapping).render(q), q.getSQL()); + + // Assure that results are correct + Record record = q.fetchOne(); + assertEquals(1, (int) record.getValue(f1)); + assertEquals(42, (int) record.getValue(f2)); + // Map both schema AND tables + // -------------------------- mapping = new SchemaMapping(); mapping.add(TAuthor(), VAuthor()); mapping.add(TBook(), VBook().getName()); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractQueryPart.java b/jOOQ/src/main/java/org/jooq/impl/AbstractQueryPart.java index 49792da6d4..7ea55de2d4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractQueryPart.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractQueryPart.java @@ -52,9 +52,7 @@ import org.jooq.Query; import org.jooq.QueryPart; import org.jooq.QueryPartInternal; import org.jooq.SQLDialect; -import org.jooq.Schema; import org.jooq.Store; -import org.jooq.Table; import org.jooq.exception.DataAccessException; import org.jooq.exception.SQLDialectNotSupportedException; @@ -206,56 +204,6 @@ abstract class AbstractQueryPart implements QueryPartInternal, AttachableInterna // Internal convenience methods // ------------------------------------------------------------------------- - /** - * Internal convenience method - */ - final Schema getMappedSchema(Configuration configuration, Schema schema) { - if (configuration.getSchemaMapping() != null) { - return configuration.getSchemaMapping().map(schema); - } - else { - return schema; - } - } - - /** - * Internal convenience method - */ - final Table getMappedTable(Configuration configuration, Table table) { - if (configuration.getSchemaMapping() != null) { - return configuration.getSchemaMapping().map(table); - } - else { - return table; - } - } - - /** - * Wrap a piece of SQL code in parentheses, if not wrapped already - */ - protected final String wrapInParentheses(String sql) { - if (sql.startsWith("(")) { - return sql; - } - else { - return "(" + sql + ")"; - } - } - - /** - * Internal convenience method - */ - protected final AttachableInternal internal(Attachable part) { - return part.internalAPI(AttachableInternal.class); - } - - /** - * Internal convenience method - */ - protected final QueryPartInternal internal(QueryPart part) { - return part.internalAPI(QueryPartInternal.class); - } - /** * Internal convenience method */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 1186b3fc98..92e54e0cde 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -365,8 +365,8 @@ public abstract class AbstractRoutine extends AbstractSchemaProviderQueryPart } private final void toSQLQualifiedName(RenderContext context) { - if (getMappedSchema(context, getSchema()) != null) { - context.sql(getMappedSchema(context, getSchema())); + if (Util.getMappedSchema(context, getSchema()) != null) { + context.sql(Util.getMappedSchema(context, getSchema())); context.sql("."); } @@ -526,6 +526,8 @@ public abstract class AbstractRoutine extends AbstractSchemaProviderQueryPart for (Parameter p : getInParameters()) { // Disambiguate overloaded function signatures + // TODO [#625] This won't work any longer, when generated + // routine artefacts are dialect-independent if (SQLDialect.POSTGRES == attachable.getDialect() && isOverloaded()) { array[i] = getInValues().get(p).cast(p.getType()); } @@ -536,10 +538,7 @@ public abstract class AbstractRoutine extends AbstractSchemaProviderQueryPart i++; } - RenderContext local = create(attachable).renderContext(); - toSQLQualifiedName(local); - - function = function(local.render(), type, array); + function = new RoutineField(getName(), type, array); } return function; @@ -559,4 +558,28 @@ public abstract class AbstractRoutine extends AbstractSchemaProviderQueryPart protected static final Parameter createParameter(String name, DataType type) { return new ParameterImpl(name, type); } + + /** + * The {@link Field} representation of this {@link Routine} + * + * @author Lukas Eder + */ + private class RoutineField extends AbstractFunction { + + /** + * Generated UID + */ + private static final long serialVersionUID = -5730297947647252624L; + + RoutineField(String name, DataType type, Field[] arguments) { + super(name, type, arguments); + } + + @Override + final Field getFunction0(Configuration configuration) { + RenderContext local = create(configuration).renderContext(); + toSQLQualifiedName(local); + return function(local.render(), getDataType(), getArguments()); + } + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java b/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java index 09e4bc6d09..c4367bcc5c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java @@ -253,7 +253,7 @@ implements .declareTables(true) .sql(table) .sql(" using ") - .sql(wrapInParentheses(context.render(using))) + .sql(Util.wrapInParentheses(context.render(using))) .declareTables(false); switch (context.getDialect()) { @@ -288,7 +288,7 @@ implements } context.sql(" on ") - .sql(wrapInParentheses(context.render(on))) + .sql(Util.wrapInParentheses(context.render(on))) .sql(" when matched then update set ") .sql(updateMap) .sql(" when not matched then insert ") diff --git a/jOOQ/src/main/java/org/jooq/impl/SequenceFunction.java b/jOOQ/src/main/java/org/jooq/impl/SequenceFunction.java index d2f92dc009..d65edd9cad 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SequenceFunction.java +++ b/jOOQ/src/main/java/org/jooq/impl/SequenceFunction.java @@ -101,7 +101,7 @@ class SequenceFunction extends AbstractFunction { RenderContext local = create(configuration).renderContext(); if (sequence.schema != null) { - local.sql(getMappedSchema(configuration, sequence.schema)); + local.sql(Util.getMappedSchema(configuration, sequence.schema)); local.sql("."); } diff --git a/jOOQ/src/main/java/org/jooq/impl/TableImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableImpl.java index 2772bad412..bb886fee2f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/TableImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/TableImpl.java @@ -108,12 +108,12 @@ public class TableImpl extends AbstractTable { alias.toSQL(context); } else { - if (getMappedSchema(context, getSchema()) != null) { - context.sql(getMappedSchema(context, getSchema())); + if (Util.getMappedSchema(context, getSchema()) != null) { + context.sql(Util.getMappedSchema(context, getSchema())); context.sql("."); } - context.literal(getMappedTable(context, this).getName()); + context.literal(Util.getMappedTable(context, this).getName()); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java b/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java index 955b1c86f7..144c7ae0b3 100644 --- a/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java +++ b/jOOQ/src/main/java/org/jooq/impl/UDTConstant.java @@ -143,8 +143,8 @@ class UDTConstant> extends AbstractField { default: { UDT udt = record.getUDT(); - if (getMappedSchema(context, udt.getSchema()) != null) { - return getMappedSchema(context, udt.getSchema()) + "." + udt.getName(); + if (Util.getMappedSchema(context, udt.getSchema()) != null) { + return Util.getMappedSchema(context, udt.getSchema()) + "." + udt.getName(); } else { return udt.getName(); diff --git a/jOOQ/src/main/java/org/jooq/impl/Util.java b/jOOQ/src/main/java/org/jooq/impl/Util.java index e2ca03e823..e4e5144839 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Util.java +++ b/jOOQ/src/main/java/org/jooq/impl/Util.java @@ -52,13 +52,20 @@ import javax.persistence.Column; import javax.persistence.Entity; import org.jooq.ArrayRecord; +import org.jooq.Attachable; +import org.jooq.AttachableInternal; import org.jooq.Configuration; import org.jooq.Cursor; import org.jooq.Field; import org.jooq.FieldProvider; import org.jooq.NamedQueryPart; +import org.jooq.QueryPart; +import org.jooq.QueryPartInternal; import org.jooq.Record; import org.jooq.RenderContext; +import org.jooq.Schema; +import org.jooq.SchemaMapping; +import org.jooq.Table; import org.jooq.Type; import org.jooq.exception.DataAccessException; import org.jooq.tools.StringUtils; @@ -571,4 +578,54 @@ final class Util { static final void setValue(Record target, Field targetField, Object value) { target.setValue(targetField, targetField.getDataType().convert(value)); } + + /** + * Map a {@link Schema} according to the configured {@link SchemaMapping} + */ + static Schema getMappedSchema(Configuration configuration, Schema schema) { + if (configuration.getSchemaMapping() != null) { + return configuration.getSchemaMapping().map(schema); + } + else { + return schema; + } + } + + /** + * Map a {@link Table} according to the configured {@link SchemaMapping} + */ + static Table getMappedTable(Configuration configuration, Table table) { + if (configuration.getSchemaMapping() != null) { + return configuration.getSchemaMapping().map(table); + } + else { + return table; + } + } + + /** + * Wrap a piece of SQL code in parentheses, if not wrapped already + */ + static String wrapInParentheses(String sql) { + if (sql.startsWith("(")) { + return sql; + } + else { + return "(" + sql + ")"; + } + } + + /** + * Expose the internal API of an {@link Attachable} + */ + static AttachableInternal internal(Attachable part) { + return part.internalAPI(AttachableInternal.class); + } + + /** + * Expose the internal API of a {@link QueryPart} + */ + static QueryPartInternal internal(QueryPart part) { + return part.internalAPI(QueryPartInternal.class); + } } \ No newline at end of file