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 772a8f4da1 Move the `SQLStore.findCRS(int)` and `findSRID(CRS)` 
methods to a separated `DataAccess` object. This separation allows to keep 
using the same SQL connection for many CRS/SRID searches or other operations.
772a8f4da1 is described below

commit 772a8f4da13c39b464cadda4f4a9e014b844b49c
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Aug 22 18:45:03 2024 +0200

    Move the `SQLStore.findCRS(int)` and `findSRID(CRS)` methods to a separated 
`DataAccess` object.
    This separation allows to keep using the same SQL connection for many 
CRS/SRID searches or other operations.
---
 .../org/apache/sis/storage/sql/DataAccess.java     | 275 +++++++++++++++++++++
 .../main/org/apache/sis/storage/sql/SQLStore.java  | 152 ++----------
 .../org/apache/sis/storage/sql/DataAccessTest.java |  69 ++++++
 .../storage/sql/feature/InfoStatementsTest.java    |  20 +-
 4 files changed, 385 insertions(+), 131 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/DataAccess.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/DataAccess.java
new file mode 100644
index 0000000000..727317a4fa
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/DataAccess.java
@@ -0,0 +1,275 @@
+/*
+ * 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;
+
+import java.util.Objects;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLNonTransientConnectionException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.DataStoreClosedException;
+import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.storage.NoSuchDataException;
+import org.apache.sis.storage.sql.feature.Database;
+import org.apache.sis.storage.sql.feature.InfoStatements;
+import org.apache.sis.util.Exceptions;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Provides a <abbr>SQL</abbr> connection to the database, together with 
helper methods.
+ * Each {@code DataAccess} object can hold a {@link Connection} (created when 
first needed),
+ * and sometime a read or write lock. The locks are used only for some 
databases such as SQLite,
+ * when concurrency issues are observed during database transactions.
+ *
+ * <p>This object shall be used in a {@code try ... finally} block for 
ensuring that the connection
+ * is closed and the lock (if any) released. Note that the <abbr>SQL</abbr> 
connection does not need
+ * to be closed by users, because it will be closed by the {@link #close()} 
method of this data access
+ * object. Example:</p>
+ *
+ * {@snippet lang="java" :
+ *   SQLStore store = ...;
+ *   try (DataAccess dao = store.newDataAccess(false)) {
+ *       Connection cnx = dao.getConnection();
+ *       try (Statement stmt = cnx.createStatement()) {
+ *           // Perform some SQL queries here.
+ *       }
+ *   }
+ *   }
+ *
+ * This class is not thread safe. Each instance should be used by a single 
thread.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.5
+ * @since   1.5
+ */
+public class DataAccess implements AutoCloseable {
+    /**
+     * The data store for which this object is providing data access.
+     * The value of this field is specified at construction time.
+     */
+    protected final SQLStore store;
+
+    /**
+     * The SQL connection, created when first needed.
+     */
+    private Connection connection;
+
+    /**
+     * Helper methods for fetching information such as coordinate reference 
systems.
+     * Created when first needed.
+     */
+    private InfoStatements statements;
+
+    /**
+     * A read or write lock to unlock when the data access will be closed, or 
{@code null} if none.
+     */
+    private Lock lock;
+
+    /**
+     * Whether this data access object will allow write operations.
+     * This flag also determines whether the lock to acquire (if any) will be 
a read lock or a write lock.
+     * The value of this field is specified at construction time.
+     */
+    protected final boolean write;
+
+    /**
+     * Whether this data access object has been closed.
+     *
+     * @see #ensureOpen()
+     * @see #close()
+     */
+    private boolean isClosed;
+
+    /**
+     * Creates a new data access object for the given SQL store.
+     *
+     * @param  store  the data store for which this object is providing data 
access.
+     * @param  write  whether write operations may be requested.
+     *
+     * @see SQLStore#newDataAccess(boolean)
+     */
+    protected DataAccess(final SQLStore store, final boolean write) {
+        this.store = Objects.requireNonNull(store);
+        this.write = write;
+    }
+
+    /**
+     * Returns the error message for the exception to throw when the 
connection is closed.
+     */
+    private String closed() {
+        return 
Errors.forLocale(store.getLocale()).getString(Errors.Keys.ConnectionClosed);
+    }
+
+    /**
+     * Returns the connection to the database.
+     * The connection is established on the first time that this method is 
invoked,
+     * then the same connection is returned until this data access object is 
{@linkplain #close() closed}.
+     * If a read or write lock is needed, it will be acquired before the 
connection is established.
+     *
+     * @return connection to the database.
+     * @throws SQLException if the connection cannot be established.
+     */
+    public final Connection getConnection() throws SQLException {
+        if (isClosed) {
+            throw new SQLNonTransientConnectionException(closed());
+        }
+        if (connection == null) {
+            final ReadWriteLock transactionLocks = store.transactionLocks;
+            if (transactionLocks != null) {
+                final Lock c = write ? transactionLocks.writeLock() : 
transactionLocks.readLock();
+                c.lock();
+                lock = c;       // Store only if the lock succeed.
+            }
+            connection = store.getDataSource().getConnection();
+        }
+        return connection;
+    }
+
+    /**
+     * Returns the helper object for fetching information from {@code 
SPATIAL_REF_SYS} table.
+     * The helper object is created the first time that this method is invoked.
+     */
+    private InfoStatements statements() throws Exception {
+        if (statements == null) {
+            final Connection c = getConnection();
+            synchronized (store) {
+                final Database<?> model = store.model(c);
+                if (model.dialect.supportsReadOnlyUpdate()) {
+                    // TODO: should be in `getConnection() if we could remove 
the need for `supportsReadOnlyUpdate()`.
+                    c.setReadOnly(!write);
+                }
+                statements = model.createInfoStatements(c);
+            }
+        }
+        return statements;
+    }
+
+    /**
+     * Returns the coordinate reference system associated to the given 
identifier. The spatial reference
+     * system identifiers (<abbr>SRID</abbr>) are the primary keys of the 
{@code "SPATIAL_REF_SYS"} table
+     * (the name of that table may vary depending on which spatial schema 
standard is used).
+     * Those identifiers are specific to each database and are not necessarily 
related to EPSG codes.
+     * They should be considered as opaque identifiers.
+     *
+     * <h4>Undefined <abbr>CRS</abbr></h4>
+     * Some standards such as Geopackage define 0 as "undefined geographic 
<abbr>CRS</abbr>" and -1 as
+     * "undefined Cartesian <abbr>CRS</abbr>". This method returns {@code 
null} for all undefined <abbr>CRS</abbr>,
+     * regardless their type. No default value is returned because this class 
cannot guess the datum and units of
+     * measurement of an undefined <abbr>CRS</abbr>. All <abbr>SRID</abbr> 
equal or less than zero are considered
+     * undefined.
+     *
+     * <h4>Axis order</h4>
+     * Some standards such as Geopackage mandate (east, north) axis order. 
{@code SQLStore} uses the axis order
+     * as defined in the <abbr>WKT</abbr> descriptions of the {@code 
"SPATIAL_REF_SYS"} table. No reordering is
+     * applied. It is data producer's responsibility to provide definitions 
with the expected axis order.
+     *
+     * @param  srid  a primary key value of the {@code "SPATIAL_REF_SYS"} 
table.
+     * @return the <abbr>CRS</abbr> associated to the given <abbr>SRID</abbr>, 
or {@code null} if the given
+     *         <abbr>SRID</abbr> is a code explicitly associated to an 
undefined <abbr>CRS</abbr>.
+     * @throws NoSuchDataException if no <abbr>CRS</abbr> is associated to the 
given <abbr>SRID</abbr>.
+     * @throws DataStoreException if the query failed for another reason.
+     */
+    public CoordinateReferenceSystem findCRS(final int srid) throws 
DataStoreException {
+        if (isClosed) {
+            throw new DataStoreClosedException(closed());
+        }
+        if (srid <= 0) {
+            return null;
+        }
+        Database<?> database = store.modelOrNull();
+        CoordinateReferenceSystem crs;
+        if (database == null || (crs = database.getCachedCRS(srid)) == null) 
try {
+            crs = statements().fetchCRS(srid);
+        } catch (DataStoreContentException e) {
+            throw new NoSuchDataException(e.getMessage(), e.getCause());
+        } catch (DataStoreException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new DataStoreException(Exceptions.unwrap(e));
+        }
+        return crs;
+    }
+
+    /**
+     * Returns the <abbr>SRID</abbr> associated to the given spatial reference 
system.
+     * This method is the converse of {@link #findCRS(int)}.
+     *
+     * <p>If the {@code write} argument given at construction time was {@code 
true}, then this method is allowed
+     * to add a new row in the {@code "SPATIAL_REF_SYS"} table if the given 
<abbr>CRS</abbr> is not found.</p>
+     *
+     * @param  crs  the CRS for which to find a SRID, or {@code null}.
+     * @return SRID for the given <abbr>CRS</abbr>, or 0 if the given 
<abbr>CRS</abbr> was null.
+     * @throws DataStoreException if an <abbr>SQL</abbr> error, parsing error 
or other error occurred.
+     */
+    public int findSRID(final CoordinateReferenceSystem crs) throws 
DataStoreException {
+        if (isClosed) {
+            throw new DataStoreClosedException(closed());
+        }
+        if (crs == null) {
+            return 0;
+        }
+        Database<?> database = store.modelOrNull();
+        if (database != null) {
+            Integer srid = database.getCachedSRID(crs);
+            if (srid != null) return srid;
+        }
+        final int srid;
+        try {
+            srid = statements().findSRID(crs);
+        } catch (DataStoreException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new DataStoreException(Exceptions.unwrap(e));
+        }
+        return srid;
+    }
+
+    /**
+     * Closes the connection and release the read or write lock (if any).
+     *
+     * @throws SQLException if an error occurred while closing the connection.
+     */
+    @Override
+    public void close() throws SQLException {
+        isClosed = true;                // Set first in case an exception is 
thrown.
+        try {
+            try {
+                final InfoStatements c = statements;
+                if (c != null) {
+                    statements = null;
+                    c.close();
+                }
+            } finally {
+                final Connection c = connection;
+                if (c != null) {
+                    connection = null;
+                    c.close();          // Does nothing if already closed by 
the user.
+                }
+            }
+        } finally {
+            final Lock c = lock;
+            if (c != null) {
+                lock = null;
+                c.unlock();
+            }
+        }
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
index fef44eb0d4..a6619fc28e 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java
@@ -20,7 +20,6 @@ import java.util.Map;
 import java.util.LinkedHashMap;
 import java.util.Optional;
 import java.util.Collection;
-import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import javax.sql.DataSource;
 import java.sql.Connection;
@@ -28,7 +27,6 @@ import java.lang.reflect.Method;
 import org.opengis.util.GenericName;
 import org.opengis.metadata.Metadata;
 import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.metadata.spatial.SpatialRepresentationType;
 import org.apache.sis.storage.Resource;
 import org.apache.sis.storage.Aggregate;
@@ -36,8 +34,6 @@ import org.apache.sis.storage.FeatureSet;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.storage.NoSuchDataException;
 import org.apache.sis.storage.IllegalNameException;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.event.StoreEvent;
@@ -45,7 +41,6 @@ import org.apache.sis.storage.event.StoreListener;
 import org.apache.sis.storage.event.WarningEvent;
 import org.apache.sis.storage.sql.feature.Database;
 import org.apache.sis.storage.sql.feature.Resources;
-import org.apache.sis.storage.sql.feature.InfoStatements;
 import org.apache.sis.storage.sql.feature.SchemaModifier;
 import org.apache.sis.storage.base.MetadataBuilder;
 import org.apache.sis.io.stream.InternalOptionKey;
@@ -146,10 +141,9 @@ public class SQLStore extends DataStore implements 
Aggregate {
      * <p>This lock is not used for cache integrity. The {@code SQLStore} 
caches are protected
      * by classical synchronized statements.</p>
      *
-     * @see #lock(boolean)
      * @see Database#transactionLocks
      */
-    private final ReadWriteLock transactionLocks;
+    final ReadWriteLock transactionLocks;
 
     /**
      * Creates a new {@code SQLStore} for the given data source and tables, 
views or queries.
@@ -248,6 +242,14 @@ public class SQLStore extends DataStore implements 
Aggregate {
         return Optional.empty();
     }
 
+    /**
+     * Returns the database model if it already exists, or {@code null} 
otherwise.
+     * This method is thread-safe.
+     */
+    final Database<?> modelOrNull() {
+        return model;
+    }
+
     /**
      * Returns the database model, analyzing the database schema when first 
needed.
      * This method is thread-safe.
@@ -275,7 +277,7 @@ public class SQLStore extends DataStore implements 
Aggregate {
      *
      * @param c  connection to the database.
      */
-    private Database<?> model(final Connection c) throws Exception {
+    final Database<?> model(final Connection c) throws Exception {
         assert Thread.holdsLock(this);
         Database<?> current = model;
         if (current == null) {
@@ -359,129 +361,29 @@ public class SQLStore extends DataStore implements 
Aggregate {
     }
 
     /**
-     * Returns the coordinate reference system associated to the given 
identifier. The spatial reference
-     * system identifiers (<abbr>SRID</abbr>) are the primary keys of the 
{@code "SPATIAL_REF_SYS"} table
-     * (the name of that table may vary depending on which spatial schema 
standard is used).
-     * Those identifiers are specific to each database and are not necessarily 
related to EPSG codes.
-     * They should be considered as opaque identifiers.
+     * Creates a new data access object. The returned object can give a 
<abbr>SQL</abbr> {@link Connection}
+     * to the database and provider methods for fetching or adding 
<abbr>CRS</abbr> definitions from/into
+     * the {@code SPATIAL_REF_SYS} table.
      *
-     * <h4>Undefined <abbr>CRS</abbr></h4>
-     * Some standards such as Geopackage define 0 as "undefined geographic 
<abbr>CRS</abbr>" and -1 as
-     * "undefined Cartesian <abbr>CRS</abbr>". This method returns {@code 
null} for all undefined <abbr>CRS</abbr>,
-     * regardless their type. No default value is returned because this class 
cannot guess the datum and units of
-     * measurement of an undefined <abbr>CRS</abbr>. All <abbr>SRID</abbr> 
equal or less than zero are considered
-     * undefined.
+     * <p>The returned object shall be used in a {@code try ... finally} block.
+     * This is needed not only for closing the connection, but also for 
releasing read or write lock.
+     * Example:</p>
      *
-     * <h4>Axis order</h4>
-     * Some standards such as Geopackage mandate (east, north) axis order. 
{@code SQLStore} uses the axis order
-     * as defined in the <abbr>WKT</abbr> descriptions of the {@code 
"SPATIAL_REF_SYS"} table. No reordering is
-     * applied. It is data producer's responsibility to provide definitions 
with the expected axis order.
+     * {@snippet lang="java" :
+     *   try (DataAccess dao = newDataAccess(false)) {
+     *       try (Statement stmt = dao.getConnection().createStatement()) {
+     *           // Perform some SQL queries here.
+     *       }
+     *   }
+     *   }
      *
-     * @param  srid  a primary key value of the {@code "SPATIAL_REF_SYS"} 
table.
-     * @return the <abbr>CRS</abbr> associated to the given <abbr>SRID</abbr>, 
or {@code null} if the given
-     *         <abbr>SRID</abbr> is a code explicitly associated to an 
undefined <abbr>CRS</abbr>.
-     * @throws NoSuchDataException if no <abbr>CRS</abbr> is associated to the 
given <abbr>SRID</abbr>.
-     * @throws DataStoreException if the query failed for another reason.
+     * @param  write  whether write operations may be requested.
+     * @return an object provider low-level access (e.g. through 
<abbr>SQL</abbr> queries) to the data.
      *
      * @since 1.5
      */
-    public CoordinateReferenceSystem findCRS(final int srid) throws 
DataStoreException {
-        if (srid <= 0) {
-            return null;
-        }
-        Database<?> database = model;
-        CoordinateReferenceSystem crs;
-        if (database == null || (crs = database.getCachedCRS(srid)) == null) {
-            final Lock lock = lock(false);
-            try {
-                try (Connection c = source.getConnection()) {
-                    if (database == null) {
-                        synchronized (this) {
-                            database = model(c);
-                        }
-                    }
-                    try (InfoStatements info = 
database.createInfoStatements(c)) {
-                        crs = info.fetchCRS(srid);
-                    }
-                } catch (DataStoreContentException e) {
-                    throw new NoSuchDataException(e.getMessage(), 
e.getCause());
-                } catch (DataStoreException e) {
-                    throw e;
-                } catch (Exception e) {
-                    throw new DataStoreException(Exceptions.unwrap(e));
-                }
-            } finally {
-                if (lock != null) {
-                    lock.unlock();
-                }
-            }
-        }
-        return crs;
-    }
-
-    /**
-     * Returns the <abbr>SRID</abbr> associated to the given spatial reference 
system.
-     * This method is the converse of {@link #findCRS(int)}.
-     *
-     * @param  crs       the CRS for which to find a SRID, or {@code null}.
-     * @param  allowAdd  whether to allow the addition of a new row in the 
{@code "SPATIAL_REF_SYS"} table
-     *                   if the given <abbr>CRS</abbr> is not found.
-     * @return SRID for the given <abbr>CRS</abbr>, or 0 if the given 
<abbr>CRS</abbr> was null.
-     * @throws DataStoreException if an <abbr>SQL</abbr> error, parsing error 
or other error occurred.
-     *
-     * @since 1.5
-     */
-    public int findSRID(final CoordinateReferenceSystem crs, final boolean 
allowAdd) throws DataStoreException {
-        if (crs == null) {
-            return 0;
-        }
-        Database<?> database = model;
-        if (database != null) {
-            Integer srid = database.getCachedSRID(crs);
-            if (srid != null) return srid;
-        }
-        final int srid;
-        final Lock lock = lock(allowAdd);
-        try {
-            try (Connection c = source.getConnection()) {
-                if (database == null) {
-                    synchronized (this) {
-                        database = model(c);
-                    }
-                }
-                if (!allowAdd && database.dialect.supportsReadOnlyUpdate()) {
-                    c.setReadOnly(true);
-                }
-                try (InfoStatements info = database.createInfoStatements(c)) {
-                    srid = info.findSRID(crs);
-                }
-            } catch (DataStoreException e) {
-                throw e;
-            } catch (Exception e) {
-                throw new DataStoreException(Exceptions.unwrap(e));
-            }
-        } finally {
-            if (lock != null) {
-                lock.unlock();
-            }
-        }
-        return srid;
-    }
-
-    /**
-     * Returns a read or write lock, or {@code null} if none.
-     * The call to {@link Lock#lock()} will be already performed.
-     *
-     * @param  write  {@code true} for the write lock, or {@code false} for 
the read lock.
-     * @return the requested lock, or {@code null} if none.
-     */
-    private Lock lock(final boolean write) {
-        if (transactionLocks == null) {
-            return null;
-        }
-        final Lock lock = write ? transactionLocks.writeLock() : 
transactionLocks.readLock();
-        lock.lock();
-        return lock;
+    public DataAccess newDataAccess(final boolean write) {
+        return new DataAccess(this, write);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/DataAccessTest.java
 
b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/DataAccessTest.java
new file mode 100644
index 0000000000..991fd55514
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/DataAccessTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+import java.util.List;
+import org.apache.sis.storage.StorageConnector;
+
+// Test dependencies
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.metadata.sql.TestDatabase;
+import org.apache.sis.referencing.crs.HardCodedCRS;
+import org.apache.sis.storage.sql.feature.InfoStatementsTest;
+
+
+/**
+ * Tests {@link DataAccess}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+public final class DataAccessTest extends TestCase {
+    /**
+     * Creates a new test case.
+     */
+    public DataAccessTest() {
+    }
+
+    /**
+     * Tests on Derby.
+     *
+     * @throws Exception if an error occurred while testing the database.
+     */
+    @Test
+    public void testOnDerby() throws Exception {
+        try (TestDatabase database = TestDatabase.create("SQL-DataAccess")) {
+            test(database);
+        }
+    }
+
+    /**
+     * Runs all tests on a single database software.
+     *
+     * @param  database  factory for creating a test database.
+     * @throws Exception if an error occurred while executing the test.
+     */
+    private void test(final TestDatabase database) throws Exception {
+        database.executeSQL(List.of(InfoStatementsTest.createSpatialRefSys()));
+        try (SQLStore store = new SQLStore(null, new 
StorageConnector(database.source), ResourceDefinition.table("%"));
+             DataAccess dao = store.newDataAccess(true))
+        {
+            assertEquals(4326, dao.findSRID(HardCodedCRS.WGS84));
+        }
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java
 
b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java
index 403bdee386..26fe0a1fc5 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/InfoStatementsTest.java
@@ -79,6 +79,19 @@ public final class InfoStatementsTest extends TestCase {
         test = TestDatabase.create("InfoStatements");
     }
 
+    /**
+     * Returns the SQL statement for creating the {@code SPATIAL_REF_SYS} 
table.
+     *
+     * @return the {@code CREATE TABLE SPATIAL_REF_SYS} statement.
+     */
+    public static String createSpatialRefSys() {
+        return "CREATE TABLE SPATIAL_REF_SYS ("
+                + "SRID INTEGER NOT NULL PRIMARY KEY, "
+                + "AUTH_NAME VARCHAR(100), "
+                + "AUTH_SRID INTEGER, "
+                + "SRTEXT VARCHAR(2000));";
+    }
+
     /**
      * Creates some tables needed by the tests, then creates a {@link 
Database} instance needed for the tests.
      *
@@ -86,12 +99,7 @@ public final class InfoStatementsTest extends TestCase {
      */
     @BeforeAll
     public void initialize() throws Exception {
-        test.executeSQL(List.of("CREATE TABLE SPATIAL_REF_SYS (" +
-                "SRID INTEGER NOT NULL PRIMARY KEY, " +
-                "AUTH_NAME VARCHAR(100), " +
-                "AUTH_SRID INTEGER, " +
-                "SRTEXT VARCHAR(2000));"));
-
+        test.executeSQL(List.of(createSpatialRefSys()));
         connection = test.source.getConnection();
         database = new Database<>(test.source, connection.getMetaData(), 
Dialect.DERBY,
                                   Geometries.factory(GeometryLibrary.JAVA2D),

Reply via email to