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 fdaa979917..9f677a9007 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -1542,6 +1542,19 @@ public abstract class AbstractDatabase implements Database { .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"); diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/IntegerRangeArrayBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/IntegerRangeArrayBinding.java index 927e9d3029..404581e20b 100644 --- a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/IntegerRangeArrayBinding.java +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/IntegerRangeArrayBinding.java @@ -42,7 +42,7 @@ import org.jooq.postgres.extensions.converters.IntegerRangeConverter; import org.jooq.postgres.extensions.types.IntegerRange; /** - * A binding for the PostgreSQL inet[] data type. + * A binding for the PostgreSQL int4range[] data type. * * @author Lukas Eder */ diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LongRangeArrayBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LongRangeArrayBinding.java new file mode 100644 index 0000000000..45808d4bed --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LongRangeArrayBinding.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.LongRangeConverter; +import org.jooq.postgres.extensions.types.LongRange; + +/** + * A binding for the PostgreSQL int8range[] data type. + * + * @author Lukas Eder + */ +public class LongRangeArrayBinding extends AbstractPostgresArrayBinding { + + private static final Converter CONVERTER = new LongRangeConverter().forArrays(); + + @Override + public Converter converter() { + return CONVERTER; + } + + @Override + protected String castType() { + return "int8range[]"; + } +} diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LongRangeBinding.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LongRangeBinding.java new file mode 100644 index 0000000000..818b1487ff --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/bindings/LongRangeBinding.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.LongRangeConverter; +import org.jooq.postgres.extensions.types.LongRange; + +/** + * A binding for the PostgreSQL int8range data type. + * + * @author Lukas Eder + */ +public class LongRangeBinding extends AbstractRangeBinding { + + private static final Converter CONVERTER = new LongRangeConverter(); + + @Override + public Converter converter() { + return CONVERTER; + } + + @Override + protected String castType() { + return "int8range"; + } +} 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 new file mode 100644 index 0000000000..5098ba6191 --- /dev/null +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/converters/LongRangeConverter.java @@ -0,0 +1,70 @@ +/* + * 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.LongRange.longRange; + +import org.jooq.postgres.extensions.types.IntegerRange; +import org.jooq.postgres.extensions.types.LongRange; + +/** + * A converter for {@link IntegerRange}. + * + * @author Lukas Eder + */ +public class LongRangeConverter extends AbstractRangeConverter { + + public LongRangeConverter() { + super(LongRange.class); + } + + @Override + final LongRange construct(String lower, boolean lowerIncluding, String upper, boolean upperIncluding) { + return longRange( + lower == null ? null : Long.valueOf(lower), + lowerIncluding, + upper == null ? null : Long.valueOf(upper), + upperIncluding + ); + } + + @Override + final LongRange empty() { + return longRange(0L, 0L); + } +} 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 13aa145702..594eeddaaa 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 @@ -39,6 +39,8 @@ package org.jooq.postgres.extensions.types; import java.util.Objects; +import org.jooq.exception.DataTypeException; + /** * A data type representing the PostgreSQL range type for discrete ranges. * @@ -52,13 +54,17 @@ abstract class AbstractDiscreteRange> e /** * Given a value t, get the next value. + * + * @throws DataTypeException on overflow. */ - abstract T next(T t); + abstract T next(T t) throws DataTypeException; /** * Given a value t, get the previous value. + * + * @throws DataTypeException on underflow. */ - abstract T prev(T t); + abstract T prev(T t) throws DataTypeException; /** * Construct a new instance of this type. @@ -79,9 +85,6 @@ abstract class AbstractDiscreteRange> e if (!lowerIncluding() && l != null) l = next(l); - - // This can overflow for Integer and Long. In PostgreSQL, an overflow - // will cause an error. We might deal with this too, in the future if (upperIncluding() && u != null) u = next(u); diff --git a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/IntegerRange.java b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/IntegerRange.java index 8641e43036..365f4f2dfd 100644 --- a/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/IntegerRange.java +++ b/jOOQ-postgres-extensions/src/main/java/org/jooq/postgres/extensions/types/IntegerRange.java @@ -37,6 +37,8 @@ */ package org.jooq.postgres.extensions.types; +import org.jooq.exception.DataTypeException; + /** * A data type representing the PostgreSQL int4range type. * @@ -70,11 +72,21 @@ public final class IntegerRange extends AbstractDiscreteRangeint8range type. + * + * @author Lukas Eder + */ +public final class LongRange extends AbstractDiscreteRange { + + private LongRange(Long lower, boolean lowerIncluding, Long upper, boolean upperIncluding) { + super(lower, lowerIncluding, upper, upperIncluding); + } + + /** + * Create a new {@link LongRange} with a inclusive lower bound and an + * exclusive upper bound. + */ + public static final LongRange longRange(Long lower, Long upper) { + return new LongRange(lower, true, upper, false); + } + + /** + * Create a new {@link LongRange}. + */ + public static final LongRange longRange(Long lower, boolean lowerIncluding, Long upper, boolean upperIncluding) { + return new LongRange(lower, lowerIncluding, upper, upperIncluding); + } + + @Override + final LongRange construct(Long lower, Long upper) { + return new LongRange(lower, true, upper, false); + } + + @Override + final Long next(Long t) { + long l = t.longValue(); + + if (l == Long.MAX_VALUE) + throw new DataTypeException("Long overflow: " + this); + else + return l + 1L; + } + + @Override + final Long prev(Long t) { + long l = t.longValue(); + + if (l == Long.MIN_VALUE) + throw new DataTypeException("Long underflow: " + this); + else + return l - 1L; + } +} 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 5d041d5a69..46ce83ceeb 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 @@ -37,6 +37,7 @@ */ 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; @@ -71,9 +72,4 @@ public class IntegerRangeTest { assertNotEquals(integerRange(0, 1), integerRange(1, 0)); } - - private void assertEqualsHashCode(Object expected, Object actual) { - assertEquals(expected, actual); - assertEquals(expected.hashCode(), actual.hashCode()); - } } 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 new file mode 100644 index 0000000000..42e3fccb62 --- /dev/null +++ b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/LongRangeTest.java @@ -0,0 +1,75 @@ +/* + * 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.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; + +public class LongRangeTest { + + @Test + public void testEqualsHashCode() { + assertEqualsHashCode(longRange(0L, 0L), longRange(0L, 0L)); + 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)); + assertEqualsHashCode(longRange(0L, 2L), longRange(-1L, false, 1L, true)); + assertEqualsHashCode(longRange(0L, 2L), longRange(-1L, false, 2L, false)); + + assertEqualsHashCode(longRange(0L, null), longRange(0L, true, null, true)); + assertEqualsHashCode(longRange(0L, null), longRange(0L, true, null, false)); + assertEqualsHashCode(longRange(0L, null), longRange(-1L, false, null, true)); + assertEqualsHashCode(longRange(0L, null), longRange(-1L, false, null, false)); + + assertEqualsHashCode(longRange(null, 2L), longRange(null, true, 1L, true)); + assertEqualsHashCode(longRange(null, 2L), longRange(null, true, 2L, false)); + assertEqualsHashCode(longRange(null, 2L), longRange(null, false, 1L, true)); + assertEqualsHashCode(longRange(null, 2L), longRange(null, false, 2L, false)); + + assertEqualsHashCode(longRange(null, null), longRange(null, true, null, true)); + assertEqualsHashCode(longRange(null, null), longRange(null, true, null, false)); + assertEqualsHashCode(longRange(null, null), longRange(null, false, null, true)); + assertEqualsHashCode(longRange(null, null), longRange(null, false, null, false)); + + assertNotEquals(longRange(0L, 1L), longRange(1L, 0L)); + } +} diff --git a/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/RangeTestUtils.java b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/RangeTestUtils.java new file mode 100644 index 0000000000..1d8a7201db --- /dev/null +++ b/jOOQ-postgres-extensions/src/test/java/org/jooq/postgres/extensions/test/RangeTestUtils.java @@ -0,0 +1,48 @@ +/* + * 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.test; + +import static org.junit.Assert.assertEquals; + +public class RangeTestUtils { + + public static void assertEqualsHashCode(Object expected, Object actual) { + assertEquals(expected, actual); + assertEquals(expected.hashCode(), actual.hashCode()); + } +}