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

jsorel 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 4a69351845 Allow FeatureSQL to understand different standards about 
the table of CRS definitions. Supported standards are:
4a69351845 is described below

commit 4a6935184574ebf6b296018737e94812ffe80c92
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Aug 7 14:10:57 2024 +0200

    Allow FeatureSQL to understand different standards about the table of CRS 
definitions.
    Supported standards are:
    
    - Geopackage
    - ISO-13249 SQL/MM
    - ISO 19125 / OGC Simple feature access part 2
    
    They have basically the same content, but with different table and column 
names.
---
 .../apache/sis/storage/sql/feature/Analyzer.java   |   2 +-
 .../apache/sis/storage/sql/feature/Database.java   |  93 ++++++++------
 .../sis/storage/sql/feature/FeatureIterator.java   |   5 +-
 .../sis/storage/sql/feature/InfoStatements.java    |  51 ++++----
 .../sis/storage/sql/feature/SpatialSchema.java     | 135 +++++++++++++++++++++
 .../apache/sis/storage/sql/postgis/Postgres.java   |  15 ++-
 6 files changed, 235 insertions(+), 66 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Analyzer.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Analyzer.java
index 44a534e9b5..a6c61b1c59 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Analyzer.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Analyzer.java
@@ -134,7 +134,7 @@ final class Analyzer {
         this.metadata      = metadata;
         this.escape        = metadata.getSearchStringEscape();
         this.nameFactory   = DefaultNameFactory.provider();
-        spatialInformation = database.isSpatial() ? 
database.createInfoStatements(connection) : null;
+        spatialInformation = database.getSpatialSchema().isPresent() ? 
database.createInfoStatements(connection) : null;
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java
index be81eba736..71503d3fd3 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java
@@ -25,6 +25,7 @@ import java.util.LinkedHashSet;
 import java.util.WeakHashMap;
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.Optional;
 import java.util.AbstractMap.SimpleImmutableEntry;
 import java.util.logging.LogRecord;
 import java.sql.Array;
@@ -79,9 +80,9 @@ import org.apache.sis.util.collection.Cache;
  * <h2>Specializations</h2>
  * Subclasses may be defined for some database engines. Methods that can be 
overridden are:
  * <ul>
+ *   <li>{@link #getPossibleSpatialSchemas(Map)}    for enumerating the 
spatial schema conventions that may be used.</li>
  *   <li>{@link #getMapping(Column)}                for adding column types to 
recognize.</li>
  *   <li>{@link #createInfoStatements(Connection)}  for more info about 
spatial information.</li>
- *   <li>{@link #addIgnoredTables(Map)}             for specifying more tables 
to ignore.</li>
  * </ul>
  *
  * <h2>Multi-threading</h2>
@@ -138,14 +139,17 @@ public class Database<G> extends Syntax  {
     private Table[] tables;
 
     /**
-     * Whether the database contains "GEOMETRY_COLUMNS" and/or 
"SPATIAL_REF_SYS" tables.
-     * May also be set to {@code true} if some database-specific tables are 
found such as
-     * {@code "geography_columns"} and {@code "raster_columns"} in PostGIS.
+     * Information about table names and column names used for the spatial 
schema, or {@code null}.
+     * This is non-null if the database contains "GEOMETRY_COLUMNS" and/or 
"SPATIAL_REF_SYS" tables,
+     * possibly with different name depending on the conventions of the 
spatial schema. May also be
+     * non-null if some database-specific tables are found such as {@code 
"geography_columns"} and
+     * {@code "raster_columns"} in PostGIS.
+     *
      * This field is initialized by {@link #analyze analyze(…)} and shall not 
be modified after that point.
      *
-     * @see #isSpatial()
+     * @see #getSpatialSchema()
      */
-    private boolean isSpatial;
+    private SpatialSchema spatialSchema;
 
     /**
      * {@code true} if this database contains at least one geometry column.
@@ -164,8 +168,8 @@ public class Database<G> extends Syntax  {
     private boolean hasRaster;
 
     /**
-     * Catalog and schema of the {@value InfoStatements#GEOMETRY_COLUMNS} and
-     * {@value InfoStatements#SPATIAL_REF_SYS} tables, or null or empty string 
if none.
+     * Catalog and schema of the {@code "GEOMETRY_COLUMNS"} and {@code 
"SPATIAL_REF_SYS"} tables,
+     * or null or empty string if none. The actual table names depend on 
{@link #spatialSchema}.
      */
     String catalogOfSpatialTables, schemaOfSpatialTables;
 
@@ -201,10 +205,10 @@ public class Database<G> extends Syntax  {
 
     /**
      * Cache of Coordinate Reference Systems created for a given SRID.
-     * SRID are primary keys in the {@value InfoStatements#SPATIAL_REF_SYS} 
table.
+     * SRID are primary keys in the {@code "SPATIAL_REF_SYS"} (or equivalent) 
table.
      * They are not EPSG codes, even if the numerical values are often the 
same.
      *
-     * <p>This mapping depend on the content of {@value 
InfoStatements#SPATIAL_REF_SYS} table.
+     * <p>This mapping depends on the content of {@code "SPATIAL_REF_SYS"} (or 
equivalent) table.
      * For that reason, a distinct cache exists for each database.</p>
      */
     final Cache<Integer, CoordinateReferenceSystem> cacheOfCRS;
@@ -342,17 +346,26 @@ public class Database<G> extends Syntax  {
          * the default case specified by the SQL standard. However, some 
databases use lower
          * cases instead.
          */
-        String tableCRS  = InfoStatements.SPATIAL_REF_SYS;
-        String tableGeom = InfoStatements.GEOMETRY_COLUMNS;
-        if (metadata.storesLowerCaseIdentifiers()) {
-            tableCRS  = tableCRS .toLowerCase(Locale.US).intern();
-            tableGeom = tableGeom.toLowerCase(Locale.US).intern();
+        final var ignoredTables = new HashMap<String,Boolean>(8);
+        for (SpatialSchema schema : getPossibleSpatialSchemas(ignoredTables)) {
+            String tableCRS  = schema.crsTable;;
+            String tableGeom = schema.geometryColumns;
+            if (metadata.storesLowerCaseIdentifiers()) {
+                tableCRS  = tableCRS .toLowerCase(Locale.US).intern();
+                tableGeom = tableGeom.toLowerCase(Locale.US).intern();
+            } else if (metadata.storesUpperCaseIdentifiers()) {
+                tableCRS  = tableCRS .toUpperCase(Locale.US).intern();
+                tableGeom = tableGeom.toUpperCase(Locale.US).intern();
+            }
+            ignoredTables.put(tableCRS,  Boolean.TRUE);
+            ignoredTables.put(tableGeom, Boolean.TRUE);
+            if (hasTable(metadata, tableTypes, ignoredTables)) {
+                spatialSchema = schema;
+                break;
+            }
+            ignoredTables.remove(tableCRS);
+            ignoredTables.remove(tableGeom);
         }
-        final Map<String,Boolean> ignoredTables = new HashMap<>(8);
-        ignoredTables.put(tableCRS,  Boolean.TRUE);
-        ignoredTables.put(tableGeom, Boolean.TRUE);
-        addIgnoredTables(ignoredTables);
-        isSpatial = hasTable(metadata, tableTypes, ignoredTables);
         /*
          * Collect the names of all tables specified by user, ignoring the 
tables
          * used for database internal working (for example by PostGIS).
@@ -434,14 +447,14 @@ public class Database<G> extends Syntax  {
      *
      * @param  metadata    value of {@code connection.getMetaData()}.
      * @param  tableTypes  value of {@link #getTableTypes(DatabaseMetaData)}.
-     * @param  tables      name of the table to search.
+     * @param  tables      name of the table to search. Will not be modified.
      * @return whether the given table has been found.
      */
     private boolean hasTable(final DatabaseMetaData metadata, final String[] 
tableTypes, final Map<String,Boolean> tables)
             throws SQLException
     {
         // `SimpleImmutableEntry` used as a way to store a (catalog,schema) 
pair of strings.
-        final FrequencySortedSet<SimpleImmutableEntry<String,String>> schemas 
= new FrequencySortedSet<>(true);
+        final var schemas = new 
FrequencySortedSet<SimpleImmutableEntry<String,String>>(true);
         int count = 0;
         for (final Map.Entry<String,Boolean> entry : tables.entrySet()) {
             if (entry.getValue()) {
@@ -527,13 +540,13 @@ public class Database<G> extends Syntax  {
     }
 
     /**
-     * Returns {@code true} if this database is a spatial database.
-     * Tables such as "SPATIAL_REF_SYS" are used as sentinel values.
+     * Returns an identification of the table and column naming conventions.
+     * This is absent if the database is not spatial.
      *
-     * @return whether this database is a spatial database.
+     * @return an identification of the table and column naming conventions.
      */
-    public final boolean isSpatial() {
-        return isSpatial;
+    public final Optional<SpatialSchema> getSpatialSchema() {
+        return Optional.ofNullable(spatialSchema);
     }
 
     /**
@@ -706,16 +719,28 @@ public class Database<G> extends Syntax  {
     }
 
     /**
-     * Adds to the given map a list of tables to ignore when searching for 
feature tables.
-     * The given map already contains the {@code "SPATIAL_REF_SYS"} and {@code 
"GEOMETRY_COLUMNS"}
-     * entries when this method is invoked. The default implementation adds 
nothing.
+     * Returns the spatial schema conventions that may possibly be supported 
by this database.
+     * The default implementation returns all {@link SpatialSchema} 
enumeration values.
+     * Subclasses may restrict to a smaller set of possibilities.
+     *
+     * <p>In addition, this method can declare in the supplied map which 
tables are used for describing
+     * the spatial schema. The default implementation does nothing because the 
entries to add depend on
+     * the {@link SpatialSchema}. For example, if Simple Features conventions 
are used, then the tables
+     * are {@code "SPATIAL_REF_SYS"} and {@code "GEOMETRY_COLUMNS"}. 
Subclasses can add other entries
+     * if they know in advance that they support only one convention, or that 
all the conventions that
+     * they support use the same table names. The table added to the map will 
be ignored when searching
+     * for feature tables.</p>
+     *
+     * <p>The values in the map tells whether the table can be used as a 
sentinel value for determining
+     * that the {@link SpatialSchema} enumeration value can be accepted.</p>
      *
-     * <p>Values tells whether the table can be used as a sentinel value for 
determining
-     * that this database {@linkplain #isSpatial is a spatial database}.</p>
+     * @param  tables  where to add names of tables that describe the spatial 
schema.
+     * @return the spatial schema conventions that may be supported by this 
database.
      *
-     * @param  ignoredTables  where to add names of tables to ignore.
+     * @see #getSpatialSchema()
      */
-    protected void addIgnoredTables(final Map<String,Boolean> ignoredTables) {
+    protected SpatialSchema[] getPossibleSpatialSchemas(Map<String,Boolean> 
tables) {
+        return SpatialSchema.values();
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
index eb60040003..01b605c8da 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureIterator.java
@@ -85,7 +85,7 @@ final class FeatureIterator implements Spliterator<Feature>, 
AutoCloseable {
 
     /**
      * A cache of statements for fetching spatial information such as geometry 
columns or SRID.
-     * This is non-null only if the {@linkplain Database#isSpatial() database 
is spatial}.
+     * This is non-null only if the {@linkplain Database#getSpatialSchema() 
database is spatial}.
      * The same instance is shared by all dependencies of this {@code 
FeatureIterator}.
      */
     private final InfoStatements spatialInformation;
@@ -118,7 +118,8 @@ final class FeatureIterator implements 
Spliterator<Feature>, AutoCloseable {
             throws SQLException, InternalDataStoreException
     {
         adapter = table.adapter(connection);
-        spatialInformation = table.database.isSpatial() ? 
table.database.createInfoStatements(connection) : null;
+        spatialInformation = table.database.getSpatialSchema().isPresent()
+                ? table.database.createInfoStatements(connection) : null;
         String sql = adapter.sql;
         if (distinct || filter != null || sort != null || offset > 0 || count 
> 0) {
             final SQLBuilder builder = new 
SQLBuilder(table.database).append(sql);
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
index 0010191315..5337f93de9 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/InfoStatements.java
@@ -74,19 +74,6 @@ import org.opengis.metadata.Identifier;
  * @see <a href="https://www.ogc.org/standards/sfs";>OGC Simple feature access 
— Part 2: SQL option</a>
  */
 public class InfoStatements implements Localized, AutoCloseable {
-    /**
-     * The table containing CRS definitions, as specified by ISO 19125 / OGC 
Simple feature access part 2.
-     * Note that the standard specifies table names in upper-case letters, 
which is also the default case
-     * specified by the SQL standard. However, some databases use lower cases 
instead. This table name can
-     * be used unquoted for letting the database engine converts the case.
-     */
-    static final String SPATIAL_REF_SYS = "SPATIAL_REF_SYS";
-
-    /**
-     * The table containing the list of geometry columns, as specified by ISO 
19125 / OGC Simple feature access part 2.
-     */
-    static final String GEOMETRY_COLUMNS = "GEOMETRY_COLUMNS";
-
     /**
      * Specifies how the geometry type is encoded in the {@code 
"GEOMETRY_TYPE"} column.
      * The OGC standard defines numeric values, but PostGIS uses textual 
values.
@@ -227,8 +214,10 @@ public class InfoStatements implements Localized, 
AutoCloseable {
     protected final PreparedStatement prepareIntrospectionStatement(final 
String table,
             final char prefix, final String column, final String otherColumn) 
throws SQLException
     {
+        final SpatialSchema schema = database.getSpatialSchema().orElseThrow();
         final SQLBuilder sql = new 
SQLBuilder(database).append(SQLBuilder.SELECT)
-                .append(prefix).append('_').append(column).append(", SRID ");
+                .append(prefix).append('_').append(column).append(", ")
+                .append(schema.crsIdentifierColumn).append(' ');
         if (otherColumn != null) sql.append(", ").append(otherColumn);
         appendFrom(sql, table);
         if (database.supportsCatalogs) appendCondition(sql, prefix, 
"TABLE_CATALOG").append(" AND ");
@@ -250,7 +239,8 @@ public class InfoStatements implements Localized, 
AutoCloseable {
      */
     public void completeIntrospection(final TableReference source, final 
Map<String,Column> columns) throws Exception {
         if (geometryColumns == null) {
-            geometryColumns = prepareIntrospectionStatement(GEOMETRY_COLUMNS, 
'F', "GEOMETRY_COLUMN", "GEOMETRY_TYPE");
+            final SpatialSchema schema = 
database.getSpatialSchema().orElseThrow();
+            geometryColumns = 
prepareIntrospectionStatement(schema.geometryColumns, 'F', "GEOMETRY_COLUMN", 
"GEOMETRY_TYPE");
         }
         configureSpatialColumns(geometryColumns, source, columns, 
GeometryTypeEncoding.NUMERIC);
     }
@@ -302,12 +292,13 @@ public class InfoStatements implements Localized, 
AutoCloseable {
     /**
      * Gets a Coordinate Reference System for to given SRID.
      * If the given SRID is zero or negative, then this method returns {@code 
null}.
-     * Otherwise the CRS is decoded from the database {@value 
#SPATIAL_REF_SYS} table.
+     * Otherwise the CRS is decoded from the database {@code 
"SPATIAL_REF_SYS"} table
+     * or equivalent (depending on the {@link SpatialSchema}).
      *
      * @param  srid  the Spatial Reference Identifier (SRID) to resolve as a 
CRS object.
      * @return the CRS associated to the given SRID, or {@code null} if the 
SRID is zero.
      * @throws DataStoreContentException if the CRS cannot be fetched. 
Possible reasons are:
-     *         no entry found in the {@value #SPATIAL_REF_SYS} table, or more 
than one entry is found,
+     *         no entry found in the {@code "SPATIAL_REF_SYS"} table, or more 
than one entry is found,
      *         or a single entry exists but has no WKT definition and its 
authority code is unsupported by SIS.
      * @throws ParseException if the WKT cannot be parsed.
      * @throws SQLException if a SQL error occurred.
@@ -323,7 +314,7 @@ public class InfoStatements implements Localized, 
AutoCloseable {
 
     /**
      * Invoked when the requested CRS is not in the cache. This method gets 
the entry from the
-     * {@value #SPATIAL_REF_SYS} table then gets the CRS from its authority 
code if possible,
+     * {@link SpatialSchema#refSysTable} then gets the CRS from its authority 
code if possible,
      * or fallback on the WKT otherwise.
      *
      * @param  srid  the Spatial Reference Identifier (SRID) of the CRS to 
create from the database content.
@@ -332,10 +323,13 @@ public class InfoStatements implements Localized, 
AutoCloseable {
      */
     private CoordinateReferenceSystem parseCRS(final int srid) throws 
Exception {
         if (wktFromSrid == null) {
+            final SpatialSchema schema = 
database.getSpatialSchema().orElseThrow();
             final SQLBuilder sql = new SQLBuilder(database);
-            sql.append("SELECT auth_name, auth_srid, srtext");
-            appendFrom(sql, SPATIAL_REF_SYS);
-            sql.append("srid=?");
+            sql.append("SELECT").append(schema.crsAuthorityNameColumn)
+                                .append(schema.crsAuthorityCodeColumn)
+                                .append(schema.crsDefinitionColumn);
+            appendFrom(sql, schema.crsTable);
+            sql.append(schema.crsIdentifierColumn).append("=?");
             wktFromSrid = connection.prepareStatement(sql.toString());
         }
         wktFromSrid.setInt(1, srid);
@@ -393,7 +387,8 @@ public class InfoStatements implements Localized, 
AutoCloseable {
                     if (crs == null) {
                         crs = v.recommendation;
                     } else if (!crs.equals(v.recommendation)) {
-                        throw invalidSRID(Resources.Keys.DuplicatedSRID_2, 
SPATIAL_REF_SYS, srid, authorityError);
+                        final SpatialSchema schema = 
database.getSpatialSchema().orElseThrow();
+                        throw invalidSRID(Resources.Keys.DuplicatedSRID_2, 
schema.crsTable, srid, authorityError);
                     }
                     warning = v.warning(false);
                     if (warning == null && fromWKT != null) {
@@ -417,7 +412,8 @@ public class InfoStatements implements Localized, 
AutoCloseable {
             if (authorityError != null) {
                 throw authorityError;
             }
-            throw invalidSRID(Resources.Keys.UnknownSRID_2, SPATIAL_REF_SYS, 
srid, null);
+            final SpatialSchema schema = 
database.getSpatialSchema().orElseThrow();
+            throw invalidSRID(Resources.Keys.UnknownSRID_2, schema.crsTable, 
srid, null);
         }
         if (warning != null) {
             warning.setLoggerName(Modules.SQL);
@@ -497,10 +493,13 @@ public class InfoStatements implements Localized, 
AutoCloseable {
                  * Get the WKT and verifies if the CRS is approximately equal.
                  */
                 if (sridFromCRS == null) {
+                    final SpatialSchema schema = 
database.getSpatialSchema().orElseThrow();
                     final SQLBuilder sql = new SQLBuilder(database);
-                    sql.append("SELECT srtext, srid");
-                    appendFrom(sql, SPATIAL_REF_SYS);
-                    sql.append("auth_name=? AND auth_srid=?");
+                    sql.append("SELECT").append(schema.crsDefinitionColumn)
+                                        .append(schema.crsIdentifierColumn);
+                    appendFrom(sql, schema.crsTable);
+                    sql.append(schema.crsAuthorityNameColumn).append("=? AND ")
+                       .append(schema.crsAuthorityCodeColumn).append("=?");
                     sridFromCRS = connection.prepareStatement(sql.toString());
                 }
                 sridFromCRS.setString(1, authority);
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java
new file mode 100644
index 0000000000..5f0f915805
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/SpatialSchema.java
@@ -0,0 +1,135 @@
+/*
+ * 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.storage.sql.feature;
+
+
+/**
+ * Information about table names and column names used for the spatial schema.
+ * There is many standards, with nearly identical content but different names.
+ *
+ * <ul>
+ *   <li>Geopackage</li>
+ *   <li>ISO-13249 SQL/MM</li>
+ *   <li>ISO 19125 / OGC Simple feature access part 2</li>
+ * </ul>
+ *
+ * The presence of tables for each standard will be tested in enumeration 
order.
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+public enum SpatialSchema {
+    /**
+     * Table and column names as specified by Geopackage. This is the same 
thing as {@link #SQL_MM}
+     * except for table names and for the case (Geopackage uses lower case).
+     */
+    GEOPACKAGE("gpkg_spatial_ref_sys", "srs_id", "organization", 
"organization_coordsys_id", "definition",
+               "gpkg_geometry_columns"),
+
+    /**
+     * Table and column names as specified by ISO-13249 SQL/MM. This is the 
same thing as {@link #SIMPLE_FEATURE}
+     * with only different names. The table definition for CRS is:
+     *
+     * {@snippet lang="sql" :
+     * CREATE TABLE ST_SPATIAL_REFERENCE_SYSTEMS(
+     *   SRS_NAME CHARACTER VARYING(ST_MaxSRSNameLength) NOT NULL,
+     *   SRS_ID INTEGER NOT NULL,
+     *   ORGANIZATION CHARACTER VARYING(ST_MaxOrganizationNameLength),
+     *   ORGANIZATION_COORDSYS_ID INTEGER,
+     *   DEFINITION CHARACTER VARYING(ST_MaxSRSDefinitionLength) NOT NULL,
+     *   DESCRIPTION CHARACTER VARYING(ST_MaxDescriptionLength))
+     * }
+     *
+     * In Geopackage, this table is named {@code "gpkg_spatial_ref_sys"} but 
otherwise has identical content
+     * except for the case (Geopackage uses lower case).
+     */
+    SQL_MM("ST_SPATIAL_REFERENCE_SYSTEMS", "SRS_ID", "ORGANIZATION", 
"ORGANIZATION_COORDSYS_ID", "DEFINITION",
+           "ST_GEOMETRY_COLUMNS"),
+
+    /**
+     * Table and column names as specified by ISO 19125 / OGC Simple feature 
access part 2.
+     * Note that the standard specifies table names in upper-case letters, 
which is also the default case
+     * specified by the SQL standard. However, some databases use lower cases 
instead. This table name can
+     * be used unquoted for letting the database engine converts the case. The 
table definition for CRS is:
+     *
+     * {@snippet lang="sql" :
+     * CREATE TABLE SPATIAL_REF_SYS (
+     *   SRID INTEGER NOT NULL PRIMARY KEY,
+     *   AUTH_NAME CHARACTER VARYING,
+     *   AUTH_SRID INTEGER,
+     *   SRTEXT CHARACTER VARYING(2048))
+     * }
+     */
+    SIMPLE_FEATURE("SPATIAL_REF_SYS", "SRID", "AUTH_NAME", "AUTH_SRID", 
"SRTEXT",
+                   "GEOMETRY_COLUMNS");
+
+    /**
+     * Name of the table for Spatial Reference System definitions.
+     * Example: {@code "SPATIAL_REF_SYS"}, {@code 
"ST_SPATIAL_REFERENCE_SYSTEMS"}.
+     */
+    final String crsTable;
+
+    /**
+     * Name of the column for CRS identifiers.
+     * Example: {@code "SRID"}, {@code "SRS_ID"}.
+     */
+    final String crsIdentifierColumn;
+
+    /**
+     * Name of the column for CRS authority names.
+     * Example: {@code "AUTH_NAME"}, {@code "ORGANIZATION"}.
+     */
+    final String crsAuthorityNameColumn;
+
+    /**
+     * Name of the column for CRS authority codes.
+     * Example: {@code "AUTH_SRID"}, {@code "ORGANIZATION_COORDSYS_ID"}.
+     */
+    final String crsAuthorityCodeColumn;
+
+    /**
+     * Name of the column for CRS definitions in Well-Known Text 
(<abbr>WKT</abbr>) format.
+     * Example: {@code "SRTEXT"}, {@code "DEFINITION"}.
+     */
+    final String crsDefinitionColumn;
+
+    /**
+     * Name of the table enumerating the geometry columns.
+     */
+    final String geometryColumns;
+
+    /**
+     * Creates a new enumeration value.
+     *
+     * @param crsTable                name of the table for Spatial Reference 
System definitions.
+     * @param crsIdentifierColumn     name of the column for CRS identifiers.
+     * @param crsAuthorityNameColumn  name of the column for CRS authority 
names.
+     * @param crsAuthorityCodeColumn  name of the column for CRS authority 
codes.
+     * @param crsDefinitionColumn     name of the column for CRS definitions 
in <abbr>WKT</abbr> format.
+     * @param geometryColumns         name of the table enumerating the 
geometry columns.
+     */
+    private SpatialSchema(String crsTable, String crsIdentifierColumn, String 
crsAuthorityNameColumn,
+                          String crsAuthorityCodeColumn, String 
crsDefinitionColumn, String geometryColumns)
+    {
+        this.crsTable               = crsTable;
+        this.crsIdentifierColumn    = crsIdentifierColumn;
+        this.crsAuthorityNameColumn = crsAuthorityNameColumn;
+        this.crsAuthorityCodeColumn = crsAuthorityCodeColumn;
+        this.crsDefinitionColumn    = crsDefinitionColumn;
+        this.geometryColumns        = geometryColumns;
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java
index 054f36b253..20a4a43d1a 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java
@@ -37,6 +37,7 @@ import org.apache.sis.storage.sql.feature.Database;
 import org.apache.sis.storage.sql.feature.ValueGetter;
 import org.apache.sis.storage.sql.feature.Resources;
 import org.apache.sis.storage.sql.feature.SelectionClauseWriter;
+import org.apache.sis.storage.sql.feature.SpatialSchema;
 import org.apache.sis.metadata.sql.privy.Dialect;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.util.Version;
@@ -185,15 +186,23 @@ public final class Postgres<G> extends Database<G> {
     }
 
     /**
-     * Adds to the given set a list of tables to ignore when searching for 
feature tables.
+     * Returns the spatial schema conventions that may possibly be supported 
by this database.
+     * The only value expected by PostGIS databases is {@link 
SpatialSchema#SIMPLE_FEATURE}.
+     * This method also completes the given map with additional tables 
describing the schema.
+     * Those tables shall be ignored when searching for feature tables.
      *
-     * @param  ignoredTables  where to add names of tables to ignore.
+     * <p>The values in the map tells whether the table can be used as a 
sentinel value for
+     * determining that the {@link SpatialSchema} enumeration value can be 
accepted.</p>
+     *
+     * @param  tables  where to add names of tables that describe the spatial 
schema.
+     * @return the spatial schema convention supported by this database.
      */
     @Override
-    protected void addIgnoredTables(final Map<String,Boolean> ignoredTables) {
+    protected SpatialSchema[] getPossibleSpatialSchemas(final 
Map<String,Boolean> ignoredTables) {
         ignoredTables.put("geography_columns", Boolean.TRUE);     // Postgis 1+
         ignoredTables.put("raster_columns",    Boolean.TRUE);     // Postgis 2
         ignoredTables.put("raster_overviews",  Boolean.FALSE);
+        return new SpatialSchema[] {SpatialSchema.SIMPLE_FEATURE};
     }
 
     /**

Reply via email to