Skip to content

Commit 228cc41

Browse files
author
Meier Roman
committed
add support for xmltype in postgres
Signed-off-by: Meier Roman <[email protected]>
1 parent e430bd8 commit 228cc41

File tree

5 files changed

+217
-41
lines changed

5 files changed

+217
-41
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package io.vertx.pgclient.data;
2+
3+
import io.vertx.codegen.annotations.Nullable;
4+
5+
import java.util.Objects;
6+
7+
public class PgSQLXML {
8+
9+
@Nullable final String xmlData;
10+
11+
public PgSQLXML(String xmlData) {
12+
this.xmlData = xmlData;
13+
}
14+
15+
public String getXmlData() {
16+
return xmlData;
17+
}
18+
19+
@Override
20+
public String toString() {
21+
return xmlData;
22+
}
23+
24+
@Override
25+
public boolean equals(Object o) {
26+
if (this == o) return true;
27+
if (o == null || getClass() != o.getClass()) return false;
28+
PgSQLXML pgSQLXML = (PgSQLXML) o;
29+
return Objects.equals(xmlData, pgSQLXML.xmlData);
30+
}
31+
32+
@Override
33+
public int hashCode() {
34+
return Objects.hash(xmlData);
35+
}
36+
}

Diff for: vertx-pg-client/src/main/java/io/vertx/pgclient/impl/RowImpl.java

+13-8
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,9 @@
1919

2020
import io.vertx.core.json.JsonArray;
2121
import io.vertx.core.json.JsonObject;
22-
import io.vertx.pgclient.data.Box;
23-
import io.vertx.pgclient.data.Circle;
24-
import io.vertx.pgclient.data.Line;
25-
import io.vertx.pgclient.data.LineSegment;
22+
import io.vertx.pgclient.data.*;
2623
import io.vertx.sqlclient.Row;
2724
import io.vertx.sqlclient.data.Numeric;
28-
import io.vertx.pgclient.data.Path;
29-
import io.vertx.pgclient.data.Polygon;
30-
import io.vertx.pgclient.data.Interval;
31-
import io.vertx.pgclient.data.Point;
3225
import io.vertx.sqlclient.impl.ArrayTuple;
3326
import io.vertx.sqlclient.impl.RowDesc;
3427
import io.vertx.core.buffer.Buffer;
@@ -118,6 +111,8 @@ public <T> T get(Class<T> type, int position) {
118111
return type.cast(getArrayOfIntervals(position));
119112
} else if (componentType == Box.class) {
120113
return type.cast(getArrayOfBoxs(position));
114+
} else if (componentType == PgSQLXML.class) {
115+
return type.cast(getArrayOfPgXMLSQLs(position));
121116
} else if (componentType == Object.class) {
122117
return type.cast(getJsonArray_(position));
123118
} else if (componentType.isEnum()) {
@@ -174,6 +169,8 @@ public <T> T get(Class<T> type, int position) {
174169
return type.cast(getJson(position));
175170
} else if (type == JsonArray.class) {
176171
return type.cast(getJson(position));
172+
} else if (type == PgSQLXML.class) {
173+
return type.cast(getPgSQLXML(position));
177174
} else if (type == Object.class) {
178175
return type.cast(getValue(position));
179176
} else if (type.isEnum()) {
@@ -215,6 +212,10 @@ private Interval getInterval(int pos) {
215212
return (Interval) getValue(pos);
216213
}
217214

215+
private PgSQLXML getPgSQLXML(int pos) {
216+
return (PgSQLXML) getValue(pos);
217+
}
218+
218219
private Object getEnum(Class enumType, int pos) {
219220
Object val = getValue(pos);
220221
if (val instanceof String) {
@@ -270,6 +271,10 @@ private Interval[] getArrayOfIntervals(int pos) {
270271
return (Interval[]) getValue(pos);
271272
}
272273

274+
private PgSQLXML[] getArrayOfPgXMLSQLs(int pos) {
275+
return (PgSQLXML[]) getValue(pos);
276+
}
277+
273278
private Object[] getArrayOfEnums(Class enumType, int pos) {
274279
Object val = getValue(pos);
275280
if (val instanceof String[]) {

Diff for: vertx-pg-client/src/main/java/io/vertx/pgclient/impl/codec/DataType.java

+6-12
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,9 @@
2222
import io.vertx.core.impl.logging.LoggerFactory;
2323
import io.vertx.core.json.JsonArray;
2424
import io.vertx.core.json.JsonObject;
25-
import io.vertx.pgclient.data.Box;
26-
import io.vertx.pgclient.data.Circle;
27-
import io.vertx.pgclient.data.Inet;
28-
import io.vertx.pgclient.data.Line;
29-
import io.vertx.pgclient.data.LineSegment;
30-
import io.vertx.pgclient.data.Money;
25+
import io.vertx.pgclient.data.*;
3126
import io.vertx.sqlclient.Tuple;
3227
import io.vertx.sqlclient.data.Numeric;
33-
import io.vertx.pgclient.data.Interval;
34-
import io.vertx.pgclient.data.Path;
35-
import io.vertx.pgclient.data.Point;
36-
import io.vertx.pgclient.data.Polygon;
3728
import io.vertx.core.buffer.Buffer;
3829

3930
import java.sql.JDBCType;
@@ -105,8 +96,8 @@ public enum DataType {
10596
JSON_ARRAY(199, true, Object[].class, JDBCType.OTHER, Tuple::getArrayOfJsons),
10697
JSONB(3802, true, Object.class, JDBCType.OTHER, Tuple::getJson),
10798
JSONB_ARRAY(3807, true, Object[].class, JDBCType.OTHER, Tuple::getArrayOfJsons),
108-
XML(142, true, Object.class, JDBCType.OTHER),
109-
XML_ARRAY(143, true, Object[].class, JDBCType.OTHER),
99+
XML(142, true, Object.class, JDBCType.SQLXML),
100+
XML_ARRAY(143, true, Object[].class, JDBCType.SQLXML),
110101
POINT(600, true, Point.class, JDBCType.OTHER),
111102
POINT_ARRAY(1017, true, Point[].class, JDBCType.OTHER),
112103
LINE(628, true, Line.class, JDBCType.OTHER),
@@ -229,5 +220,8 @@ static DataType lookup(Class<?> type) {
229220
encodingTypeToDataType.put(Polygon[].class, POLYGON_ARRAY);
230221
encodingTypeToDataType.put(Circle.class, CIRCLE);
231222
encodingTypeToDataType.put(Circle[].class, CIRCLE_ARRAY);
223+
224+
encodingTypeToDataType.put(PgSQLXML.class, XML);
225+
encodingTypeToDataType.put(PgSQLXML[].class, XML_ARRAY);
232226
}
233227
}

Diff for: vertx-pg-client/src/main/java/io/vertx/pgclient/impl/codec/DataTypeCodec.java

+47-21
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@
2020
import io.netty.buffer.ByteBuf;
2121
import io.netty.buffer.Unpooled;
2222
import io.netty.handler.codec.DecoderException;
23+
import io.vertx.core.buffer.Buffer;
2324
import io.vertx.core.impl.logging.Logger;
2425
import io.vertx.core.impl.logging.LoggerFactory;
2526
import io.vertx.core.json.Json;
26-
import io.vertx.sqlclient.Tuple;
27-
import io.vertx.sqlclient.data.Numeric;
28-
import io.vertx.pgclient.data.*;
29-
import io.vertx.pgclient.impl.util.UTF8StringEndDetector;
30-
import io.vertx.core.buffer.Buffer;
3127
import io.vertx.core.json.JsonArray;
3228
import io.vertx.core.json.JsonObject;
29+
import io.vertx.pgclient.data.*;
30+
import io.vertx.pgclient.impl.util.UTF8StringEndDetector;
31+
import io.vertx.sqlclient.Tuple;
32+
import io.vertx.sqlclient.data.Numeric;
3333
import io.vertx.sqlclient.impl.codec.CommonCodec;
3434

3535
import java.net.Inet4Address;
@@ -50,7 +50,7 @@
5050

5151
import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
5252
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;
53-
import static java.util.concurrent.TimeUnit.*;
53+
import static java.util.concurrent.TimeUnit.NANOSECONDS;
5454

5555
/**
5656
* @author <a href="mailto:[email protected]">Julien Viet</a>
@@ -91,6 +91,8 @@ public class DataTypeCodec {
9191
private static final OffsetDateTime OFFSET_DATE_TIME_EPOCH = LocalDateTime.of(2000, 1, 1, 0, 0, 0).atOffset(ZoneOffset.UTC);
9292
private static final Inet[] empty_inet_array = new Inet[0];
9393
private static final Money[] empty_money_array = new Money[0];
94+
private static final PgSQLXML[] empty_pgsqlxml_array = new PgSQLXML[0];
95+
9496

9597
// Sentinel used when an object is refused by the data type
9698
public static final Object REFUSED_SENTINEL = new Object();
@@ -107,7 +109,7 @@ public class DataTypeCodec {
107109
private static final IntFunction<OffsetTime[]> OFFSETTIME_ARRAY_FACTORY = size -> size == 0 ? empty_offset_time_array : new OffsetTime[size];
108110
private static final IntFunction<LocalDateTime[]> LOCALDATETIME_ARRAY_FACTORY = size -> size == 0 ? empty_local_date_time_array : new LocalDateTime[size];
109111
private static final IntFunction<OffsetDateTime[]> OFFSETDATETIME_ARRAY_FACTORY = size -> size == 0 ? empty_offset_date_time_array : new OffsetDateTime[size];
110-
private static final IntFunction<Buffer[]> BUFFER_ARRAY_FACTORY =size -> size == 0 ? empty_buffer_array : new Buffer[size];
112+
private static final IntFunction<Buffer[]> BUFFER_ARRAY_FACTORY = size -> size == 0 ? empty_buffer_array : new Buffer[size];
111113
private static final IntFunction<UUID[]> UUID_ARRAY_FACTORY = size -> size == 0 ? empty_uuid_array : new UUID[size];
112114
private static final IntFunction<Object[]> JSON_ARRAY_FACTORY = size -> size == 0 ? empty_json_array : new Object[size];
113115
private static final IntFunction<Numeric[]> NUMERIC_ARRAY_FACTORY = size -> size == 0 ? empty_numeric_array : new Numeric[size];
@@ -121,20 +123,18 @@ public class DataTypeCodec {
121123
private static final IntFunction<Interval[]> INTERVAL_ARRAY_FACTORY = size -> size == 0 ? empty_interval_array : new Interval[size];
122124
private static final IntFunction<Inet[]> INET_ARRAY_FACTORY = size -> size == 0 ? empty_inet_array : new Inet[size];
123125
private static final IntFunction<Money[]> MONEY_ARRAY_FACTORY = size -> size == 0 ? empty_money_array : new Money[size];
124-
126+
private static final IntFunction<PgSQLXML[]> PGSQLXML_ARRAY_FACTORY = size -> size == 0 ? empty_pgsqlxml_array : new PgSQLXML[size];
125127
private static final java.time.format.DateTimeFormatter TIMETZ_FORMAT = new DateTimeFormatterBuilder()
126128
.parseCaseInsensitive()
127129
.append(ISO_LOCAL_TIME)
128130
.appendOffset("+HH:mm", "00:00")
129131
.toFormatter();
130-
131132
private static final java.time.format.DateTimeFormatter TIMESTAMP_FORMAT = new DateTimeFormatterBuilder()
132133
.parseCaseInsensitive()
133134
.append(ISO_LOCAL_DATE)
134135
.appendLiteral(' ')
135136
.append(ISO_LOCAL_TIME)
136137
.toFormatter();
137-
138138
private static final java.time.format.DateTimeFormatter TIMESTAMPTZ_FORMAT = new DateTimeFormatterBuilder()
139139
.append(TIMESTAMP_FORMAT)
140140
.appendOffset("+HH:mm", "00:00")
@@ -360,6 +360,12 @@ public static void encodeBinary(DataType id, Object value, ByteBuf buff) {
360360
case MONEY_ARRAY:
361361
binaryEncodeArray((Money[]) value, DataType.MONEY, buff);
362362
break;
363+
case XML:
364+
binaryEncodePgXMLSQL((PgSQLXML) value, buff);
365+
break;
366+
case XML_ARRAY:
367+
binaryEncodeArray((PgSQLXML[]) value, DataType.XML, buff);
368+
break;
363369
default:
364370
logger.debug("Data type " + id + " does not support binary encoding");
365371
defaultEncodeBinary(value, buff);
@@ -497,6 +503,10 @@ public static Object decodeBinary(DataType id, int index, int len, ByteBuf buff)
497503
return binaryDecodeMoney(index, len, buff);
498504
case MONEY_ARRAY:
499505
return binaryDecodeArray(MONEY_ARRAY_FACTORY, DataType.MONEY, index, len, buff);
506+
case XML:
507+
return binaryDecodePgXMLSQL(index, len, buff);
508+
case XML_ARRAY:
509+
return binaryDecodeArray(PGSQLXML_ARRAY_FACTORY, DataType.XML, index, len, buff);
500510
default:
501511
logger.debug("Data type " + id + " does not support binary decoding");
502512
return defaultDecodeBinary(index, len, buff);
@@ -637,6 +647,10 @@ public static Object decodeText(DataType id, int index, int len, ByteBuf buff) {
637647
return textDecodeMoney(index, len, buff);
638648
case MONEY_ARRAY:
639649
return textDecodeArray(MONEY_ARRAY_FACTORY, DataType.MONEY, index, len, buff);
650+
case XML:
651+
return textDecodePgSQLXML(index, len, buff);
652+
case XML_ARRAY:
653+
return textDecodeArray(PGSQLXML_ARRAY_FACTORY, DataType.XML, index, len, buff);
640654
default:
641655
return defaultDecodeText(index, len, buff);
642656
}
@@ -669,7 +683,7 @@ private static Boolean binaryDecodeBOOL(int index, int len, ByteBuf buff) {
669683
}
670684

671685
private static Boolean textDecodeBOOL(int index, int len, ByteBuf buff) {
672-
if(buff.getByte(index) == 't') {
686+
if (buff.getByte(index) == 't') {
673687
return Boolean.TRUE;
674688
} else {
675689
return Boolean.FALSE;
@@ -770,7 +784,7 @@ private static Line textDecodeLine(int index, int len, ByteBuf buff) {
770784

771785
private static LineSegment textDecodeLseg(int index, int len, ByteBuf buff) {
772786
// Lseg representation: [p1,p2]
773-
int idxOfPointsSeparator = buff.indexOf(index, index+len, (byte) ')') + 1;
787+
int idxOfPointsSeparator = buff.indexOf(index, index + len, (byte) ')') + 1;
774788
int lenOfP1 = idxOfPointsSeparator - index - 1;
775789
Point p1 = textDecodePOINT(index + 1, lenOfP1, buff);
776790
Point p2 = textDecodePOINT(idxOfPointsSeparator + 1, len - lenOfP1 - 3, buff);
@@ -779,7 +793,7 @@ private static LineSegment textDecodeLseg(int index, int len, ByteBuf buff) {
779793

780794
private static Box textDecodeBox(int index, int len, ByteBuf buff) {
781795
// Box representation: p1,p2
782-
int idxOfPointsSeparator = buff.indexOf(index, index+len, (byte) ')') + 1;
796+
int idxOfPointsSeparator = buff.indexOf(index, index + len, (byte) ')') + 1;
783797
int lenOfUpperRightCornerPoint = idxOfPointsSeparator - index;
784798
Point upperRightCorner = textDecodePOINT(index, lenOfUpperRightCornerPoint, buff);
785799
Point lowerLeftCorner = textDecodePOINT(idxOfPointsSeparator + 1, len - lenOfUpperRightCornerPoint - 1, buff);
@@ -905,7 +919,7 @@ private static Interval textDecodeINTERVAL(int index, int len, ByteBuf buff) {
905919
: Integer.parseInt(timeChunk.substring(sidx));
906920
} else {
907921
// seconds with microseconds
908-
seconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx).substring(0, m))
922+
seconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx).substring(0, m))
909923
: Integer.parseInt(timeChunk.substring(sidx).substring(0, m));
910924
microseconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx).substring(m + 1))
911925
: Integer.parseInt(timeChunk.substring(sidx).substring(m + 1));
@@ -990,7 +1004,6 @@ private static String textDecodeNAME(int index, int len, ByteBuf buff) {
9901004
return buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString();
9911005
}
9921006

993-
9941007
private static void binaryEncodeNAME(String value, ByteBuf buff) {
9951008
String s = String.valueOf(value);
9961009
buff.writeCharSequence(s, StandardCharsets.UTF_8);
@@ -1466,7 +1479,7 @@ private static void binaryEncodeMoney(Money money, ByteBuf buff) {
14661479

14671480
private static Money binaryDecodeMoney(int index, int len, ByteBuf buff) {
14681481
long value = binaryDecodeINT8(index, len, buff);
1469-
return new Money(value / 100, Math.abs(((int)value % 100)));
1482+
return new Money(value / 100, Math.abs(((int) value % 100)));
14701483
}
14711484

14721485
private static String binaryDecodeTsQuery(int index, int len, ByteBuf buff) {
@@ -1477,6 +1490,19 @@ private static void binaryEncodeTsQuery(String value, ByteBuf buff) {
14771490
buff.writeCharSequence(String.valueOf(value), StandardCharsets.UTF_8);
14781491
}
14791492

1493+
private static PgSQLXML binaryDecodePgXMLSQL(int index, int len, ByteBuf buff) {
1494+
return new PgSQLXML(buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString());
1495+
}
1496+
1497+
private static void binaryEncodePgXMLSQL(PgSQLXML value, ByteBuf buff) {
1498+
buff.writeCharSequence(value.toString(), StandardCharsets.UTF_8);
1499+
}
1500+
1501+
private static PgSQLXML textDecodePgSQLXML(int index, int len, ByteBuf buff) {
1502+
String s = textDecodeVARCHAR(index, len, buff);
1503+
return new PgSQLXML(s);
1504+
}
1505+
14801506
private static String textDecodeTsVector(int index, int len, ByteBuf buff) {
14811507
return buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString();
14821508
}
@@ -1535,7 +1561,7 @@ private static Money textDecodeMoney(int index, int len, ByteBuf buff) {
15351561
* Decode the specified {@code buff} formatted as an hex string starting at the buffer readable index
15361562
* with the specified {@code length} to a {@link Buffer}.
15371563
*
1538-
* @param len the hex string length
1564+
* @param len the hex string length
15391565
* @param buff the byte buff to read from
15401566
* @return the decoded value as a Buffer
15411567
*/
@@ -1551,7 +1577,7 @@ private static Buffer decodeHexStringToBytes(int index, int len, ByteBuf buff) {
15511577
}
15521578

15531579
private static byte decodeHexChar(byte ch) {
1554-
return (byte)(((ch & 0x1F) + ((ch >> 6) * 0x19) - 0x10) & 0x0F);
1580+
return (byte) (((ch & 0x1F) + ((ch >> 6) * 0x19) - 0x10) & 0x0F);
15551581
}
15561582

15571583
private static boolean isHexFormat(int index, int len, ByteBuf buff) {
@@ -1619,7 +1645,7 @@ private static <T> T[] binaryDecodeArray(IntFunction<T[]> supplier, DataType typ
16191645
return array;
16201646
}
16211647

1622-
private static <T> void binaryEncodeArray(T[] values, DataType type, ByteBuf buff){
1648+
private static <T> void binaryEncodeArray(T[] values, DataType type, ByteBuf buff) {
16231649
int startIndex = buff.writerIndex();
16241650
buff.writeInt(1); // ndim
16251651
buff.writeInt(0); // dataoffset
@@ -1681,7 +1707,7 @@ private static <T> T textDecodeArrayElement(DataType type, int index, int len, B
16811707
// Some escaping - improve that later...
16821708
String s = buff.toString(index + 1, len - 2, StandardCharsets.UTF_8);
16831709
StringBuilder sb = new StringBuilder();
1684-
for (int i = 0;i < s.length();i++) {
1710+
for (int i = 0; i < s.length(); i++) {
16851711
char c = s.charAt(i);
16861712
if (c == '\\') {
16871713
c = s.charAt(++i);
@@ -1696,7 +1722,7 @@ private static <T> T textDecodeArrayElement(DataType type, int index, int len, B
16961722
}
16971723
}
16981724

1699-
private static <T> void textEncodeArray(T[] values, DataType type, ByteBuf buff){
1725+
private static <T> void textEncodeArray(T[] values, DataType type, ByteBuf buff) {
17001726
buff.writeByte('{');
17011727
int len = values.length;
17021728
for (int i = 0; i < len; i++) {

0 commit comments

Comments
 (0)