[jOOQ/jOOQ#10763] Official jOOQ-postgres-extensions bindings should register themselves as low priority bindings if found on the code generation classpath

This commit is contained in:
Lukas Eder 2022-02-28 15:32:40 +01:00
parent f264904485
commit c2a5d8addc
6 changed files with 219 additions and 70 deletions

View File

@ -72,6 +72,7 @@ import org.jooq.DSLContext;
import org.jooq.Log.Level;
import org.jooq.impl.DSL;
import org.jooq.meta.CatalogVersionProvider;
import org.jooq.meta.ClassUtils;
import org.jooq.meta.Database;
import org.jooq.meta.Databases;
import org.jooq.meta.Definition;
@ -587,6 +588,7 @@ public class GenerationTool {
database.setConfiguredCustomTypes(d.getCustomTypes());
database.setConfiguredEnumTypes(d.getEnumTypes());
database.setConfiguredForcedTypes(d.getForcedTypes());
database.setForcedTypesForBuiltinDataTypeExtensions(d.isForcedTypesForBuiltinDataTypeExtensions());
database.setConfiguredEmbeddables(d.getEmbeddables());
database.setConfiguredComments(d.getComments());
database.setConfiguredSyntheticObjects(d.getSyntheticObjects());
@ -1072,7 +1074,7 @@ public class GenerationTool {
// [#2283] If no explicit class loader was provided try loading the class
// with "default" techniques
if (loader == null) {
return loadClass0(className);
return ClassUtils.loadClass(className);
}
// Prefer the explicit class loader if available
@ -1091,7 +1093,7 @@ public class GenerationTool {
alternativeLoop:
for (String pkg : new String[] { "org.jooq.meta", "org.jooq.meta.extensions", "org.jooq.codegen", "org.jooq.codegen.maven" }) {
try {
alternative = loadClass0(className.replace("org.jooq.util", pkg)).getName();
alternative = ClassUtils.loadClass(className.replace("org.jooq.util", pkg)).getName();
break alternativeLoop;
}
catch (ClassNotFoundException ignore) {}
@ -1137,15 +1139,6 @@ public class GenerationTool {
}
}
private Class<?> loadClass0(String className) throws ClassNotFoundException {
try {
return Class.forName(className);
}
catch (ClassNotFoundException e) {
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
}
private static String trim(String string) {
return (string == null ? null : string.trim());
}

View File

@ -158,77 +158,78 @@ public abstract class AbstractDatabase implements Database {
private Connection connection;
private boolean regexMatchesPartialQualification;
private boolean sqlMatchesPartialQualification;
private OnError onError = OnError.FAIL;
private OnError onError = OnError.FAIL;
private List<Filter> filters;
private String[] excludes;
private String[] includes = { ".*" };
private boolean includeExcludeColumns = false;
private boolean includeExcludePackageRoutines = false;
private boolean includeInvisibleColumns = true;
private boolean includeTables = true;
private boolean includeEmbeddables = true;
private boolean includeRoutines = true;
private boolean includeTriggerRoutines = false;
private boolean includePackages = true;
private boolean includePackageRoutines = true;
private boolean includePackageUDTs = true;
private boolean includePackageConstants = true;
private boolean includeUDTs = true;
private boolean includeDomains = true;
private boolean includeSequences = true;
private boolean includeIndexes = true;
private boolean includeCheckConstraints = true;
private boolean includeSystemTables = false;
private boolean includeSystemIndexes = false;
private boolean includeSystemCheckConstraints = false;
private boolean includeSystemSequences = false;
private boolean includeSystemUDTs = false;
private boolean includePrimaryKeys = true;
private boolean includeUniqueKeys = true;
private boolean includeForeignKeys = true;
private boolean forceIntegerTypesOnZeroScaleDecimals = true;
private String[] includes = { ".*" };
private boolean includeExcludeColumns = false;
private boolean includeExcludePackageRoutines = false;
private boolean includeInvisibleColumns = true;
private boolean includeTables = true;
private boolean includeEmbeddables = true;
private boolean includeRoutines = true;
private boolean includeTriggerRoutines = false;
private boolean includePackages = true;
private boolean includePackageRoutines = true;
private boolean includePackageUDTs = true;
private boolean includePackageConstants = true;
private boolean includeUDTs = true;
private boolean includeDomains = true;
private boolean includeSequences = true;
private boolean includeIndexes = true;
private boolean includeCheckConstraints = true;
private boolean includeSystemTables = false;
private boolean includeSystemIndexes = false;
private boolean includeSystemCheckConstraints = false;
private boolean includeSystemSequences = false;
private boolean includeSystemUDTs = false;
private boolean includePrimaryKeys = true;
private boolean includeUniqueKeys = true;
private boolean includeForeignKeys = true;
private boolean forceIntegerTypesOnZeroScaleDecimals = true;
private String[] recordVersionFields;
private String[] recordTimestampFields;
private String embeddablePrimaryKeys = null;
private String embeddableUniqueKeys = null;
private String embeddableDomains = null;
private boolean readonlyIdentities = false;
private boolean readonlyComputedColumns = true;
private boolean readonlyNonUpdatableColumns = true;
private String embeddablePrimaryKeys = null;
private String embeddableUniqueKeys = null;
private String embeddableDomains = null;
private boolean readonlyIdentities = false;
private boolean readonlyComputedColumns = true;
private boolean readonlyNonUpdatableColumns = true;
private boolean supportsUnsignedTypes;
private boolean integerDisplayWidths;
private boolean ignoreProcedureReturnValues;
private boolean dateAsTimestamp;
private boolean javaTimeTypes = true;
private List<CatalogMappingType> configuredCatalogs = new ArrayList<>();
private List<SchemaMappingType> configuredSchemata = new ArrayList<>();
private List<CustomType> configuredCustomTypes = new ArrayList<>();
private List<EnumType> configuredEnumTypes = new ArrayList<>();
private boolean javaTimeTypes = true;
private List<CatalogMappingType> configuredCatalogs = new ArrayList<>();
private List<SchemaMappingType> configuredSchemata = new ArrayList<>();
private List<CustomType> configuredCustomTypes = new ArrayList<>();
private List<EnumType> configuredEnumTypes = new ArrayList<>();
private boolean forcedTypesForBuiltinDataTypeExtensions = true;
private List<ForcedType> configuredForcedTypes;
private Set<ForcedType> unusedForcedTypes = new HashSet<>();
private List<EmbeddableDefinitionType> configuredEmbeddables = new ArrayList<>();
private Set<EmbeddableDefinitionType> unusedEmbeddables = new HashSet<>();
private List<CommentType> configuredComments = new ArrayList<>();
private Set<CommentType> unusedComments = new HashSet<>();
private List<SyntheticReadonlyColumnType> configuredSyntheticReadonlyColumns = new ArrayList<>();
private Set<SyntheticReadonlyColumnType> unusedSyntheticReadonlyColumns = new HashSet<>();
private List<SyntheticReadonlyRowidType> configuredSyntheticReadonlyRowids = new ArrayList<>();
private Set<SyntheticReadonlyRowidType> unusedSyntheticReadonlyRowids = new HashSet<>();
private List<SyntheticIdentityType> configuredSyntheticIdentities = new ArrayList<>();
private Set<SyntheticIdentityType> unusedSyntheticIdentities = new HashSet<>();
private List<SyntheticPrimaryKeyType> configuredSyntheticPrimaryKeys = new ArrayList<>();
private Set<SyntheticPrimaryKeyType> unusedSyntheticPrimaryKeys = new HashSet<>();
private List<SyntheticUniqueKeyType> configuredSyntheticUniqueKeys = new ArrayList<>();
private Set<SyntheticUniqueKeyType> unusedSyntheticUniqueKeys = new HashSet<>();
private List<SyntheticForeignKeyType> configuredSyntheticForeignKeys = new ArrayList<>();
private Set<SyntheticForeignKeyType> unusedSyntheticForeignKeys = new HashSet<>();
private List<SyntheticViewType> configuredSyntheticViews = new ArrayList<>();
private Set<SyntheticViewType> unusedSyntheticViews = new HashSet<>();
private Set<ForcedType> unusedForcedTypes = new HashSet<>();
private List<EmbeddableDefinitionType> configuredEmbeddables = new ArrayList<>();
private Set<EmbeddableDefinitionType> unusedEmbeddables = new HashSet<>();
private List<CommentType> configuredComments = new ArrayList<>();
private Set<CommentType> unusedComments = new HashSet<>();
private List<SyntheticReadonlyColumnType> configuredSyntheticReadonlyColumns = new ArrayList<>();
private Set<SyntheticReadonlyColumnType> unusedSyntheticReadonlyColumns = new HashSet<>();
private List<SyntheticReadonlyRowidType> configuredSyntheticReadonlyRowids = new ArrayList<>();
private Set<SyntheticReadonlyRowidType> unusedSyntheticReadonlyRowids = new HashSet<>();
private List<SyntheticIdentityType> configuredSyntheticIdentities = new ArrayList<>();
private Set<SyntheticIdentityType> unusedSyntheticIdentities = new HashSet<>();
private List<SyntheticPrimaryKeyType> configuredSyntheticPrimaryKeys = new ArrayList<>();
private Set<SyntheticPrimaryKeyType> unusedSyntheticPrimaryKeys = new HashSet<>();
private List<SyntheticUniqueKeyType> configuredSyntheticUniqueKeys = new ArrayList<>();
private Set<SyntheticUniqueKeyType> unusedSyntheticUniqueKeys = new HashSet<>();
private List<SyntheticForeignKeyType> configuredSyntheticForeignKeys = new ArrayList<>();
private Set<SyntheticForeignKeyType> unusedSyntheticForeignKeys = new HashSet<>();
private List<SyntheticViewType> configuredSyntheticViews = new ArrayList<>();
private Set<SyntheticViewType> unusedSyntheticViews = new HashSet<>();
private SchemaVersionProvider schemaVersionProvider;
private CatalogVersionProvider catalogVersionProvider;
private Comparator<Definition> orderProvider;
private boolean includeRelations = true;
private boolean tableValuedFunctions = true;
private boolean includeRelations = true;
private boolean tableValuedFunctions = true;
private int logSlowQueriesAfterSeconds;
private int logSlowResultsAfterSeconds;
@ -1477,6 +1478,45 @@ public abstract class AbstractDatabase implements Database {
return configuredForcedTypes;
}
@Override
public boolean getForcedTypesForBuiltinDataTypeExtensions() {
return this.forcedTypesForBuiltinDataTypeExtensions;
}
@Override
public void setForcedTypesForBuiltinDataTypeExtensions(boolean forcedTypesForBuiltinDataTypeExtensions) {
this.forcedTypesForBuiltinDataTypeExtensions = forcedTypesForBuiltinDataTypeExtensions;
if (forcedTypesForBuiltinDataTypeExtensions) {
try {
ClassUtils.loadClass("org.jooq.postgres.extensions.types.Hstore");
// [#13161] TODO: Add also array type bindings here
getConfiguredForcedTypes().add(new ForcedType()
.withUserType("org.jooq.postgres.extensions.types.Hstore")
.withBinding("org.jooq.postgres.extensions.bindings.HstoreBinding")
.withIncludeTypes("hstore")
.withPriority(Integer.MAX_VALUE)
);
getConfiguredForcedTypes().add(new ForcedType()
.withUserType("org.jooq.postgres.extensions.types.Inet")
.withBinding("org.jooq.postgres.extensions.bindings.InetBinding")
.withIncludeTypes("inet")
.withPriority(Integer.MAX_VALUE)
);
getConfiguredForcedTypes().add(new ForcedType()
.withUserType("org.jooq.postgres.extensions.types.Cidr")
.withBinding("org.jooq.postgres.extensions.bindings.CidrBinding")
.withIncludeTypes("cidr")
.withPriority(Integer.MAX_VALUE)
);
}
catch (ClassNotFoundException ignore) {
log.debug("Built in data types", "org.jooq.postgres.extensions.types.Hstore not found on classpath, ignoring built in data type extensions");
}
}
}
@Override
public final int getLogSlowQueriesAfterSeconds() {
return logSlowQueriesAfterSeconds;

View File

@ -0,0 +1,58 @@
/*
* 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
*
* http://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: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.meta;
import org.jetbrains.annotations.ApiStatus.Internal;
/**
* Utilities related to {@link Class} and {@link ClassLoader} actions.
*
* @author Lukas Eder
*/
@Internal
public class ClassUtils {
public static Class<?> loadClass(String className) throws ClassNotFoundException {
try {
return Class.forName(className);
}
catch (ClassNotFoundException e) {
return Thread.currentThread().getContextClassLoader().loadClass(className);
}
}
}

View File

@ -929,6 +929,18 @@ public interface Database extends AutoCloseable {
*/
void setConfiguredForcedTypes(List<ForcedType> types);
/**
* Whether some additional forced types for built in data type extensions,
* such as the ones from <code>jooq-codegen-postgres</code> should be added.
*/
boolean getForcedTypesForBuiltinDataTypeExtensions();
/**
* Whether some additional forced types for built in data type extensions,
* such as the ones from <code>jooq-codegen-postgres</code> should be added.
*/
void setForcedTypesForBuiltinDataTypeExtensions(boolean forcedTypesForBuiltinDataTypeExtensions);
/**
* Log slow queries after this amount of seconds.
*/

View File

@ -157,6 +157,8 @@ public class Database implements Serializable, XMLAppendable
@XmlElement(defaultValue = "true")
protected Boolean readonlyNonUpdatableColumns = true;
@XmlElement(defaultValue = "true")
protected Boolean forcedTypesForBuiltinDataTypeExtensions = true;
@XmlElement(defaultValue = "true")
protected Boolean forceIntegerTypesOnZeroScaleDecimals = true;
protected Boolean tableValuedFunctions;
@XmlElement(defaultValue = "5")
@ -1657,6 +1659,30 @@ public class Database implements Serializable, XMLAppendable
this.readonlyNonUpdatableColumns = value;
}
/**
* Enable some default forced type configurations for built in data type extensions, such as the ones from the jooq-postgres-extensions module.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean isForcedTypesForBuiltinDataTypeExtensions() {
return forcedTypesForBuiltinDataTypeExtensions;
}
/**
* Sets the value of the forcedTypesForBuiltinDataTypeExtensions property.
*
* @param value
* allowed object is
* {@link Boolean }
*
*/
public void setForcedTypesForBuiltinDataTypeExtensions(Boolean value) {
this.forcedTypesForBuiltinDataTypeExtensions = value;
}
/**
* Historically, zero-scale decimal types are generated as their most appropriate, corresponding integer type (e.g. NUMBER(2, 0) and less: Byte). This allows for turning off this feature. In case of conflict between this rule and actual {@link #getForcedTypes()}, the latter will win.
*
@ -2385,6 +2411,11 @@ public class Database implements Serializable, XMLAppendable
return this;
}
public Database withForcedTypesForBuiltinDataTypeExtensions(Boolean value) {
setForcedTypesForBuiltinDataTypeExtensions(value);
return this;
}
public Database withForceIntegerTypesOnZeroScaleDecimals(Boolean value) {
setForceIntegerTypesOnZeroScaleDecimals(value);
return this;
@ -2644,6 +2675,7 @@ public class Database implements Serializable, XMLAppendable
builder.append("readonlyIdentities", readonlyIdentities);
builder.append("readonlyComputedColumns", readonlyComputedColumns);
builder.append("readonlyNonUpdatableColumns", readonlyNonUpdatableColumns);
builder.append("forcedTypesForBuiltinDataTypeExtensions", forcedTypesForBuiltinDataTypeExtensions);
builder.append("forceIntegerTypesOnZeroScaleDecimals", forceIntegerTypesOnZeroScaleDecimals);
builder.append("tableValuedFunctions", tableValuedFunctions);
builder.append("logSlowQueriesAfterSeconds", logSlowQueriesAfterSeconds);
@ -3172,6 +3204,15 @@ public class Database implements Serializable, XMLAppendable
return false;
}
}
if (forcedTypesForBuiltinDataTypeExtensions == null) {
if (other.forcedTypesForBuiltinDataTypeExtensions!= null) {
return false;
}
} else {
if (!forcedTypesForBuiltinDataTypeExtensions.equals(other.forcedTypesForBuiltinDataTypeExtensions)) {
return false;
}
}
if (forceIntegerTypesOnZeroScaleDecimals == null) {
if (other.forceIntegerTypesOnZeroScaleDecimals!= null) {
return false;
@ -3342,6 +3383,7 @@ public class Database implements Serializable, XMLAppendable
result = ((prime*result)+((readonlyIdentities == null)? 0 :readonlyIdentities.hashCode()));
result = ((prime*result)+((readonlyComputedColumns == null)? 0 :readonlyComputedColumns.hashCode()));
result = ((prime*result)+((readonlyNonUpdatableColumns == null)? 0 :readonlyNonUpdatableColumns.hashCode()));
result = ((prime*result)+((forcedTypesForBuiltinDataTypeExtensions == null)? 0 :forcedTypesForBuiltinDataTypeExtensions.hashCode()));
result = ((prime*result)+((forceIntegerTypesOnZeroScaleDecimals == null)? 0 :forceIntegerTypesOnZeroScaleDecimals.hashCode()));
result = ((prime*result)+((tableValuedFunctions == null)? 0 :tableValuedFunctions.hashCode()));
result = ((prime*result)+((logSlowQueriesAfterSeconds == null)? 0 :logSlowQueriesAfterSeconds.hashCode()));

View File

@ -947,6 +947,10 @@ This feature is available in the commercial distribution only.]]></jxb:javadoc><
<element name="forcedTypes" type="tns:ForcedTypes" minOccurs="0" maxOccurs="1">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Configure type overrides for generated fields, attributes, sequences, parameters.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="forcedTypesForBuiltinDataTypeExtensions" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Enable some default forced type configurations for built in data type extensions, such as the ones from the jooq-postgres-extensions module.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="forceIntegerTypesOnZeroScaleDecimals" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Historically, zero-scale decimal types are generated as their most appropriate, corresponding integer type (e.g. NUMBER(2, 0) and less: Byte). This allows for turning off this feature. In case of conflict between this rule and actual {@link #getForcedTypes()}, the latter will win.]]></jxb:javadoc></jxb:property></appinfo></annotation>