private int performDeleteBlob(IdFilter filter, Lock lock) throws FeatureStoreException {
   int deleted = 0;
   PreparedStatement stmt = null;
   try {
     stmt =
         conn.prepareStatement(
             "DELETE FROM "
                 + blobMapping.getTable()
                 + " WHERE "
                 + blobMapping.getGMLIdColumn()
                 + "=?");
     for (ResourceId id : filter.getSelectedIds()) {
       stmt.setString(1, id.getRid());
       stmt.addBatch();
       if (fs.getCache() != null) {
         fs.getCache().remove(id.getRid());
       }
     }
     int[] deletes = stmt.executeBatch();
     for (int noDeleted : deletes) {
       deleted += noDeleted;
     }
   } catch (SQLException e) {
     LOG.debug(e.getMessage(), e);
     throw new FeatureStoreException(e.getMessage(), e);
   } finally {
     JDBCUtils.close(stmt);
   }
   LOG.debug("Deleted " + deleted + " features.");
   return deleted;
 }
 /**
  * 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;
 }
 /**
  * Creates a new {@link SQLFeatureStoreTransaction} instance.
  *
  * @param store corresponding feature store instance, must not be <code>null</code>
  * @param conn JDBC connection associated with the transaction, must not be <code>null</code> and
  *     have <code>autocommit</code> set to <code>false</code>
  * @param schema application schema with mapping information, must not be <code>null</code>
  * @param inspectors feature inspectors, must not be <code>null</code>
  */
 SQLFeatureStoreTransaction(
     SQLFeatureStore store,
     Connection conn,
     MappedAppSchema schema,
     List<FeatureInspector> inspectors) {
   this.fs = store;
   this.conn = conn;
   this.schema = schema;
   this.inspectors = inspectors;
   blobMapping = schema.getBlobMapping();
   if (blobMapping != null) {
     DBField bboxColumn = new DBField(blobMapping.getBBoxColumn());
     GeometryStorageParams geometryParams =
         new GeometryStorageParams(blobMapping.getCRS(), null, DIM_2);
     GeometryMapping blobGeomMapping =
         new GeometryMapping(null, true, bboxColumn, GeometryType.GEOMETRY, geometryParams, null);
     blobGeomConverter = fs.getGeometryConverter(blobGeomMapping);
   }
   this.bboxTracker = new BBoxTracker();
 }
 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 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 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);
  }