//$Header: /home/deegree/jail/deegreerepository/deegree/src/org/deegree/io/datastore/sql/transaction/UpdateHandler.java,v 1.25 2006/09/20 11:35:41 mschneider Exp $
/*---------------- FILE HEADER ------------------------------------------
This file is part of deegree.
Copyright (C) 2001-2006 by:
EXSE, Department of Geography, University of Bonn
http://www.giub.uni-bonn.de/deegree/
lat/lon GmbH
http://www.lat-lon.de
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; either
version 2.1 of the License, or (at your option) any later version.
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.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact:
Andreas Poth
lat/lon GmbH
Aennchenstraße 19
53177 Bonn
Germany
E-Mail: poth@lat-lon.de
Prof. Dr. Klaus Greve
Department of Geography
University of Bonn
Meckenheimer Allee 166
53115 Bonn
Germany
E-Mail: greve@giub.uni-bonn.de
---------------------------------------------------------------------------*/
package org.deegree.io.datastore.sql.transaction;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.deegree.datatypes.QualifiedName;
import org.deegree.datatypes.Types;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.i18n.Messages;
import org.deegree.io.datastore.DatastoreException;
import org.deegree.io.datastore.FeatureId;
import org.deegree.io.datastore.idgenerator.FeatureIdAssigner;
import org.deegree.io.datastore.schema.MappedFeaturePropertyType;
import org.deegree.io.datastore.schema.MappedFeatureType;
import org.deegree.io.datastore.schema.MappedGeometryPropertyType;
import org.deegree.io.datastore.schema.MappedPropertyType;
import org.deegree.io.datastore.schema.MappedSimplePropertyType;
import org.deegree.io.datastore.schema.TableRelation;
import org.deegree.io.datastore.schema.TableRelation.FK_INFO;
import org.deegree.io.datastore.schema.content.MappingField;
import org.deegree.io.datastore.schema.content.MappingGeometryField;
import org.deegree.io.datastore.schema.content.SimpleContent;
import org.deegree.io.datastore.sql.AbstractRequestHandler;
import org.deegree.io.datastore.sql.StatementBuffer;
import org.deegree.io.datastore.sql.TableAliasGenerator;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.schema.FeaturePropertyType;
import org.deegree.model.filterencoding.Filter;
import org.deegree.model.spatialschema.Geometry;
import org.deegree.ogcbase.PropertyPath;
import org.deegree.ogcwebservices.wfs.operation.transaction.Insert;
import org.deegree.ogcwebservices.wfs.operation.transaction.Transaction;
import org.deegree.ogcwebservices.wfs.operation.transaction.Update;
/**
* Handler for {@link Update} operations (usually contained in {@link Transaction}
* requests).
*
* @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
* @author last edited by: $Author: mschneider $
*
* @version $Revision: 1.25 $, $Date: 2006/09/20 11:35:41 $
*/
public class UpdateHandler extends AbstractRequestHandler {
private static final ILogger LOG = LoggerFactory.getLogger( UpdateHandler.class );
private SQLTransaction dsTa;
/**
* Creates a new <code>UpdateHandler</code> from the given parameters.
*
* @param dsTa
* @param aliasGenerator
* @param conn
*/
public UpdateHandler( SQLTransaction dsTa, TableAliasGenerator aliasGenerator, Connection conn ) {
super( dsTa.getDatastore(), aliasGenerator, conn );
this.dsTa = dsTa;
}
/**
* Performs an update operation against the associated datastore.
*
* @param ft
* @param properties
* @param filter
* @return number of updated (root) feature instances
* @throws DatastoreException
*/
public int performUpdate( MappedFeatureType ft, Map<PropertyPath, Object> properties,
Filter filter )
throws DatastoreException {
List<FeatureId> fids = determineAffectedFIDs( ft, filter );
LOG.logDebug( "Updating: " + ft );
for ( PropertyPath property : properties.keySet() ) {
Object propertyValue = properties.get( property );
for ( FeatureId fid : fids ) {
LOG.logDebug( "Updating feature: " + fid );
performUpdate( fid, ft, property, propertyValue );
}
}
return fids.size();
}
/**
* Performs an update operation against the associated datastore.
* <p>
* The filter must match exactly one feature instance (or none) which is then replaced
* by the specified replacement feature.
*
* @param mappedFeatureType
* @param replacementFeature
* @param filter
* @return number of updated (root) feature instances (0 or 1)
* @throws DatastoreException
*/
public int performUpdate( MappedFeatureType mappedFeatureType, Feature replacementFeature,
Filter filter )
throws DatastoreException {
LOG.logDebug( "Updating (replace): " + mappedFeatureType );
if ( filter != null ) {
LOG.logDebug( " filter: " + filter.toXML() );
}
List<FeatureId> fids = determineAffectedFIDs( mappedFeatureType, filter );
if ( fids.size() > 1 ) {
String msg = Messages.getMessage( "DATASTORE_MORE_THAN_ONE_FEATURE" );
throw new DatastoreException( msg );
}
DeleteHandler deleteHandler = new DeleteHandler( this.dsTa, this.aliasGenerator, this.conn );
deleteHandler.performDelete( mappedFeatureType, filter );
// identify stored subfeatures / assign feature ids
FeatureIdAssigner fidAssigner = new FeatureIdAssigner( Insert.ID_GEN.GENERATE_NEW );
fidAssigner.assignFID( replacementFeature, this.dsTa );
// TODO remove this hack
fidAssigner.markStoredFeatures();
InsertHandler insertHandler = new InsertHandler( this.dsTa, this.aliasGenerator, this.conn );
List<Feature> features = new ArrayList<Feature>();
features.add( replacementFeature );
insertHandler.performInsert( features );
return fids.size();
}
/**
* Performs the update (replacing of a property) of the given feature instance.
* <p>
* If the selected property is a direct property of the feature, the root feature
* is updated, otherwise the targeted subfeatures have to be determined first.
*
* @param fid
* @param ft
* @param propertyName
* @param replacementValue
* @throws DatastoreException
*/
private void performUpdate( FeatureId fid, MappedFeatureType ft, PropertyPath propertyName,
Object replacementValue )
throws DatastoreException {
LOG.logDebug( "Updating fid: " + fid + ", propertyName: " + propertyName + " -> "
+ replacementValue );
int steps = propertyName.getSteps();
QualifiedName propName = propertyName.getStep( steps - 1 ).getPropertyName();
if ( steps > 2 ) {
QualifiedName subFtName = propertyName.getStep( steps - 2 ).getPropertyName();
MappedFeatureType subFt = this.datastore.getFeatureType( subFtName );
MappedPropertyType pt = (MappedPropertyType) subFt.getProperty( propName );
List<TableRelation> tablePath = getTablePath( ft, propertyName );
List<FeatureId> subFids = determineAffectedFIDs( fid, subFt, tablePath );
for ( FeatureId subFid : subFids ) {
updateProperty( subFid, subFt, pt, replacementValue );
}
} else {
MappedPropertyType pt = (MappedPropertyType) ft.getProperty( propName );
updateProperty( fid, ft, pt, replacementValue );
}
}
/**
* Determines the subfeature instances that are targeted by the given PropertyName.
*
* @param fid
* @param subFt
* @param propertyName
* @return the matched feature ids
* @throws DatastoreException
*/
private List<FeatureId> determineAffectedFIDs( FeatureId fid, MappedFeatureType subFt,
List<TableRelation> path )
throws DatastoreException {
List<FeatureId> subFids = new ArrayList<FeatureId>();
this.aliasGenerator.reset();
String[] tableAliases = this.aliasGenerator.generateUniqueAliases( path.size() + 1 );
String toTableAlias = tableAliases[tableAliases.length - 1];
StatementBuffer query = new StatementBuffer();
query.append( "SELECT " );
appendFeatureIdColumns( subFt, toTableAlias, query );
query.append( " FROM " );
query.append( path.get( 0 ).getFromTable() );
query.append( " " );
query.append( tableAliases[0] );
// append joins
for ( int i = 0; i < path.size(); i++ ) {
query.append( " JOIN " );
query.append( path.get( i ).getToTable() );
query.append( " " );
query.append( tableAliases[i + 1] );
query.append( " ON " );
MappingField[] fromFields = path.get( i ).getFromFields();
MappingField[] toFields = path.get( i ).getToFields();
for ( int j = 0; j < fromFields.length; j++ ) {
query.append( tableAliases[i] );
query.append( '.' );
query.append( fromFields[j].getField() );
query.append( '=' );
query.append( tableAliases[i + 1] );
query.append( '.' );
query.append( toFields[j].getField() );
}
}
query.append( " WHERE " );
MappingField[] fidFields = fid.getFidDefinition().getIdFields();
for ( int i = 0; i < fidFields.length; i++ ) {
query.append( tableAliases[0] );
query.append( '.' );
query.append( fidFields[i].getField() );
query.append( "=?" );
query.addArgument( fid.getValue( i ), fidFields[i].getType() );
if ( i != fidFields.length - 1 ) {
query.append( " AND " );
}
}
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = this.datastore.prepareStatement( conn, query );
rs = stmt.executeQuery();
subFids = extractFeatureIds( rs, subFt );
} catch ( SQLException e ) {
throw new DatastoreException( "Error in determineAffectedFIDs(): " + e.getMessage() );
} finally {
try {
if ( rs != null ) {
try {
rs.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing result set: '" + e.getMessage() + "'.", e );
}
}
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
}
return subFids;
}
/**
* Returns the relations (the "path") that lead from the feature type's table to the
* subfeature table which is targeted by the specified property name.
*
* @param ft source feature type
* @param path property name
* @return relations that lead from the feature type's table to the subfeature table
*/
private List<TableRelation> getTablePath( MappedFeatureType ft, PropertyPath path ) {
List<TableRelation> relations = new ArrayList<TableRelation>();
for ( int i = 1; i < path.getSteps() - 2; i += 2 ) {
QualifiedName propName = path.getStep( i ).getPropertyName();
MappedFeaturePropertyType pt = (MappedFeaturePropertyType) ft.getProperty( propName );
TableRelation[] tableRelations = pt.getTableRelations();
for ( int j = 0; j < tableRelations.length; j++ ) {
relations.add( tableRelations[j] );
}
ft = pt.getFeatureTypeReference().getFeatureType();
}
return relations;
}
/**
* Replaces the specified feature's property with the given value.
*
* @param fid
* @param ft
* @param pt
* @param replacementValue
* @throws DatastoreException
*/
private void updateProperty( FeatureId fid, MappedFeatureType ft, MappedPropertyType pt,
Object replacementValue )
throws DatastoreException {
LOG.logDebug( "Updating property '" + pt.getName() + "' of feature '" + fid + "'." );
if ( !ft.isUpdatable() ) {
String msg = Messages.getMessage( "DATASTORE_FT_NOT_UPDATABLE", ft.getName() );
throw new DatastoreException( msg );
}
TableRelation[] tablePath = pt.getTableRelations();
if ( pt instanceof MappedSimplePropertyType ) {
SimpleContent content = ( (MappedSimplePropertyType) pt ).getContent();
if ( content.isUpdateable() ) {
if ( content instanceof MappingField ) {
updateProperty( fid, tablePath, (MappingField) content, replacementValue );
}
} else {
LOG.logInfo( "Ignoring property '" + pt.getName() + "' in update - is virtual." );
}
} else if ( pt instanceof MappedGeometryPropertyType ) {
MappingGeometryField dbField = ( (MappedGeometryPropertyType) pt ).getMappingField();
Object dbGeometry = this.datastore.convertDeegreeToDBGeometry(
(Geometry) replacementValue,
dbField.getSRS(),
this.conn );
// TODO remove this Oracle hack
if ( this.datastore.getClass().getName().contains( "OracleDatastore" ) ) {
dbField = new MappingGeometryField( dbField.getTable(), dbField.getField(),
Types.STRUCT, dbField.getSRS() );
}
updateProperty( fid, tablePath, dbField, dbGeometry );
} else if ( pt instanceof FeaturePropertyType ) {
updateProperty( fid, ft, (MappedFeaturePropertyType) pt, (Feature) replacementValue );
} else {
throw new DatastoreException( "Internal error: Properties with type '" + pt.getClass()
+ "' are not handled in UpdateHandler." );
}
}
/**
* Updates a simple / geometry property of the specified feature.
* <p>
* Three cases have to be distinguished (which all have to be handled differently):
* <ol>
* <li>property value stored in feature table</li>
* <li>property value stored in property table, fk in property table</li>
* <li>property value stored in property table, fk in feature table</li>
* </ol>
*
* @param fid
* @param tablePath
* @param dbField
* @param replacementValue
* @throws DatastoreException
*/
private void updateProperty( FeatureId fid, TableRelation[] tablePath, MappingField dbField,
Object replacementValue )
throws DatastoreException {
if ( tablePath.length == 0 ) {
updateProperty( fid, dbField, replacementValue );
} else if ( tablePath.length == 1 ) {
TableRelation relation = tablePath[0];
if ( tablePath[0].getFKInfo() == FK_INFO.fkIsToField ) {
Object[] keyValues = determineKeyValues( fid, relation );
if ( keyValues != null ) {
deletePropertyRows( relation, keyValues );
}
insertPropertyRow( relation, keyValues, dbField, replacementValue );
} else {
Object[] oldKeyValues = determineKeyValues( fid, relation );
Object[] newKeyValues = findOrInsertPropertyRow( relation, dbField,
replacementValue );
updateFeatureRow( fid, relation, newKeyValues );
if ( oldKeyValues != null ) {
deleteOrphanedPropertyRows( relation, oldKeyValues );
}
}
} else {
throw new DatastoreException( "Updating of properties that are stored in "
+ "related tables using join tables is not "
+ "supported." );
}
}
private void updateFeatureRow( FeatureId fid, TableRelation relation, Object[] newKeyValues )
throws DatastoreException {
StatementBuffer query = new StatementBuffer();
query.append( "UPDATE " );
query.append( relation.getFromTable() );
query.append( " SET " );
MappingField[] fromFields = relation.getFromFields();
for ( int i = 0; i < newKeyValues.length; i++ ) {
query.append( fromFields[i].getField() );
query.append( "=?" );
query.addArgument( newKeyValues[i], fromFields[i].getType() );
}
query.append( " WHERE " );
appendFIDWhereCondition( query, fid );
LOG.logDebug( "Performing update: " + query.getQueryString() );
PreparedStatement stmt = null;
try {
stmt = this.datastore.prepareStatement( conn, query );
stmt.execute();
} catch ( SQLException e ) {
throw new DatastoreException( "Error in performUpdate(): " + e.getMessage() );
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
}
/**
* Updates a simple / geometry property of the specified feature.
* <p>
* This method handles the case where the property is stored in the feature table itself, so
* a single UPDATE statement is sufficient.
*
* @param fid
* @param dbField
* @param replacementValue
* @throws DatastoreException
*/
private void updateProperty( FeatureId fid, MappingField dbField, Object replacementValue )
throws DatastoreException {
StatementBuffer query = new StatementBuffer();
query.append( "UPDATE " );
query.append( dbField.getTable() );
query.append( " SET " );
query.append( dbField.getField() );
query.append( "=?" );
query.addArgument( replacementValue, dbField.getType() );
query.append( " WHERE " );
appendFIDWhereCondition( query, fid );
LOG.logDebug( "Performing update: " + query.getQueryString() );
PreparedStatement stmt = null;
try {
stmt = this.datastore.prepareStatement( conn, query );
stmt.execute();
} catch ( SQLException e ) {
throw new DatastoreException( "Error in performUpdate(): " + e.getMessage() );
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
}
/**
* Determines the values for the key columns that are referenced by the given table
* relation (as from fields).
*
* @param fid
* @param relation
* @return the values for the key columns
* @throws DatastoreException
*/
private Object[] determineKeyValues( FeatureId fid, TableRelation relation )
throws DatastoreException {
StatementBuffer query = new StatementBuffer();
query.append( "SELECT " );
MappingField[] fromFields = relation.getFromFields();
for ( int i = 0; i < fromFields.length; i++ ) {
query.append( fromFields[i].getField() );
if ( i != fromFields.length - 1 ) {
query.append( ',' );
}
}
query.append( " FROM " );
query.append( relation.getFromTable() );
query.append( " WHERE " );
appendFIDWhereCondition( query, fid );
Object[] keyValues = new Object[fromFields.length];
LOG.logDebug( "determineKeyValues: " + query.getQueryString() );
PreparedStatement stmt = null;
try {
stmt = this.datastore.prepareStatement( conn, query );
ResultSet rs = stmt.executeQuery();
if ( rs.next() ) {
for ( int i = 0; i < keyValues.length; i++ ) {
Object value = rs.getObject( i + 1 );
if ( value != null ) {
keyValues[i] = value;
} else {
keyValues = null;
break;
}
}
} else {
LOG.logError( "Internal error. Result is empty (no rows)." );
throw new SQLException();
}
} catch ( SQLException e ) {
throw new DatastoreException( "Error in performUpdate(): " + e.getMessage() );
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
return keyValues;
}
private void deletePropertyRows( TableRelation relation, Object[] keyValues )
throws DatastoreException {
StatementBuffer query = new StatementBuffer();
query.append( "DELETE FROM " );
query.append( relation.getToTable() );
query.append( " WHERE " );
MappingField[] toFields = relation.getToFields();
for ( int i = 0; i < toFields.length; i++ ) {
query.append( toFields[i].getField() );
query.append( "=?" );
query.addArgument( keyValues[i], toFields[i].getType() );
if ( i != toFields.length - 1 ) {
query.append( " AND " );
}
}
PreparedStatement stmt = null;
LOG.logDebug( "deletePropertyRows: " + query.getQueryString() );
try {
stmt = this.datastore.prepareStatement( conn, query );
stmt.execute();
} catch ( SQLException e ) {
throw new DatastoreException( "Error in performUpdate(): " + e.getMessage() );
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
}
private void insertPropertyRow( TableRelation relation, Object[] keyValues,
MappingField dbField, Object replacementValue )
throws DatastoreException {
if ( keyValues == null ) {
if ( relation.getFromFields().length > 1 ) {
throw new DatastoreException( "Key generation for compound keys is not supported." );
}
// generate new primary key
keyValues = new Object[1];
keyValues[0] = relation.getIdGenerator().getNewId( dsTa );
}
StatementBuffer query = new StatementBuffer();
query.append( "INSERT INTO " );
query.append( relation.getToTable() );
query.append( " (" );
MappingField[] toFields = relation.getToFields();
for ( int i = 0; i < toFields.length; i++ ) {
query.append( toFields[i].getField() );
query.append( ',' );
}
query.append( dbField.getField() );
query.append( ") VALUES (" );
for ( int i = 0; i < toFields.length; i++ ) {
query.append( '?' );
query.addArgument( keyValues[i], toFields[i].getType() );
query.append( ',' );
}
query.append( "?)" );
query.addArgument( replacementValue, dbField.getType() );
PreparedStatement stmt = null;
LOG.logDebug( "insertPropertyRow: " + query.getQueryString() );
try {
stmt = this.datastore.prepareStatement( conn, query );
stmt.execute();
} catch ( SQLException e ) {
throw new DatastoreException( "Error in performUpdate(): " + e.getMessage() );
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
}
/**
* Returns the foreign key value(s) for the row that stores the given property.
* <p>
* If the row already exists, the existing key is returned, otherwise a new row for the
* property is inserted first.
*
* @param relation
* @param dbField
* @param replacementValue
* @return foreign key value(s) for the row that stores the given property
* @throws DatastoreException
*/
private Object[] findOrInsertPropertyRow( TableRelation relation, MappingField dbField,
Object replacementValue )
throws DatastoreException {
Object[] keyValues = null;
if ( dbField.getType() != Types.GEOMETRY ) {
StatementBuffer query = new StatementBuffer();
query.append( "SELECT " );
MappingField[] toFields = relation.getToFields();
for ( int i = 0; i < toFields.length; i++ ) {
query.append( toFields[i].getField() );
if ( i != toFields.length - 1 ) {
query.append( ',' );
}
}
query.append( " FROM " );
query.append( relation.getToTable() );
query.append( " WHERE " );
query.append( dbField.getField() );
query.append( "=?" );
query.addArgument( replacementValue, dbField.getType() );
PreparedStatement stmt = null;
LOG.logDebug( "findOrInsertPropertyRow: " + query.getQueryString() );
try {
stmt = this.datastore.prepareStatement( conn, query );
ResultSet rs = stmt.executeQuery();
if ( rs.next() ) {
keyValues = new Object[toFields.length];
for ( int i = 0; i < toFields.length; i++ ) {
keyValues[i] = rs.getObject( i + 1 );
}
}
} catch ( SQLException e ) {
throw new DatastoreException( "Error in findOrInsertPropertyRow(): "
+ e.getMessage() );
} finally {
if ( stmt != null ) {
try {
stmt.close();
} catch ( SQLException e ) {
LOG.logError( "Error closing statement: '" + e.getMessage() + "'.", e );
}
}
}
if ( keyValues != null ) {
return keyValues;
}
}
if ( relation.getToFields().length > 1 ) {
throw new DatastoreException( "Key generation for compound keys is not supported." );
}
// property does not yet exist (or it's a geometry)
keyValues = new Object[1];
// generate new PK
keyValues[0] = relation.getNewPK( this.dsTa );
insertPropertyRow( relation, keyValues, dbField, replacementValue );
return keyValues;
}
private void deleteOrphanedPropertyRows( TableRelation relation, Object[] keyValues )
throws DatastoreException {
Map<String, Object> keyColumns = new HashMap<String, Object>();
for ( int i = 0; i < keyValues.length; i++ ) {
keyColumns.put( relation.getToFields()[i].getField(), keyValues[i] );
}
DeleteNode node = new DeleteNode( relation.getToTable(), keyColumns );
DeleteHandler deleteHandler = new DeleteHandler( this.dsTa, this.aliasGenerator, this.conn );
if ( deleteHandler.getReferencingRows( node ).size() == 0 ) {
try {
deleteHandler.performDelete( node );
} catch ( SQLException e ) {
throw new DatastoreException( e.getMessage() );
}
}
}
private void updateProperty( @SuppressWarnings("unused")
FeatureId fid, @SuppressWarnings("unused")
MappedFeatureType ft, @SuppressWarnings("unused")
MappedFeaturePropertyType pt, @SuppressWarnings("unused")
Feature replacementFeature ) {
throw new UnsupportedOperationException(
"Updating of feature properties is not implemented yet." );
}
private void appendFIDWhereCondition( StatementBuffer query, FeatureId fid ) {
MappingField[] fidFields = fid.getFidDefinition().getIdFields();
for ( int i = 0; i < fidFields.length; i++ ) {
query.append( fidFields[i].getField() );
query.append( "=?" );
query.addArgument( fid.getValue( i ), fidFields[i].getType() );
if ( i != fidFields.length - 1 ) {
query.append( " AND " );
}
}
}
}
/* ********************************************************************
Changes to this class. What the people have been up to:
$Log: UpdateHandler.java,v $
Revision 1.25 2006/09/20 11:35:41 mschneider
Merged datastore related messages with org.deegree.18n.
Revision 1.24 2006/09/19 14:57:01 mschneider
Fixed warnings, improved javadoc.
Revision 1.23 2006/09/05 14:43:24 mschneider
Adapted due to merging of messages.
Revision 1.22 2006/08/29 15:53:57 mschneider
Changed SimpleContent#isVirtual() to SimpleContent#isUpdateable().
Revision 1.21 2006/08/23 16:35:58 mschneider
Added handling of virtual properties. Virtual properties are skipped on update.
Revision 1.20 2006/08/22 18:14:42 mschneider
Refactored due to cleanup of org.deegree.io.datastore.schema package.
Revision 1.19 2006/08/21 16:42:36 mschneider
Refactored due to cleanup (and splitting) of org.deegree.io.datastore.schema package.
Revision 1.18 2006/08/21 15:46:53 mschneider
Refactored due to cleanup (and splitting) of org.deegree.io.datastore.schema package.
Revision 1.17 2006/08/06 20:49:30 poth
UnsupportedOperationException instead of datastoreException thrown
Revision 1.16 2006/07/26 18:57:29 mschneider
Fixed spelling in method name.
Revision 1.15 2006/06/29 10:26:20 mschneider
Moved identifying of stored features / assigning of feature ids from TransactionHandler here.
Revision 1.14 2006/06/28 08:53:35 poth
*** empty log message ***
Revision 1.13 2006/06/27 08:14:55 poth
bug fix - just log filter if available
Revision 1.12 2006/06/01 16:01:19 mschneider
Added exception that is thrown in case of FeatureProperty updates.
Revision 1.11 2006/05/30 17:04:06 mschneider
Update on geometry properties should work now.
Revision 1.10 2006/05/29 16:39:24 mschneider
Update on simple properties should work now.
Revision 1.9 2006/05/24 15:25:03 mschneider
Update for simple / geometry properties should work now (only when they are stored in the feature table).
Revision 1.8 2006/05/23 22:40:57 mschneider
"Standard" update throws Exception now (to let the user know that it is not fully implemented yet).
Revision 1.7 2006/05/23 16:06:34 mschneider
Changed signature of performUpdate().
Revision 1.6 2006/05/18 15:48:02 mschneider
Added handling of non-standard update (feature replace).
Revision 1.5 2006/05/17 18:28:49 mschneider
Initial work on Update.
Revision 1.4 2006/05/16 16:20:10 mschneider
Added update method for deegree specific update operation.
Revision 1.3 2006/04/18 12:47:40 mschneider
Improved javadoc.
Revision 1.2 2006/04/06 20:25:27 poth
*** empty log message ***
Revision 1.1 2006/02/13 17:54:55 mschneider
Initial version.
********************************************************************** */