Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add xmltype in postgres #1112

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,9 @@

import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.pgclient.data.Box;
import io.vertx.pgclient.data.Circle;
import io.vertx.pgclient.data.Line;
import io.vertx.pgclient.data.LineSegment;
import io.vertx.pgclient.data.*;
import io.vertx.sqlclient.Row;
import io.vertx.sqlclient.data.Numeric;
import io.vertx.pgclient.data.Path;
import io.vertx.pgclient.data.Polygon;
import io.vertx.pgclient.data.Interval;
import io.vertx.pgclient.data.Point;
import io.vertx.sqlclient.impl.ArrayTuple;
import io.vertx.sqlclient.impl.RowDesc;
import io.vertx.core.buffer.Buffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,9 @@
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.pgclient.data.Box;
import io.vertx.pgclient.data.Circle;
import io.vertx.pgclient.data.Inet;
import io.vertx.pgclient.data.Line;
import io.vertx.pgclient.data.LineSegment;
import io.vertx.pgclient.data.Money;
import io.vertx.pgclient.data.*;
import io.vertx.sqlclient.Tuple;
import io.vertx.sqlclient.data.Numeric;
import io.vertx.pgclient.data.Interval;
import io.vertx.pgclient.data.Path;
import io.vertx.pgclient.data.Point;
import io.vertx.pgclient.data.Polygon;
import io.vertx.core.buffer.Buffer;

import java.sql.JDBCType;
Expand Down Expand Up @@ -105,8 +96,8 @@ public enum DataType {
JSON_ARRAY(199, true, Object[].class, JDBCType.OTHER, Tuple::getArrayOfJsons),
JSONB(3802, true, Object.class, JDBCType.OTHER, Tuple::getJson),
JSONB_ARRAY(3807, true, Object[].class, JDBCType.OTHER, Tuple::getArrayOfJsons),
XML(142, true, Object.class, JDBCType.OTHER),
XML_ARRAY(143, true, Object[].class, JDBCType.OTHER),
XML(142, true, String.class, JDBCType.SQLXML),
XML_ARRAY(143, true, String[].class, JDBCType.SQLXML),
POINT(600, true, Point.class, JDBCType.OTHER),
POINT_ARRAY(1017, true, Point[].class, JDBCType.OTHER),
LINE(628, true, Line.class, JDBCType.OTHER),
Expand Down Expand Up @@ -229,5 +220,8 @@ static DataType lookup(Class<?> type) {
encodingTypeToDataType.put(Polygon[].class, POLYGON_ARRAY);
encodingTypeToDataType.put(Circle.class, CIRCLE);
encodingTypeToDataType.put(Circle[].class, CIRCLE_ARRAY);

// encodingTypeToDataType.put(String.class, XML);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this commented ?

Copy link
Author

@mauravan mauravan Jan 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the Comment from the 22. of Dec:

So i did it using String now and it works just fine i think - one problem i encountered was the mapping in the DataType.java because there is already a mapping for String to Varchar

encodingTypeToDataType.put(String.class, VARCHAR); encodingTypeToDataType.put(String[].class, VARCHAR_ARRAY); encodingTypeToDataType.put(String.class, XML); encodingTypeToDataType.put(String[].class, XML_ARRAY);

Which seems to be only important in case of a PrepareStatementCommand with parameterTypes which the test i'm executing are apparently not using. Maybe you have some more insight into that?

// encodingTypeToDataType.put(String[].class, XML_ARRAY);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.DecoderException;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.json.Json;
import io.vertx.sqlclient.Tuple;
import io.vertx.sqlclient.data.Numeric;
import io.vertx.pgclient.data.*;
import io.vertx.pgclient.impl.util.UTF8StringEndDetector;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.pgclient.data.*;
import io.vertx.pgclient.impl.util.UTF8StringEndDetector;
import io.vertx.sqlclient.Tuple;
import io.vertx.sqlclient.data.Numeric;
import io.vertx.sqlclient.impl.codec.CommonCodec;

import java.net.Inet4Address;
Expand All @@ -50,18 +50,22 @@

import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE;
import static java.time.format.DateTimeFormatter.ISO_LOCAL_TIME;
import static java.util.concurrent.TimeUnit.*;
import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
* @author <a href="mailto:[email protected]">Julien Viet</a>
* @author <a href="mailto:[email protected]">Emad Alblueshi</a>
*
* <p>
* See also https://www.npgsql.org/doc/dev/type-representations.html
*/
public class DataTypeCodec {

// Sentinel used when an object is refused by the data type
public static final Object REFUSED_SENTINEL = new Object();
// 4714-11-24 00:00:00 BC
public static final LocalDateTime LDT_MINUS_INFINITY = LocalDateTime.parse("4714-11-24 00:00:00 BC",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss G", Locale.ROOT));
private static final Logger logger = LoggerFactory.getLogger(DataTypeCodec.class);

private static final String[] empty_string_array = new String[0];
private static final LocalDate[] empty_local_date_array = new LocalDate[0];
private static final LocalTime[] empty_local_time_array = new LocalTime[0];
Expand All @@ -88,13 +92,11 @@ public class DataTypeCodec {
private static final Double[] empty_double_array = new Double[0];
private static final LocalDate LOCAL_DATE_EPOCH = LocalDate.of(2000, 1, 1);
private static final LocalDateTime LOCAL_DATE_TIME_EPOCH = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
// 294277-01-09 04:00:54.775807
public static final LocalDateTime LDT_PLUS_INFINITY = LOCAL_DATE_TIME_EPOCH.plus(Long.MAX_VALUE, ChronoUnit.MICROS);
private static final OffsetDateTime OFFSET_DATE_TIME_EPOCH = LocalDateTime.of(2000, 1, 1, 0, 0, 0).atOffset(ZoneOffset.UTC);
private static final Inet[] empty_inet_array = new Inet[0];
private static final Money[] empty_money_array = new Money[0];

// Sentinel used when an object is refused by the data type
public static final Object REFUSED_SENTINEL = new Object();

private static final IntFunction<Boolean[]> BOOLEAN_ARRAY_FACTORY = size -> size == 0 ? empty_boolean_array : new Boolean[size];
private static final IntFunction<Short[]> SHORT_ARRAY_FACTORY = size -> size == 0 ? empty_short_array : new Short[size];
private static final IntFunction<Integer[]> INTEGER_ARRAY_FACTORY = size -> size == 0 ? empty_integer_array : new Integer[size];
Expand All @@ -107,7 +109,7 @@ public class DataTypeCodec {
private static final IntFunction<OffsetTime[]> OFFSETTIME_ARRAY_FACTORY = size -> size == 0 ? empty_offset_time_array : new OffsetTime[size];
private static final IntFunction<LocalDateTime[]> LOCALDATETIME_ARRAY_FACTORY = size -> size == 0 ? empty_local_date_time_array : new LocalDateTime[size];
private static final IntFunction<OffsetDateTime[]> OFFSETDATETIME_ARRAY_FACTORY = size -> size == 0 ? empty_offset_date_time_array : new OffsetDateTime[size];
private static final IntFunction<Buffer[]> BUFFER_ARRAY_FACTORY =size -> size == 0 ? empty_buffer_array : new Buffer[size];
private static final IntFunction<Buffer[]> BUFFER_ARRAY_FACTORY = size -> size == 0 ? empty_buffer_array : new Buffer[size];
private static final IntFunction<UUID[]> UUID_ARRAY_FACTORY = size -> size == 0 ? empty_uuid_array : new UUID[size];
private static final IntFunction<Object[]> JSON_ARRAY_FACTORY = size -> size == 0 ? empty_json_array : new Object[size];
private static final IntFunction<Numeric[]> NUMERIC_ARRAY_FACTORY = size -> size == 0 ? empty_numeric_array : new Numeric[size];
Expand All @@ -121,20 +123,17 @@ public class DataTypeCodec {
private static final IntFunction<Interval[]> INTERVAL_ARRAY_FACTORY = size -> size == 0 ? empty_interval_array : new Interval[size];
private static final IntFunction<Inet[]> INET_ARRAY_FACTORY = size -> size == 0 ? empty_inet_array : new Inet[size];
private static final IntFunction<Money[]> MONEY_ARRAY_FACTORY = size -> size == 0 ? empty_money_array : new Money[size];

private static final java.time.format.DateTimeFormatter TIMETZ_FORMAT = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_TIME)
.appendOffset("+HH:mm", "00:00")
.toFormatter();

private static final java.time.format.DateTimeFormatter TIMESTAMP_FORMAT = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.append(ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(ISO_LOCAL_TIME)
.toFormatter();

private static final java.time.format.DateTimeFormatter TIMESTAMPTZ_FORMAT = new DateTimeFormatterBuilder()
.append(TIMESTAMP_FORMAT)
.appendOffset("+HH:mm", "00:00")
Expand Down Expand Up @@ -277,13 +276,13 @@ public static void encodeBinary(DataType id, Object value, ByteBuf buff) {
binaryEncodeArray((UUID[]) value, DataType.UUID, buff);
break;
case JSON:
binaryEncodeJSON((Object) value, buff);
binaryEncodeJSON(value, buff);
break;
case JSON_ARRAY:
binaryEncodeArray((Object[]) value, DataType.JSON, buff);
break;
case JSONB:
binaryEncodeJSONB((Object) value, buff);
binaryEncodeJSONB(value, buff);
break;
case JSONB_ARRAY:
binaryEncodeArray((Object[]) value, DataType.JSONB, buff);
Expand Down Expand Up @@ -360,6 +359,12 @@ public static void encodeBinary(DataType id, Object value, ByteBuf buff) {
case MONEY_ARRAY:
binaryEncodeArray((Money[]) value, DataType.MONEY, buff);
break;
case XML:
binaryEncodeXML((String) value, buff);
break;
case XML_ARRAY:
binaryEncodeArray((String[]) value, DataType.XML, buff);
break;
default:
logger.debug("Data type " + id + " does not support binary encoding");
defaultEncodeBinary(value, buff);
Expand Down Expand Up @@ -497,6 +502,10 @@ public static Object decodeBinary(DataType id, int index, int len, ByteBuf buff)
return binaryDecodeMoney(index, len, buff);
case MONEY_ARRAY:
return binaryDecodeArray(MONEY_ARRAY_FACTORY, DataType.MONEY, index, len, buff);
case XML:
return binaryDecodeXML(index, len, buff);
case XML_ARRAY:
return binaryDecodeArray(STRING_ARRAY_FACTORY, DataType.XML, index, len, buff);
default:
logger.debug("Data type " + id + " does not support binary decoding");
return defaultDecodeBinary(index, len, buff);
Expand Down Expand Up @@ -637,6 +646,10 @@ public static Object decodeText(DataType id, int index, int len, ByteBuf buff) {
return textDecodeMoney(index, len, buff);
case MONEY_ARRAY:
return textDecodeArray(MONEY_ARRAY_FACTORY, DataType.MONEY, index, len, buff);
case XML:
return textDecodeXML(index, len, buff);
case XML_ARRAY:
return textDecodeArray(STRING_ARRAY_FACTORY, DataType.XML, index, len, buff);
default:
return defaultDecodeText(index, len, buff);
}
Expand Down Expand Up @@ -669,7 +682,7 @@ private static Boolean binaryDecodeBOOL(int index, int len, ByteBuf buff) {
}

private static Boolean textDecodeBOOL(int index, int len, ByteBuf buff) {
if(buff.getByte(index) == 't') {
if (buff.getByte(index) == 't') {
return Boolean.TRUE;
} else {
return Boolean.FALSE;
Expand Down Expand Up @@ -770,7 +783,7 @@ private static Line textDecodeLine(int index, int len, ByteBuf buff) {

private static LineSegment textDecodeLseg(int index, int len, ByteBuf buff) {
// Lseg representation: [p1,p2]
int idxOfPointsSeparator = buff.indexOf(index, index+len, (byte) ')') + 1;
int idxOfPointsSeparator = buff.indexOf(index, index + len, (byte) ')') + 1;
int lenOfP1 = idxOfPointsSeparator - index - 1;
Point p1 = textDecodePOINT(index + 1, lenOfP1, buff);
Point p2 = textDecodePOINT(idxOfPointsSeparator + 1, len - lenOfP1 - 3, buff);
Expand All @@ -779,7 +792,7 @@ private static LineSegment textDecodeLseg(int index, int len, ByteBuf buff) {

private static Box textDecodeBox(int index, int len, ByteBuf buff) {
// Box representation: p1,p2
int idxOfPointsSeparator = buff.indexOf(index, index+len, (byte) ')') + 1;
int idxOfPointsSeparator = buff.indexOf(index, index + len, (byte) ')') + 1;
int lenOfUpperRightCornerPoint = idxOfPointsSeparator - index;
Point upperRightCorner = textDecodePOINT(index, lenOfUpperRightCornerPoint, buff);
Point lowerLeftCorner = textDecodePOINT(idxOfPointsSeparator + 1, len - lenOfUpperRightCornerPoint - 1, buff);
Expand Down Expand Up @@ -862,7 +875,7 @@ private static Interval textDecodeINTERVAL(int index, int len, ByteBuf buff) {
int years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds = 0, microseconds = 0;
final List<String> chunks = new ArrayList<>(7);
int idx = 0;
for (;;) {
for (; ; ) {
int newIdx = value.indexOf(' ', idx);
if (newIdx == -1) {
chunks.add(value.substring(idx));
Expand Down Expand Up @@ -895,25 +908,25 @@ private static Interval textDecodeINTERVAL(int index, int len, ByteBuf buff) {
boolean isNeg = timeChunk.charAt(0) == '-';
if (isNeg) timeChunk = timeChunk.substring(1);
int sidx = 0;
for (;;) {
for (; ; ) {
int newIdx = timeChunk.indexOf(':', sidx);
if (newIdx == -1) {
int m = timeChunk.substring(sidx).indexOf('.');
if(m == -1) {
if (m == -1) {
// seconds without microseconds
seconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx))
: Integer.parseInt(timeChunk.substring(sidx));
} else {
// seconds with microseconds
seconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx).substring(0, m))
seconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx).substring(0, m))
: Integer.parseInt(timeChunk.substring(sidx).substring(0, m));
microseconds = isNeg ? -Integer.parseInt(timeChunk.substring(sidx).substring(m + 1))
: Integer.parseInt(timeChunk.substring(sidx).substring(m + 1));
}
break;
}
// hours
if(sidx == 0) {
if (sidx == 0) {
hours = isNeg ? -Integer.parseInt(timeChunk.substring(sidx, newIdx))
: Integer.parseInt(timeChunk.substring(sidx, newIdx));
} else {
Expand Down Expand Up @@ -990,7 +1003,6 @@ private static String textDecodeNAME(int index, int len, ByteBuf buff) {
return buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString();
}


private static void binaryEncodeNAME(String value, ByteBuf buff) {
String s = String.valueOf(value);
buff.writeCharSequence(s, StandardCharsets.UTF_8);
Expand Down Expand Up @@ -1069,12 +1081,6 @@ private static OffsetTime textDecodeTIMETZ(int index, int len, ByteBuf buff) {
return OffsetTime.parse(cs, TIMETZ_FORMAT);
}

// 294277-01-09 04:00:54.775807
public static final LocalDateTime LDT_PLUS_INFINITY = LOCAL_DATE_TIME_EPOCH.plus(Long.MAX_VALUE, ChronoUnit.MICROS);
// 4714-11-24 00:00:00 BC
public static final LocalDateTime LDT_MINUS_INFINITY = LocalDateTime.parse("4714-11-24 00:00:00 BC",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss G", Locale.ROOT));

private static void binaryEncodeTIMESTAMP(LocalDateTime value, ByteBuf buff) {
if (value.compareTo(LDT_PLUS_INFINITY) >= 0) {
value = LDT_PLUS_INFINITY;
Expand Down Expand Up @@ -1466,7 +1472,7 @@ private static void binaryEncodeMoney(Money money, ByteBuf buff) {

private static Money binaryDecodeMoney(int index, int len, ByteBuf buff) {
long value = binaryDecodeINT8(index, len, buff);
return new Money(value / 100, Math.abs(((int)value % 100)));
return new Money(value / 100, Math.abs(((int) value % 100)));
}

private static String binaryDecodeTsQuery(int index, int len, ByteBuf buff) {
Expand All @@ -1477,6 +1483,18 @@ private static void binaryEncodeTsQuery(String value, ByteBuf buff) {
buff.writeCharSequence(String.valueOf(value), StandardCharsets.UTF_8);
}

private static String binaryDecodeXML(int index, int len, ByteBuf buff) {
return buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString();
}

private static void binaryEncodeXML(String value, ByteBuf buff) {
buff.writeCharSequence(value, StandardCharsets.UTF_8);
}

private static String textDecodeXML(int index, int len, ByteBuf buff) {
return buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString();
}

private static String textDecodeTsVector(int index, int len, ByteBuf buff) {
return buff.getCharSequence(index, len, StandardCharsets.UTF_8).toString();
}
Expand Down Expand Up @@ -1535,7 +1553,7 @@ private static Money textDecodeMoney(int index, int len, ByteBuf buff) {
* Decode the specified {@code buff} formatted as an hex string starting at the buffer readable index
* with the specified {@code length} to a {@link Buffer}.
*
* @param len the hex string length
* @param len the hex string length
* @param buff the byte buff to read from
* @return the decoded value as a Buffer
*/
Expand All @@ -1551,7 +1569,7 @@ private static Buffer decodeHexStringToBytes(int index, int len, ByteBuf buff) {
}

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

private static boolean isHexFormat(int index, int len, ByteBuf buff) {
Expand Down Expand Up @@ -1619,7 +1637,7 @@ private static <T> T[] binaryDecodeArray(IntFunction<T[]> supplier, DataType typ
return array;
}

private static <T> void binaryEncodeArray(T[] values, DataType type, ByteBuf buff){
private static <T> void binaryEncodeArray(T[] values, DataType type, ByteBuf buff) {
int startIndex = buff.writerIndex();
buff.writeInt(1); // ndim
buff.writeInt(0); // dataoffset
Expand Down Expand Up @@ -1681,7 +1699,7 @@ private static <T> T textDecodeArrayElement(DataType type, int index, int len, B
// Some escaping - improve that later...
String s = buff.toString(index + 1, len - 2, StandardCharsets.UTF_8);
StringBuilder sb = new StringBuilder();
for (int i = 0;i < s.length();i++) {
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\') {
c = s.charAt(++i);
Expand All @@ -1696,7 +1714,7 @@ private static <T> T textDecodeArrayElement(DataType type, int index, int len, B
}
}

private static <T> void textEncodeArray(T[] values, DataType type, ByteBuf buff){
private static <T> void textEncodeArray(T[] values, DataType type, ByteBuf buff) {
buff.writeByte('{');
int len = values.length;
for (int i = 0; i < len; i++) {
Expand Down
Loading