diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java index c09b4d8ebd..1915ba804d 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java @@ -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()); } diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java index 90c8d06490..90bd94697e 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -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 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 configuredCatalogs = new ArrayList<>(); - private List configuredSchemata = new ArrayList<>(); - private List configuredCustomTypes = new ArrayList<>(); - private List configuredEnumTypes = new ArrayList<>(); + private boolean javaTimeTypes = true; + private List configuredCatalogs = new ArrayList<>(); + private List configuredSchemata = new ArrayList<>(); + private List configuredCustomTypes = new ArrayList<>(); + private List configuredEnumTypes = new ArrayList<>(); + private boolean forcedTypesForBuiltinDataTypeExtensions = true; private List configuredForcedTypes; - private Set unusedForcedTypes = new HashSet<>(); - private List configuredEmbeddables = new ArrayList<>(); - private Set unusedEmbeddables = new HashSet<>(); - private List configuredComments = new ArrayList<>(); - private Set unusedComments = new HashSet<>(); - private List configuredSyntheticReadonlyColumns = new ArrayList<>(); - private Set unusedSyntheticReadonlyColumns = new HashSet<>(); - private List configuredSyntheticReadonlyRowids = new ArrayList<>(); - private Set unusedSyntheticReadonlyRowids = new HashSet<>(); - private List configuredSyntheticIdentities = new ArrayList<>(); - private Set unusedSyntheticIdentities = new HashSet<>(); - private List configuredSyntheticPrimaryKeys = new ArrayList<>(); - private Set unusedSyntheticPrimaryKeys = new HashSet<>(); - private List configuredSyntheticUniqueKeys = new ArrayList<>(); - private Set unusedSyntheticUniqueKeys = new HashSet<>(); - private List configuredSyntheticForeignKeys = new ArrayList<>(); - private Set unusedSyntheticForeignKeys = new HashSet<>(); - private List configuredSyntheticViews = new ArrayList<>(); - private Set unusedSyntheticViews = new HashSet<>(); + private Set unusedForcedTypes = new HashSet<>(); + private List configuredEmbeddables = new ArrayList<>(); + private Set unusedEmbeddables = new HashSet<>(); + private List configuredComments = new ArrayList<>(); + private Set unusedComments = new HashSet<>(); + private List configuredSyntheticReadonlyColumns = new ArrayList<>(); + private Set unusedSyntheticReadonlyColumns = new HashSet<>(); + private List configuredSyntheticReadonlyRowids = new ArrayList<>(); + private Set unusedSyntheticReadonlyRowids = new HashSet<>(); + private List configuredSyntheticIdentities = new ArrayList<>(); + private Set unusedSyntheticIdentities = new HashSet<>(); + private List configuredSyntheticPrimaryKeys = new ArrayList<>(); + private Set unusedSyntheticPrimaryKeys = new HashSet<>(); + private List configuredSyntheticUniqueKeys = new ArrayList<>(); + private Set unusedSyntheticUniqueKeys = new HashSet<>(); + private List configuredSyntheticForeignKeys = new ArrayList<>(); + private Set unusedSyntheticForeignKeys = new HashSet<>(); + private List configuredSyntheticViews = new ArrayList<>(); + private Set unusedSyntheticViews = new HashSet<>(); private SchemaVersionProvider schemaVersionProvider; private CatalogVersionProvider catalogVersionProvider; private Comparator 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; diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/ClassUtils.java b/jOOQ-meta/src/main/java/org/jooq/meta/ClassUtils.java new file mode 100644 index 0000000000..3d3329e88e --- /dev/null +++ b/jOOQ-meta/src/main/java/org/jooq/meta/ClassUtils.java @@ -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); + } + } +} diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java index 17d30c4b08..d714722b45 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java @@ -929,6 +929,18 @@ public interface Database extends AutoCloseable { */ void setConfiguredForcedTypes(List types); + /** + * Whether some additional forced types for built in data type extensions, + * such as the ones from jooq-codegen-postgres should be added. + */ + boolean getForcedTypesForBuiltinDataTypeExtensions(); + + /** + * Whether some additional forced types for built in data type extensions, + * such as the ones from jooq-codegen-postgres should be added. + */ + void setForcedTypesForBuiltinDataTypeExtensions(boolean forcedTypesForBuiltinDataTypeExtensions); + /** * Log slow queries after this amount of seconds. */ diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java index e113958978..0ee50b59a5 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java @@ -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())); diff --git a/jOOQ-meta/src/main/resources/org/jooq/meta/xsd/jooq-codegen-3.17.0.xsd b/jOOQ-meta/src/main/resources/org/jooq/meta/xsd/jooq-codegen-3.17.0.xsd index 1b97236c5d..5bb7b8eb04 100644 --- a/jOOQ-meta/src/main/resources/org/jooq/meta/xsd/jooq-codegen-3.17.0.xsd +++ b/jOOQ-meta/src/main/resources/org/jooq/meta/xsd/jooq-codegen-3.17.0.xsd @@ -947,6 +947,10 @@ This feature is available in the commercial distribution only.]]>< + + + +