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 1915ba804d..e45438cba5 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java @@ -555,6 +555,20 @@ public class GenerationTool { database.setConfiguredSchemata(schemata); database.setIncludes(new String[] { defaultString(d.getIncludes()) }); database.setExcludes(new String[] { defaultString(d.getExcludes()) }); + + // [#10763] Currently, the javaTimeTypes flag needs to be set before + // the forcedTypesForBuiltinDataTypeExtensions flag. + if (d.isDateAsTimestamp() != null) + database.setDateAsTimestamp(d.isDateAsTimestamp()); + if (g.getGenerate().isJavaTimeTypes() != null) + database.setJavaTimeTypes(g.getGenerate().isJavaTimeTypes()); + if (d.isUnsignedTypes() != null) + database.setSupportsUnsignedTypes(d.isUnsignedTypes()); + if (d.isIntegerDisplayWidths() != null) + database.setIntegerDisplayWidths(d.isIntegerDisplayWidths()); + if (d.isIgnoreProcedureReturnValues() != null) + database.setIgnoreProcedureReturnValues(d.isIgnoreProcedureReturnValues()); + database.setIncludeExcludeColumns(TRUE.equals(d.isIncludeExcludeColumns())); database.setIncludeExcludePackageRoutines(TRUE.equals(d.isIncludeExcludePackageRoutines())); database.setIncludeForeignKeys(!FALSE.equals(d.isIncludeForeignKeys())); @@ -667,18 +681,6 @@ public class GenerationTool { log.warn("DEPRECATED", "The configuration property /configuration/generator/database/enumTypes is experimental and deprecated and will be removed in the future."); if (Boolean.TRUE.equals(d.isDateAsTimestamp())) log.warn("DEPRECATED", "The configuration property /configuration/generator/database/dateAsTimestamp is deprecated as it is superseded by custom bindings and converters. It will thus be removed in the future."); - - if (d.isDateAsTimestamp() != null) - database.setDateAsTimestamp(d.isDateAsTimestamp()); - if (g.getGenerate().isJavaTimeTypes() != null) - database.setJavaTimeTypes(g.getGenerate().isJavaTimeTypes()); - if (d.isUnsignedTypes() != null) - database.setSupportsUnsignedTypes(d.isUnsignedTypes()); - if (d.isIntegerDisplayWidths() != null) - database.setIntegerDisplayWidths(d.isIntegerDisplayWidths()); - if (d.isIgnoreProcedureReturnValues() != null) - database.setIgnoreProcedureReturnValues(d.isIgnoreProcedureReturnValues()); - if (Boolean.TRUE.equals(d.isIgnoreProcedureReturnValues())) log.warn("DEPRECATED", "The flag is deprecated and used for backwards-compatibility only. It will be removed in the future."); 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 9f677a9007..f8bc1d2756 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -205,6 +205,7 @@ public abstract class AbstractDatabase implements Database { private List configuredCustomTypes = new ArrayList<>(); private List configuredEnumTypes = new ArrayList<>(); private boolean forcedTypesForBuiltinDataTypeExtensions = true; + private boolean builtInForcedTypesInitialised = false; private List configuredForcedTypes; private Set unusedForcedTypes = new HashSet<>(); private List configuredEmbeddables = new ArrayList<>(); @@ -1486,80 +1487,6 @@ public abstract class AbstractDatabase implements Database { @Override public void setForcedTypesForBuiltinDataTypeExtensions(boolean forcedTypesForBuiltinDataTypeExtensions) { this.forcedTypesForBuiltinDataTypeExtensions = forcedTypesForBuiltinDataTypeExtensions; - - if (forcedTypesForBuiltinDataTypeExtensions) { - try { - ClassUtils.loadClass("org.jooq.postgres.extensions.types.Hstore"); - - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.Hstore") - .withBinding("org.jooq.postgres.extensions.bindings.HstoreBinding") - .withIncludeTypes("hstore") - .withPriority(Integer.MIN_VALUE) - ); - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.Hstore[]") - .withBinding("org.jooq.postgres.extensions.bindings.HstoreArrayBinding") - .withIncludeTypes("_hstore") - .withPriority(Integer.MIN_VALUE) - ); - - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.Inet") - .withBinding("org.jooq.postgres.extensions.bindings.InetBinding") - .withIncludeTypes("inet") - .withPriority(Integer.MIN_VALUE) - ); - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.Inet[]") - .withBinding("org.jooq.postgres.extensions.bindings.InetArrayBinding") - .withIncludeTypes("_inet") - .withPriority(Integer.MIN_VALUE) - ); - - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.Cidr") - .withBinding("org.jooq.postgres.extensions.bindings.CidrBinding") - .withIncludeTypes("cidr") - .withPriority(Integer.MIN_VALUE) - ); - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.Cidr[]") - .withBinding("org.jooq.postgres.extensions.bindings.CidrArrayBinding") - .withIncludeTypes("_cidr") - .withPriority(Integer.MIN_VALUE) - ); - - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.IntegerRange") - .withBinding("org.jooq.postgres.extensions.bindings.IntegerRangeBinding") - .withIncludeTypes("int4range") - .withPriority(Integer.MIN_VALUE) - ); - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.IntegerRange[]") - .withBinding("org.jooq.postgres.extensions.bindings.IntegerRangeArrayBinding") - .withIncludeTypes("_int4range") - .withPriority(Integer.MIN_VALUE) - ); - - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.LongRange") - .withBinding("org.jooq.postgres.extensions.bindings.LongRangeBinding") - .withIncludeTypes("int8range") - .withPriority(Integer.MIN_VALUE) - ); - getConfiguredForcedTypes().add(new ForcedType() - .withUserType("org.jooq.postgres.extensions.types.LongRange[]") - .withBinding("org.jooq.postgres.extensions.bindings.LongRangeArrayBinding") - .withIncludeTypes("_int8range") - .withPriority(Integer.MIN_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 @@ -1956,6 +1883,7 @@ public abstract class AbstractDatabase implements Database { @Override public final ForcedType getConfiguredForcedType(Definition definition, DataTypeDefinition definedType) { + initBuiltinForcedTypes(); // [#5885] Only the first matching is applied to the data type definition. forcedTypeLoop: @@ -2001,6 +1929,113 @@ public abstract class AbstractDatabase implements Database { return null; } + private void initBuiltinForcedTypes() { + if (forcedTypesForBuiltinDataTypeExtensions && !builtInForcedTypesInitialised) { + builtInForcedTypesInitialised = true; + + try { + ClassUtils.loadClass("org.jooq.postgres.extensions.types.Hstore"); + + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.Hstore") + .withBinding("org.jooq.postgres.extensions.bindings.HstoreBinding") + .withIncludeTypes("hstore") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.Hstore[]") + .withBinding("org.jooq.postgres.extensions.bindings.HstoreArrayBinding") + .withIncludeTypes("_hstore") + .withPriority(Integer.MIN_VALUE) + ); + + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.Inet") + .withBinding("org.jooq.postgres.extensions.bindings.InetBinding") + .withIncludeTypes("inet") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.Inet[]") + .withBinding("org.jooq.postgres.extensions.bindings.InetArrayBinding") + .withIncludeTypes("_inet") + .withPriority(Integer.MIN_VALUE) + ); + + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.Cidr") + .withBinding("org.jooq.postgres.extensions.bindings.CidrBinding") + .withIncludeTypes("cidr") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.Cidr[]") + .withBinding("org.jooq.postgres.extensions.bindings.CidrArrayBinding") + .withIncludeTypes("_cidr") + .withPriority(Integer.MIN_VALUE) + ); + + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.IntegerRange") + .withBinding("org.jooq.postgres.extensions.bindings.IntegerRangeBinding") + .withIncludeTypes("int4range") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.IntegerRange[]") + .withBinding("org.jooq.postgres.extensions.bindings.IntegerRangeArrayBinding") + .withIncludeTypes("_int4range") + .withPriority(Integer.MIN_VALUE) + ); + + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.LongRange") + .withBinding("org.jooq.postgres.extensions.bindings.LongRangeBinding") + .withIncludeTypes("int8range") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.LongRange[]") + .withBinding("org.jooq.postgres.extensions.bindings.LongRangeArrayBinding") + .withIncludeTypes("_int8range") + .withPriority(Integer.MIN_VALUE) + ); + + if (javaTimeTypes()) { + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.LocalDateRange") + .withBinding("org.jooq.postgres.extensions.bindings.LocalDateRangeBinding") + .withIncludeTypes("daterange") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.LocalDateRange[]") + .withBinding("org.jooq.postgres.extensions.bindings.LocalDateRangeArrayBinding") + .withIncludeTypes("_daterange") + .withPriority(Integer.MIN_VALUE) + ); + } + else { + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.DateRange") + .withBinding("org.jooq.postgres.extensions.bindings.DateRangeBinding") + .withIncludeTypes("daterange") + .withPriority(Integer.MIN_VALUE) + ); + getConfiguredForcedTypes().add(new ForcedType() + .withUserType("org.jooq.postgres.extensions.types.DateRange[]") + .withBinding("org.jooq.postgres.extensions.bindings.DateRangeArrayBinding") + .withIncludeTypes("_daterange") + .withPriority(Integer.MIN_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"); + } + } + } + private boolean typeMatchesExcludeInclude(DataTypeDefinition type, String exclude, String include) { if (exclude != null && matches(type, patterns.pattern(exclude))) return false; diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/DateRangeArrayBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/DateRangeArrayBinding.java new file mode 100644 index 0000000000..ef105c9a75 --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/DateRangeArrayBinding.java @@ -0,0 +1,62 @@ +/* + * 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.postgres.extensions.bindings; + +import org.jooq.Converter; +import org.jooq.postgres.extensions.converters.DateRangeConverter; +import org.jooq.postgres.extensions.types.DateRange; + +/** + * A binding for the PostgreSQL daterange[] data type. + * + * @author Lukas Eder + */ +public class DateRangeArrayBinding extends AbstractPostgresArrayBinding { + + private static final Converter CONVERTER = new DateRangeConverter().forArrays(); + + @Override + public Converter converter() { + return CONVERTER; + } + + @Override + protected String castType() { + return "daterange[]"; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/DateRangeBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/DateRangeBinding.java new file mode 100644 index 0000000000..78d1c4d149 --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/DateRangeBinding.java @@ -0,0 +1,62 @@ +/* + * 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.postgres.extensions.bindings; + +import org.jooq.Converter; +import org.jooq.postgres.extensions.converters.DateRangeConverter; +import org.jooq.postgres.extensions.types.DateRange; + +/** + * A binding for the PostgreSQL daterange data type. + * + * @author Lukas Eder + */ +public class DateRangeBinding extends AbstractRangeBinding { + + private static final Converter CONVERTER = new DateRangeConverter(); + + @Override + public Converter converter() { + return CONVERTER; + } + + @Override + protected String castType() { + return "daterange"; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LocalDateRangeArrayBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LocalDateRangeArrayBinding.java new file mode 100644 index 0000000000..65a1f7d564 --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LocalDateRangeArrayBinding.java @@ -0,0 +1,62 @@ +/* + * 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.postgres.extensions.bindings; + +import org.jooq.Converter; +import org.jooq.postgres.extensions.converters.LocalDateRangeConverter; +import org.jooq.postgres.extensions.types.LocalDateRange; + +/** + * A binding for the PostgreSQL daterange[] data type. + * + * @author Lukas Eder + */ +public class LocalDateRangeArrayBinding extends AbstractPostgresArrayBinding { + + private static final Converter CONVERTER = new LocalDateRangeConverter().forArrays(); + + @Override + public Converter converter() { + return CONVERTER; + } + + @Override + protected String castType() { + return "daterange[]"; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LocalDateRangeBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LocalDateRangeBinding.java new file mode 100644 index 0000000000..49796e8607 --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LocalDateRangeBinding.java @@ -0,0 +1,62 @@ +/* + * 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.postgres.extensions.bindings; + +import org.jooq.Converter; +import org.jooq.postgres.extensions.converters.LocalDateRangeConverter; +import org.jooq.postgres.extensions.types.LocalDateRange; + +/** + * A binding for the PostgreSQL daterange data type. + * + * @author Lukas Eder + */ +public class LocalDateRangeBinding extends AbstractRangeBinding { + + private static final Converter CONVERTER = new LocalDateRangeConverter(); + + @Override + public Converter converter() { + return CONVERTER; + } + + @Override + protected String castType() { + return "daterange"; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/DateRangeConverter.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/DateRangeConverter.java new file mode 100644 index 0000000000..2dedf059b9 --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/DateRangeConverter.java @@ -0,0 +1,78 @@ +/* + * 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.postgres.extensions.converters; + +import static org.jooq.postgres.extensions.types.DateRange.dateRange; +import static org.jooq.postgres.extensions.types.LocalDateRange.localDateRange; + +import java.sql.Date; +import java.time.LocalDate; + +import org.jooq.postgres.extensions.types.DateRange; +import org.jooq.postgres.extensions.types.IntegerRange; +import org.jooq.postgres.extensions.types.LocalDateRange; + +/** + * A converter for {@link IntegerRange}. + * + * @author Lukas Eder + */ +public class DateRangeConverter extends AbstractRangeConverter { + + private static final Date EPOCH = Date.valueOf("1970-01-01"); + private static final DateRange EMPTY = dateRange(EPOCH, EPOCH); + + public DateRangeConverter() { + super(DateRange.class); + } + + @Override + final DateRange construct(String lower, boolean lowerIncluding, String upper, boolean upperIncluding) { + return dateRange( + lower == null ? null : Date.valueOf(lower), + lowerIncluding, + upper == null ? null : Date.valueOf(upper), + upperIncluding + ); + } + + @Override + final DateRange empty() { + return EMPTY; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/IntegerRangeConverter.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/IntegerRangeConverter.java index 61a8c3d5e1..6d2e8ebb70 100644 --- a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/IntegerRangeConverter.java +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/IntegerRangeConverter.java @@ -48,6 +48,8 @@ import org.jooq.postgres.extensions.types.IntegerRange; */ public class IntegerRangeConverter extends AbstractRangeConverter { + private static final IntegerRange EMPTY = integerRange(0, 0); + public IntegerRangeConverter() { super(IntegerRange.class); } @@ -64,6 +66,6 @@ public class IntegerRangeConverter extends AbstractRangeConverter { + + private static final LocalDate EPOCH = LocalDate.parse("1970-01-01"); + private static final LocalDateRange EMPTY = localDateRange(EPOCH, EPOCH); + + public LocalDateRangeConverter() { + super(LocalDateRange.class); + } + + @Override + final LocalDateRange construct(String lower, boolean lowerIncluding, String upper, boolean upperIncluding) { + return localDateRange( + lower == null ? null : LocalDate.parse(lower), + lowerIncluding, + upper == null ? null : LocalDate.parse(upper), + upperIncluding + ); + } + + @Override + final LocalDateRange empty() { + return EMPTY; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/LongRangeConverter.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/LongRangeConverter.java index 5098ba6191..5437f6d919 100644 --- a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/LongRangeConverter.java +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/LongRangeConverter.java @@ -37,6 +37,7 @@ */ package org.jooq.postgres.extensions.converters; +import static org.jooq.postgres.extensions.types.IntegerRange.integerRange; import static org.jooq.postgres.extensions.types.LongRange.longRange; import org.jooq.postgres.extensions.types.IntegerRange; @@ -49,6 +50,8 @@ import org.jooq.postgres.extensions.types.LongRange; */ public class LongRangeConverter extends AbstractRangeConverter { + private static final LongRange EMPTY = longRange(0L, 0L); + public LongRangeConverter() { super(LongRange.class); } @@ -65,6 +68,6 @@ public class LongRangeConverter extends AbstractRangeConverter @Override final LongRange empty() { - return longRange(0L, 0L); + return EMPTY; } } diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractDiscreteRange.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractDiscreteRange.java index 594eeddaaa..e46d8e01cc 100644 --- a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractDiscreteRange.java +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractDiscreteRange.java @@ -92,8 +92,18 @@ abstract class AbstractDiscreteRange> e } @Override - public int hashCode() { + public boolean isEmpty() { if (isCanonical()) + return super.isEmpty(); + else + return canonical().isEmpty(); + } + + @Override + public int hashCode() { + if (isEmpty()) + return 0; + else if (isCanonical()) return Objects.hash(lower(), upper()); else return canonical().hashCode(); @@ -116,6 +126,9 @@ abstract class AbstractDiscreteRange> e R r1 = c1 ? (R) this : canonical(); R r2 = c2 ? other : other.canonical(); + if (r1.isEmpty()) + return r2.isEmpty(); + return Objects.equals(r1.lower(), r2.lower()) && Objects.equals(r1.upper(), r2.upper()); } } diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractRange.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractRange.java index 35c5424001..a7eafb272d 100644 --- a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractRange.java +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/AbstractRange.java @@ -61,6 +61,13 @@ public abstract class AbstractRange implements Serializable { this.upperIncluding = upperIncluding; } + /** + * In PostgreSQL, a [x,x) range is considered "empty". + */ + public /* non-final */ boolean isEmpty() { + return lowerIncluding && !upperIncluding && Objects.equals(lower, upper); + } + @Nullable public final T lower() { return lower; @@ -81,7 +88,10 @@ public abstract class AbstractRange implements Serializable { @Override public int hashCode() { - return Objects.hash(lower, lowerIncluding, upper, upperIncluding); + if (isEmpty()) + return 0; + else + return Objects.hash(lower, lowerIncluding, upper, upperIncluding); } @Override @@ -92,7 +102,11 @@ public abstract class AbstractRange implements Serializable { return false; if (getClass() != obj.getClass()) return false; + AbstractRange other = (AbstractRange) obj; + if (isEmpty()) + return other.isEmpty(); + return Objects.equals(lower, other.lower) && lowerIncluding == other.lowerIncluding && Objects.equals(upper, other.upper) && upperIncluding == other.upperIncluding; } diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/DateRange.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/DateRange.java new file mode 100644 index 0000000000..00bdd98d6d --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/DateRange.java @@ -0,0 +1,82 @@ +/* + * 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.postgres.extensions.types; + +import java.sql.Date; + +/** + * A data type representing the PostgreSQL daterange type. + * + * @author Lukas Eder + */ +public final class DateRange extends AbstractDiscreteRange { + + private DateRange(Date lower, boolean lowerIncluding, Date upper, boolean upperIncluding) { + super(lower, lowerIncluding, upper, upperIncluding); + } + + /** + * Create a new {@link DateRange} with a inclusive lower bound and an + * exclusive upper bound. + */ + public static final DateRange dateRange(Date lower, Date upper) { + return new DateRange(lower, true, upper, false); + } + + /** + * Create a new {@link DateRange}. + */ + public static final DateRange dateRange(Date lower, boolean lowerIncluding, Date upper, boolean upperIncluding) { + return new DateRange(lower, lowerIncluding, upper, upperIncluding); + } + + @Override + final DateRange construct(Date lower, Date upper) { + return new DateRange(lower, true, upper, false); + } + + @Override + final Date next(Date t) { + return Date.valueOf(t.toLocalDate().plusDays(1)); + } + + @Override + final Date prev(Date t) { + return Date.valueOf(t.toLocalDate().minusDays(1)); + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/LocalDateRange.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/LocalDateRange.java new file mode 100644 index 0000000000..7b9858727e --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/LocalDateRange.java @@ -0,0 +1,82 @@ +/* + * 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.postgres.extensions.types; + +import java.time.LocalDate; + +/** + * A data type representing the PostgreSQL daterange type. + * + * @author Lukas Eder + */ +public final class LocalDateRange extends AbstractDiscreteRange { + + private LocalDateRange(LocalDate lower, boolean lowerIncluding, LocalDate upper, boolean upperIncluding) { + super(lower, lowerIncluding, upper, upperIncluding); + } + + /** + * Create a new {@link LocalDateRange} with a inclusive lower bound and an + * exclusive upper bound. + */ + public static final LocalDateRange localDateRange(LocalDate lower, LocalDate upper) { + return new LocalDateRange(lower, true, upper, false); + } + + /** + * Create a new {@link LocalDateRange}. + */ + public static final LocalDateRange localDateRange(LocalDate lower, boolean lowerIncluding, LocalDate upper, boolean upperIncluding) { + return new LocalDateRange(lower, lowerIncluding, upper, upperIncluding); + } + + @Override + final LocalDateRange construct(LocalDate lower, LocalDate upper) { + return new LocalDateRange(lower, true, upper, false); + } + + @Override + final LocalDate next(LocalDate t) { + return t.plusDays(1); + } + + @Override + final LocalDate prev(LocalDate t) { + return t.minusDays(1); + } +} diff --git a/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/IntegerRangeTest.java b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/IntegerRangeTest.java index 46ce83ceeb..99a7f0854c 100644 --- a/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/IntegerRangeTest.java +++ b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/IntegerRangeTest.java @@ -39,7 +39,6 @@ package org.jooq.postgres.extensions.test; import static org.jooq.postgres.extensions.test.RangeTestUtils.assertEqualsHashCode; import static org.jooq.postgres.extensions.types.IntegerRange.integerRange; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import org.junit.Test; @@ -49,6 +48,7 @@ public class IntegerRangeTest { @Test public void testEqualsHashCode() { assertEqualsHashCode(integerRange(0, 0), integerRange(0, 0)); + assertEqualsHashCode(integerRange(0, 0), integerRange(1, 1)); assertEqualsHashCode(integerRange(0, 1), integerRange(0, 1)); assertEqualsHashCode(integerRange(0, 2), integerRange(0, true, 1, true)); assertEqualsHashCode(integerRange(0, 2), integerRange(0, true, 2, false)); diff --git a/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/LongRangeTest.java b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/LongRangeTest.java index 42e3fccb62..030152ab67 100644 --- a/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/LongRangeTest.java +++ b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/LongRangeTest.java @@ -39,7 +39,6 @@ package org.jooq.postgres.extensions.test; import static org.jooq.postgres.extensions.test.RangeTestUtils.assertEqualsHashCode; import static org.jooq.postgres.extensions.types.LongRange.longRange; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import org.junit.Test; @@ -49,6 +48,7 @@ public class LongRangeTest { @Test public void testEqualsHashCode() { assertEqualsHashCode(longRange(0L, 0L), longRange(0L, 0L)); + assertEqualsHashCode(longRange(0L, 0L), longRange(1L, 1L)); assertEqualsHashCode(longRange(0L, 1L), longRange(0L, 1L)); assertEqualsHashCode(longRange(0L, 2L), longRange(0L, true, 1L, true)); assertEqualsHashCode(longRange(0L, 2L), longRange(0L, true, 2L, false));