use of org.postgresql.geometric.PGline in project debezium by debezium.
the class Wal2JsonReplicationMessage method getValue.
/**
* Converts the value (string representation) coming from wal2json plugin to
* a Java value based on the type of the column from the message. This value will be converted later on if necessary by the
* {@link PostgresValueConverter#converter(Column, Field)} instance to match whatever the Connect schema type expects.
*
* Note that the logic here is tightly coupled (i.e. dependent) on the wal2json plugin logic which writes the actual
* JSON messages.
* @param a supplier to get a connection to Postgres instance for array handling
*
* @return the value; may be null
*/
public Object getValue(String columnName, PostgresType type, String fullType, Value rawValue, final PgConnectionSupplier connection, boolean includeUnknownDatatypes) {
if (rawValue.isNull()) {
// nulls are null
return null;
}
if (type.isArrayType()) {
try {
final String dataString = rawValue.asString();
PgArray arrayData = new PgArray(connection.get(), type.getOid(), dataString);
Object deserializedArray = arrayData.getArray();
return Arrays.asList((Object[]) deserializedArray);
} catch (SQLException e) {
LOGGER.warn("Unexpected exception trying to process PgArray ({}) column '{}', {}", fullType, columnName, e);
}
return null;
}
switch(type.getName()) {
// plus aliases from the shorter names produced by older wal2json
case "boolean":
case "bool":
return rawValue.asBoolean();
case "integer":
case "int":
case "int4":
case "smallint":
case "int2":
case "smallserial":
case "serial":
case "serial2":
case "serial4":
case "oid":
return rawValue.asInteger();
case "bigint":
case "bigserial":
case "int8":
return rawValue.asLong();
case "real":
case "float4":
return rawValue.isNumber() ? rawValue.asFloat() : Float.valueOf(rawValue.asString());
case "double precision":
case "float8":
return rawValue.isNumber() ? rawValue.asDouble() : Double.valueOf(rawValue.asString());
case "numeric":
case "decimal":
if (rawValue.isInteger()) {
return new SpecialValueDecimal(new BigDecimal(rawValue.asInteger()));
} else if (rawValue.isLong()) {
return new SpecialValueDecimal(new BigDecimal(rawValue.asLong()));
} else if (rawValue.isBigInteger()) {
return new SpecialValueDecimal(new BigDecimal(rawValue.asBigInteger()));
}
return SpecialValueDecimal.valueOf(rawValue.asString());
case "character":
case "char":
case "character varying":
case "varchar":
case "bpchar":
case "text":
return rawValue.asString();
case "date":
return DateTimeFormat.get().date(rawValue.asString());
case "timestamp with time zone":
case "timestamptz":
return DateTimeFormat.get().timestampWithTimeZone(rawValue.asString());
case "timestamp":
case "timestamp without time zone":
return DateTimeFormat.get().timestamp(rawValue.asString());
case "time":
case "time without time zone":
return DateTimeFormat.get().time(rawValue.asString());
case "time with time zone":
case "timetz":
return DateTimeFormat.get().timeWithTimeZone(rawValue.asString());
case "bytea":
return Strings.hexStringToByteArray(rawValue.asString());
// i.e. those values won't actually be propagated to the outbound message until that's the case
case "box":
try {
return new PGbox(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "circle":
try {
return new PGcircle(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse circle {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "interval":
try {
return new PGInterval(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "line":
try {
return new PGline(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "lseg":
try {
return new PGlseg(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "money":
try {
return new PGmoney(rawValue.asString()).val;
} catch (final SQLException e) {
LOGGER.error("Failed to parse money {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "path":
try {
return new PGpath(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "point":
try {
return new PGpoint(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
case "polygon":
try {
return new PGpolygon(rawValue.asString());
} catch (final SQLException e) {
LOGGER.error("Failed to parse point {}, {}", rawValue.asString(), e);
throw new ConnectException(e);
}
// ValueConverter turns them into the correct types
case "geometry":
case "geography":
return rawValue.asString();
case "bit":
case "bit varying":
case "varbit":
case "json":
case "jsonb":
case "xml":
case "uuid":
case "tstzrange":
return rawValue.asString();
// TODO: improve with more specific/useful classes here?
case "cidr":
case "inet":
case "macaddr":
case "macaddr8":
case "pg_lsn":
case "tsquery":
case "tsvector":
case "txid_snapshot":
// catch-all for unknown (extension module/custom) types
default:
break;
}
if (includeUnknownDatatypes) {
// this includes things like PostGIS geometries or other custom types.
// leave up to the downstream message recipient to deal with.
LOGGER.debug("processing column '{}' with unknown data type '{}' as byte array", columnName, fullType);
return rawValue.asString();
}
LOGGER.debug("Unknown column type {} for column {} – ignoring", fullType, columnName);
return null;
}
Aggregations