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 <[email protected]>
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),