/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2013, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.db.postgres;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.geotoolkit.data.query.DefaultQueryCapabilities;
import org.geotoolkit.data.query.Query;
import org.geotoolkit.data.query.QueryCapabilities;
import org.geotoolkit.db.DefaultJDBCFeatureStore;
import org.geotoolkit.db.JDBCFeatureStoreUtilities;
import org.geotoolkit.db.dialect.SQLQueryBuilder;
import org.geotoolkit.internal.sql.ScriptRunner;
import org.apache.sis.storage.DataStoreException;
import org.geotoolkit.parameter.Parameters;
import org.geotoolkit.version.VersionControl;
import org.geotoolkit.version.VersioningException;
import org.opengis.feature.FeatureType;
import org.opengis.parameter.ParameterValueGroup;
/**
* Extends default jdbc feature store with versioning and subsampling capabilities.
*
* @author Johann Sorel (Geomatys)
*/
public class PostgresFeatureStore extends DefaultJDBCFeatureStore{
private static final QueryCapabilities PG_CAPA = new DefaultQueryCapabilities(false, true, new String[]{Query.GEOTK_QOM, CUSTOM_SQL});
//historisation informations
private Boolean hasHSFunctions;
private PostgresQueryBuilder querybuilder = null;
public PostgresFeatureStore(String host, int port, String database, String schema, String user, String password) throws DataStoreException {
super(toParameters(host,port,database,schema,user,password), PostgresFeatureStoreFactory.NAME);
((PostgresFeatureStoreFactory)getFactory()).prepareStore(this, parameters);
}
public PostgresFeatureStore(ParameterValueGroup params, String factoryId) {
super(params, factoryId);
}
private static ParameterValueGroup toParameters(String host, int port,
String database, String schema, String user, String password){
final ParameterValueGroup params = PostgresFeatureStoreFactory.PARAMETERS_DESCRIPTOR.createValue();
Parameters.getOrCreate(PostgresFeatureStoreFactory.HOST, params).setValue(host);
Parameters.getOrCreate(PostgresFeatureStoreFactory.PORT, params).setValue(port);
Parameters.getOrCreate(PostgresFeatureStoreFactory.DATABASE,params).setValue(database);
Parameters.getOrCreate(PostgresFeatureStoreFactory.SCHEMA, params).setValue(schema);
Parameters.getOrCreate(PostgresFeatureStoreFactory.USER, params).setValue(user);
Parameters.getOrCreate(PostgresFeatureStoreFactory.PASSWORD,params).setValue(password);
return params;
}
@Override
public QueryCapabilities getQueryCapabilities() {
return PG_CAPA;
}
@Override
protected SQLQueryBuilder getQueryBuilder() {
if(querybuilder == null){
querybuilder = new PostgresQueryBuilder(this);
}
return querybuilder;
}
////////////////////////////////////////////////////////////////////////////
// Versioning control //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
@Override
public VersionControl getVersioning(String typeName) throws VersioningException {
final FeatureType type;
try {
type = getFeatureType(typeName);
} catch (DataStoreException ex) {
throw new VersioningException(ex.getMessage(),ex);
}
return new PostgresVersionControl(this, type);
}
/**
* Search for historisation functions.
* @return true if HS_ functions are available
* @throws VersioningException
*/
public synchronized boolean hasHSFunctions() throws VersioningException {
if(hasHSFunctions!=null) return hasHSFunctions;
//search if historization procedure are present
Connection cnx = null;
Statement stmt = null;
ResultSet rs = null;
try{
cnx = getDataSource().getConnection();
stmt = cnx.createStatement();
rs = stmt.executeQuery("select count(proname) from pg_proc where upper(\"proname\") like 'HS\\_%'");
rs.next();
hasHSFunctions = rs.getInt(1) > 0;
}catch(SQLException ex){
throw new VersioningException(ex.getMessage(),ex);
}finally{
JDBCFeatureStoreUtilities.closeSafe(getLogger(), cnx,stmt,rs);
}
return hasHSFunctions;
}
/**
* Install the ISO-13249:7 History functions.
* @throws VersioningException
*/
public synchronized void installHSFunctions() throws VersioningException {
hasHSFunctions = null;
Connection cnx = null;
try{
cnx = getDataSource().getConnection();
final ScriptRunner scriptRunner = new ScriptRunner(cnx);
scriptRunner.run(PostgresFeatureStore.class.getResourceAsStream("/org/geotoolkit/db/postgres/HS_Functions.sql"));
}catch(IOException ex){
throw new VersioningException(ex.getMessage(),ex);
}catch(SQLException ex){
throw new VersioningException(ex.getMessage(),ex);
}finally{
JDBCFeatureStoreUtilities.closeSafe(getLogger(), cnx);
}
}
/**
* Uninstall the ISO-13249:7 History functions.
* @throws VersioningException
*/
public synchronized void dropHSFunctions() throws VersioningException {
hasHSFunctions = null;
Connection cnx = null;
try{
cnx = getDataSource().getConnection();
final ScriptRunner scriptRunner = new ScriptRunner(cnx);
scriptRunner.run(PostgresFeatureStore.class.getResourceAsStream("/org/geotoolkit/db/postgres/HS_DropFunctions.sql"));
}catch(IOException ex){
throw new VersioningException(ex.getMessage(),ex);
}catch(SQLException ex){
throw new VersioningException(ex.getMessage(),ex);
}finally{
JDBCFeatureStoreUtilities.closeSafe(getLogger(), cnx);
}
}
@Override
public void deleteFeatureType(final String typeName) throws DataStoreException {
try {
getVersioning(typeName).dropVersioning();
} catch (VersioningException ex) {
throw new DataStoreException(ex);
}
super.deleteFeatureType(typeName);
}
/**
* Delete postgres schema.
*
* @param name The postgres schema name.
* @throws DataStoreException
*/
public void dropPostgresSchema(final String name) throws DataStoreException {
Statement stmt = null;
Connection cnx = null;
String sql = null;
try {
cnx = getDataSource().getConnection();
sql = "DROP SCHEMA \""+ name +"\" CASCADE;";
stmt = cnx.createStatement();
stmt.execute(sql);
} catch (SQLException ex) {
throw new DataStoreException("Failed to delete features : " + ex.getMessage() + "\nSQL Query :" + sql, ex);
} finally {
JDBCFeatureStoreUtilities.closeSafe(getLogger(), cnx, stmt, null);
}
}
}