sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ama...@apache.org
Subject [sis] 14/22: refactor(SQLStore): prepare module for dialect specific syntax.
Date Thu, 14 Nov 2019 11:46:48 GMT
This is an automated email from the ASF dual-hosted git repository.

amanin pushed a commit to branch refactor/sql-store
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 4821044595e1d41840f4a9b806995d543235095c
Author: Alexis Manin <amanin@apache.org>
AuthorDate: Mon Nov 4 18:08:52 2019 +0100

    refactor(SQLStore): prepare module for dialect specific syntax.
---
 .../apache/sis/internal/feature/Geometries.java    |  14 ++-
 .../sis/internal/sql/feature/ANSIMapping.java      | 105 ++++++++++++++++++++
 .../apache/sis/internal/sql/feature/Analyzer.java  |   2 +-
 .../sis/internal/sql/feature/ColumnAdapter.java    |  35 +++++++
 .../sis/internal/sql/feature/DialectMapping.java   |  12 +++
 .../sis/internal/sql/feature/FeatureAdapter.java   |   2 -
 .../internal/sql/feature/PostGISInterpreter.java   |  19 ++++
 .../sis/internal/sql/feature/PostGISMapping.java   |  29 ++++++
 .../sis/internal/sql/feature/QueryFeatureSet.java  |   5 +-
 .../sis/internal/sql/feature/SQLQueryAdapter.java  |  25 ++++-
 .../sis/internal/sql/feature/SpatialFunctions.java | 107 +++------------------
 11 files changed, 256 insertions(+), 99 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
index f4c6507..3f78d61 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
@@ -310,6 +310,16 @@ public abstract class Geometries<G> {
     public abstract G createPolyline(int dimension, Vector... coordinates);
 
     /**
+     * Force conversion of input geometry to a polygon. If input is a closed line (e.g: Linear
ring), it should be
+     * converted to polygon object. Otherwise, an error should be thrown.
+     *
+     * @param polyline The polyline to see as a polygon.
+     * @return A polygon object.
+     * @throws IllegalArgumentException If given object is not a closed line (linear ring).
+     */
+    public abstract G toPolygon(G polyline) throws IllegalArgumentException;
+
+    /**
      * Merges a sequence of polyline instances if the first instance is an implementation
of this library.
      *
      * @param  first      the first instance to merge.
@@ -444,7 +454,7 @@ public abstract class Geometries<G> {
          * it, because in an orthonormal space, I don't see any case where it could be useful.
However, in case it
          * have to be added, we can do it here by amending created ring(s).
          */
-        return mainRect;
+        return toPolygon(mainRect);
     }
 
     /**
@@ -480,7 +490,7 @@ public abstract class Geometries<G> {
 
     public abstract double[] getPoints(Object geometry);
 
-    abstract Object createMultiPolygonImpl(final Object... polygonsOrLinearRings);
+    abstract G createMultiPolygonImpl(final Object... polygonsOrLinearRings);
 
     public static Object createMultiPolygon(final Object... polygonsOrLinearRings) {
         return findStrategy(g -> g.createMultiPolygonImpl(polygonsOrLinearRings));
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ANSIMapping.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ANSIMapping.java
new file mode 100644
index 0000000..f430e40
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ANSIMapping.java
@@ -0,0 +1,105 @@
+package org.apache.sis.internal.sql.feature;
+
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.time.Instant;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZoneOffset;
+import java.util.Optional;
+
+import org.apache.sis.internal.metadata.sql.Dialect;
+
+public class ANSIMapping implements DialectMapping {
+
+    /**
+     * Whether {@link Types#TINYINT} is an unsigned integer. Both conventions (-128 … 127
range and
+     * 0 … 255 range) are found on the web. If unspecified, we conservatively assume unsigned
bytes.
+     * All other integer types are presumed signed.
+     */
+    private final boolean isByteUnsigned;
+
+    public ANSIMapping(boolean isByteUnsigned) {
+        this.isByteUnsigned = isByteUnsigned;
+    }
+
+    @Override
+    public Dialect getDialect() {
+        return Dialect.ANSI;
+    }
+
+    @Override
+    public Optional<ColumnAdapter<?>> getMapping(int sqlType, String sqlTypeName)
{
+        return Optional.ofNullable(getMappingImpl(sqlType, sqlTypeName));
+    }
+
+    public ColumnAdapter<?> getMappingImpl(int sqlType, String sqlTypeName) {
+        switch (sqlType) {
+            case Types.BIT:
+            case Types.BOOLEAN:                 return forceCast(Boolean.class);
+            case Types.TINYINT:                 if (!isByteUnsigned) return forceCast(Byte.class);
 // else fallthrough.
+            case Types.SMALLINT:                return forceCast(Short.class);
+            case Types.INTEGER:                 return forceCast(Integer.class);
+            case Types.BIGINT:                  return forceCast(Long.class);
+            case Types.REAL:                    return forceCast(Float.class);
+            case Types.FLOAT:                   // Despite the name, this is implemented
as DOUBLE in major databases.
+            case Types.DOUBLE:                  return forceCast(Double.class);
+            case Types.NUMERIC:                 // Similar to DECIMAL except that it uses
exactly the specified precision.
+            case Types.DECIMAL:                 return forceCast(BigDecimal.class);
+            case Types.CHAR:
+            case Types.VARCHAR:
+            case Types.LONGVARCHAR:             return new ColumnAdapter<>(String.class,
ResultSet::getString);
+            case Types.DATE:                    return new ColumnAdapter<>(Date.class,
ResultSet::getDate);
+            case Types.TIME:                    return new ColumnAdapter<>(LocalTime.class,
ANSIMapping::toLocalTime);
+            case Types.TIMESTAMP:               return new ColumnAdapter<>(Instant.class,
ANSIMapping::toInstant);
+            case Types.TIME_WITH_TIMEZONE:      return new ColumnAdapter<>(OffsetTime.class,
ANSIMapping::toOffsetTime);
+            case Types.TIMESTAMP_WITH_TIMEZONE: return new ColumnAdapter<>(OffsetDateTime.class,
ANSIMapping::toODT);
+            case Types.BINARY:
+            case Types.VARBINARY:
+            case Types.LONGVARBINARY:           return new ColumnAdapter<>(byte[].class,
ResultSet::getBytes);
+            case Types.ARRAY:                   return forceCast(Object[].class);
+            case Types.OTHER:                   // Database-specific accessed via getObject
and setObject.
+            case Types.JAVA_OBJECT:             return new ColumnAdapter<>(Object.class,
ResultSet::getObject);
+            default:                            return null;
+        }
+    }
+
+    private static LocalTime toLocalTime(ResultSet source, int columnIndex) throws SQLException
{
+        final Time time = source.getTime(columnIndex);
+        return time == null ? null : time.toLocalTime();
+    }
+
+    private static Instant toInstant(ResultSet source, int columnIndex) throws SQLException
{
+        final Timestamp t = source.getTimestamp(columnIndex);
+        return t == null ? null : t.toInstant();
+    }
+
+    private static OffsetDateTime toODT(ResultSet source, int columnIndex) throws SQLException
{
+        final Timestamp t = source.getTimestamp(columnIndex);
+        final int offsetMinute = t.getTimezoneOffset();
+        return t == null ? null : t.toInstant()
+                .atOffset(ZoneOffset.ofHoursMinutes(offsetMinute / 60, offsetMinute % 60));
+    }
+
+    private static OffsetTime toOffsetTime(ResultSet source, int columnIndex) throws SQLException
{
+        final Time t = source.getTime(columnIndex);
+        final int offsetMinute = t.getTimezoneOffset();
+        return t == null ? null : t.toLocalTime()
+                .atOffset(ZoneOffset.ofHoursMinutes(offsetMinute / 60, offsetMinute % 60));
+    }
+
+    private static <T> ColumnAdapter<T> forceCast(final Class<T> targetType)
{
+        return new ColumnAdapter<>(targetType, (r, i) -> forceCast(targetType, r,
i));
+    }
+
+    private static <T> T forceCast(final Class<T> targetType, ResultSet source,
final Integer columnIndex) throws SQLException {
+        final Object value = source.getObject(columnIndex);
+        return value == null ? null : targetType.cast(value);
+    }
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Analyzer.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Analyzer.java
index 11c9e35..4a9cdd1 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Analyzer.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Analyzer.java
@@ -345,7 +345,7 @@ final class Analyzer {
         int i = 0;
         for (SQLColumn col : spec.getColumns()) {
             i++;
-            final SpatialFunctions.ColumnAdapter<?> colAdapter = functions.toJavaType(col.getType(),
col.getTypeName());
+            final ColumnAdapter<?> colAdapter = functions.toJavaType(col.getType(),
col.getTypeName());
             Class<?> type = colAdapter.javaType;
             final String colName = col.getName().getColumnName();
             final String attrName = col.getName().getAttributeName();
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ColumnAdapter.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ColumnAdapter.java
new file mode 100644
index 0000000..8fdd3a5
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/ColumnAdapter.java
@@ -0,0 +1,35 @@
+package org.apache.sis.internal.sql.feature;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.function.Function;
+
+import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+
+/**
+ * Utility to handle conversion of a result set cell value. This object is a bi-function
whose input is a result set
+ * placed on row of interest, and an index specifying which column defines the cell to read
on this line.
+ *
+ * @param <T> Type of object decoded from cell.
+ */
+class ColumnAdapter<T> implements SQLBiFunction<ResultSet, Integer, T> {
+    final Class<T> javaType;
+    private final SQLBiFunction<ResultSet, Integer, T> fetchValue;
+
+    protected ColumnAdapter(Class<T> javaType, SQLBiFunction<ResultSet, Integer,
T> fetchValue) {
+        ensureNonNull("Result java type", javaType);
+        ensureNonNull("Function for value retrieval", fetchValue);
+        this.javaType = javaType;
+        this.fetchValue = fetchValue;
+    }
+
+    @Override
+    public T apply(ResultSet resultSet, Integer integer) throws SQLException {
+        return fetchValue.apply(resultSet, integer);
+    }
+
+    @Override
+    public <V> SQLBiFunction<ResultSet, Integer, V> andThen(Function<? super
T, ? extends V> after) {
+        return fetchValue.andThen(after);
+    }
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/DialectMapping.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/DialectMapping.java
new file mode 100644
index 0000000..ce6e403
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/DialectMapping.java
@@ -0,0 +1,12 @@
+package org.apache.sis.internal.sql.feature;
+
+import java.util.Optional;
+
+import org.apache.sis.internal.metadata.sql.Dialect;
+
+public interface DialectMapping {
+
+    Dialect getDialect();
+
+    Optional<ColumnAdapter<?>> getMapping(final int sqlType, final String sqlTypeName);
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureAdapter.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureAdapter.java
index e346571..88c7546 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureAdapter.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/FeatureAdapter.java
@@ -10,8 +10,6 @@ import java.util.List;
 import org.opengis.feature.Feature;
 import org.opengis.feature.FeatureType;
 
-import org.apache.sis.internal.sql.feature.SpatialFunctions.ColumnAdapter;
-
 import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
 
 class FeatureAdapter {
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISInterpreter.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISInterpreter.java
new file mode 100644
index 0000000..684c1d8
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISInterpreter.java
@@ -0,0 +1,19 @@
+package org.apache.sis.internal.sql.feature;
+
+import org.opengis.filter.spatial.BBOX;
+
+public class PostGISInterpreter extends ANSIInterpreter {
+
+    /**
+     * Filter encoding specifies bbox as a filter between envelopes. Default ANSI interpreter
performs a standard
+     * intersection between geometries, which is not compliant. PostGIS has its own bbox
operator:
+     * <a href="https://postgis.net/docs/geometry_overlaps.html">Geometry overlapping</a>.
+     * @param filter BBox filter specifying properties to compare.
+     * @param extraData A context to handle some corner cases. Not used. Can be null.
+     * @return A text (sql query) representation of input filter.
+     */
+    @Override
+    public CharSequence visit(BBOX filter, Object extraData) {
+        return join(filter, "&&", extraData);
+    }
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
new file mode 100644
index 0000000..9c9303d
--- /dev/null
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/PostGISMapping.java
@@ -0,0 +1,29 @@
+package org.apache.sis.internal.sql.feature;
+
+import java.sql.Types;
+import java.util.Optional;
+
+import org.apache.sis.internal.metadata.sql.Dialect;
+
+public class PostGISMapping implements DialectMapping {
+    @Override
+    public Dialect getDialect() {
+        return Dialect.POSTGRESQL;
+    }
+
+    @Override
+    public Optional<ColumnAdapter<?>> getMapping(int sqlType, String sqlTypeName)
{
+        switch (sqlType) {
+            case (Types.OTHER):
+        }
+        return Optional.empty();
+    }
+
+    private ColumnAdapter<?> forOther(String sqlTypeName) {
+        switch (sqlTypeName.toLowerCase()) {
+            case "geometry":
+            case "geography":
+            default: return null;
+        }
+    }
+}
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
index e5d991c..a117b13 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
@@ -6,7 +6,6 @@ import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.List;
 import java.util.Spliterator;
-import java.util.StringJoiner;
 import java.util.function.Consumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -226,6 +225,10 @@ public class QueryFeatureSet extends AbstractFeatureSet {
 
     class SubsetAdapter extends SQLQueryAdapter {
 
+        SubsetAdapter() {
+            super(queryBuilder.dialect);
+        }
+
         @Override
         protected FeatureSet create(CharSequence where, SortBy[] sorting, ColumnRef[] columns)
{
             // TODO: use columns.
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SQLQueryAdapter.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SQLQueryAdapter.java
index 94c2d11..2932c98 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SQLQueryAdapter.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SQLQueryAdapter.java
@@ -3,10 +3,12 @@ package org.apache.sis.internal.sql.feature;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
+import java.util.function.Supplier;
 
 import org.opengis.filter.Filter;
 import org.opengis.filter.sort.SortBy;
 
+import org.apache.sis.internal.metadata.sql.Dialect;
 import org.apache.sis.internal.storage.SubsetAdapter;
 import org.apache.sis.internal.storage.query.SimpleQuery;
 import org.apache.sis.storage.FeatureSet;
@@ -18,6 +20,20 @@ abstract class SQLQueryAdapter implements SubsetAdapter.AdapterBuilder
{
 
     private CharSequence where;
 
+    private final Supplier<? extends ANSIInterpreter> filterInterpreter;
+
+    protected SQLQueryAdapter() {
+        this(() -> new ANSIInterpreter());
+    }
+
+    protected SQLQueryAdapter(final Dialect dbDialect) {
+        this(forDialect(dbDialect));
+    }
+
+    protected SQLQueryAdapter(Supplier<? extends ANSIInterpreter> filterInterpreter)
{
+        this.filterInterpreter = filterInterpreter;
+    }
+
     /**
      * No-op implementation. SQL optimisation is dynamically applied through {@link StreamSQL}.
      * @param offset The offset to handle.
@@ -41,7 +57,7 @@ abstract class SQLQueryAdapter implements SubsetAdapter.AdapterBuilder {
     @Override
     public final Filter filter(Filter filter) {
         try {
-            final Object result = filter.accept(new ANSIInterpreter(), null);
+            final Object result = filter.accept(filterInterpreter.get(), null);
             if (ANSIInterpreter.isNonEmptyText(result)) {
                 where = (CharSequence) result;
                 return Filter.INCLUDE;
@@ -88,6 +104,7 @@ abstract class SQLQueryAdapter implements SubsetAdapter.AdapterBuilder
{
     static class Table extends SQLQueryAdapter {
         final org.apache.sis.internal.sql.feature.Table parent;
         public Table(org.apache.sis.internal.sql.feature.Table parent) {
+            super(parent.createStatement().dialect);
             this.parent = parent;
         }
 
@@ -99,4 +116,10 @@ abstract class SQLQueryAdapter implements SubsetAdapter.AdapterBuilder
{
         }
     }
 
+    public static Supplier<ANSIInterpreter> forDialect(final Dialect dialect) {
+        switch (dialect) {
+            case POSTGRESQL: return () -> new PostGISInterpreter();
+            default: return () -> new ANSIInterpreter();
+        }
+    }
 }
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
index 2975d95..ca5ff05 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/SpatialFunctions.java
@@ -16,28 +16,18 @@
  */
 package org.apache.sis.internal.sql.feature;
 
-import java.math.BigDecimal;
 import java.sql.DatabaseMetaData;
-import java.sql.Date;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import java.sql.Time;
-import java.sql.Timestamp;
 import java.sql.Types;
-import java.time.Instant;
-import java.time.LocalTime;
-import java.time.OffsetDateTime;
-import java.time.OffsetTime;
-import java.time.ZoneOffset;
-import java.util.function.Function;
+import java.util.Optional;
 
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 
+import org.apache.sis.internal.metadata.sql.Dialect;
 import org.apache.sis.internal.metadata.sql.Reflection;
 import org.apache.sis.setup.GeometryLibrary;
 
-import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
-
 
 /**
  * Access to functions provided by geospatial databases.
@@ -64,6 +54,9 @@ class SpatialFunctions {
      */
     final GeometryLibrary library;
 
+    private final ANSIMapping defaultMapping;
+    private final Optional<DialectMapping> specificMapping;
+
     /**
      * Creates a new accessor to geospatial functions for the database described by given
metadata.
      */
@@ -88,6 +81,10 @@ class SpatialFunctions {
          * For now use the default library.
          */
         library = null;
+
+        final Dialect dialect = Dialect.guess(metadata);
+        specificMapping = forDialect(dialect);
+        defaultMapping = new ANSIMapping(isByteUnsigned);
     }
 
     /**
@@ -105,58 +102,8 @@ class SpatialFunctions {
      */
     @SuppressWarnings("fallthrough")
     protected ColumnAdapter<?> toJavaType(final int sqlType, final String sqlTypeName)
{
-        switch (sqlType) {
-            case Types.BIT:
-            case Types.BOOLEAN:                 return forceCast(Boolean.class);
-            case Types.TINYINT:                 if (!isByteUnsigned) return forceCast(Byte.class);
 // else fallthrough.
-            case Types.SMALLINT:                return forceCast(Short.class);
-            case Types.INTEGER:                 return forceCast(Integer.class);
-            case Types.BIGINT:                  return forceCast(Long.class);
-            case Types.REAL:                    return forceCast(Float.class);
-            case Types.FLOAT:                   // Despite the name, this is implemented
as DOUBLE in major databases.
-            case Types.DOUBLE:                  return forceCast(Double.class);
-            case Types.NUMERIC:                 // Similar to DECIMAL except that it uses
exactly the specified precision.
-            case Types.DECIMAL:                 return forceCast(BigDecimal.class);
-            case Types.CHAR:
-            case Types.VARCHAR:
-            case Types.LONGVARCHAR:             return new ColumnAdapter<>(String.class,
ResultSet::getString);
-            case Types.DATE:                    return new ColumnAdapter<>(Date.class,
ResultSet::getDate);
-            case Types.TIME:                    return new ColumnAdapter<>(LocalTime.class,
SpatialFunctions::toLocalTime);
-            case Types.TIMESTAMP:               return new ColumnAdapter<>(Instant.class,
SpatialFunctions::toInstant);
-            case Types.TIME_WITH_TIMEZONE:      return new ColumnAdapter<>(OffsetTime.class,
SpatialFunctions::toOffsetTime);
-            case Types.TIMESTAMP_WITH_TIMEZONE: return new ColumnAdapter<>(OffsetDateTime.class,
SpatialFunctions::toODT);
-            case Types.BINARY:
-            case Types.VARBINARY:
-            case Types.LONGVARBINARY:           return new ColumnAdapter<>(byte[].class,
ResultSet::getBytes);
-            case Types.ARRAY:                   return forceCast(Object[].class);
-            case Types.OTHER:                   // Database-specific accessed via getObject
and setObject.
-            case Types.JAVA_OBJECT:             return new ColumnAdapter<>(Object.class,
ResultSet::getObject);
-            default:                            return null;
-        }
-    }
-
-    private static LocalTime toLocalTime(ResultSet source, int columnIndex) throws SQLException
{
-        final Time time = source.getTime(columnIndex);
-        return time == null ? null : time.toLocalTime();
-    }
-
-    private static Instant toInstant(ResultSet source, int columnIndex) throws SQLException
{
-        final Timestamp t = source.getTimestamp(columnIndex);
-        return t == null ? null : t.toInstant();
-    }
-
-    private static OffsetDateTime toODT(ResultSet source, int columnIndex) throws SQLException
{
-        final Timestamp t = source.getTimestamp(columnIndex);
-        final int offsetMinute = t.getTimezoneOffset();
-        return t == null ? null : t.toInstant()
-                .atOffset(ZoneOffset.ofHoursMinutes(offsetMinute / 60, offsetMinute % 60));
-    }
-
-    private static OffsetTime toOffsetTime(ResultSet source, int columnIndex) throws SQLException
{
-        final Time t = source.getTime(columnIndex);
-        final int offsetMinute = t.getTimezoneOffset();
-        return t == null ? null : t.toLocalTime()
-                .atOffset(ZoneOffset.ofHoursMinutes(offsetMinute / 60, offsetMinute % 60));
+        return specificMapping.flatMap(dialect -> dialect.getMapping(sqlType, sqlTypeName))
+                .orElseGet(() -> defaultMapping.getMappingImpl(sqlType, sqlTypeName));
     }
 
     /**
@@ -174,34 +121,10 @@ class SpatialFunctions {
         return null;
     }
 
-    private static <T> ColumnAdapter<T> forceCast(final Class<T> targetType)
{
-        return new ColumnAdapter<>(targetType, (r, i) -> forceCast(targetType, r,
i));
-    }
-
-    private static <T> T forceCast(final Class<T> targetType, ResultSet source,
final Integer columnIndex) throws SQLException {
-        final Object value = source.getObject(columnIndex);
-        return value == null ? null : targetType.cast(value);
-    }
-
-    protected static class ColumnAdapter<T> implements SQLBiFunction<ResultSet,
Integer, T> {
-        final Class<T> javaType;
-        private final SQLBiFunction<ResultSet, Integer, T> fetchValue;
-
-        protected ColumnAdapter(Class<T> javaType, SQLBiFunction<ResultSet, Integer,
T> fetchValue) {
-            ensureNonNull("Result java type", javaType);
-            ensureNonNull("Function for value retrieval", fetchValue);
-            this.javaType = javaType;
-            this.fetchValue = fetchValue;
-        }
-
-        @Override
-        public T apply(ResultSet resultSet, Integer integer) throws SQLException {
-            return fetchValue.apply(resultSet, integer);
-        }
-
-        @Override
-        public <V> SQLBiFunction<ResultSet, Integer, V> andThen(Function<?
super T, ? extends V> after) {
-            return fetchValue.andThen(after);
+    static Optional<DialectMapping> forDialect(final Dialect dialect) {
+        switch (dialect) {
+            case POSTGRESQL: return Optional.of(new PostGISMapping());
+            default: return Optional.empty();
         }
     }
 }


Mime
View raw message