# Class SQLStore

Object
DataStore
SQLStore

All Implemented Interfaces:
  `AutoCloseable, Aggregate, Resource, Localized`

Direct Known Subclasses:
  `SimpleFeatureStore`

public abstract class SQLStore extends DataStore implements Aggregate
An abstract data store for reading or writing resources from/to a spatial database. `SQLStore` requires a `DataSource` to be specified (indirectly) at construction time. While not mandatory, a pooled data source is recommended because `SQLStore` may open and close connections many times.

This class provides basic support for ISO 19125-2, also known as OGC Simple feature access - Part 2: SQL option: selected tables, views and queries can be viewed as `FeatureSet` resources. This selection is specified by implementing the `readResourceDefinitions(DataAccess)` method. The mapping from table structures to feature types is described in the package Javadoc.

Since:
  1.0

- ## Nested Class Summary

  ### Nested classes/interfaces inherited from interface Resource

  `Resource​.FileSet`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final Locale`
  `contentLocale`
  The locale to use for international texts to write in a database table.
  `protected final DataSource`
  `source`
  The data source to use for obtaining connections to the database.

  ### Fields inherited from class DataStore

  `listeners, provider`

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `SQLStore(DataStoreProvider provider, StorageConnector connector)`
  Creates a new `SQLStore` for the given data source.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `<T extends StoreEvent>
  void`
  `addListener(Class<T> eventType, StoreListener<? super T> listener)`
  Registers a listener to notify when the specified kind of event occurs in this data store.
  `void`
  `close()`
  Closes this SQL store and releases any underlying resources.
  `Collection<? extends Resource>`
  `components()`
  Returns the resources (feature set or coverages) in this SQL store.
  `Resource`
  `findResource(String identifier)`
  Searches for a resource identified by the given identifier.
  `Map<String,Version>`
  `getDatabaseSoftwareVersions()`
  Returns the version of the database software, together with versions of extensions if any.
  `DataSource`
  `getDataSource()`
  Returns the data source to use for obtaining connections to the database.
  `Optional<GenericName>`
  `getIdentifier()`
  Returns an identifier for the root resource of this SQL store, or an empty value if none.
  `Metadata`
  `getMetadata()`
  Returns information about the dataset as a whole.
  `Optional<ParameterValueGroup>`
  `getOpenParameters()`
  Returns parameters that can be used for opening this SQL data store.
  `protected void`
  `initialize(Connection connection)`
  Invoked the first time that `SQLStore` opens a connection on the database, or after refresh.
  `DataAccess`
  `newDataAccess(boolean write)`
  Creates a new low-level data access object.
  `protected abstract ResourceDefinition[]`
  `readResourceDefinitions(DataAccess dao)`
  A callback for providing the resource definitions of a database, typically from a content table.
  `void`
  `refresh()`
  Clears the cache so that next operations will reload all needed information from the database.
  `void`
  `vacuum()`
  Executes the `"VACUUM"` statement on the database.

  ### Methods inherited from class DataStore

  `getDisplayName, getLocale, getNativeMetadata, getProvider, removeListener, setLocale, toString`

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

  ### Methods inherited from interface Resource

  `getFileSet, removeListener`

- ## Field Details

  - ### source

    protected final DataSource source
    The data source to use for obtaining connections to the database. This is the storage given (indirectly, through the `StorageConnector` argument) at construction time.
    Since:
      1.5
    See Also:
      - `getDataSource()`

  - ### contentLocale

    protected final Locale contentLocale
    The locale to use for international texts to write in a database table. This is not necessarily the same locale as `DataStore​.getLocale()`, because the latter is for warning and error messages to shown in user applications.

    Example: if a new CRS needs to be added in the `"SPATIAL_REF_SYS"` table and if that table contains a `"description"` column (as in the Geopackage format), then the text to write in that column will be localized with this locale.

    If the value is `null`, then a default locale is used.

    Since:
      1.5
    See Also:
      - `OptionKey​.LOCALE`

- ## Constructor Details

  - ### SQLStore

    protected SQLStore(DataStoreProvider provider, StorageConnector connector) throws DataStoreException
    Creates a new `SQLStore` for the given data source. The given `connector` shall contain a `DataSource` instance. Tables or views to include in the store will be specified by the `readResourceDefinitions(DataAccess)` method, which will be invoked when first needed.
    Parameters:
      `provider` - the factory that created this `DataStore` instance, or `null` if unspecified.
      `connector` - information about the storage (JDBC data source, etc).
    Throws:
      `DataStoreException` - if an error occurred while creating the data store for the given storage.
    Since:
      1.5

- ## Method Details

  - ### initialize

    protected void initialize(Connection connection) throws DataStoreException, SQLException
    Invoked the first time that `SQLStore` opens a connection on the database, or after refresh. The default implementation does nothing. Subclasses can override this method if they need to create tables in an empty database, or for fetching more information.

    If `refresh()` has been invoked, then this initialization method will be invoked again the next time that a connection is needed. This method is invoked before `readResourceDefinitions(DataAccess)`.

    Parameters:
      `connection` - a connection to the database.
    Throws:
      `DataStoreException` - if an error occurred during the initialization.
      `SQLException` - if an error occurred during the execution of an SQL query.
    Since:
      1.5

  - ### getDataSource

    public DataSource getDataSource()
    Returns the data source to use for obtaining connections to the database.
    Returns:
      the data source to use for obtaining connections to the database.
    Since:
      1.5

  - ### getOpenParameters

    public Optional<ParameterValueGroup> getOpenParameters()
    Returns parameters that can be used for opening this SQL data store. The parameters are described by `SQLStoreProvider​.getOpenParameters()` and contains at least a parameter named "location" with a `DataSource` value.
    Specified by:
      `getOpenParameters` in class `DataStore`
    Returns:
      parameters used for opening this data store.
    See Also:
      - `DataStoreProvider​.getOpenParameters()`

  - ### getIdentifier

    public Optional<GenericName> getIdentifier() throws DataStoreException
    Returns an identifier for the root resource of this SQL store, or an empty value if none. The default implementation returns the database name if this property can be found in the `DataSource` implementation.
    Specified by:
      `getIdentifier` in interface `Resource`
    Overrides:
      `getIdentifier` in class `DataStore`
    Returns:
      an identifier for the root resource of this SQL store.
    Throws:
      `DataStoreException` - if an error occurred while fetching the identifier.
    See Also:
      - `DataStore​.getMetadata()`
      - `DataStore​.getDisplayName()`

  - ### getDatabaseSoftwareVersions

    public Map<String,Version> getDatabaseSoftwareVersions() throws DataStoreException
    Returns the version of the database software, together with versions of extensions if any. For example, in the case of a database on PostgreSQL, this map may contain two entries: the first one with the "PostgreSQL" key, optionally followed by an entry with the "PostGIS" key.
    Returns:
      version of the database software as the first entry, followed by versions of extensions if any.
    Throws:
      `DataStoreException` - if an error occurred while fetching the metadata.
    Since:
      1.5

  - ### getMetadata

    public Metadata getMetadata() throws DataStoreException
    Returns information about the dataset as a whole. The returned metadata object can contain information such as the list of feature types.
    Specified by:
      `getMetadata` in interface `Resource`
    Specified by:
      `getMetadata` in class `DataStore`
    Returns:
      information about the dataset.
    Throws:
      `DataStoreException` - if an error occurred while fetching the metadata.
    See Also:
      - `DataStore​.getIdentifier()`
      - `DefaultMetadata​.deepCopy(Metadata)`

  - ### components

    public Collection<? extends Resource> components() throws DataStoreException
    Returns the resources (feature set or coverages) in this SQL store. The collection of resources should be constructed only when first needed and cached for future invocations of this method. The cache can be cleared by `refresh()`. This method should not load immediately the whole data of the `Resource` elements, as `Resource` sub-interfaces provide the API for deferred loading.

    #### Default implementation

    By default, the collection contains one `FeatureSet` per table, view or query matching a `ResourceDefinition` returned by `readResourceDefinitions(DataAccess)`.
    Specified by:
      `components` in interface `Aggregate`
    Returns:
      children resources that are components of this SQL store.
    Throws:
      `DataStoreException` - if an error occurred while fetching the components.

  - ### findResource

    public Resource findResource(String identifier) throws DataStoreException
    Searches for a resource identified by the given identifier. This method shall recognize at least the identifiers of the resources returned by `components()`, but may also (optionally) recognize the identifiers of auxiliary resources such as component dependencies (e.g., tables referenced by foreigner keys).

    #### Default implementation

    By default, this method searches for a table, view or query with a name matching the given identifier. The scope of the search includes the tables, views or queries matching a `ResourceDefinition`, together with other tables referenced by foreigner keys (the dependencies). The given identifier may be qualified with the schema name, or may be only the table name if there is no ambiguity.
    Overrides:
      `findResource` in class `DataStore`
    Parameters:
      `identifier` - identifier of the resource to fetch. Must be non-null.
    Returns:
      resource associated to the given identifier (never `null`).
    Throws:
      `IllegalNameException` - if no resource is found for the given identifier, or if more than one resource is found.
      `DataStoreException` - if another kind of error occurred while searching resources.
    See Also:
      - `Resource​.getIdentifier()`
      - `FeatureNaming`

  - ### readResourceDefinitions

    protected abstract ResourceDefinition[] readResourceDefinitions(DataAccess dao) throws DataStoreException
    A callback for providing the resource definitions of a database, typically from a content table. `SQLStore` will invoke this method when first needed after construction or after calls to `refresh()`. Implementations can use the SQL connection and methods provided by the `dao` argument. This method does not need to cache the result.
    Example: in a database conform to the Geopackage standard, the resource definitions are provided by the `"gpkg_contents"` table. Therefore, the
    invalid reference

        org​.apache​.sis​.storage​.geopackage​.GpkgStore

    subclass will read the content of that table every times this method is invoked.
    Parameters:
      `dao` - low-level access (such as SQL connection) to the database.
    Returns:
      tables or views to include in the store. Only the main tables need to be specified. Dependencies (inferred from the foreigner keys) will be followed automatically.
    Throws:
      `DataStoreException` - if an error occurred while fetching the resource definitions.
    Since:
      1.5
    See Also:
      - `initialize(Connection)`

  - ### newDataAccess

    public DataAccess newDataAccess(boolean write)
    Creates a new low-level data access object. Each `DataAccess` instance can provide a single SQL `Connection` to the database (sometime protected by a read or write lock), together with methods for fetching or adding CRS definitions from/into the `SPATIAL_REF_SYS` table.

    The returned object shall be used in a `try ... finally` block. This is needed not only for closing the connection, but also for releasing read or write lock. Example:

        try (DataAccess dao = newDataAccess(false)) {
            try (Statement stmt = dao.getConnection().createStatement()) {
                // Perform some SQL queries here.
            }
        }

    Parameters:
      `write` - whether write operations may be performed.
    Returns:
      an object provider low-level access (e.g. through SQL queries) to the data.
    Since:
      1.5

  - ### addListener

    public <T extends StoreEvent> void addListener(Class<T> eventType, StoreListener<? super T> listener)
    Registers a listener to notify when the specified kind of event occurs in this data store. The current implementation of this data store can emit only `WarningEvent`s; any listener specified for another kind of events will be ignored.
    Specified by:
      `addListener` in interface `Resource`
    Overrides:
      `addListener` in class `DataStore`
    Type Parameters:
      `T` - compile-time value of the `eventType` argument.
    Parameters:
      `eventType` - type of `StoreEvent` to listen (cannot be `null`).
      `listener` - listener to notify about events.

  - ### vacuum

    public void vacuum() throws DataStoreException
    Executes the `"VACUUM"` statement on the database. This is a non-standard feature that exists on some databases such as PostgreSQL and SQLite. This method executes the statement only if the SQL keywords declared in the database metadata contains `"VACUUM"`, ignoring case.

    This is a potentially costly operation which should be rarely executed. A typical use case if to compress a newly created Geopackage file (which are SQLite database).

    Throws:
      `DataStoreException` - if an error occurred while executing the vacuum.
    Since:
      1.5

  - ### refresh

    public void refresh()
    Clears the cache so that next operations will reload all needed information from the database. This method can be invoked when the database content has been modified by a process other than the methods in this class.
    Since:
      1.5

  - ### close

    public void close() throws DataStoreException
    Closes this SQL store and releases any underlying resources.
    Specified by:
      `close` in interface `AutoCloseable`
    Specified by:
      `close` in class `DataStore`
    Throws:
      `DataStoreException` - if an error occurred while closing the SQL store.
    See Also:
      - `StoreListeners​.close()`