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();
  }