Skip to content

Commit 69d832b

Browse files
author
Tim van Eijndhoven
committed
Add codec for BigIntegers
Applicable to any numeric type with scale 0 [resolves #233]
1 parent a1bef7e commit 69d832b

File tree

5 files changed

+193
-8
lines changed

5 files changed

+193
-8
lines changed

README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ This reference table shows the type mapping between [PostgreSQL][p] and Java dat
301301

302302
| PostgreSQL Type | Supported Data Type |
303303
|:------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------|
304-
| [`bigint`][psql-bigint-ref] | [**`Long`**][java-long-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`BigDecimal`][java-bigdecimal-ref] |
304+
| [`bigint`][psql-bigint-ref] | [**`Long`**][java-long-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref] |
305305
| [`bit`][psql-bit-ref] | Not yet supported.|
306306
| [`bit varying`][psql-bit-ref] | Not yet supported.|
307307
| [`boolean or bool`][psql-boolean-ref] | [`Boolean`][java-boolean-ref]|
@@ -314,7 +314,7 @@ This reference table shows the type mapping between [PostgreSQL][p] and Java dat
314314
| [`date`][psql-date-ref] | [`LocalDate`][java-ld-ref]|
315315
| [`double precision`][psql-floating-point-ref] | [**`Double`**][java-double-ref], [`Float`][java-float-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref]|
316316
| [`inet`][psql-inet-ref] | [**`InetAddress`**][java-inet-ref]|
317-
| [`integer`][psql-integer-ref] | [**`Integer`**][java-integer-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref]|
317+
| [`integer`][psql-integer-ref] | [**`Integer`**][java-integer-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref]|
318318
| [`interval`][psql-interval-ref] | Not yet supported.|
319319
| [`json`][psql-json-ref] | **`Json`**, [`String`][java-string-ref]. Reading: `ByteBuf`[`byte[]`][java-primitive-ref], [`ByteBuffer`][java-ByteBuffer-ref], [`String`][java-string-ref], [`InputStream`][java-inputstream-ref]|
320320
| [`jsonb`][psql-json-ref] | **`Json`**, [`String`][java-string-ref]. Reading: `ByteBuf`[`byte[]`][java-primitive-ref], [`ByteBuffer`][java-ByteBuffer-ref], [`String`][java-string-ref], [`InputStream`][java-inputstream-ref]|
@@ -323,16 +323,16 @@ This reference table shows the type mapping between [PostgreSQL][p] and Java dat
323323
| [`macaddr`][psql-macaddr-ref] | Not yet supported.|
324324
| [`macaddr8`][psql-macaddr8-ref] | Not yet supported.|
325325
| [`money`][psql-money-ref] | Not yet supported.|
326-
| [`numeric`][psql-bignumeric-ref] | [`BigDecimal`][java-bigdecimal-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref]|
327-
| [`oid`][psql-oid-ref] | [**`Integer`**][java-integer-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref]|
326+
| [`numeric`][psql-bignumeric-ref] | [`BigDecimal`][java-bigdecimal-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref], [`BigInteger`][java-biginteger-ref]|
327+
| [`oid`][psql-oid-ref] | [**`Integer`**][java-integer-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref]|
328328
| [`path`][psql-path-ref] | Not yet supported.|
329329
| [`pg_lsn`][psql-pg_lsn-ref] | Not yet supported.|
330330
| [`point`][psql-point-ref] | Not yet supported.|
331331
| [`polygon`][psql-polygon-ref] | Not yet supported.|
332-
| [`real`][psql-real-ref] | [**`Float`**][java-float-ref], [`Double`][java-double-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref]|
333-
| [`smallint`][psql-smallint-ref] | [**`Short`**][java-short-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref]|
334-
| [`smallserial`][psql-smallserial-ref] | [**`Integer`**][java-integer-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref]|
335-
| [`serial`][psql-serial-ref] | [**`Long`**][java-long-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`BigDecimal`][java-bigdecimal-ref]|
332+
| [`real`][psql-real-ref] | [**`Float`**][java-float-ref], [`Double`][java-double-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref]|
333+
| [`smallint`][psql-smallint-ref] | [**`Short`**][java-short-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Integer`][java-integer-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref]|
334+
| [`smallserial`][psql-smallserial-ref] | [**`Integer`**][java-integer-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Long`][java-long-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref]|
335+
| [`serial`][psql-serial-ref] | [**`Long`**][java-long-ref], [`Boolean`][java-boolean-ref], [`Byte`][java-byte-ref], [`Short`][java-short-ref], [`Integer`][java-integer-ref], [`BigDecimal`][java-bigdecimal-ref], [`BigInteger`][java-biginteger-ref]|
336336
| [`text`][psql-text-ref] | [**`String`**][java-string-ref], [`Clob`][r2dbc-clob-ref]|
337337
| [`time [without time zone]`][psql-time-ref] | [`LocalTime`][java-lt-ref]|
338338
| [`time [with time zone]`][psql-time-ref] | Not yet supported.|
@@ -396,6 +396,7 @@ Support for the following single-dimensional arrays (read and write):
396396
[r2dbc-clob-ref]: https://r2dbc.io/spec/0.8.0.RELEASE/api/io/r2dbc/spi/Clob.html
397397

398398
[java-bigdecimal-ref]: https://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html
399+
[java-biginteger-ref]: https://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html
399400
[java-boolean-ref]: https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html
400401
[java-byte-ref]: https://docs.oracle.com/javase/8/docs/api/java/lang/Byte.html
401402
[java-ByteBuffer-ref]: https://docs.oracle.com/javase/8/docs/api/java/nio/ByteBuffer.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright 2017-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.r2dbc.postgresql.codec;
18+
19+
import io.netty.buffer.ByteBuf;
20+
import io.netty.buffer.ByteBufAllocator;
21+
import io.r2dbc.postgresql.client.Parameter;
22+
import io.r2dbc.postgresql.message.Format;
23+
import io.r2dbc.postgresql.type.PostgresqlObjectId;
24+
import io.r2dbc.postgresql.util.Assert;
25+
import io.r2dbc.postgresql.util.ByteBufUtils;
26+
import reactor.util.annotation.Nullable;
27+
28+
import java.math.BigInteger;
29+
30+
import static io.r2dbc.postgresql.message.Format.FORMAT_TEXT;
31+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.NUMERIC;
32+
33+
public class BigIntegerCodec extends AbstractNumericCodec<BigInteger> {
34+
35+
private final ByteBufAllocator byteBufAllocator;
36+
37+
public BigIntegerCodec(ByteBufAllocator byteBufAllocator) {
38+
super(BigInteger.class);
39+
this.byteBufAllocator = Assert.requireNonNull(byteBufAllocator, "byteBufAllocator must not be null");
40+
}
41+
42+
@Override
43+
public Parameter encodeNull() {
44+
return createNull(NUMERIC, FORMAT_TEXT);
45+
}
46+
47+
@Override
48+
BigInteger doDecode(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format format, @Nullable Class<? extends BigInteger> type) {
49+
Assert.requireNonNull(buffer, "byteBuf must not be null");
50+
51+
return this.decodeNumber(buffer, dataType, format, BigInteger.class, it -> new BigInteger(it.toString()));
52+
}
53+
54+
@Override
55+
Parameter doEncode(BigInteger value) {
56+
Assert.requireNonNull(value, "value must not be null");
57+
58+
return create(NUMERIC, FORMAT_TEXT, () -> ByteBufUtils.encode(this.byteBufAllocator, value.toString()));
59+
}
60+
61+
@Override
62+
PostgresqlObjectId getDefaultType() {
63+
return NUMERIC;
64+
}
65+
}

src/main/java/io/r2dbc/postgresql/codec/DefaultCodecs.java

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public DefaultCodecs(ByteBufAllocator byteBufAllocator) {
5454
new BinaryByteArrayCodec(byteBufAllocator),
5555

5656
new BigDecimalCodec(byteBufAllocator),
57+
new BigIntegerCodec(byteBufAllocator),
5758
new BooleanCodec(byteBufAllocator),
5859
new CharacterCodec(byteBufAllocator),
5960
new DoubleCodec(byteBufAllocator),

src/test/java/io/r2dbc/postgresql/AbstractCodecIntegrationTests.java

+16
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.io.IOException;
3737
import java.io.InputStream;
3838
import java.math.BigDecimal;
39+
import java.math.BigInteger;
3940
import java.net.InetAddress;
4041
import java.net.MalformedURLException;
4142
import java.net.URI;
@@ -76,6 +77,21 @@ void bigDecimal() {
7677
testCodec(BigDecimal.class, new BigDecimal("100"), "FLOAT8");
7778
}
7879

80+
@Test
81+
void bigInteger() {
82+
testCodec(BigInteger.class, new BigInteger("1000"), "NUMERIC");
83+
testCodec(BigInteger.class, new BigInteger("-1"), "NUMERIC");
84+
testCodec(BigInteger.class, new BigInteger("10000"), "NUMERIC");
85+
testCodec(BigInteger.class, new BigInteger("10010"), "NUMERIC");
86+
testCodec(BigInteger.class, new BigInteger("2000010010"), "NUMERIC");
87+
testCodec(BigInteger.class, new BigInteger("0"), "NUMERIC");
88+
testCodec(BigInteger.class, new BigInteger("100"), "INT2");
89+
testCodec(BigInteger.class, new BigInteger("100"), "INT4");
90+
testCodec(BigInteger.class, new BigInteger("100"), "INT8");
91+
testCodec(BigInteger.class, new BigInteger("100"), "FLOAT4");
92+
testCodec(BigInteger.class, new BigInteger("100"), "FLOAT8");
93+
}
94+
7995
@Test
8096
void booleanPrimitive() {
8197
testCodec(Boolean.class, true, "BOOL");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright 2017-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.r2dbc.postgresql.codec;
18+
19+
import io.r2dbc.postgresql.client.Parameter;
20+
import org.junit.jupiter.api.Test;
21+
22+
import java.math.BigInteger;
23+
24+
import static io.r2dbc.postgresql.client.Parameter.NULL_VALUE;
25+
import static io.r2dbc.postgresql.client.ParameterAssert.assertThat;
26+
import static io.r2dbc.postgresql.message.Format.FORMAT_BINARY;
27+
import static io.r2dbc.postgresql.message.Format.FORMAT_TEXT;
28+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.MONEY;
29+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.NUMERIC;
30+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.VARCHAR;
31+
import static io.r2dbc.postgresql.util.ByteBufUtils.encode;
32+
import static io.r2dbc.postgresql.util.TestByteBufAllocator.TEST;
33+
import static org.assertj.core.api.Assertions.assertThat;
34+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
35+
36+
class BigIntegerCodecTest {
37+
38+
private static final int dataType = NUMERIC.getObjectId();
39+
40+
@Test
41+
void constructorNoByteBufAllocator() {
42+
assertThatIllegalArgumentException().isThrownBy(() -> new BigIntegerCodec(null))
43+
.withMessage("byteBufAllocator must not be null");
44+
}
45+
46+
@Test
47+
void decode() {
48+
BigInteger bigInteger = new BigInteger("100");
49+
50+
assertThat(new BigIntegerCodec(TEST).decode(encode(TEST, bigInteger.toString()), dataType, FORMAT_TEXT, BigInteger.class))
51+
.isEqualTo(bigInteger);
52+
}
53+
54+
@Test
55+
void decodeNoByteBuf() {
56+
assertThat(new BigIntegerCodec(TEST).decode(null, dataType, FORMAT_TEXT, BigInteger.class)).isNull();
57+
}
58+
59+
@Test
60+
void doCanDecode() {
61+
BigIntegerCodec codec = new BigIntegerCodec(TEST);
62+
63+
assertThat(codec.doCanDecode(NUMERIC, FORMAT_BINARY)).isTrue();
64+
assertThat(codec.doCanDecode(MONEY, FORMAT_TEXT)).isFalse();
65+
assertThat(codec.doCanDecode(NUMERIC, FORMAT_TEXT)).isTrue();
66+
}
67+
68+
@Test
69+
void doCanDecodeNoFormat() {
70+
assertThatIllegalArgumentException().isThrownBy(() -> new BigIntegerCodec(TEST).doCanDecode(VARCHAR, null))
71+
.withMessage("format must not be null");
72+
}
73+
74+
@Test
75+
void doCanDecodeNoType() {
76+
assertThatIllegalArgumentException().isThrownBy(() -> new BigIntegerCodec(TEST).doCanDecode(null, FORMAT_TEXT))
77+
.withMessage("type must not be null");
78+
}
79+
80+
@Test
81+
void doEncode() {
82+
BigInteger bigInteger = new BigInteger("100");
83+
84+
assertThat(new BigIntegerCodec(TEST).doEncode(bigInteger))
85+
.hasFormat(FORMAT_TEXT)
86+
.hasType(NUMERIC.getObjectId())
87+
.hasValue(encode(TEST, "100"));
88+
}
89+
90+
@Test
91+
void doEncodeNoValue() {
92+
assertThatIllegalArgumentException().isThrownBy(() -> new BigIntegerCodec(TEST).doEncode(null))
93+
.withMessage("value must not be null");
94+
}
95+
96+
@Test
97+
void encodeNull() {
98+
assertThat(new BigIntegerCodec(TEST).encodeNull())
99+
.isEqualTo(new Parameter(FORMAT_TEXT, NUMERIC.getObjectId(), NULL_VALUE));
100+
}
101+
102+
}

0 commit comments

Comments
 (0)