private String createRelationalUpdateStatement( FeatureTypeMapping ftMapping, FIDMapping fidMapping, List<ParsedPropertyReplacement> replacementProps, List<ResourceId> list) throws FilterEvaluationException, FeatureStoreException, SQLException { StringBuffer sql = new StringBuffer("UPDATE "); sql.append(ftMapping.getFtTable()); sql.append(" SET "); boolean first = true; for (ParsedPropertyReplacement replacement : replacementProps) { Property replacementProp = replacement.getNewValue(); QName propName = replacementProp.getType().getName(); Mapping mapping = ftMapping.getMapping(propName); if (mapping != null) { if (mapping.getJoinedTable() != null && !mapping.getJoinedTable().isEmpty()) { addRelationallyMappedMultiProperty(replacement, mapping, ftMapping, list); continue; } String column = null; ParticleConverter<TypedObjectNode> converter = (ParticleConverter<TypedObjectNode>) fs.getConverter(mapping); if (mapping instanceof PrimitiveMapping) { MappingExpression me = ((PrimitiveMapping) mapping).getMapping(); if (!(me instanceof DBField)) { continue; } column = ((DBField) me).getColumn(); if (!first) { sql.append(","); } else { first = false; } sql.append(column); sql.append("="); // TODO communicate value for non-prepared statement converters sql.append(converter.getSetSnippet(null)); } else if (mapping instanceof GeometryMapping) { MappingExpression me = ((GeometryMapping) mapping).getMapping(); if (!(me instanceof DBField)) { continue; } column = ((DBField) me).getColumn(); if (!first) { sql.append(","); } else { first = false; } sql.append(column); sql.append("="); // TODO communicate value for non-prepared statement converters sql.append(converter.getSetSnippet(null)); } else { LOG.warn( "Updating of " + mapping.getClass() + " is currently not implemented. Omitting."); continue; } } else { LOG.warn("No mapping for update property '" + propName + "'. Omitting."); } } // only property changes in multi properties? if (first) { return null; } sql.append(" WHERE "); sql.append(fidMapping.getColumns().get(0).first); sql.append("=?"); for (int i = 1; i < fidMapping.getColumns().size(); i++) { sql.append(" AND "); sql.append(fidMapping.getColumns().get(i)); sql.append("=?"); } return sql.toString(); }
@Override public List<String> performInsert(FeatureCollection fc, IDGenMode mode) throws FeatureStoreException { LOG.debug("performInsert()"); Set<Geometry> geometries = new LinkedHashSet<Geometry>(); Set<Feature> features = new LinkedHashSet<Feature>(); Set<String> fids = new LinkedHashSet<String>(); Set<String> gids = new LinkedHashSet<String>(); for (Feature member : fc) { findFeaturesAndGeometries(member, geometries, features, fids, gids); } LOG.debug(features.size() + " features / " + geometries.size() + " geometries"); for (FeatureInspector inspector : inspectors) { for (Feature f : features) { // TODO cope with inspectors that return a different instance inspector.inspect(f); } } long begin = System.currentTimeMillis(); String fid = null; try { PreparedStatement blobInsertStmt = null; if (blobMapping != null) { switch (mode) { case GENERATE_NEW: { // TODO don't change incoming features / geometries for (Feature feature : features) { String newFid = "FEATURE_" + generateNewId(); String oldFid = feature.getId(); if (oldFid != null) { fids.remove(oldFid); } fids.add(newFid); feature.setId(newFid); } for (Geometry geometry : geometries) { String newGid = "GEOMETRY_" + generateNewId(); String oldGid = geometry.getId(); if (oldGid != null) { gids.remove(oldGid); } gids.add(newGid); geometry.setId(newGid); } break; } case REPLACE_DUPLICATE: { throw new FeatureStoreException("REPLACE_DUPLICATE is not available yet."); } case USE_EXISTING: { // TODO don't change incoming features / geometries for (Feature feature : features) { if (feature.getId() == null) { String newFid = "FEATURE_" + generateNewId(); feature.setId(newFid); fids.add(newFid); } } for (Geometry geometry : geometries) { if (geometry.getId() == null) { String newGid = "GEOMETRY_" + generateNewId(); geometry.setId(newGid); gids.add(newGid); } } break; } } StringBuilder sql = new StringBuilder("INSERT INTO "); sql.append(blobMapping.getTable()); sql.append(" ("); sql.append(blobMapping.getGMLIdColumn()); sql.append(","); sql.append(blobMapping.getTypeColumn()); sql.append(","); sql.append(blobMapping.getDataColumn()); sql.append(","); sql.append(blobMapping.getBBoxColumn()); sql.append(") VALUES(?,?,?,"); sql.append(blobGeomConverter.getSetSnippet(null)); sql.append(")"); LOG.debug("Inserting: {}", sql); blobInsertStmt = conn.prepareStatement(sql.toString()); for (Feature feature : features) { fid = feature.getId(); if (blobInsertStmt != null) { insertFeatureBlob(blobInsertStmt, feature); } FeatureTypeMapping ftMapping = fs.getMapping(feature.getName()); if (ftMapping != null) { throw new UnsupportedOperationException(); } ICRS storageSrs = blobMapping.getCRS(); bboxTracker.insert(feature, storageSrs); } if (blobInsertStmt != null) { blobInsertStmt.close(); } } else { // pure relational mode List<FeatureRow> idAssignments = new ArrayList<FeatureRow>(); InsertRowManager insertManager = new InsertRowManager(fs, conn, mode); for (Feature feature : features) { FeatureTypeMapping ftMapping = fs.getMapping(feature.getName()); if (ftMapping == null) { throw new FeatureStoreException( "Cannot insert feature of type '" + feature.getName() + "'. No mapping defined and BLOB mode is off."); } idAssignments.add(insertManager.insertFeature(feature, ftMapping)); Pair<TableName, GeometryMapping> mapping = ftMapping.getDefaultGeometryMapping(); if (mapping != null) { ICRS storageSrs = mapping.second.getCRS(); bboxTracker.insert(feature, storageSrs); } } if (insertManager.getDelayedRows() != 0) { String msg = "After insertion, " + insertManager.getDelayedRows() + " delayed rows left uninserted. Probably a cyclic key constraint blocks insertion."; throw new RuntimeException(msg); } // TODO why is this necessary? fids.clear(); for (FeatureRow assignment : idAssignments) { fids.add(assignment.getNewId()); } } } catch (Throwable t) { String msg = "Error inserting feature: " + t.getMessage(); LOG.error(msg); LOG.trace("Stack trace:", t); throw new FeatureStoreException(msg, t); } long elapsed = System.currentTimeMillis() - begin; LOG.debug("Insertion of " + features.size() + " features: " + elapsed + " [ms]"); return new ArrayList<String>(fids); }