private void insert(
     final Record object, final PathName typePath, final RecordDefinition recordDefinition)
     throws SQLException {
   PreparedStatement statement = this.typeInsertStatementMap.get(typePath);
   if (statement == null) {
     final String sql = getInsertSql(recordDefinition, false);
     try {
       statement = this.connection.prepareStatement(sql);
       this.typeInsertStatementMap.put(typePath, statement);
     } catch (final SQLException e) {
       LOG.error(sql, e);
     }
   }
   int parameterIndex = 1;
   for (final FieldDefinition fieldDefinition : recordDefinition.getFields()) {
     final JdbcFieldDefinition jdbcFieldDefinition = (JdbcFieldDefinition) fieldDefinition;
     parameterIndex =
         jdbcFieldDefinition.setInsertPreparedStatementValue(statement, parameterIndex, object);
   }
   statement.addBatch();
   Integer batchCount = this.typeInsertBatchCountMap.get(typePath);
   if (batchCount == null) {
     batchCount = 1;
     this.typeInsertBatchCountMap.put(typePath, 1);
   } else {
     batchCount += 1;
     this.typeInsertBatchCountMap.put(typePath, batchCount);
   }
   if (batchCount >= this.batchSize) {
     final String sql = getInsertSql(recordDefinition, false);
     processCurrentBatch(typePath, sql, statement, this.typeInsertBatchCountMap);
   }
 }
  private String getUpdateSql(final RecordDefinition type) {
    final PathName typePath = type.getPathName();
    final String tableName = this.recordStore.getDatabaseQualifiedTableName(typePath);
    String sql = this.typeUpdateSqlMap.get(typePath);
    if (sql == null) {
      final StringBuilder sqlBuffer = new StringBuilder();
      if (this.sqlPrefix != null) {
        sqlBuffer.append(this.sqlPrefix);
      }
      sqlBuffer.append("update ");
      if (this.hints != null) {
        sqlBuffer.append(this.hints);
      }
      sqlBuffer.append(tableName);
      sqlBuffer.append(" set ");
      final List<FieldDefinition> idFields = type.getIdFields();
      boolean first = true;
      for (final FieldDefinition attribute : type.getFields()) {
        if (!idFields.contains(attribute)) {
          final JdbcFieldDefinition jdbcAttribute = (JdbcFieldDefinition) attribute;
          if (first) {
            first = false;
          } else {
            sqlBuffer.append(", ");
          }
          addSqlColumEqualsPlaceholder(sqlBuffer, jdbcAttribute);
        }
      }
      sqlBuffer.append(" where ");
      first = true;
      for (final FieldDefinition idField : idFields) {
        if (first) {
          first = false;
        } else {
          sqlBuffer.append(" AND ");
        }
        final JdbcFieldDefinition idJdbcAttribute = (JdbcFieldDefinition) idField;
        addSqlColumEqualsPlaceholder(sqlBuffer, idJdbcAttribute);
      }

      sqlBuffer.append(" ");
      if (this.sqlSuffix != null) {
        sqlBuffer.append(this.sqlSuffix);
      }
      sql = sqlBuffer.toString();

      this.typeUpdateSqlMap.put(typePath, sql);
    }
    return sql;
  }
 private void update(final Record object) throws SQLException {
   final RecordDefinition objectType = object.getRecordDefinition();
   final PathName typePath = objectType.getPathName();
   final RecordDefinition recordDefinition = getRecordDefinition(typePath);
   flushIfRequired(recordDefinition);
   PreparedStatement statement = this.typeUpdateStatementMap.get(typePath);
   if (statement == null) {
     final String sql = getUpdateSql(recordDefinition);
     try {
       statement = this.connection.prepareStatement(sql);
       this.typeUpdateStatementMap.put(typePath, statement);
     } catch (final SQLException e) {
       LOG.error(sql, e);
     }
   }
   int parameterIndex = 1;
   final List<FieldDefinition> idFields = recordDefinition.getIdFields();
   for (final FieldDefinition fieldDefinition : recordDefinition.getFields()) {
     if (!idFields.contains(fieldDefinition)) {
       final JdbcFieldDefinition jdbcFieldDefinition = (JdbcFieldDefinition) fieldDefinition;
       parameterIndex =
           jdbcFieldDefinition.setInsertPreparedStatementValue(statement, parameterIndex, object);
     }
   }
   for (final FieldDefinition idField : idFields) {
     final JdbcFieldDefinition jdbcFieldDefinition = (JdbcFieldDefinition) idField;
     parameterIndex =
         jdbcFieldDefinition.setInsertPreparedStatementValue(statement, parameterIndex, object);
   }
   statement.addBatch();
   Integer batchCount = this.typeUpdateBatchCountMap.get(typePath);
   if (batchCount == null) {
     batchCount = 1;
     this.typeUpdateBatchCountMap.put(typePath, 1);
   } else {
     batchCount += 1;
     this.typeUpdateBatchCountMap.put(typePath, batchCount);
   }
   if (batchCount >= this.batchSize) {
     final String sql = getUpdateSql(recordDefinition);
     processCurrentBatch(typePath, sql, statement, this.typeUpdateBatchCountMap);
   }
   this.recordStore.addStatistic("Update", object);
 }
  public static void write(
      final File file, final RecordDefinition recordDefinition, final String dataSource)
      throws IOException {
    try (XmlWriter writer = new XmlWriter(new FileWriter(file))) {
      writer.setIndent(true);
      writer.startDocument("UTF-8", "1.0");
      writer.startTag("OGRVRTDataSource");
      writer.startTag("OGRVRTLayer");
      final String typeName = recordDefinition.getName();
      writer.attribute("name", typeName);
      writer.startTag("SrcDataSource");
      writer.attribute("relativeToVRT", "1");
      writer.text(dataSource);
      writer.endTag("SrcDataSource");

      writer.element(new QName("SrcLayer"), typeName);

      for (final FieldDefinition attribute : recordDefinition.getFields()) {
        final String fieldName = attribute.getName();
        final DataType fieldType = attribute.getDataType();
        final Class<?> typeClass = attribute.getTypeClass();
        if (Geometry.class.isAssignableFrom(typeClass)) {
          final GeometryFactory geometryFactory = recordDefinition.getGeometryFactory();
          writer.element("GeometryType", "wkb" + fieldType);
          if (geometryFactory != null) {
            writer.element("LayerSRS", "EPSG:" + geometryFactory.getCoordinateSystemId());
          }
          writer.startTag("GeometryField");
          writer.attribute("encoding", "WKT");
          writer.attribute("field", fieldName);
          writer.attribute("name", fieldName);
          writer.attribute("reportSrcColumn", "FALSE");
          writer.element("GeometryType", "wkb" + fieldType);
          if (geometryFactory != null) {
            writer.element("SRS", "EPSG:" + geometryFactory.getCoordinateSystemId());
          }
          writer.endTag("GeometryField");
        } else {
          writer.startTag("Field");
          writer.attribute("name", fieldName);
          String type = "String";
          if (Arrays.asList(
                  DataTypes.BYTE, DataTypes.SHORT, DataTypes.INT, DataTypes.LONG, DataTypes.INTEGER)
              .contains(fieldType)) {
            type = "Integer";
          } else if (Arrays.asList(DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.DECIMAL)
              .contains(fieldType)) {
            type = "Real";
          } else if (DataTypes.DATE.equals(type)) {
            type = "Date";
          } else if (DataTypes.DATE_TIME.equals(type)) {
            type = "DateTime";
          } else {
            type = "String";
          }
          writer.attribute("type", type);
          final int length = attribute.getLength();
          if (length > 0) {
            writer.attribute("width", length);
          }
          final int scale = attribute.getScale();
          if (scale > 0) {
            writer.attribute("scale", scale);
          }
          writer.attribute("src", fieldName);
          writer.endTag("Field");
        }
      }
      writer.endTag("OGRVRTLayer");
      writer.endTag("OGRVRTDataSource");
      writer.endDocument();
    }
  }