protected List<SchemaAndValueField> schemaAndValuesForPostgisArrayTypes() { Schema geomSchema = Geometry.builder() .optional() .build(); List<Struct> values = Arrays.asList( // 'GEOMETRYCOLLECTION EMPTY'::postgis.geometry Geometry.createValue(geomSchema, DatatypeConverter.parseHexBinary("010700000000000000"), null), // 'POLYGON((166.51 -46.64, 178.52 -46.64, 178.52 -34.45, 166.51 -34.45, 166.51 -46.64))'::postgis.geometry Geometry.createValue(geomSchema, DatatypeConverter.parseHexBinary("01030000000100000005000000B81E85EB51D0644052B81E85EB5147C0713D0AD7A350664052B81E85EB5147C0713D0AD7A35066409A999999993941C0B81E85EB51D064409A999999993941C0B81E85EB51D0644052B81E85EB5147C0"), null) ); return Arrays.asList( // geometries are encoded here as HexEWKB new SchemaAndValueField("ga", SchemaBuilder.array(geomSchema).optional().build(), values ), new SchemaAndValueField("gann", SchemaBuilder.array(geomSchema).build(), values ) ); }
/** * Create a value for this schema using WKB * @param pointSchema a {@link Schema} instance which represents a point; may not be null * @param wkb the original Well-Known binary representation of the coordinate; may not be null * @param srid the coordinate reference system identifier; null if unset/unknown * @return a {@link Struct} which represents a Connect value for this schema; never null */ public static Struct createValue(Schema geomSchema, byte[] wkb, Integer srid) throws IllegalArgumentException { Struct result = Geometry.createValue(geomSchema, wkb, srid); double[] pt = parseWKBPoint(wkb); result.put(X_FIELD, pt[0]); result.put(Y_FIELD, pt[1]); return result; } }
/** * Returns a {@link SchemaBuilder} for a Geometry field, with all other default Schema settings. * * @return the schema * @see #builder() */ public static Schema schema() { return builder().build(); }
/** * Creates a value for this schema using 2 given coordinates. * * @param pointSchema a {@link Schema} instance which represents a point; may not be null * @param x the X coordinate of the point; may not be null * @param y the Y coordinate of the point; may not be null * @return a {@link Struct} which represents a Connect value for this schema; never null */ public static Struct createValue(Schema geomSchema, double x, double y){ // turn the specified points byte[] wkb = buildWKBPoint(x, y); Struct result = Geometry.createValue(geomSchema, wkb, null); result.put(X_FIELD, x); result.put(Y_FIELD, y); return result; }
@Test public void shouldLoadSchemaForPostgisTypes() throws Exception { TestHelper.executeDDL("init_postgis.ddl"); TestHelper.executeDDL("postgis_create_tables.ddl"); PostgresConnectorConfig config = new PostgresConnectorConfig(TestHelper.defaultConfig().build()); schema = TestHelper.getSchema(config); try (PostgresConnection connection = TestHelper.create()) { schema.refresh(connection, false); final String[] testTables = new String[] {"public.postgis_table"}; assertTablesIncluded(testTables); Arrays.stream(testTables).forEach(tableId -> assertKeySchema(tableId, "pk", Schema.INT32_SCHEMA)); assertTableSchema("public.postgis_table", "p, ml", Geometry.builder().optional().build(), Geography.builder().optional().build()); } }
protected List<SchemaAndValueField> schemaAndValuesForPostgisTypes() { Schema geomSchema = Geometry.builder().optional().build(); Schema geogSchema = Geography.builder().optional().build(); return Arrays.asList( // geometries are encoded here as HexEWKB new SchemaAndValueField("p", geomSchema, // 'SRID=3187;POINT(174.9479 -36.7208)'::postgis.geometry Geometry.createValue(geomSchema, DatatypeConverter.parseHexBinary("0101000020730C00001C7C613255DE6540787AA52C435C42C0"), 3187)), new SchemaAndValueField("ml", geogSchema, // 'MULTILINESTRING((169.1321 -44.7032, 167.8974 -44.6414))'::postgis.geography Geography.createValue(geogSchema, DatatypeConverter.parseHexBinary("0105000020E610000001000000010200000002000000A779C7293A2465400B462575025A46C0C66D3480B7FC6440C3D32B65195246C0"), 4326)) ); }
protected Object convertGeometry(Column column, Field fieldDefn, Object data) { final PostgisGeometry empty = PostgisGeometry.createEmpty(); return convertValue(column, fieldDefn, data, io.debezium.data.geometry.Geometry.createValue(fieldDefn.schema(), empty.getWkb(), empty.getSrid()), (r) -> { try { final Schema schema = fieldDefn.schema(); if (data instanceof byte[]) { PostgisGeometry geom = PostgisGeometry.fromHexEwkb(new String((byte[])data, "ASCII")); r.deliver(io.debezium.data.geometry.Geometry.createValue(schema, geom.getWkb(), geom.getSrid())); } else if (data instanceof PGobject) { PGobject pgo = (PGobject)data; PostgisGeometry geom = PostgisGeometry.fromHexEwkb(pgo.getValue()); r.deliver(io.debezium.data.geometry.Geometry.createValue(schema, geom.getWkb(), geom.getSrid())); } else if (data instanceof String) { PostgisGeometry geom = PostgisGeometry.fromHexEwkb((String)data); r.deliver(io.debezium.data.geometry.Geometry.createValue(schema, geom.getWkb(), geom.getSrid())); } } catch (IllegalArgumentException | UnsupportedEncodingException e) { logger.warn("Error converting to a Geometry type", column); } }); }
|| matches(typeName, "MULTIPOLYGON") || isGeometryCollection(typeName)) { return io.debezium.data.geometry.Geometry.builder();
protected List<SchemaAndValueField> schemaAndValuesForPostgisArrayTypes() { Schema geomSchema = Geometry.builder() .optional() .build(); List<Struct> values = Arrays.asList( // 'GEOMETRYCOLLECTION EMPTY'::postgis.geometry Geometry.createValue(geomSchema, DatatypeConverter.parseHexBinary("010700000000000000"), null), // 'POLYGON((166.51 -46.64, 178.52 -46.64, 178.52 -34.45, 166.51 -34.45, 166.51 -46.64))'::postgis.geometry Geometry.createValue(geomSchema, DatatypeConverter.parseHexBinary("01030000000100000005000000B81E85EB51D0644052B81E85EB5147C0713D0AD7A350664052B81E85EB5147C0713D0AD7A35066409A999999993941C0B81E85EB51D064409A999999993941C0B81E85EB51D0644052B81E85EB5147C0"), null) ); return Arrays.asList( // geometries are encoded here as HexEWKB new SchemaAndValueField("ga", SchemaBuilder.array(geomSchema).optional().build(), values ), new SchemaAndValueField("gann", SchemaBuilder.array(geomSchema).build(), values ) ); }
/** * Convert the a value representing a GEOMETRY {@code byte[]} value to a Geometry value used in a {@link SourceRecord}. * * @param column the column in which the value appears * @param fieldDefn the field definition for the {@link SourceRecord}'s {@link Schema}; never null * @param data the data; may be null * @return the converted value, or null if the conversion could not be made and the column allows nulls * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls */ protected Object convertGeometry(Column column, Field fieldDefn, Object data) { final MySqlGeometry empty = MySqlGeometry.createEmpty(); return convertValue(column, fieldDefn, data, io.debezium.data.geometry.Geometry.createValue(fieldDefn.schema(), empty.getWkb(), empty.getSrid()), (r) -> { if (data instanceof byte[]) { // The binlog utility sends a byte array for any Geometry type, we will use our own binaryParse to parse the byte to WKB, hence // to the suitable class if (data instanceof byte[]) { // The binlog utility sends a byte array for any Geometry type, we will use our own binaryParse to parse the byte to WKB, hence // to the suitable class MySqlGeometry mySqlGeometry = MySqlGeometry.fromBytes((byte[]) data); r.deliver(io.debezium.data.geometry.Geometry.createValue(fieldDefn.schema(), mySqlGeometry.getWkb(), mySqlGeometry.getSrid())); } } }); }
protected List<SchemaAndValueField> schemaAndValuesForPostgisTypes() { Schema geomSchema = Geometry.builder().optional().build(); Schema geogSchema = Geography.builder().optional().build(); return Arrays.asList( // geometries are encoded here as HexEWKB new SchemaAndValueField("p", geomSchema, // 'SRID=3187;POINT(174.9479 -36.7208)'::postgis.geometry Geometry.createValue(geomSchema, DatatypeConverter.parseHexBinary("0101000020730C00001C7C613255DE6540787AA52C435C42C0"), 3187)), new SchemaAndValueField("ml", geogSchema, // 'MULTILINESTRING((169.1321 -44.7032, 167.8974 -44.6414))'::postgis.geography Geography.createValue(geogSchema, DatatypeConverter.parseHexBinary("0105000020E610000001000000010200000002000000A779C7293A2465400B462575025A46C0C66D3480B7FC6440C3D32B65195246C0"), 4326)) ); }
/** * Convert the a value representing a POINT {@code byte[]} value to a Point value used in a {@link SourceRecord}. * * @param column the column in which the value appears * @param fieldDefn the field definition for the {@link SourceRecord}'s {@link Schema}; never null * @param data the data; may be null * @return the converted value, or null if the conversion could not be made and the column allows nulls * @throws IllegalArgumentException if the value could not be converted but the column does not allow nulls */ protected Object convertPoint(Column column, Field fieldDefn, Object data){ final MySqlGeometry empty = MySqlGeometry.createEmpty(); return convertValue(column, fieldDefn, data, io.debezium.data.geometry.Geometry.createValue(fieldDefn.schema(), empty.getWkb(), empty.getSrid()), (r) -> { if (data instanceof byte[]) { // The binlog utility sends a byte array for any Geometry type, we will use our own binaryParse to parse the byte to WKB, hence // to the suitable class MySqlGeometry mySqlGeometry = MySqlGeometry.fromBytes((byte[]) data); if (mySqlGeometry.isPoint()) { r.deliver(io.debezium.data.geometry.Point.createValue(fieldDefn.schema(), mySqlGeometry.getWkb(), mySqlGeometry.getSrid())); } else { throw new ConnectException("Failed to parse and read a value of type POINT on " + column); } } }); }
/** * Returns a {@link SchemaBuilder} for a Geometry field, with all other default Schema settings. * * @return the schema * @see #builder() */ public static Schema schema() { return builder().build(); }
/** * Create a value for this schema using WKB * @param pointSchema a {@link Schema} instance which represents a point; may not be null * @param wkb the original Well-Known binary representation of the coordinate; may not be null * @param srid the coordinate reference system identifier; null if unset/unknown * @return a {@link Struct} which represents a Connect value for this schema; never null */ public static Struct createValue(Schema geomSchema, byte[] wkb, Integer srid) throws IllegalArgumentException { Struct result = Geometry.createValue(geomSchema, wkb, srid); double[] pt = parseWKBPoint(wkb); result.put(X_FIELD, pt[0]); result.put(Y_FIELD, pt[1]); return result; } }
@Test public void shouldLoadSchemaForPostgisTypes() throws Exception { TestHelper.executeDDL("init_postgis.ddl"); TestHelper.executeDDL("postgis_create_tables.ddl"); PostgresConnectorConfig config = new PostgresConnectorConfig(TestHelper.defaultConfig().build()); schema = TestHelper.getSchema(config); try (PostgresConnection connection = TestHelper.create()) { schema.refresh(connection, false); final String[] testTables = new String[] {"public.postgis_table"}; assertTablesIncluded(testTables); Arrays.stream(testTables).forEach(tableId -> assertKeySchema(tableId, "pk", Schema.INT32_SCHEMA)); assertTableSchema("public.postgis_table", "p, ml", Geometry.builder().optional().build(), Geography.builder().optional().build()); } }
/** * Creates a value for this schema using 2 given coordinates. * * @param pointSchema a {@link Schema} instance which represents a point; may not be null * @param x the X coordinate of the point; may not be null * @param y the Y coordinate of the point; may not be null * @return a {@link Struct} which represents a Connect value for this schema; never null */ public static Struct createValue(Schema geomSchema, double x, double y){ // turn the specified points byte[] wkb = buildWKBPoint(x, y); Struct result = Geometry.createValue(geomSchema, wkb, null); result.put(X_FIELD, x); result.put(Y_FIELD, y); return result; }
protected Object convertGeometry(Column column, Field fieldDefn, Object data) { final PostgisGeometry empty = PostgisGeometry.createEmpty(); return convertValue(column, fieldDefn, data, io.debezium.data.geometry.Geometry.createValue(fieldDefn.schema(), empty.getWkb(), empty.getSrid()), (r) -> { try { final Schema schema = fieldDefn.schema(); if (data instanceof byte[]) { PostgisGeometry geom = PostgisGeometry.fromHexEwkb(new String((byte[])data, "ASCII")); r.deliver(io.debezium.data.geometry.Geometry.createValue(schema, geom.getWkb(), geom.getSrid())); } else if (data instanceof PGobject) { PGobject pgo = (PGobject)data; PostgisGeometry geom = PostgisGeometry.fromHexEwkb(pgo.getValue()); r.deliver(io.debezium.data.geometry.Geometry.createValue(schema, geom.getWkb(), geom.getSrid())); } else if (data instanceof String) { PostgisGeometry geom = PostgisGeometry.fromHexEwkb((String)data); r.deliver(io.debezium.data.geometry.Geometry.createValue(schema, geom.getWkb(), geom.getSrid())); } } catch (IllegalArgumentException | UnsupportedEncodingException e) { logger.warn("Error converting to a Geometry type", column); } }); }