/**
   * Convert the current row in a ResultSet into a TableRow object.
   *
   * @param results A ResultSet to process
   * @param table The name of the table
   * @param pColumnNames The name of the columns in this resultset
   * @return A TableRow object with the data from the ResultSet
   * @exception SQLException If a database error occurs
   */
  static TableRow process(ResultSet results, String table, List<String> pColumnNames)
      throws SQLException {
    ResultSetMetaData meta = results.getMetaData();
    int columns = meta.getColumnCount() + 1;

    // If we haven't been passed the column names try to generate them from the metadata / table
    List<String> columnNames =
        pColumnNames != null
            ? pColumnNames
            : ((table == null) ? getColumnNames(meta) : getColumnNames(table));

    TableRow row = new TableRow(canonicalize(table), columnNames);

    // Process the columns in order
    // (This ensures maximum backwards compatibility with
    // old JDBC drivers)
    for (int i = 1; i < columns; i++) {
      String name = meta.getColumnName(i);
      int jdbctype = meta.getColumnType(i);

      switch (jdbctype) {
        case Types.BOOLEAN:
        case Types.BIT:
          row.setColumn(name, results.getBoolean(i));
          break;

        case Types.INTEGER:
          if (isOracle) {
            long longValue = results.getLong(i);
            if (longValue <= (long) Integer.MAX_VALUE) {
              row.setColumn(name, (int) longValue);
            } else {
              row.setColumn(name, longValue);
            }
          } else {
            row.setColumn(name, results.getInt(i));
          }
          break;

        case Types.BIGINT:
          row.setColumn(name, results.getLong(i));
          break;

        case Types.NUMERIC:
        case Types.DECIMAL:
          row.setColumn(name, results.getBigDecimal(i));
          break;

        case Types.DOUBLE:
          row.setColumn(name, results.getDouble(i));
          break;

        case Types.CLOB:
          if (isOracle) {
            row.setColumn(name, results.getString(i));
          } else {
            throw new IllegalArgumentException("Unsupported JDBC type: " + jdbctype);
          }
          break;

        case Types.VARCHAR:
          try {
            byte[] bytes = results.getBytes(i);

            if (bytes != null) {
              String mystring = new String(results.getBytes(i), "UTF-8");
              row.setColumn(name, mystring);
            } else {
              row.setColumn(name, results.getString(i));
            }
          } catch (UnsupportedEncodingException e) {
            log.error("Unable to parse text from database", e);
          }
          break;

        case Types.DATE:
          row.setColumn(name, results.getDate(i));
          break;

        case Types.TIME:
          row.setColumn(name, results.getTime(i));
          break;

        case Types.TIMESTAMP:
          row.setColumn(name, results.getTimestamp(i));
          break;

        default:
          throw new IllegalArgumentException("Unsupported JDBC type: " + jdbctype);
      }

      // Determines if the last column was null, and sets the tablerow accordingly
      if (results.wasNull()) {
        row.setColumnNull(name);
      }
    }

    // Now that we've prepped the TableRow, reset the flags so that we can detect which columns have
    // changed
    row.resetChanged();
    return row;
  }
 /**
  * Constructor
  *
  * @param table The name of the database table containing this row.
  * @param columns A list of column names. Each member of the List is a String. After construction,
  *     the list of columns is fixed; attempting to access a column not in the list will cause an
  *     IllegalArgumentException to be thrown.
  */
 public TableRow(String table, List columns) {
   this.table = table;
   nullColumns(columns);
   resetChanged(columns);
 }