[jOOQ/jOOQ#579] Auto alias unnamed field expressions in derived tables

This commit is contained in:
Lukas Eder 2024-02-26 13:33:21 +01:00
parent eb6150893d
commit dfcaa4c3aa
19 changed files with 232 additions and 20 deletions

View File

@ -79,7 +79,8 @@ public final class Constants {
/**
* The current jooq-runtime XSD file name.
*/
public static final String XSD_RUNTIME = "jooq-runtime-3.19.0.xsd";
public static final String XSD_RUNTIME = "jooq-runtime-3.20.0.xsd";
/**
* The current jooq-runtime XML namespace.

View File

@ -79,7 +79,7 @@ public final class Constants {
/**
* The current jooq-runtime XSD file name.
*/
public static final String XSD_RUNTIME = "jooq-runtime-3.19.0.xsd";
public static final String XSD_RUNTIME = "jooq-runtime-3.20.0.xsd";
/**
* The current jooq-runtime XML namespace.

View File

@ -79,7 +79,7 @@ public final class Constants {
/**
* The current jooq-runtime XSD file name.
*/
public static final String XSD_RUNTIME = "jooq-runtime-3.19.0.xsd";
public static final String XSD_RUNTIME = "jooq-runtime-3.20.0.xsd";
/**
* The current jooq-runtime XML namespace.

View File

@ -0,0 +1,39 @@
package org.jooq.conf;
import jakarta.xml.bind.annotation.XmlEnum;
import jakarta.xml.bind.annotation.XmlType;
/**
* <p>Java class for AutoAliasExpressions.
*
* <p>The following schema fragment specifies the expected content contained within this class.
* <pre>
* &lt;simpleType name="AutoAliasExpressions"&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string"&gt;
* &lt;enumeration value="NEVER"/&gt;
* &lt;enumeration value="UNNAMED"/&gt;
* &lt;enumeration value="ALWAYS"/&gt;
* &lt;/restriction&gt;
* &lt;/simpleType&gt;
* </pre>
*
*/
@XmlType(name = "AutoAliasExpressions")
@XmlEnum
public enum AutoAliasExpressions {
NEVER,
UNNAMED,
ALWAYS;
public String value() {
return name();
}
public static AutoAliasExpressions fromValue(String v) {
return valueOf(v);
}
}

View File

@ -24,7 +24,7 @@ import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
private final static QName _Settings_QNAME = new QName("http://www.jooq.org/xsd/jooq-runtime-3.19.0.xsd", "settings");
private final static QName _Settings_QNAME = new QName("http://www.jooq.org/xsd/jooq-runtime-3.20.0.xsd", "settings");
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.jooq.conf
@ -121,7 +121,7 @@ public class ObjectFactory {
* @return
* the new instance of {@link JAXBElement }{@code <}{@link Settings }{@code >}
*/
@XmlElementDecl(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.19.0.xsd", name = "settings")
@XmlElementDecl(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.20.0.xsd", name = "settings")
public JAXBElement<Settings> createSettings(Settings value) {
return new JAXBElement<Settings>(_Settings_QNAME, Settings.class, null, value);
}

View File

@ -70,6 +70,9 @@ public class Settings
@XmlElement(defaultValue = "false")
protected Boolean renderFormatted = false;
protected RenderFormatting renderFormatting;
@XmlElement(defaultValue = "NEVER")
@XmlSchemaType(name = "string")
protected AutoAliasExpressions renderAutoAliasedDerivedTableExpressions = AutoAliasExpressions.NEVER;
@XmlElement(defaultValue = "DEFAULT")
@XmlSchemaType(name = "string")
protected RenderOptionalKeyword renderOptionalAssociativityParentheses = RenderOptionalKeyword.DEFAULT;
@ -894,6 +897,26 @@ public class Settings
this.renderFormatting = value;
}
/**
* Whether to auto-alias expressions in derived tables.
* <p>
* This feature is available in the commercial distribution only.
*
*/
public AutoAliasExpressions getRenderAutoAliasedDerivedTableExpressions() {
return renderAutoAliasedDerivedTableExpressions;
}
/**
* Whether to auto-alias expressions in derived tables.
* <p>
* This feature is available in the commercial distribution only.
*
*/
public void setRenderAutoAliasedDerivedTableExpressions(AutoAliasExpressions value) {
this.renderAutoAliasedDerivedTableExpressions = value;
}
/**
* Whether to render optional parentheses to make associativity explicit, e.g. <code>((a + b) + c)</code> instead of (a + b + c).
*
@ -6817,6 +6840,17 @@ public class Settings
return this;
}
/**
* Whether to auto-alias expressions in derived tables.
* <p>
* This feature is available in the commercial distribution only.
*
*/
public Settings withRenderAutoAliasedDerivedTableExpressions(AutoAliasExpressions value) {
setRenderAutoAliasedDerivedTableExpressions(value);
return this;
}
/**
* Whether to render optional parentheses to make associativity explicit, e.g. <code>((a + b) + c)</code> instead of (a + b + c).
*
@ -9421,6 +9455,7 @@ public class Settings
builder.append("renderLocale", renderLocale);
builder.append("renderFormatted", renderFormatted);
builder.append("renderFormatting", renderFormatting);
builder.append("renderAutoAliasedDerivedTableExpressions", renderAutoAliasedDerivedTableExpressions);
builder.append("renderOptionalAssociativityParentheses", renderOptionalAssociativityParentheses);
builder.append("renderOptionalAsKeywordForTableAliases", renderOptionalAsKeywordForTableAliases);
builder.append("renderOptionalAsKeywordForFieldAliases", renderOptionalAsKeywordForFieldAliases);
@ -9778,6 +9813,15 @@ public class Settings
return false;
}
}
if (renderAutoAliasedDerivedTableExpressions == null) {
if (other.renderAutoAliasedDerivedTableExpressions!= null) {
return false;
}
} else {
if (!renderAutoAliasedDerivedTableExpressions.equals(other.renderAutoAliasedDerivedTableExpressions)) {
return false;
}
}
if (renderOptionalAssociativityParentheses == null) {
if (other.renderOptionalAssociativityParentheses!= null) {
return false;
@ -11689,6 +11733,7 @@ public class Settings
result = ((prime*result)+((renderLocale == null)? 0 :renderLocale.hashCode()));
result = ((prime*result)+((renderFormatted == null)? 0 :renderFormatted.hashCode()));
result = ((prime*result)+((renderFormatting == null)? 0 :renderFormatting.hashCode()));
result = ((prime*result)+((renderAutoAliasedDerivedTableExpressions == null)? 0 :renderAutoAliasedDerivedTableExpressions.hashCode()));
result = ((prime*result)+((renderOptionalAssociativityParentheses == null)? 0 :renderOptionalAssociativityParentheses.hashCode()));
result = ((prime*result)+((renderOptionalAsKeywordForTableAliases == null)? 0 :renderOptionalAsKeywordForTableAliases.hashCode()));
result = ((prime*result)+((renderOptionalAsKeywordForFieldAliases == null)? 0 :renderOptionalAsKeywordForFieldAliases.hashCode()));

View File

@ -1,2 +1,2 @@
@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.19.0.xsd", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED)
@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://www.jooq.org/xsd/jooq-runtime-3.20.0.xsd", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.jooq.conf;

View File

@ -113,6 +113,7 @@ import org.jooq.Select;
import org.jooq.Table;
import org.jooq.conf.RenderOptionalKeyword;
import org.jooq.impl.QOM.UEmpty;
import org.jooq.impl.Tools.BooleanDataKey;
/**
* @author Lukas Eder
@ -421,8 +422,22 @@ final class Alias<Q extends QueryPart> extends AbstractQueryPart implements UEmp
else
ctx.sql('(');
if (nestedJoinTable && NO_SUPPORT_ALIASED_JOIN_TABLES.contains(ctx.dialect()))
if (nestedJoinTable && NO_SUPPORT_ALIASED_JOIN_TABLES.contains(ctx.dialect())) {
ctx.visit(select(asterisk()).from((Table<?>) wrapped));
}
else
ctx.visit(wrapped);

View File

@ -44,7 +44,6 @@ import org.jooq.Field;
import org.jooq.Name;
import org.jooq.QueryPart;
// ...
import org.jooq.Table;
// ...
import org.jetbrains.annotations.NotNull;
@ -52,7 +51,14 @@ import org.jetbrains.annotations.NotNull;
/**
* @author Lukas Eder
*/
final class FieldAlias<T> extends AbstractField<T> implements QOM.FieldAlias<T>, SimpleCheckQueryPart {
final class FieldAlias<T>
extends
AbstractField<T>
implements
QOM.FieldAlias<T>,
SimpleCheckQueryPart,
NamedField<T>
{
private final Alias<Field<T>> alias;

View File

@ -125,5 +125,6 @@ package org.jooq.impl;

View File

@ -0,0 +1,53 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: https://www.jooq.org/legal/licensing
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import org.jooq.Field;
/**
* A marker interface for fields whose name is defined.
* <p>
* While all {@link Field} implementations are {@link Named}, not all of them
* produce a name known to the underlying dialect's SQL engine. E.g.
* <code>'a' || 'b'</code> has a name called "concat", but this may not be the
* name the SQL engine uses for this expression. In some cases, jOOQ needs to
* explicitly produce the name for unnamed fields.
*
* @author Lukas Eder
*/
interface NamedField<T> extends Field<T> {}

View File

@ -129,5 +129,6 @@ package org.jooq.impl;

View File

@ -44,7 +44,13 @@ import org.jooq.SQL;
import org.jooq.impl.QOM.UEmpty;
import org.jooq.impl.QOM.UEmptyCondition;
final class SQLCondition extends AbstractCondition implements UEmptyCondition {
final class SQLCondition
extends
AbstractCondition
implements
UEmptyCondition,
NamedField<Boolean>
{
private final SQL delegate;

View File

@ -43,7 +43,14 @@ import org.jooq.QueryPart;
import org.jooq.SQL;
import org.jooq.impl.QOM.UEmptyField;
final class SQLField<T> extends AbstractField<T> implements UEmptyField<T>, TypedReference<T> {
final class SQLField<T>
extends
AbstractField<T>
implements
UEmptyField<T>,
TypedReference<T>,
NamedField<T>
{
final SQLImpl delegate;

View File

@ -103,7 +103,6 @@ import static org.jooq.SQLDialect.MYSQL;
// ...
// ...
// ...
// ...
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
@ -229,7 +228,6 @@ import static org.jooq.impl.Tools.BooleanDataKey.DATA_INSERT_SELECT_WITHOUT_INSE
import static org.jooq.impl.Tools.BooleanDataKey.DATA_MULTISET_CONTENT;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_NESTED_SET_OPERATIONS;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_OMIT_INTO_CLAUSE;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_RENDER_IMPLICIT_JOIN;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_UNALIAS_ALIASED_EXPRESSIONS;
import static org.jooq.impl.Tools.BooleanDataKey.DATA_WRAP_DERIVED_TABLES_IN_PARENTHESES;
@ -248,7 +246,6 @@ import static org.jooq.impl.Transformations.transformGroupByColumnIndex;
import static org.jooq.impl.Transformations.transformInlineCTE;
import static org.jooq.impl.Transformations.transformQualify;
import static org.jooq.impl.Transformations.transformRownum;
import static org.jooq.tools.StringUtils.defaultIfNull;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
@ -269,8 +266,6 @@ import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.jooq.Asterisk;
import org.jooq.Clause;
@ -324,8 +319,8 @@ import org.jooq.TableRecord;
// ...
import org.jooq.WindowDefinition;
import org.jooq.XML;
import org.jooq.conf.AutoAliasExpressions;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.AbstractContext.JoinNode;
import org.jooq.impl.ForLock.ForLockMode;
import org.jooq.impl.ForLock.ForLockWaitMode;
import org.jooq.impl.QOM.CompareCondition;
@ -1746,14 +1741,28 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
Object renderTrailingLimit = context.data(DATA_RENDER_TRAILING_LIMIT_IF_APPLICABLE);
Name[] selectAliases = (Name[]) context.data(DATA_SELECT_ALIASES);
try {
List<Field<?>> originalFields = null;
List<Field<?>> alternativeFields = null;
if (selectAliases != null) {
context.data().remove(DATA_SELECT_ALIASES);
Name[] a = selectAliases;
alternativeFields = map(originalFields = getSelect(),
(f, i) -> i < selectAliases.length ? f.as(selectAliases[i]) : f
(f, i) -> i < a.length && a[i] != null ? f.as(a[i]) : f
);
}

View File

@ -89,6 +89,7 @@ implements
TableField<R, T>,
SimpleQueryPart,
TypedReference<T>,
NamedField<T>,
ScopeMappable,
UEmpty
{

View File

@ -527,6 +527,13 @@ final class Tools {
/**

View File

@ -89,6 +89,7 @@ implements
UDTPathField<R, U, T>,
SimpleQueryPart,
TypedReference<T>,
NamedField<T>,
ScopeMappable,
UEmpty
{

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:jooq-runtime="http://www.jooq.org/xsd/jooq-runtime-3.19.0.xsd"
xmlns:jooq-runtime="http://www.jooq.org/xsd/jooq-runtime-3.20.0.xsd"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:annox="http://annox.dev.java.net"
targetNamespace="http://www.jooq.org/xsd/jooq-runtime-3.19.0.xsd"
targetNamespace="http://www.jooq.org/xsd/jooq-runtime-3.20.0.xsd"
elementFormDefault="qualified"
jxb:extensionBindingPrefixes="annox"
jxb:version="2.1">
@ -129,6 +129,12 @@ providing a name to parameters, resulting in <code>:1</code> or <code>@1</code>
<element name="renderFormatting" type="jooq-runtime:RenderFormatting" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[All sorts of formatting flags / settings.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderAutoAliasedDerivedTableExpressions" type="jooq-runtime:AutoAliasExpressions" minOccurs="0" maxOccurs="1" default="NEVER">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether to auto-alias expressions in derived tables.
<p>
This feature is available in the commercial distribution only.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderOptionalAssociativityParentheses" type="jooq-runtime:RenderOptionalKeyword" minOccurs="0" maxOccurs="1" default="DEFAULT">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether to render optional parentheses to make associativity explicit, e.g. <code>((a + b) + c)</code> instead of (a + b + c).]]></jxb:javadoc></jxb:property></appinfo></annotation>
@ -2454,4 +2460,18 @@ Either &lt;input/&gt; or &lt;inputExpression/&gt; must be provided]]></jxb:javad
<enumeration value="ALWAYS"/>
</restriction>
</simpleType>
<simpleType name="AutoAliasExpressions">
<restriction base="string">
<!-- Never auto-alias expressions. -->
<enumeration value="NEVER"/>
<!-- Auto-alias only unnamed expressions. -->
<enumeration value="UNNAMED"/>
<!-- Always auto-alias expressions. -->
<enumeration value="ALWAYS"/>
</restriction>
</simpleType>
</schema>