code: /*
   * Copyright (c) 2022 Airbyte, Inc., all rights reserved.
   */
  
  package io.airbyte.integrations.source.db2;
  
  import com.fasterxml.jackson.databind.JsonNode;
  import com.fasterxml.jackson.databind.node.ObjectNode;
  import io.airbyte.commons.json.Jsons;
  import io.airbyte.db.jdbc.JdbcSourceOperations;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.util.Collections;
  import java.util.List;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  public class Db2SourceOperations extends JdbcSourceOperations {
  
    private static final Logger LOGGER = LoggerFactory.getLogger(Db2SourceOperations.class);
    private static final List<String> DB2_UNIQUE_NUMBER_TYPES = List.of("DECFLOAT");
  
    @Override
    public JsonNode rowToJson(final ResultSet queryContext) throws SQLException {
      final int columnCount = queryContext.getMetaData().getColumnCount();
      final ObjectNode jsonNode = (ObjectNode) Jsons.jsonNode(Collections.emptyMap());
  
      for (int i = 1; i <= columnCount; i++) {
        setFields(queryContext, i, jsonNode);
      }
  
      return jsonNode;
    }
  
    /* Helpers */
  
    private void setFields(ResultSet queryContext, int index, ObjectNode jsonNode) throws SQLException {
      try {
        queryContext.getObject(index);
        if (!queryContext.wasNull()) {
          setJsonField(queryContext, index, jsonNode);
        }
      } catch (SQLException e) {
        if (DB2_UNIQUE_NUMBER_TYPES.contains(queryContext.getMetaData().getColumnTypeName(index))) {
          db2UniqueTypes(queryContext, index, jsonNode);
        } else {
          throw new SQLException(e.getCause());
        }
      }
    }
  
    private void db2UniqueTypes(ResultSet resultSet, int index, ObjectNode jsonNode) throws SQLException {
      String columnType = resultSet.getMetaData().getColumnTypeName(index);
      String columnName = resultSet.getMetaData().getColumnName(index);
      if (DB2_UNIQUE_NUMBER_TYPES.contains(columnType)) {
        putDecfloat(jsonNode, columnName, resultSet, index);
      }
    }
  
    private void putDecfloat(final ObjectNode node,
                             final String columnName,
                             final ResultSet resultSet,
                             final int index) {
      try {
        final double value = resultSet.getDouble(index);
        node.put(columnName, value);
      } catch (final SQLException e) {
        node.put(columnName, (Double) null);
      }
    }
  
  }
  