/** * Inserts the given feature into BLOB table and returns the generated primary key. * * @param stmt * @param feature * @return primary key of the feature * @throws SQLException * @throws FeatureStoreException */ private int insertFeatureBlob(PreparedStatement stmt, Feature feature) throws SQLException, FeatureStoreException { LOG.debug("Inserting feature with id '" + feature.getId() + "' (BLOB)"); if (fs.getSchema().getFeatureType(feature.getName()) == null) { throw new FeatureStoreException( "Cannot insert feature '" + feature.getName() + "': feature type is not served by this feature store."); } ICRS crs = blobMapping.getCRS(); stmt.setString(1, feature.getId()); stmt.setShort(2, fs.getFtId(feature.getName())); byte[] bytes = encodeFeatureBlob(feature, crs); stmt.setBytes(3, bytes); LOG.debug("Feature blob size: " + bytes.length); Geometry bboxGeom = getFeatureEnvelopeAsGeometry(feature); blobGeomConverter.setParticle(stmt, bboxGeom, 4); stmt.execute(); int internalId = -1; // ResultSet rs = null; // try { // // TODO only supported for PostgreSQL >= 8.2 // rs = stmt.getGeneratedKeys(); // rs.next(); // internalId = rs.getInt( 1 ); // } finally { // if ( rs != null ) { // rs.close(); // } // } return internalId; }
private void updateFeatureBlob(final PreparedStatement stmt, final Feature feature) throws SQLException { LOG.debug("Updating feature with id '" + feature.getId() + "' (BLOB)"); final ICRS crs = blobMapping.getCRS(); final byte[] bytes = encodeFeatureBlob(feature, crs); stmt.setBytes(1, bytes); LOG.debug("Feature blob size: " + bytes.length); final Geometry bboxGeom = getFeatureEnvelopeAsGeometry(feature); blobGeomConverter.setParticle(stmt, bboxGeom, 2); stmt.setString(3, feature.getId()); stmt.execute(); }
private Geometry getFeatureEnvelopeAsGeometry(final Feature feature) { Geometry bboxGeom = null; try { Envelope bbox = feature.getEnvelope(); if (bbox != null) { bboxGeom = Geometries.getAsGeometry(bbox); } } catch (Exception e) { LOG.warn( "Unable to determine bbox of feature with id '" + feature.getId() + "': " + e.getMessage()); } return bboxGeom; }
private IdFilter getIdFilter(QName ftName, OperatorFilter filter) throws FeatureStoreException { Set<String> ids = new HashSet<String>(); Query query = new Query(ftName, filter, -1, -1, -1); FeatureInputStream rs = null; try { rs = fs.query(query); for (Feature feature : rs) { ids.add(feature.getId()); } } catch (FilterEvaluationException e) { throw new FeatureStoreException(e); } finally { if (rs != null) { rs.close(); } } return new IdFilter(ids); }
@Override public <T> boolean evaluate(T obj, XPathEvaluator<T> xpathEvaluator) throws FilterEvaluationException { Expression param1 = getParam1(); if (param1 != null) { for (TypedObjectNode paramValue : param1.evaluate(obj, xpathEvaluator)) { Geometry param1Value = checkGeometryOrNull(paramValue); if (param1Value != null) { Geometry transformedGeom = getCompatibleGeometry(param1Value, geometry); return transformedGeom.intersects(param1Value); } } } else if (obj instanceof Feature) { // handle the case where the property name is empty Feature f = (Feature) obj; for (Property prop : f.getProperties()) { if (prop.getValue() instanceof Geometry) { Geometry geom = (Geometry) prop.getValue(); Geometry transformedGeom = getCompatibleGeometry(geometry, geom); if (transformedGeom.intersects(geometry)) { return true; } } } if (f.getExtraProperties() != null) { for (Property prop : f.getExtraProperties().getProperties()) { if (prop.getValue() instanceof Geometry) { Geometry geom = (Geometry) prop.getValue(); Geometry transformedGeom = getCompatibleGeometry(geometry, geom); if (transformedGeom.intersects(geometry)) { return true; } } } } } else { LOG.warn("Evaluating Intersects on non-Feature object and property name not specified."); } return false; }
private List<String> performUpdateBlob( final QName ftName, final List<ParsedPropertyReplacement> replacementProps, final Filter filter, final Lock lock) throws FeatureStoreException { final List<String> updatedFids = new ArrayList<String>(); final Query query = new Query(ftName, filter, -1, -1, -1); final StringBuilder sql = new StringBuilder("UPDATE "); sql.append(blobMapping.getTable()); sql.append(" SET "); sql.append(blobMapping.getDataColumn()); sql.append("=?,"); sql.append(blobMapping.getBBoxColumn()); sql.append("=? WHERE "); sql.append(blobMapping.getGMLIdColumn()); sql.append("=?"); PreparedStatement blobUpdateStmt = null; FeatureInputStream features = null; try { LOG.debug("Preparing update stmt: {}", sql); blobUpdateStmt = conn.prepareStatement(sql.toString()); features = fs.query(query); for (final Feature feature : features) { new FeatureUpdater().update(feature, replacementProps); updateFeatureBlob(blobUpdateStmt, feature); updatedFids.add(feature.getId()); } } catch (final Exception e) { final String msg = "Error while performing Update (BLOB): " + e.getMessage(); LOG.trace(msg, e); throw new FeatureStoreException(msg); } finally { if (features != null) { features.close(); } } return updatedFids; }
@Override public String performReplace( final Feature replacement, final Filter filter, final Lock lock, final IDGenMode idGenMode) throws FeatureStoreException { if (filter instanceof IdFilter) { performDelete((IdFilter) filter, lock); } else { performDelete(replacement.getName(), (OperatorFilter) filter, lock); } final GenericFeatureCollection col = new GenericFeatureCollection(); col.add(replacement); final List<String> ids = performInsert(col, idGenMode); if (ids.isEmpty() || ids.size() > 1) { throw new FeatureStoreException("Unable to determine new feature id."); } return ids.get(0); }
@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); }