Skip to content

Commit 58cd9d5

Browse files
Francisco Guerreromp911de
Francisco Guerrero
authored andcommitted
Implement Polygon[] codec support
[pgjdbc#394][pgjdbc#403]
1 parent 82086c4 commit 58cd9d5

File tree

7 files changed

+166
-3
lines changed

7 files changed

+166
-3
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,8 @@ Support for the following single-dimensional arrays (read and write):
438438
| [`uuid[]`][psql-uuid-ref] | [`UUID[]`][java-uuid-ref]|
439439
| [`boolean[] or bool[]`][psql-boolean-ref] | [`Boolean[]`][java-boolean-ref] |
440440
| [`double precision[]`][psql-floating-point-ref] | [`Double[]`][java-double-ref] |
441-
| [`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]|
441+
| [`polygon[]`][psql-polygon-ref] | **`Polygon[]`**|
442+
| [`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]|
442443
| [`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]|
443444
| [`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]|
444445
| [`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]|

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
import java.util.ArrayList;
2323
import java.util.List;
2424

25+
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.POLYGON_ARRAY;
26+
2527
/**
2628
* @since 0.8.5
2729
*/
28-
final class PolygonCodec extends AbstractGeometryCodec<Polygon> {
30+
final class PolygonCodec extends AbstractGeometryCodec<Polygon> implements ArrayCodecDelegate<Polygon> {
2931

3032
PolygonCodec(ByteBufAllocator byteBufAllocator) {
3133
super(Polygon.class, PostgresqlObjectId.POLYGON, byteBufAllocator);
@@ -68,4 +70,14 @@ ByteBuf doEncodeBinary(Polygon value) {
6870
return buffer;
6971
}
7072

73+
@Override
74+
public String encodeToText(Polygon value) {
75+
return String.format("\"%s\"", value);
76+
}
77+
78+
@Override
79+
public PostgresTypeIdentifier getArrayDataType() {
80+
return POLYGON_ARRAY;
81+
}
82+
7183
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,15 @@ public enum PostgresqlObjectId implements Type, PostgresTypeIdentifier {
270270
POINT_ARRAY(1017, Point[].class),
271271

272272
/**
273-
* the polygon object id
273+
* the polygon object id.
274274
*/
275275
POLYGON(604, Polygon.class),
276276

277+
/**
278+
* the polygon array object id.
279+
*/
280+
POLYGON_ARRAY( 1027, Polygon[].class),
281+
277282
/**
278283
* The ref cursor object id.
279284
*/

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,12 +592,24 @@ void path() {
592592
testCodec(Path.class, Path.open(Point.of(1.1, 2.2), Point.of(10.10, 10.10), Point.of(0.42, 5.3), Point.of(-3.5, 0.0)), "PATH");
593593
}
594594

595+
@Test
596+
void polygonArray() {
597+
testCodec(Polygon[].class, new Polygon[]{Polygon.of(Point.of(1.1, 2.2), Point.of(10.10, 10.10), Point.of(.42, 5.3)),
598+
Polygon.of(Point.of(1.1, 2.2), Point.of(10.10, 10.10), Point.of(.42, 5.3), Point.of(-3.5, 0.))}, "POLYGON[]");
599+
}
600+
595601
@Test
596602
void polygon() {
597603
testCodec(Polygon.class, Polygon.of(Point.of(1.1, 2.2), Point.of(10.10, 10.10), Point.of(.42, 5.3)), "POLYGON");
598604
testCodec(Polygon.class, Polygon.of(Point.of(1.1, 2.2), Point.of(10.10, 10.10), Point.of(.42, 5.3), Point.of(-3.5, 0.)), "POLYGON");
599605
}
600606

607+
@Test
608+
void polygonTwoDimensionalArray() {
609+
testCodec(Polygon[][].class, new Polygon[][]{{null, Polygon.of(Point.of(1.1, 2.2), Point.of(10.10, 10.10), Point.of(.42, 5.3))}, {Polygon.of(Point.of(1.1, 2.2), Point.of(10.10, 10.10),
610+
Point.of(.42, 5.3), Point.of(-3.5, 0.)), null}}, "POLYGON[][]");
611+
}
612+
601613
private static <T> Mono<T> close(Connection connection) {
602614
return Mono.from(connection
603615
.close())

src/test/java/io/r2dbc/postgresql/codec/DefaultCodecsUnitTests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.INT4;
3737
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.INT4_ARRAY;
3838
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.INT8_ARRAY;
39+
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.POLYGON_ARRAY;
3940
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.TIMESTAMP;
4041
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.TIMESTAMPTZ;
4142
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.VARCHAR;
@@ -111,6 +112,8 @@ void delegatePriority() {
111112
assertThat(codecs.decode(ByteBufUtils.encode(TEST, "{alpha,bravo}"), VARCHAR_ARRAY.getObjectId(), FORMAT_TEXT, Object.class)).isEqualTo(new String[]{"alpha", "bravo"});
112113
assertThat(codecs.decode(ByteBufUtils.encode(TEST, "{\"((1.2, 123.1), 10)\",NULL}"), CIRCLE_ARRAY.getObjectId(), FORMAT_TEXT, Object.class))
113114
.isEqualTo(new Circle[]{Circle.of(Point.of(1.2, 123.1), 10), null});
115+
assertThat(codecs.decode(ByteBufUtils.encode(TEST, "{\"((-10.42,3.14),(10.42,-3.14))\",NULL}"), POLYGON_ARRAY.getObjectId(), FORMAT_TEXT, Object.class))
116+
.isEqualTo(new Polygon[]{Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14)), null});
114117
}
115118

116119
@Test
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package io.r2dbc.postgresql.codec;
2+
3+
import io.netty.buffer.ByteBuf;
4+
5+
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.POLYGON;
6+
import static io.r2dbc.postgresql.codec.PostgresqlObjectId.POLYGON_ARRAY;
7+
import static io.r2dbc.postgresql.util.TestByteBufAllocator.TEST;
8+
9+
/**
10+
* Unit tests for {@link ArrayCodec<Polygon>}.
11+
*/
12+
final class PolygonArrayCodecUnitTests extends AbstractArrayCodecUnitTests<Polygon> {
13+
14+
private final ByteBuf SINGLE_DIM_BINARY_ARRAY = TEST
15+
.buffer()
16+
.writeInt(1) // num of dimensions
17+
.writeInt(0) // flag: has nulls
18+
.writeInt(604) // oid
19+
.writeInt(2) // num of elements
20+
.writeInt(1) // ignore Lower Bound
21+
.writeInt(4 + 16 * /* number of points */2) // number of bytes to follow
22+
.writeInt(2) // number of points
23+
.writeDouble(-10.42) // point 1 x
24+
.writeDouble(3.14) // point 1 y
25+
.writeDouble(10.42) // point 2 x
26+
.writeDouble(-3.14) // point 2 y
27+
.writeInt(4 + 16 * /* number of points */4) // number of bytes to follow
28+
.writeInt(4) // number of points
29+
.writeDouble(10.42) // point 1 x
30+
.writeDouble(3.14) // point 1 y
31+
.writeDouble(10.42) // point 2 x
32+
.writeDouble(-3.14) // point 2 y
33+
.writeDouble(-10.42) // point 3 x
34+
.writeDouble(-3.14) // point 3 y
35+
.writeDouble(-10.42) // point 4 x
36+
.writeDouble(3.14); // point 4 y
37+
38+
private final ByteBuf TWO_DIM_BINARY_ARRAY = TEST
39+
.buffer()
40+
.writeInt(2) // num of dims
41+
.writeInt(1) // flag: has nulls
42+
.writeInt(604) // oid
43+
.writeInt(2) // dim 1 length
44+
.writeInt(1) // dim 1 lower bound
45+
.writeInt(1) // dim 2 length
46+
.writeInt(1) // dim 2 lower bound
47+
.writeInt(4 + 16 * /* number of points */2) // number of bytes to follow
48+
.writeInt(2) // number of points
49+
.writeDouble(-10.42) // point 1 x
50+
.writeDouble(3.14) // point 1 y
51+
.writeDouble(10.42) // point 2 x
52+
.writeDouble(-3.14) // point 2 y
53+
.writeInt(-1); // length of null element
54+
55+
@Override
56+
ArrayCodec<Polygon> createInstance() {
57+
return new ArrayCodec<>(TEST, POLYGON_ARRAY, new PolygonCodec(TEST), Polygon.class);
58+
}
59+
60+
@Override
61+
PostgresqlObjectId getPostgresqlObjectId() {
62+
return POLYGON;
63+
}
64+
65+
@Override
66+
PostgresqlObjectId getArrayPostgresqlObjectId() {
67+
return POLYGON_ARRAY;
68+
}
69+
70+
@Override
71+
ByteBuf getSingleDimensionBinaryArray() {
72+
return SINGLE_DIM_BINARY_ARRAY;
73+
}
74+
75+
@Override
76+
ByteBuf getTwoDimensionBinaryArray() {
77+
return TWO_DIM_BINARY_ARRAY;
78+
}
79+
80+
@Override
81+
Class<? extends Polygon[]> getSingleDimensionArrayType() {
82+
return Polygon[].class;
83+
}
84+
85+
@Override
86+
Class<? extends Polygon[][]> getTwoDimensionArrayType() {
87+
return Polygon[][].class;
88+
}
89+
90+
@Override
91+
Polygon[] getExpectedSingleDimensionArray() {
92+
return new Polygon[]{Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14)), Polygon.of(Point.of(10.42, 3.14), Point.of(10.42, -3.14), Point.of(-10.42, -3.14), Point.of(-10.42, 3.14))};
93+
}
94+
95+
@Override
96+
Polygon[][] getExpectedTwoDimensionArray() {
97+
return new Polygon[][]{{Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14))}, {null}};
98+
}
99+
100+
@Override
101+
String getSingleDimensionStringInput() {
102+
return "{\"((-10.42,3.14),(10.42,-3.14))\",\"((10.42,3.14),(10.42,-3.14),(-10.42,-3.14),(-10.42,3.14))\"}";
103+
}
104+
105+
@Override
106+
String getTwoDimensionStringInput() {
107+
return "{{\"((-10.42,3.14),(10.42,-3.14))\"},{NULL}}";
108+
}
109+
110+
}

src/test/java/io/r2dbc/postgresql/codec/PolygonCodecUnitTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,26 @@ void doEncodeNoValue() {
9797
.withMessage("value must not be null");
9898
}
9999

100+
@Test
101+
void decodeText() {
102+
// Polygons are represented by lists of points (the vertexes of the polygon).
103+
// Values of type polygon are specified using any of the following syntaxes:
104+
// ( ( x1 , y1 ) , ... , ( xn , yn ) )
105+
// ( x1 , y1 ) , ... , ( xn , yn )
106+
// ( x1 , y1 , ... , xn , yn )
107+
// x1 , y1 , ... , xn , yn
108+
PolygonCodec codec = new PolygonCodec(TEST);
109+
110+
assertThat(codec.decode(encode(TEST, "((-10.42,3.14),(10.42,-3.14))"), dataType, FORMAT_TEXT, Polygon.class))
111+
.isEqualTo(Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14)));
112+
assertThat(codec.decode(encode(TEST, "(-10.42,3.14),(10.42,-3.14)"), dataType, FORMAT_TEXT, Polygon.class))
113+
.isEqualTo(Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14)));
114+
assertThat(codec.decode(encode(TEST, "(-10.42,3.14,10.42,-3.14)"), dataType, FORMAT_TEXT, Polygon.class))
115+
.isEqualTo(Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14)));
116+
assertThat(codec.decode(encode(TEST, "-10.42,3.14,10.42,-3.14"), dataType, FORMAT_TEXT, Polygon.class))
117+
.isEqualTo(Polygon.of(Point.of(-10.42, 3.14), Point.of(10.42, -3.14)));
118+
}
119+
100120
@Test
101121
void encodeNull() {
102122
ParameterAssert.assertThat(new PolygonCodec(TEST).encodeNull())

0 commit comments

Comments
 (0)