This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 4f930df  Refactor the parsing of hexadecimal strings for making 
possible to control the decoding algorithm according the database driver. The 
mechanism is applied on geometries and shared by rasters. Tests are 
consolidated in a "SpatialFeatures" database schema.
4f930df is described below

commit 4f930dfc2057a5f9b8cc66536291b8889f5613ec
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Dec 23 23:20:54 2021 +0100

    Refactor the parsing of hexadecimal strings for making possible to control 
the decoding algorithm according the database driver.
    The mechanism is applied on geometries and shared by rasters. Tests are 
consolidated in a "SpatialFeatures" database schema.
---
 .../org/apache/sis/internal/jdk9/HexFormat.java    |  76 +++++++++++
 .../org/apache/sis/internal/jdk9/package-info.java |   2 +-
 storage/sis-sqlstore/pom.xml                       |   5 +
 .../sis/internal/sql/feature/BinaryEncoding.java   | 138 ++++++++++++++++++++
 .../apache/sis/internal/sql/feature/Column.java    |   4 +-
 .../apache/sis/internal/sql/feature/Database.java  |  34 +++--
 .../{EWKBReader.java => GeometryGetter.java}       |  72 ++---------
 .../sis/internal/sql/feature/InfoStatements.java   |   1 -
 .../sis/internal/sql/feature/ValueGetter.java      |  17 ++-
 .../apache/sis/internal/sql/postgis/Postgres.java  |  17 ++-
 .../apache/sis/internal/sql/feature/EWKBTest.java  | 125 ------------------
 .../internal/sql/feature/GeometryGetterTest.java   | 139 +++++++++++++++++++++
 .../sis/internal/sql/postgis/PostgresTest.java     |  22 +++-
 .../org/apache/sis/test/suite/SQLTestSuite.java    |   2 +-
 .../sis/internal/sql/feature/hexa_ewkb_4326.csv    |  21 ----
 .../sis/internal/sql/feature/hexa_ewkb_4326.sql    |  43 -------
 .../sis/internal/sql/postgis/SpatialFeatures.sql   |  59 ++++++++-
 17 files changed, 499 insertions(+), 278 deletions(-)

diff --git 
a/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/HexFormat.java 
b/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/HexFormat.java
new file mode 100644
index 0000000..0019ed2
--- /dev/null
+++ b/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/HexFormat.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.jdk9;
+
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Place holder for a functionality defined only in JDK17.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   1.2
+ * @version 1.2
+ * @module
+ */
+public final class HexFormat {
+    private static final HexFormat INSTANCE = new HexFormat();
+
+    private HexFormat() {
+    }
+
+    public static HexFormat of() {
+        return INSTANCE;
+    }
+
+    /**
+     * Returns the byte array parsed from the given hexadecimal string.
+     *
+     * @param  string  the hexadecimal string.
+     * @return the parsed bytes.
+     * @throws NumberFormatException if a character is not a hexadecimal digit.
+     */
+    public byte[] parseHex(final CharSequence string) {
+        final int length = string.length();
+        if ((length & 1) != 0) {
+            throw new 
IllegalArgumentException(Errors.format(Errors.Keys.OddArrayLength_1, "wkb"));
+        }
+        final byte[] data = new byte[length >>> 1];
+        for (int i=0; i<length;) {
+            data[i >>> 1] = (byte) ((fromHexDigit(string.charAt(i++)) << 4) | 
fromHexDigit(string.charAt(i++)));
+        }
+        return data;
+    }
+
+    /**
+     * Returns the numerical value of the given hexadecimal digit.
+     * The hexadecimal digit can be the decimal digits 0 to 9, or the letters 
A to F ignoring case.
+     *
+     * <div class="note"><b>Implementation note:</b>
+     * we do not use {@link Character#digit(char, int)} because that method 
handled a large
+     * range of Unicode characters, which is a wider scope than what is 
intended here.</div>
+     *
+     * @param  c  the hexadecimal digit.
+     * @throws NumberFormatException if the given character is not a 
hexadecimal digit.
+     */
+    public static int fromHexDigit(final int c) {
+        if (c >= '0' && c <= '9') return c - '0';
+        if (c >= 'A' && c <= 'F') return c - ('A' - 10);
+        if (c >= 'a' && c <= 'f') return c - ('a' - 10);
+        throw new 
NumberFormatException(Errors.format(Errors.Keys.CanNotParse_1, 
String.valueOf(c)));
+    }
+}
diff --git 
a/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/package-info.java 
b/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/package-info.java
index a396f43..2409866 100644
--- 
a/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/package-info.java
+++ 
b/core/sis-utility/src/main/java/org/apache/sis/internal/jdk9/package-info.java
@@ -24,7 +24,7 @@
  * may change in incompatible ways in any future version without notice.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   1.1
+ * @since   1.2
  * @version 0.8
  * @module
  */
diff --git a/storage/sis-sqlstore/pom.xml b/storage/sis-sqlstore/pom.xml
index 6a04a05..ae0751f 100644
--- a/storage/sis-sqlstore/pom.xml
+++ b/storage/sis-sqlstore/pom.xml
@@ -144,6 +144,11 @@
       <artifactId>jts-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>com.esri.geometry</groupId>
+      <artifactId>esri-geometry-api</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/BinaryEncoding.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/BinaryEncoding.java
new file mode 100644
index 0000000..215007f
--- /dev/null
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/BinaryEncoding.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.sql.feature;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import org.apache.sis.internal.jdk9.HexFormat;
+
+
+/**
+ * The way binary data are encoded in a table column.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.2
+ * @module
+ */
+public enum BinaryEncoding {
+    /**
+     * The bytes returned by the JDBC driver in a query are directly the 
binary data.
+     */
+    RAW,
+
+    /**
+     * The bytes returned by the JDBC driver are encoded as hexadecimal 
numbers.
+     */
+    HEXADECIMAL() {
+        /** Returns the value in the specified column as an array of decoded 
bytes. */
+        @Override public byte[] getBytes(final ResultSet results, final int 
columnIndex) throws SQLException {
+            final String value = results.getString(columnIndex);
+            return (value != null) ? HexFormat.of().parseHex(value) : null;
+        }
+
+        /** Returns an input stream decoding bytes on-the-fly. */
+        @Override public InputStream decode(final InputStream source) {
+            return new FromHex(source);
+        }
+    };
+
+    /**
+     * Returns the value in the specified column as an array of decoded bytes.
+     * If the bytes returned by the JDBC driver are encoded, this method 
decode them.
+     *
+     * @param  results       the result set from which to get the values.
+     * @param  columnIndex   column from which to get the values.
+     * @return the column values, or {@code null} if none.
+     * @throws SQLException if an error occurred while fetching column values.
+     *
+     * @see ResultSet#getBytes(int)
+     */
+    public byte[] getBytes(final ResultSet results, final int columnIndex) 
throws SQLException {
+        return results.getBytes(columnIndex);
+    }
+
+    /**
+     * Returns an input stream decoding bytes on-the-fly.
+     *
+     * @param  source  the stream of data in their encoded format.
+     * @return a stream of decoded bytes.
+     *
+     * @see ResultSet#getBinaryStream(int)
+     */
+    public InputStream decode(final InputStream source) {
+        return source;
+    }
+
+    /**
+     * An input stream which converts hexadecimal string on-the-fly.
+     */
+    private static final class FromHex extends InputStream {
+        /** The input stream providing hexadecimal digits. */
+        private final InputStream source;
+
+        /** Creates a new input stream which will decode the given source. */
+        FromHex(final InputStream source) {
+            this.source = source;
+        }
+
+        /** Returns the next decoded byte. */
+        @Override public int read() throws IOException {
+            final int hi = source.read(); if (hi < 0) return -1;
+            final int lo = source.read(); if (lo < 0) throw new EOFException();
+            return (HexFormat.fromHexDigit(hi) << 4) | 
HexFormat.fromHexDigit(lo);
+        }
+
+        /** Skips over and discards <var>n</var> bytes of data. */
+        @Override public long skip(long n) throws IOException {
+            if ((n & 0xC000000000000000L) == 0) n <<= 1;
+            n = source.skip(n);
+            if ((n & 1) != 0 && source.read() >= 0) n++;
+            return n >> 1;
+        }
+
+        /** Returns an estimate of the number of bytes that can be read. */
+        @Override public int available() throws IOException {
+            return source.available() >> 1;
+        }
+
+        /** Tests if this input stream supports the mark and reset methods. */
+        @Override public boolean markSupported() {
+            return source.markSupported();
+        }
+
+        /** Marks the current position in this input stream. */
+        @Override public void mark(int n) {
+            if ((n & 0xC0000000) == 0) n <<= 1;
+            else n = Integer.MAX_VALUE;
+            source.mark(n);
+        }
+
+        /** Repositions this stream to the position of the mark. */
+        @Override public void reset() throws IOException {
+            source.reset();
+        }
+
+        /** Closes this input stream. */
+        @Override public void close() throws IOException {
+            source.close();
+        }
+    }
+}
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Column.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Column.java
index 36418a9..f6a558a 100644
--- 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Column.java
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Column.java
@@ -70,7 +70,7 @@ public final class Column {
     String propertyName;
 
     /**
-     * Type of values as one of the constant enumerated in {@link Types} class.
+     * Type of values as one of the constants enumerated in {@link Types} 
class.
      *
      * @see Reflection#DATA_TYPE
      */
@@ -124,7 +124,7 @@ public final class Column {
      * This method does not change cursor position.
      *
      * @param  analyzer  the analyzer which is creating this column.
-     * @param  metadata  the
+     * @param  metadata  the result of {@code DatabaseMetaData.getColumns(…)}.
      * @throws SQLException if an error occurred while fetching metadata.
      *
      * @see DatabaseMetaData#getColumns(String, String, String, String)
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
index cf81859..8bd9f8b 100644
--- 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
@@ -501,17 +501,35 @@ public class Database<G> extends Syntax  {
             case Types.TIMESTAMP:                 return 
ValueGetter.AsInstant.INSTANCE;
             case Types.TIME_WITH_TIMEZONE:        return 
ValueGetter.AsOffsetTime.INSTANCE;
             case Types.TIMESTAMP_WITH_TIMEZONE:   return 
ValueGetter.AsOffsetDateTime.INSTANCE;
-            case Types.BINARY:
-            case Types.VARBINARY:
-            case Types.LONGVARBINARY:             return 
ValueGetter.AsBytes.INSTANCE;
+            case Types.BLOB:                      return 
ValueGetter.AsBytes.INSTANCE;
             case Types.ARRAY:                     // TODO
             case Types.OTHER:
             case Types.JAVA_OBJECT:               return 
ValueGetter.AsObject.INSTANCE;
-            default:                              return null;
+            case Types.BINARY:
+            case Types.VARBINARY:
+            case Types.LONGVARBINARY: {
+                final BinaryEncoding encoding = 
getBinaryEncoding(columnDefinition);
+                switch (encoding) {
+                    case RAW:         return ValueGetter.AsBytes.INSTANCE;
+                    case HEXADECIMAL: return ValueGetter.AsBytes.HEXADECIMAL;
+                    default: throw new AssertionError(encoding);
+                }
+            }
+            default: return null;
         }
     }
 
     /**
+     * Returns an identifier of the way binary data are encoded by the JDBC 
driver.
+     *
+     * @param  columnDefinition  information about the column to extract 
binary values from.
+     * @return how the binary data are returned by the JDBC driver.
+     */
+    protected BinaryEncoding getBinaryEncoding(final Column columnDefinition) {
+        return BinaryEncoding.RAW;
+    }
+
+    /**
      * Returns a function for getting values from a geometry column.
      * This is a helper method for {@link #getMapping(Column)} implementations.
      *
@@ -521,12 +539,8 @@ public class Database<G> extends Syntax  {
     protected final ValueGetter<?> forGeometry(final Column columnDefinition) {
         final GeometryType type = columnDefinition.getGeometryType();
         final Class<? extends G> geometryClass = 
geomLibrary.getGeometryClass(type).asSubclass(geomLibrary.rootClass);
-        /*
-         * TODO: verify if the condition below works. We should have 
`hexadecimal = true` on PostGIS.
-         */
-        final boolean hexadecimal = (columnDefinition.type != Types.BLOB);
-        return new EWKBReader<>(geomLibrary, geometryClass, 
columnDefinition.getGeometryCRS(), hexadecimal);
-        // TODO: need to invoke EWKBReader.setSridResolver(statements(…)) 
somewhere.
+        return new GeometryGetter<>(geomLibrary, geometryClass, 
columnDefinition.getGeometryCRS(), getBinaryEncoding(columnDefinition));
+        // TODO: need to invoke GeometryGetter.setSridResolver(statements(…)) 
somewhere.
     }
 
     /**
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/EWKBReader.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/GeometryGetter.java
similarity index 67%
rename from 
storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/EWKBReader.java
rename to 
storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/GeometryGetter.java
index 2590b8f..1151690 100644
--- 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/EWKBReader.java
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/GeometryGetter.java
@@ -23,8 +23,6 @@ import java.sql.ResultSet;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.internal.feature.GeometryWrapper;
 import org.apache.sis.internal.feature.Geometries;
-import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -50,11 +48,11 @@ import org.apache.sis.util.resources.Errors;
  * @param <G> the type of geometry objects created by the factory.
  * @param <V> the type of geometry objects returned by this getter.
  *
- * @version 1.1
+ * @version 1.2
  * @since   1.1
  * @module
  */
-final class EWKBReader<G, V extends G> extends ValueGetter<V> {
+final class GeometryGetter<G, V extends G> extends ValueGetter<V> {
     /**
      * The factory to use for creating geometries from WKB definitions.
      */
@@ -63,7 +61,7 @@ final class EWKBReader<G, V extends G> extends ValueGetter<V> 
{
     /**
      * The mapper to use for resolving a Spatial Reference Identifier (SRID) 
integer
      * as Coordinate Reference System (CRS) object.
-     * This is {@code null} is there is no mapping to apply.
+     * This is {@code null} if there is no mapping to apply.
      */
     private InfoStatements fromSridToCRS;
 
@@ -74,9 +72,9 @@ final class EWKBReader<G, V extends G> extends ValueGetter<V> 
{
     private final CoordinateReferenceSystem defaultCRS;
 
     /**
-     * Whether binary data are encoded in an hexadecimal string.
+     * The way binary data are encoded in the geometry column.
      */
-    private final boolean hexadecimal;
+    private final BinaryEncoding encoding;
 
     /**
      * Creates a new reader. The same instance can be reused for parsing an 
arbitrary
@@ -85,16 +83,16 @@ final class EWKBReader<G, V extends G> extends 
ValueGetter<V> {
      * @param  geometryFactory  the factory to use for creating geometries 
from WKB definitions.
      * @param  geometryClass    the type of geometry to be returned by this 
{@code ValueGetter}.
      * @param  defaultCRS       the CRS to use if none can be mapped from the 
SRID, or {@code null} if none.
-     * @param  hexadecimal      whether binary data are encoded in an 
hexadecimal string.
+     * @param  encoding         the way binary data are encoded in the 
geometry column.
      * @return a WKB reader resolving SRID with the specified mapper and 
default CRS.
      */
-    EWKBReader(final Geometries<G> geometryFactory, final Class<V> 
geometryClass,
-            final CoordinateReferenceSystem defaultCRS, final boolean 
hexadecimal)
+    GeometryGetter(final Geometries<G> geometryFactory, final Class<V> 
geometryClass,
+            final CoordinateReferenceSystem defaultCRS, final BinaryEncoding 
encoding)
     {
         super(geometryClass);
         this.geometryFactory = geometryFactory;
         this.defaultCRS      = defaultCRS;
-        this.hexadecimal     = hexadecimal;
+        this.encoding        = encoding;
     }
 
     /**
@@ -131,59 +129,13 @@ final class EWKBReader<G, V extends G> extends 
ValueGetter<V> {
      */
     @Override
     public V getValue(final ResultSet source, final int columnIndex) throws 
Exception {
-        final GeometryWrapper<G> geom;
-        if (hexadecimal) {
-            final String wkb = source.getString(columnIndex);
-            if (wkb == null) return null;
-            geom = readHexa(wkb);
-        } else {
-            final byte[] wkb = source.getBytes(columnIndex);
-            if (wkb == null) return null;
-            geom = read(wkb);
-        }
+        final byte[] wkb = encoding.getBytes(source, columnIndex);
+        if (wkb == null) return null;
+        final GeometryWrapper<G> geom = read(wkb);
         return valueType.cast(geom.implementation());
     }
 
     /**
-     * Parses a WKB encoded as hexadecimal numbers in a character string.
-     * Each byte uses 2 characters. No separator is allowed between bytes.
-     *
-     * @param  wkb  the hexadecimal values to decode. Should neither be null 
nor empty.
-     * @return geometry parsed from the given hexadecimal text. Never null, 
never empty.
-     * @throws Exception if the WKB can not be parsed. The exception type 
depends on the geometry implementation.
-     */
-    final GeometryWrapper<G> readHexa(final String wkb) throws Exception {
-        final int length = wkb.length();
-        if ((length & 1) != 0) {
-            throw new 
DataStoreContentException(Errors.format(Errors.Keys.OddArrayLength_1, "wkb"));
-        }
-        final byte[] data = new byte[length >>> 1];
-        for (int i=0; i<length;) {
-            data[i >>> 1] = (byte) ((digit(wkb.charAt(i++)) << 4) | 
digit(wkb.charAt(i++)));
-        }
-        return read(data);
-    }
-
-    /**
-     * Returns the numerical value of the given hexadecimal digit.
-     * The hexadecimal digit can be the decimal digits 0 to 9, or the letters 
A to F ignoring case.
-     *
-     * <div class="note"><b>Implementation note:</b>
-     * we do not use {@link Character#digit(char, int)} because that method 
handled a large
-     * range of Unicode characters, which is a wider scope than what is 
intended here.</div>
-     *
-     * @param  c  the hexadecimal digit.
-     * @return numerical value of given digit.
-     * @throws DataStoreContentException if the given character is not a 
hexadecimal digit.
-     */
-    private static int digit(final char c) throws DataStoreContentException {
-        if (c >= '0' && c <= '9') return c - '0';
-        if (c >= 'A' && c <= 'F') return c - ('A' - 10);
-        if (c >= 'a' && c <= 'f') return c - ('a' - 10);
-        throw new 
DataStoreContentException(Errors.format(Errors.Keys.CanNotParse_1, 
String.valueOf(c)));
-    }
-
-    /**
      * Parses a WKB stored in the given byte array.
      *
      * @param  wkb  the array containing the WKB to decode. Should neither be 
null nor empty.
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/InfoStatements.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/InfoStatements.java
index 3b62c34..2ec5cf5 100644
--- 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/InfoStatements.java
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/InfoStatements.java
@@ -375,7 +375,6 @@ public class InfoStatements implements Localized, 
AutoCloseable {
          * Finished to parse entries from the "SPATIAL_REF_SYS" table.
          * Reports warning if any, then return the non-null CRS.
          */
-        wktFromSrid.clearParameters();
         if (crs == null) {
             if (authorityError != null) {
                 throw authorityError;
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ValueGetter.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ValueGetter.java
index ed7c967..4920b95 100644
--- 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ValueGetter.java
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ValueGetter.java
@@ -46,7 +46,7 @@ import org.apache.sis.util.ArgumentChecks;
  *
  * @author  Alexis Manin (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.1
  * @module
  */
@@ -129,13 +129,20 @@ public abstract class ValueGetter<T> {
      * This getter delegates to {@link ResultSet#getBytes(int)} and returns 
that value with no change.
      */
     static final class AsBytes extends ValueGetter<byte[]> {
-        /** The unique instance of this accessor. */
-        public static final AsBytes INSTANCE = new AsBytes();
-        private AsBytes() {super(byte[].class);}
+        /** The encoding of bytes returned by JDBC driver. */
+        private final BinaryEncoding encoding;
+
+        /** The instance of this accessor for array of bytes without encoding. 
*/
+        public static final AsBytes INSTANCE    = new 
AsBytes(BinaryEncoding.RAW);
+        public static final AsBytes HEXADECIMAL = new 
AsBytes(BinaryEncoding.HEXADECIMAL);
+        private AsBytes(final BinaryEncoding encoding) {
+            super(byte[].class);
+            this.encoding = encoding;
+        }
 
         /** Fetches the value from the specified column in the given result 
set. */
         @Override public byte[] getValue(ResultSet source, int columnIndex) 
throws SQLException {
-            return source.getBytes(columnIndex);
+            return encoding.getBytes(source, columnIndex);
         }
     }
 
diff --git 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/Postgres.java
 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/Postgres.java
index 507f681..cb36120 100644
--- 
a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/Postgres.java
+++ 
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/postgis/Postgres.java
@@ -17,6 +17,7 @@
 package org.apache.sis.internal.sql.postgis;
 
 import java.util.Set;
+import java.sql.Types;
 import java.sql.Connection;
 import java.sql.Statement;
 import java.sql.ResultSet;
@@ -25,6 +26,7 @@ import java.sql.SQLException;
 import javax.sql.DataSource;
 import java.util.logging.Level;
 import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.sql.feature.BinaryEncoding;
 import org.apache.sis.internal.sql.feature.InfoStatements;
 import org.apache.sis.internal.sql.feature.Column;
 import org.apache.sis.internal.sql.feature.Database;
@@ -42,7 +44,7 @@ import org.apache.sis.util.Version;
  *
  * @author  Alexis Manin (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.1
  * @module
  */
@@ -118,6 +120,19 @@ public final class Postgres<G> extends Database<G> {
     }
 
     /**
+     * Returns an identifier of the way binary data are encoded by the JDBC 
driver.
+     * Data stored as PostgreSQL {@code BYTEA} type are encoded in hexadecimal.
+     */
+    @Override
+    protected BinaryEncoding getBinaryEncoding(final Column columnDefinition) {
+        if (columnDefinition.type == Types.BLOB) {
+            return super.getBinaryEncoding(columnDefinition);
+        } else {
+            return BinaryEncoding.HEXADECIMAL;
+        }
+    }
+
+    /**
      * Prepares a cache of statements about spatial information using the 
given connection.
      * Statements will be created only when first needed.
      *
diff --git 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/feature/EWKBTest.java
 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/feature/EWKBTest.java
deleted file mode 100644
index b39bee2..0000000
--- 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/feature/EWKBTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.sis.internal.sql.feature;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import org.opengis.referencing.crs.GeographicCRS;
-import org.apache.sis.internal.feature.Geometries;
-import org.apache.sis.internal.feature.GeometryWrapper;
-import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.setup.GeometryLibrary;
-import org.apache.sis.test.TestCase;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-/**
- * Tests the parsing of geometries encoded in Extended Well Known Binary 
(EWKB) format.
- *
- * @author  Alexis Manin (Geomatys)
- * @version 1.1
- * @since   1.1
- * @module
- *
- * @todo Run the same test for all supported geometry implementations (ESRI 
and JTS).
- */
-public strictfp class EWKBTest extends TestCase {
-    /**
-     * The factory to use for creating geometric objects.
-     * It requires a geometry implementation to be available on the classpath.
-     */
-    private final Geometries<?> GF;
-
-    /**
-     * Creates a new test using JTS geometry implementation.
-     */
-    public EWKBTest() {
-        GF = Geometries.implementation(GeometryLibrary.JTS);
-    }
-
-    /**
-     * Creates a reader to use for testing.
-     */
-    private static <G> EWKBReader<G, ? extends G> createReader(final 
Geometries<G> GF, final GeographicCRS crs) {
-        return new EWKBReader<>(GF, GF.rootClass, crs, false);
-    }
-
-    /**
-     * Decodes a geometry encoded in EWKB format and compares with the 
geometry specified in WKT format.
-     *
-     * @param  wkt  WKT representation of the geometry. This is used as the 
reference value.
-     * @param  wkb  WKB representation of the same geometry. This is the value 
to test.
-     * @throws Exception if an error occurred while decoding one of the given 
strings.
-     */
-    public void decodeHexadecimal(final String wkt, final String wkb) throws 
Exception {
-        final GeographicCRS expectedCRS = CommonCRS.defaultGeographic();
-        final EWKBReader<?,?> reader = createReader(GF, expectedCRS);
-        assertEquals("WKT and hexadecimal EWKB representation don't match",
-                GF.parseWKT(wkt).implementation(),
-                reader.readHexa(wkb).implementation());
-    }
-
-    /**
-     * Tests the decoding of a geometry from a byte array. The purpose of this 
test is not to check complex geometries,
-     * which are validated by {@link #decodeHexadecimal(String, String)}. This 
test only ensures that decoding directly
-     * a byte array behaves in the same way than decoding a string of 
hexadecimal digits.
-     *
-     * @throws Exception if an error occurred while decoding the WKB.
-     */
-    @Test
-    public void testBinary() throws Exception {
-        final ByteBuffer point = ByteBuffer.allocate(21);
-        point.put((byte) 0);    // XDR mode.
-
-        // Create a 2D point.
-        point.putInt(1);
-        point.putDouble(42.2);
-        point.putDouble(43.3);
-
-        // Read the point.
-        point.rewind();
-        final GeometryWrapper<?> read = createReader(GF, 
null).read(point.array());
-        assertEquals(GF.createPoint(42.2, 43.3), read.implementation());
-    }
-
-    /**
-     * Temporary test for simulating JUnit 5 execution of {@link 
#decodeHexadecimal(String, String)}
-     * as a parameterized test. To be removed after migration to JUnit 5.
-     *
-     * @throws Exception if test file can not be decoded.
-     */
-    @Test
-    public void testDecodeHexadecimal() throws Exception {
-        try (final BufferedReader in = new BufferedReader(new 
InputStreamReader(
-                EWKBTest.class.getResourceAsStream("hexa_ewkb_4326.csv"), 
StandardCharsets.UTF_8)))
-        {
-            String line;
-            int numLinesToSkip = 1;
-            while ((line = in.readLine()) != null) {
-                if (!(line = line.trim()).isEmpty() && line.charAt(0) != '#' 
&& --numLinesToSkip < 0) {
-                    final String[] columns = line.split("\t");
-                    assertEquals(2, columns.length);
-                    decodeHexadecimal(columns[0], columns[1]);
-                }
-            }
-        }
-    }
-}
diff --git 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/feature/GeometryGetterTest.java
 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/feature/GeometryGetterTest.java
new file mode 100644
index 0000000..e57e0c5
--- /dev/null
+++ 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/feature/GeometryGetterTest.java
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.sql.feature;
+
+import java.nio.ByteBuffer;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.ResultSet;
+import org.apache.sis.internal.feature.Geometries;
+import org.apache.sis.internal.feature.GeometryWrapper;
+import org.apache.sis.referencing.crs.HardCodedCRS;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.setup.GeometryLibrary;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+// Optional dependencies
+import org.locationtech.jts.geom.Geometry;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests the parsing of geometries encoded in Well-Known Binary (WKB) format.
+ *
+ * @author  Alexis Manin (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ * @since   1.1
+ * @module
+ */
+public strictfp final class GeometryGetterTest extends TestCase {
+    /**
+     * The factory to use for creating geometric objects.
+     */
+    private Geometries<?> GF;
+
+    /**
+     * Creates a new test case.
+     */
+    public GeometryGetterTest() {
+    }
+
+    /**
+     * Creates a reader to use for testing.
+     *
+     * @param  library   the geometry implementation to use (JTS or ESRI).
+     * @param  encoding  the way binary data are encoded (raw or hexadecimal).
+     */
+    @SuppressWarnings("unchecked")
+    private GeometryGetter<?,?> createReader(final GeometryLibrary library, 
final BinaryEncoding encoding) {
+        GF = Geometries.implementation(library);
+        return new GeometryGetter<>(GF, (Class) GF.rootClass, 
HardCodedCRS.WGS84, encoding);
+    }
+
+    /**
+     * Tests the decoding of a geometry from a byte array using JTS library.
+     * The array does not use any encoding.
+     *
+     * @throws Exception if an error occurred while decoding the WKB.
+     */
+    @Test
+    public void testBinaryWithJTS() throws Exception {
+        testBinary(GeometryLibrary.JTS);
+    }
+
+    /**
+     * Tests the decoding of a geometry from a byte array using ESRI library.
+     * The array does not use any encoding.
+     *
+     * @throws Exception if an error occurred while decoding the WKB.
+     */
+    @Test
+    public void testBinaryWithESRI() throws Exception {
+        testBinary(GeometryLibrary.ESRI);
+    }
+
+    /**
+     * Implementation of {@link #testBinaryWithJTS()} and {@link 
#testBinaryWithESRI()} methods.
+     */
+    private void testBinary(final GeometryLibrary library) throws Exception {
+        final ByteBuffer point = ByteBuffer.allocate(21);
+        point.put((byte) 0);    // XDR mode.
+
+        // Create a 2D point.
+        point.putInt(1);
+        point.putDouble(42.2);
+        point.putDouble(43.3);
+
+        // Read the point.
+        point.rewind();
+        final GeometryWrapper<?> read = createReader(library, 
BinaryEncoding.RAW).read(point.array());
+        assertSame(HardCodedCRS.WGS84, read.getCoordinateReferenceSystem());
+        assertEquals(GF.createPoint(42.2, 43.3), read.implementation());
+    }
+
+    /**
+     * Compares WKB with WKT parsing using the {@code features."Geometries"} 
view of test database.
+     * This test is <em>not</em> executed by this {@code GeometryGetterTest} 
class. This is a method
+     * to be invoked from {@linkplain 
org.apache.sis.internal.sql.postgis.PostgresTest#testGeometryGetter
+     * another test class} having a connection to a database.
+     *
+     * @param  connection     connection to the database.
+     * @param  spatialRefSys  helper method for fetching CRS from SRID codes.
+     * @param  encoding       the way binary data are encoded (raw or 
hexadecimal).
+     * @throws Exception if an error occurred while querying the database or 
parsing the WKT or WKB.
+     */
+    public void testFromDatabase(final Connection connection, final 
InfoStatements spatialRefSys,
+            final BinaryEncoding encoding) throws Exception
+    {
+        final GeometryGetter<?,?> reader = createReader(GeometryLibrary.JTS, 
encoding);
+        reader.setSridResolver(spatialRefSys);
+        try (Statement stmt = connection.createStatement();
+             ResultSet results = stmt.executeQuery("SELECT \"WKT\",\"WKB\" 
FROM features.\"Geometries\""))
+        {
+            while (results.next()) {
+                final String wkt = results.getString(1);
+                final Geometry geometry = (Geometry) reader.getValue(results, 
2);
+                final GeometryWrapper<?> expected = GF.parseWKT(wkt);
+                assertEquals("WKT and WKB parsings gave different results.", 
expected.implementation(), geometry);
+                assertSame("SRID", CommonCRS.WGS84.normalizedGeographic(), 
GF.castOrWrap(geometry).getCoordinateReferenceSystem());
+            }
+        }
+    }
+}
diff --git 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/postgis/PostgresTest.java
 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/postgis/PostgresTest.java
index a473b64..8eed2b7 100644
--- 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/postgis/PostgresTest.java
+++ 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/internal/sql/postgis/PostgresTest.java
@@ -21,6 +21,7 @@ import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.nio.ByteBuffer;
 import java.nio.channels.Channels;
+import java.nio.channels.ReadableByteChannel;
 import java.lang.reflect.Method;
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.apache.sis.setup.OptionKey;
@@ -31,6 +32,8 @@ import org.apache.sis.storage.sql.ResourceDefinition;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.sql.SQLStoreTest;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
+import org.apache.sis.internal.sql.feature.BinaryEncoding;
+import org.apache.sis.internal.sql.feature.GeometryGetterTest;
 import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.test.sql.TestDatabase;
 import org.apache.sis.test.DependsOn;
@@ -87,7 +90,8 @@ public final strictfp class PostgresTest extends TestCase {
                      ExtendedInfo info = new ExtendedInfo(pg, connection))
                 {
                     testInfoStatements(info);
-//                  testRasterReader(TestRaster.USHORT, info, connection);
+                    testGeometryGetter(info, connection);
+                    testRasterReader(TestRaster.USHORT, info, connection);
                 }
             }
         }
@@ -104,16 +108,28 @@ public final strictfp class PostgresTest extends TestCase 
{
     }
 
     /**
+     * Tests {@link org.apache.sis.internal.sql.feature.GeometryGetter}
+     * in the context of querying a database.
+     *
+     * @throws Exception if an error occurred while testing the database.
+     */
+    private void testGeometryGetter(final ExtendedInfo info, final Connection 
connection) throws Exception {
+        final GeometryGetterTest test = new GeometryGetterTest();
+        test.testFromDatabase(connection, info, BinaryEncoding.HEXADECIMAL);
+    }
+
+    /**
      * Tests {@link RasterReader}.
      */
     private void testRasterReader(final TestRaster test, final ExtendedInfo 
info, final Connection connection) throws Exception {
+        final BinaryEncoding encoding = BinaryEncoding.HEXADECIMAL;
         final RasterReader reader = new RasterReader(info);
         try (PreparedStatement stmt = connection.prepareStatement("SELECT 
image FROM features.\"SpatialData\" WHERE filename=?")) {
             stmt.setString(1, test.filename);
             final ResultSet r = stmt.executeQuery();
             assertTrue(r.next());
-            final ChannelDataInput input = new ChannelDataInput(test.filename,
-                    Channels.newChannel(r.getBinaryStream(1)), 
ByteBuffer.allocate(50), false);
+            final ReadableByteChannel channel = 
Channels.newChannel(encoding.decode(r.getBinaryStream(1)));
+            final ChannelDataInput input = new ChannelDataInput(test.filename, 
channel, ByteBuffer.allocate(50), false);
             RasterReaderTest.compareReadResult(test, reader, input);
             assertFalse(r.next());
         }
diff --git 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/test/suite/SQLTestSuite.java
 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/test/suite/SQLTestSuite.java
index 47f1db3..566261d 100644
--- 
a/storage/sis-sqlstore/src/test/java/org/apache/sis/test/suite/SQLTestSuite.java
+++ 
b/storage/sis-sqlstore/src/test/java/org/apache/sis/test/suite/SQLTestSuite.java
@@ -25,7 +25,7 @@ import org.junit.BeforeClass;
  * All tests from the {@code sis-sqlstore} module, in rough dependency order.
  */
 @Suite.SuiteClasses({
-    org.apache.sis.internal.sql.feature.EWKBTest.class,
+    org.apache.sis.internal.sql.feature.GeometryGetterTest.class,
     org.apache.sis.internal.sql.feature.SelectionClauseWriterTest.class,
     org.apache.sis.internal.sql.postgis.BandTest.class,
     org.apache.sis.internal.sql.postgis.RasterReaderTest.class,
diff --git 
a/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/feature/hexa_ewkb_4326.csv
 
b/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/feature/hexa_ewkb_4326.csv
deleted file mode 100644
index f8fc6a5..0000000
--- 
a/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/feature/hexa_ewkb_4326.csv
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Licensed to the Apache Software Foundation (ASF) under one or more
-# contributor license agreements. See the NOTICE file distributed with
-# this work for additional information regarding copyright ownership.
-
-#
-# This dataset has been generated using SQL script given in 
'hexa_ewkb_4326.sql'
-# in this folder, against a PostGIS 2.5.2. It contains two columns separated by
-# a tabulation:
-#
-#  - The geometry in WKT format.
-#  - The same geometry in EWKB format, with bytes encoded as hexadecimal 
numbers.
-#
-
-WKT    hexadecimal EWKB
-POINT(0 0)     0101000020E610000000000000000000000000000000000000
-LINESTRING(-71.160281 42.258729,-71.160837 42.259113,-71.161144 42.25932)      
0102000020E610000003000000E44A3D0B42CA51C06EC328081E21454027BF45274BCA51C0F67B629D2A214540957CEC2E50CA51C07099D36531214540
-POLYGON((0 0,0 1,1 1,1 0,0 0)) 
0103000020E61000000100000005000000000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F000000000000F03F000000000000000000000000000000000000000000000000
-POLYGON((-71.1776585052917 42.3902909739571,-71.1776820268866 
42.3903701743239,-71.1776063012595 42.3903825660754,-71.1775826583081 
42.3903033653531,-71.1776585052917 42.3902909739571))      
0103000020E610000001000000050000006285C7C15ECB51C0ED88FC0DF531454028A46F245FCB51C009075EA6F731454047DED1E65DCB51C0781C510EF83145404871A7835DCB51C0EBDAEE75F53145406285C7C15ECB51C0ED88FC0DF5314540
-MULTILINESTRING((-71.160281 42.258729,-71.160837 42.259113,-71.161144 
42.25932),(-71.1031627617667 42.3152960829043,-71.102923838298 
42.3149156848307))        
0105000020E610000002000000010200000003000000E44A3D0B42CA51C06EC328081E21454027BF45274BCA51C0F67B629D2A214540957CEC2E50CA51C07099D36531214540010200000002000000FEFCFB379AC651C0C0503E9F5B284540FFDDDD4D96C651C033AC3B284F284540
-MULTIPOLYGON(((-71.1031880899493 42.3152774590236,-71.1031627617667 
42.3152960829043,-71.102923838298 42.3149156848307,-71.1023097974109 
42.3151969047397,-71.1019285062273 42.3147384934248,-71.102505233663 
42.3144722937587,-71.10277487471 42.3141658254797,-71.103113945163 
42.3142739188902,-71.10324876416 42.31402489987,-71.1033002961013 
42.3140393340215,-71.1033488797549 42.3139495090772,-71.103396240451 
42.3138632439557,-71.1041521907712 42.3141153348029,-71.1041411411543 
42.31415450145 [...]
diff --git 
a/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/feature/hexa_ewkb_4326.sql
 
b/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/feature/hexa_ewkb_4326.sql
deleted file mode 100644
index ce508c7..0000000
--- 
a/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/feature/hexa_ewkb_4326.sql
+++ /dev/null
@@ -1,43 +0,0 @@
-
--- Licensed to the Apache Software Foundation (ASF) under one or more
--- contributor license agreements. See the NOTICE file distributed with
--- this work for additional information regarding copyright ownership.
-
-
--- This SQL script generates the content of `hexa_ewkb_4326.csv` file.
--- This file is not used directly by the tests.
-
-SELECT wkt, ST_GeomFromText(wkt, 4326) AS hexadecimal_ewkb
-FROM (
-         VALUES ('POINT(0 0)'),
-                ('LINESTRING(-71.160281 42.258729,-71.160837 
42.259113,-71.161144 42.25932)'),
-                ('POLYGON((0 0,0 1,1 1,1 0,0 0))'),
-                ('POLYGON((-71.1776585052917 
42.3902909739571,-71.1776820268866 42.3903701743239,' ||
-                 '-71.1776063012595 42.3903825660754,-71.1775826583081 
42.3903033653531,' ||
-                 '-71.1776585052917 42.3902909739571))'),
-                ('MULTILINESTRING((-71.160281 42.258729,-71.160837 
42.259113,-71.161144 42.25932),' ||
-                 '(-71.1031627617667 42.3152960829043,-71.102923838298 
42.3149156848307))'),
-                ('MULTIPOLYGON(((-71.1031880899493 42.3152774590236,' ||
-                 '-71.1031627617667 42.3152960829043,-71.102923838298 
42.3149156848307,' ||
-                 '-71.1023097974109 42.3151969047397,-71.1019285062273 
42.3147384934248,' ||
-                 '-71.102505233663 42.3144722937587,-71.10277487471 
42.3141658254797,' ||
-                 '-71.103113945163 42.3142739188902,-71.10324876416 
42.31402489987,' ||
-                 '-71.1033002961013 42.3140393340215,-71.1033488797549 
42.3139495090772,' ||
-                 '-71.103396240451 42.3138632439557,-71.1041521907712 
42.3141153348029,' ||
-                 '-71.1041411411543 42.3141545014533,-71.1041287795912 
42.3142114839058,' ||
-                 '-71.1041188134329 42.3142693656241,-71.1041112482575 
42.3143272556118,' ||
-                 '-71.1041072845732 42.3143851580048,-71.1041057218871 
42.3144430686681,' ||
-                 '-71.1041065602059 42.3145009876017,-71.1041097995362 
42.3145589148055,' ||
-                 '-71.1041166403905 42.3146168544148,-71.1041258822717 
42.3146748022936,' ||
-                 '-71.1041375307579 42.3147318674446,-71.1041492906949 
42.3147711126569,' ||
-                 '-71.1041598612795 42.314808571739,-71.1042515013869 
42.3151287620809,' ||
-                 '-71.1041173835118 42.3150739481917,-71.1040809891419 
42.3151344119048,' ||
-                 '-71.1040438678912 42.3151191367447,-71.1040194562988 
42.3151832057859,' ||
-                 '-71.1038734225584 42.3151140942995,-71.1038446938243 
42.3151006300338,' ||
-                 '-71.1038315271889 42.315094347535,-71.1037393329282 
42.315054824985,' ||
-                 '-71.1035447555574 42.3152608696313,-71.1033436658644 
42.3151648370544,' ||
-                 '-71.1032580383161 42.3152269126061,-71.103223066939 
42.3152517403219,' ||
-                 '-71.1031880899493 42.3152774590236)),' ||
-                 '((-71.1043632495873 42.315113108546,-71.1043583974082 
42.3151211109857,' ||
-                 '-71.1043443253471 42.3150676015829,-71.1043850704575 
42.3150793250568,-71.1043632495873 42.315113108546)))')
-     ) AS WKTS (wkt)
\ No newline at end of file
diff --git 
a/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/postgis/SpatialFeatures.sql
 
b/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/postgis/SpatialFeatures.sql
index 20a1bda..7302488 100644
--- 
a/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/postgis/SpatialFeatures.sql
+++ 
b/storage/sis-sqlstore/src/test/resources/org/apache/sis/internal/sql/postgis/SpatialFeatures.sql
@@ -10,12 +10,61 @@ SET search_path TO public;
 
 CREATE TABLE features."SpatialData" (
     "filename" VARCHAR(20) NOT NULL,
-    "image"    RASTER      NOT NULL,
+    "geometry" GEOMETRY,
+    "image"    RASTER,
 
     CONSTRAINT "PK_SpatialData" PRIMARY KEY ("filename")
 );
 
-INSERT INTO features."SpatialData" ("filename", "image")
-  VALUES('raster-ushort.wkb', 
('0100000200000000000000F43F000000000000044000000000000054C00000000000004EC0000000'
-      || 
'00000000000000000000000000E6100000030004000600006F0079008300D300DD00E700370141014B019B01A501AF01060000'
-      || '70007A008400D400DE00E800380142014C019C01A601B001')::raster);
+
+--
+-- Rasters with dummy sample values. Those data are duplicated in two ways:
+-- The same rasters are created in Java code by the `TestRaster` class, and
+-- the same bytes are stored in test files with ".wkb" extension.
+--
+INSERT INTO features."SpatialData" ("filename", "image") VALUES
+  ('raster-ushort.wkb', 
('0100000200000000000000F43F000000000000044000000000000054C00000000000004EC0000000'
+   || 
'00000000000000000000000000E6100000030004000600006F0079008300D300DD00E700370141014B019B01A501AF01060'
+   || '00070007A008400D400DE00E800380142014C019C01A601B001')::raster);
+
+
+--
+-- Geometries with arbitrary coordinate values.
+--
+INSERT INTO features."SpatialData" ("filename", "geometry") VALUES
+  ('hexa-wkb.csv:1', ST_GeomFromText('POINT(0 0)', 4326)),
+  ('hexa-wkb.csv:2', ST_GeomFromText('LINESTRING(-71.160281 
42.258729,-71.160837 42.259113,-71.161144 42.25932)', 4326)),
+  ('hexa-wkb.csv:3', ST_GeomFromText('POLYGON((0 0,0 1,1 1,1 0,0 0))', 4326)),
+  ('hexa-wkb.csv:4', ST_GeomFromText('POLYGON'
+   || '((-71.1776585052917 42.3902909739571,-71.1776820268866 
42.3903701743239,-71.1776063012595 42.3903825660754,'
+   ||   '-71.1775826583081 42.3903033653531,-71.1776585052917 
42.3902909739571))', 4326)),
+  ('hexa-wkb.csv:5', ST_GeomFromText('MULTILINESTRING'
+   || '((-71.160281 42.258729,-71.160837 42.259113,-71.161144 42.25932),'
+   ||  '(-71.1031627617667 42.3152960829043,-71.102923838298 
42.3149156848307))', 4326)),
+  ('hexa-wkb.csv:6', ST_GeomFromText('MULTIPOLYGON('
+   || '((-71.1031880899493 42.3152774590236,-71.1031627617667 
42.3152960829043,-71.102923838298 42.3149156848307,'
+   ||   '-71.1023097974109 42.3151969047397,-71.1019285062273 
42.3147384934248,-71.102505233663 42.3144722937587,'
+   ||   '-71.1027748747100 42.3141658254797,-71.1031139451630 
42.3142739188902,-71.103248764160 42.3140248998700,'
+   ||   '-71.1033002961013 42.3140393340215,-71.1033488797549 
42.3139495090772,-71.103396240451 42.3138632439557,'
+   ||   '-71.1041521907712 42.3141153348029,-71.1041411411543 
42.3141545014533,-71.104128779591 42.3142114839058,'
+   ||   '-71.1041188134329 42.3142693656241,-71.1041112482575 
42.3143272556118,-71.104107284573 42.3143851580048,'
+   ||   '-71.1041057218871 42.3144430686681,-71.1041065602059 
42.3145009876017,-71.104109799536 42.3145589148055,'
+   ||   '-71.1041166403905 42.3146168544148,-71.1041258822717 
42.3146748022936,-71.104137530758 42.3147318674446,'
+   ||   '-71.1041492906949 42.3147711126569,-71.1041598612795 
42.3148085717390,-71.104251501387 42.3151287620809,'
+   ||   '-71.1041173835118 42.3150739481917,-71.1040809891419 
42.3151344119048,-71.104043867891 42.3151191367447,'
+   ||   '-71.1040194562988 42.3151832057859,-71.1038734225584 
42.3151140942995,-71.103844693824 42.3151006300338,'
+   ||   '-71.1038315271889 42.3150943475350,-71.1037393329282 
42.3150548249850,-71.103544755557 42.3152608696313,'
+   ||   '-71.1033436658644 42.3151648370544,-71.1032580383161 
42.3152269126061,-71.103223066939 42.3152517403219,'
+   ||   '-71.1031880899493 42.3152774590236)),'
+   || '((-71.1043632495873 42.3151131085460,-71.1043583974082 
42.3151211109857,-71.1043443253471 42.315067601583,'
+   ||   '-71.1043850704575 42.3150793250568,-71.1043632495873 
42.315113108546)))', 4326));
+
+
+--
+-- Geometries with WKT representation in one column and WKB in another column.
+-- Used for parsing the same geometry in two ways and comparing the results.
+--
+CREATE VIEW features."Geometries" AS
+  SELECT ST_AsText(geometry) AS "WKT", geometry AS "WKB"
+  FROM   features."SpatialData"
+  WHERE  geometry IS NOT NULL;

Reply via email to