getUDT();
}
diff --git a/jOOQ/src/main/java/org/jooq/UDTPathField.java b/jOOQ/src/main/java/org/jooq/UDTPathField.java
new file mode 100644
index 0000000000..d7fe1e87b0
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/UDTPathField.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A field dereferenced from a UDT path.
+ *
+ * Instances of this type cannot be created directly. They are available from
+ * generated code.
+ *
+ * @param The record type
+ * @param The field type
+ * @author Lukas Eder
+ */
+public interface UDTPathField, T> extends UDTField {
+
+ /**
+ * @return The UDT path this field is contained in.
+ */
+ @NotNull
+ RecordQualifier getQualifier();
+
+ /**
+ * @return The UDT path represented by this field.
+ */
+ @NotNull
+ RecordQualifier asQualifier();
+
+}
diff --git a/jOOQ/src/main/java/org/jooq/UDTPathTableField.java b/jOOQ/src/main/java/org/jooq/UDTPathTableField.java
new file mode 100644
index 0000000000..80a060b614
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/UDTPathTableField.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A field dereferenced from a UDT path.
+ *
+ * Instances of this type cannot be created directly. They are available from
+ * generated code.
+ *
+ * @param The record type
+ * @param The field type
+ * @author Lukas Eder
+ */
+public interface UDTPathTableField, T> extends TableField, UDTPathField {
+
+ /**
+ * @return The UDT path this field is contained in.
+ */
+ @Override
+ @NotNull
+ RecordQualifier getQualifier();
+}
diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java
index 1ec9640028..b4dabe5db6 100644
--- a/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java
+++ b/jOOQ/src/main/java/org/jooq/impl/FieldMapsForInsert.java
@@ -52,7 +52,6 @@ import static org.jooq.conf.WriteIfReadonly.IGNORE;
import static org.jooq.conf.WriteIfReadonly.THROW;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.select;
-import static org.jooq.impl.FieldMapsForInsert.toSQLInsertSelect;
import static org.jooq.impl.Keywords.K_DEFAULT_VALUES;
import static org.jooq.impl.Keywords.K_VALUES;
import static org.jooq.impl.QueryPartCollectionView.wrap;
@@ -64,6 +63,7 @@ import static org.jooq.impl.Tools.flattenCollection;
import static org.jooq.impl.Tools.flattenFieldOrRows;
import static org.jooq.impl.Tools.lazy;
import static org.jooq.impl.Tools.row0;
+import static org.jooq.impl.Tools.BooleanDataKey.DATA_STORE_ASSIGNMENT;
import java.util.AbstractList;
import java.util.AbstractMap;
@@ -754,7 +754,7 @@ final class FieldMapsForInsert extends AbstractQueryPart implements UNotYetImple
fields = keysFlattened(ctx, GeneratorStatementType.INSERT);
if (!fields.isEmpty())
- ctx.sql(" (").visit(wrap(fields).qualify(false)).sql(')');
+ ctx.data(DATA_STORE_ASSIGNMENT, true, c -> c.sql(" (").visit(wrap(fields).qualify(false)).sql(')'));
return fields;
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Internal.java b/jOOQ/src/main/java/org/jooq/impl/Internal.java
index 7692a3d3a5..022077caaf 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Internal.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Internal.java
@@ -67,6 +67,7 @@ import org.jooq.Domain;
import org.jooq.EmbeddableRecord;
import org.jooq.Field;
import org.jooq.ForeignKey;
+import org.jooq.Generator;
import org.jooq.Identity;
import org.jooq.Index;
import org.jooq.InverseForeignKey;
@@ -79,6 +80,7 @@ import org.jooq.Queries;
import org.jooq.Query;
import org.jooq.QueryPart;
import org.jooq.Record;
+import org.jooq.RecordQualifier;
// ...
// ...
import org.jooq.Result;
@@ -95,11 +97,16 @@ import org.jooq.TableField;
// ...
// ...
import org.jooq.UDT;
+import org.jooq.UDTField;
+import org.jooq.UDTPathField;
+import org.jooq.UDTPathTableField;
import org.jooq.UDTRecord;
import org.jooq.UniqueKey;
// ...
import org.jooq.exception.DataAccessException;
+import org.jooq.exception.DataTypeException;
import org.jooq.impl.QOM.CreateTable;
+import org.jooq.impl.QOM.GenerationLocation;
// ...
// ...
@@ -118,6 +125,222 @@ import org.reactivestreams.Subscription;
@org.jooq.Internal
public final class Internal {
+ public static final , T, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ Table table,
+ Class returnType
+ ) {
+ return createUDTPathTableField(name, type, table, null, returnType, null, null, null);
+ }
+
+ public static final , T, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ Table table,
+ String comment,
+ Class returnType
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, null, null, null);
+ }
+
+ public static final , T, U, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ Table table,
+ String comment,
+ Class returnType,
+ Converter converter
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, converter, null, null);
+ }
+
+ public static final , T, U, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ Table table,
+ String comment,
+ Class returnType,
+ Binding binding
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, null, binding, null);
+ }
+
+ public static final , T, X, U, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ Table table,
+ String comment,
+ Class returnType,
+ Converter converter,
+ Binding binding
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, converter, binding, null);
+ }
+
+ public static final , UR extends UDTRecord, T, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ TR table,
+ String comment,
+ Class returnType,
+ Generator generator
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, null, null, generator);
+ }
+
+ public static final , UR extends UDTRecord, T, U, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ TR table,
+ String comment,
+ Class returnType,
+ Converter converter,
+ Generator generator
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, converter, null, generator);
+ }
+
+ public static final , UR extends UDTRecord, T, U, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ TR table,
+ String comment,
+ Class returnType,
+ Binding binding,
+ Generator generator
+ ) {
+ return createUDTPathTableField(name, type, table, comment, returnType, null, binding, generator);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static final , UR extends UDTRecord, T, X, U, P extends UDTPathTableField> P createUDTPathTableField(
+ Name name,
+ DataType type,
+ TR table,
+ String comment,
+ Class returnType,
+ Converter converter,
+ Binding binding,
+ Generator generator
+ ) {
+ Binding actualBinding = DefaultBinding.newBinding(converter, type, binding);
+ DataType actualType =
+ converter == null && binding == null
+ ? (DataType) type
+ : type.asConvertedDataType(actualBinding);
+
+ if (generator != null)
+ actualType = actualType.generatedAlwaysAs(generator).generationLocation(GenerationLocation.CLIENT);
+
+ // [#5999] TODO: Allow for user-defined Names
+ try {
+ P tableField = newInstance(name, table, null, comment, returnType, actualBinding, actualType);
+
+ // [#1199] The public API of Table returns immutable field lists
+ if (table instanceof TableImpl> t)
+ t.fields.add(tableField);
+
+ return tableField;
+ }
+ catch (Exception e) {
+ throw new DataTypeException("Cannot instantiate " + returnType + ".", e);
+ }
+ }
+
+ public static final , T, P extends UDTField> P createUDTPathField(
+ Name name,
+ DataType type,
+ UDTPathField qualifier,
+ Class returnType
+ ) {
+ return createUDTPathField(name, type, qualifier, null, returnType, null, null);
+ }
+
+ public static final , T, P extends UDTField> P createUDTPathField(
+ Name name,
+ DataType type,
+ UDTPathField qualifier,
+ String comment,
+ Class returnType
+ ) {
+ return createUDTPathField(name, type, qualifier, comment, returnType, null, null);
+ }
+
+ public static final , T, U, P extends UDTField> P createUDTPathField(
+ Name name,
+ DataType type,
+ UDTPathField qualifier,
+ String comment,
+ Class returnType,
+ Converter converter
+ ) {
+ return createUDTPathField(name, type, qualifier, comment, returnType, converter, null);
+ }
+
+ public static final , T, U, P extends UDTField> P createUDTPathField(
+ Name name,
+ DataType type,
+ UDTPathField qualifier,
+ String comment,
+ Class returnType,
+ Binding binding
+ ) {
+ return createUDTPathField(name, type, qualifier, comment, returnType, null, binding);
+ }
+
+ public static final , T, X, U, P extends UDTField> P createUDTPathField(
+ Name name,
+ DataType type,
+ UDTPathField qualifier,
+ String comment,
+ Class returnType,
+ Converter converter,
+ Binding binding
+ ) {
+ Binding actualBinding = DefaultBinding.newBinding(converter, type, binding);
+ DataType actualType =
+ converter == null && binding == null
+ ? (DataType) type
+ : type.asConvertedDataType(actualBinding);
+
+ // [#5999] TODO: Allow for user-defined Names
+ try {
+
+ // [#228] While it would be cleaner to pass around a Function5 constructor reference,
+ // chances are that the cost on compilation speed is significantly higher than
+ // if we just use reflection
+ return newInstance(name, null, qualifier, comment, returnType, actualBinding, actualType);
+ }
+ catch (Exception e) {
+ throw new DataTypeException("Cannot instantiate " + returnType + ".", e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static , T, X, U, P extends UDTField> P newInstance(
+ Name name,
+ RecordQualifier qualifier,
+ UDTPathField path,
+ String comment,
+ Class returnType,
+ Binding actualBinding,
+ DataType actualType
+ ) throws Exception {
+
+ // [#228] This case only happens in generated UDTPath types, never in generated Table types
+ if (returnType == UDTField.class)
+ return (P) new UDTPathFieldImpl<>(name, actualType, path.asQualifier(), path.getUDT(), DSL.comment(comment), actualBinding);
+
+ // [#228] While it would be cleaner to pass around a Function5 constructor reference,
+ // chances are that the cost on compilation speed is significantly higher than
+ // if we just use reflection
+ else
+ return returnType
+ .getConstructor(Name.class, DataType.class, RecordQualifier.class, Comment.class, Binding.class)
+ .newInstance(name, actualType, qualifier == null ? path.asQualifier() : qualifier, DSL.comment(comment), actualBinding);
+ }
+
/**
* Factory method for embeddable types.
*/
diff --git a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java
index 0cc739177a..1882e2e89e 100644
--- a/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java
+++ b/jOOQ/src/main/java/org/jooq/impl/TableFieldImpl.java
@@ -78,7 +78,7 @@ import org.jooq.tools.StringUtils;
*/
final class TableFieldImpl
extends
- AbstractField
+ AbstractField
implements
TableField,
SimpleQueryPart,
@@ -201,11 +201,15 @@ implements
}
private final void accept1(Context> ctx) {
- ctx.data(DATA_OMIT_CLAUSE_EVENT_EMISSION, true, c -> {
- if (c.qualify() && getTable() != null && !FALSE.equals(ctx.data(DATA_RENDER_TABLE)))
- c.visit(getTable()).sql('.');
+ accept2(ctx, getTable(), getUnqualifiedName());
+ }
- c.visit(getUnqualifiedName());
+ static final void accept2(Context> ctx, Table> table, Name unqualifiedName) {
+ ctx.data(DATA_OMIT_CLAUSE_EVENT_EMISSION, true, c -> {
+ if (c.qualify() && table != null && !FALSE.equals(ctx.data(DATA_RENDER_TABLE)))
+ c.visit(table).sql('.');
+
+ c.visit(unqualifiedName);
});
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java
index dc1b9a9535..fae50b5c32 100644
--- a/jOOQ/src/main/java/org/jooq/impl/Tools.java
+++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java
@@ -658,8 +658,14 @@ final class Tools {
DATA_PARSE_ON_CONFLICT,
/**
- * [#13808] We're in a store assignment context (e.g.
- * UPDATE or assignment statement).
+ * [#228] [#13808] We're in a store assignment context.
+ *
+ * This includes e.g.
+ *
+ * INSERT columns list.
+ * UPDATE … SET clause.
+ * - The procedural assignment statement.
+ *
*/
DATA_STORE_ASSIGNMENT,
@@ -668,7 +674,6 @@ final class Tools {
* not the query itself.
*/
DATA_RENDER_IMPLICIT_JOIN,
-
;
private final boolean resetInSubqueryScope;
diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTPathFieldImpl.java b/jOOQ/src/main/java/org/jooq/impl/UDTPathFieldImpl.java
new file mode 100644
index 0000000000..add35ffbb0
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/impl/UDTPathFieldImpl.java
@@ -0,0 +1,248 @@
+/*
+ * 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 static java.lang.Boolean.TRUE;
+import static org.jooq.impl.SchemaImpl.DEFAULT_SCHEMA;
+import static org.jooq.impl.Tools.BooleanDataKey.DATA_STORE_ASSIGNMENT;
+import static org.jooq.tools.StringUtils.defaultIfNull;
+
+import java.util.stream.Stream;
+
+import org.jooq.Binding;
+import org.jooq.Catalog;
+import org.jooq.Clause;
+import org.jooq.Comment;
+import org.jooq.Context;
+import org.jooq.DataType;
+import org.jooq.Field;
+import org.jooq.Name;
+import org.jooq.Package;
+import org.jooq.QueryPart;
+import org.jooq.Record;
+import org.jooq.RecordQualifier;
+// ...
+import org.jooq.Row;
+import org.jooq.Schema;
+import org.jooq.Table;
+// ...
+import org.jooq.UDT;
+import org.jooq.UDTPathField;
+import org.jooq.UDTRecord;
+import org.jooq.impl.QOM.UEmpty;
+import org.jooq.impl.QOM.UNotYetImplemented;
+import org.jooq.impl.Tools.BooleanDataKey;
+import org.jooq.tools.StringUtils;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.ApiStatus.Internal;
+
+/**
+ * A common base type for UDT path fields.
+ *
+ * @author Lukas Eder
+ */
+@Internal
+public /* non-final */ class UDTPathFieldImpl, T>
+extends
+ AbstractField
+implements
+ UDTPathField,
+ SimpleQueryPart,
+ TypedReference,
+ ScopeMappable,
+ UEmpty
+{
+
+ private final RecordQualifier qualifier;
+ private final UDT udt;
+
+ UDTPathFieldImpl(Name name, DataType type, RecordQualifier qualifier, UDT udt, Comment comment, Binding, T> binding) {
+ super(qualify(qualifier, name), type, comment, binding);
+
+ this.qualifier = qualifier;
+ this.udt = udt;
+
+ qualifier.$name();
+ }
+
+ @Override
+ public final RecordQualifier getQualifier() {
+ return qualifier;
+ }
+
+ @Override
+ public final RecordQualifier asQualifier() {
+ return new UDTPathFieldImplAsQualifier();
+ }
+
+ // [#228] TODO Refactor this logic into UDTImpl
+ private class UDTPathFieldImplAsQualifier
+ extends AbstractNamed
+ implements
+ RecordQualifier,
+ FieldsTrait,
+ UNotYetImplemented
+ {
+ UDTPathFieldImplAsQualifier() {
+ super(UDTPathFieldImpl.this.getQualifiedName(), UDTPathFieldImpl.this.getCommentPart());
+ }
+
+ RecordQualifier getQualifier() {
+ return UDTPathFieldImpl.this.getQualifier();
+ }
+
+ @Override
+ public final Catalog getCatalog() {
+ return null;
+ }
+
+ @Override
+ public final Schema getSchema() {
+ return null;
+ }
+
+ @Override
+ public final Schema $schema() {
+ return null;
+ }
+
+ @Override
+ public final Row fieldsRow() {
+ return getUDT().fieldsRow();
+ }
+
+ @Override
+ public final Package getPackage() {
+ return getUDT().getPackage();
+ }
+
+ @Override
+ public final Class extends U> getRecordType() {
+ return getUDT().getRecordType();
+ }
+
+ @Override
+ public final DataType getDataType() {
+ return getUDT().getDataType();
+ }
+
+ @Override
+ public final U newRecord() {
+ return getUDT().newRecord();
+ }
+
+ @Override
+ public final void accept(Context> ctx) {
+ UDTPathFieldImpl.this.accept(ctx);
+ }
+ }
+
+ @Override
+ public final UDT getUDT() {
+ return udt;
+ }
+
+ // ------------------------------------------------------------------------
+ // XXX: QueryPart API
+ // ------------------------------------------------------------------------
+
+ @Override
+ final boolean parenthesised(Context> ctx) {
+ return true;
+ }
+
+ @Override
+ public boolean declaresFields() {
+ return super.declaresFields();
+ }
+
+ @Override
+ public final Clause[] clauses(Context> ctx) {
+ return null;
+ }
+
+ @Override
+ public final void accept(Context> ctx) {
+ RecordQualifier q = getQualifier();
+
+ // [#228] The disambiguating wrapping in parentheses is only required in references to
+ // a UDT path identifier expression, not in assignments (where it is disallowed)
+ if (!TRUE.equals(ctx.data(DATA_STORE_ASSIGNMENT)) && q instanceof UDTPathFieldImpl.UDTPathFieldImplAsQualifier && ((UDTPathFieldImpl, ?, ?>.UDTPathFieldImplAsQualifier) q).getQualifier() instanceof Table)
+ ctx.sql('(').visit(q).sql(").").visit(getUnqualifiedName());
+ else if (q instanceof Table> t)
+ TableFieldImpl.accept2(ctx, t, getUnqualifiedName());
+ else
+ ctx.visit(q).sql('.').visit(getUnqualifiedName());
+ }
+
+ // -------------------------------------------------------------------------
+ // XXX: Query Object Model
+ // -------------------------------------------------------------------------
+
+ // ------------------------------------------------------------------------
+ // XXX: Object API
+ // ------------------------------------------------------------------------
+
+ @Override
+ public int hashCode() {
+ return defaultIfNull(getQualifier().getSchema(), DEFAULT_SCHEMA.get()).getQualifiedName()
+ .append(getQualifier().getUnqualifiedName())
+ .append(getUDT().getUnqualifiedName())
+ .append(getUnqualifiedName()).hashCode();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (this == that)
+ return true;
+
+ // [#2144] UDTPathFieldImpl equality can be decided without executing the
+ // rather expensive implementation of AbstractQueryPart.equals()
+ if (that instanceof UDTPathField, ?, ?> other) {
+ return
+ StringUtils.equals(getQualifier(), other.getQualifier()) &&
+ StringUtils.equals(getUDT(), other.getUDT()) &&
+ StringUtils.equals(getName(), other.getName());
+ }
+
+ return super.equals(that);
+ }
+}
diff --git a/jOOQ/src/main/java/org/jooq/impl/UDTPathTableFieldImpl.java b/jOOQ/src/main/java/org/jooq/impl/UDTPathTableFieldImpl.java
new file mode 100644
index 0000000000..827c1c2dcb
--- /dev/null
+++ b/jOOQ/src/main/java/org/jooq/impl/UDTPathTableFieldImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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.Binding;
+import org.jooq.Comment;
+import org.jooq.DataType;
+import org.jooq.Name;
+import org.jooq.Record;
+import org.jooq.RecordQualifier;
+import org.jooq.Table;
+import org.jooq.UDT;
+import org.jooq.UDTPathField;
+import org.jooq.UDTPathTableField;
+import org.jooq.UDTRecord;
+
+import org.jetbrains.annotations.ApiStatus.Internal;
+
+/**
+ * A common base type for table fields that are also {@link UDTPathField}.
+ *
+ * @author Lukas Eder
+ */
+@Internal
+public /* non-final */ class UDTPathTableFieldImpl, T>
+extends
+ UDTPathFieldImpl
+implements
+ UDTPathTableField
+{
+
+ public UDTPathTableFieldImpl(Name name, DataType type, RecordQualifier qualifier, UDT udt, Comment comment, Binding, T> binding) {
+ super(name, type, qualifier, udt, comment, binding);
+ }
+
+ @Override
+ public final Table getTable() {
+ return getQualifier() instanceof Table t ? t : null;
+ }
+}
diff --git a/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java b/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java
index e11ab16a4e..c63b168f4f 100644
--- a/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java
+++ b/jOOQ/src/main/java/org/jooq/tools/reflect/Reflect.java
@@ -118,7 +118,7 @@ public class Reflect {
*
* Supplier<String> supplier = Reflect.compile("org.joor.Test", """
* package org.joor;
- * @MyAnnotation
+ * @MyAnnotation
* class Test implements java.util.function.Supplier<String> {
* public String get() {
* return "Hello World!";
@@ -146,7 +146,7 @@ public class Reflect {
*
* Supplier<String> supplier = Reflect.compile("org.joor.Test", """
* package org.joor;
- * @MyAnnotation
+ * @MyAnnotation
* class Test implements java.util.function.Supplier<String> {
* public String get() {
* return "Hello World!";