Ejemplo n.º 1
1
  private void testUnsupportedOperations() throws Exception {
    Connection conn = getConnection();
    stat = conn.createStatement();
    stat.execute("create table test(id int, c clob, b blob)");
    stat.execute("insert into test values(1, 'x', x'00')");
    ResultSet rs = stat.executeQuery("select * from test order by id");
    rs.next();
    Clob clob = rs.getClob(2);
    byte[] data = IOUtils.readBytesAndClose(clob.getAsciiStream(), -1);
    assertEquals("x", new String(data, "UTF-8"));
    assertTrue(clob.toString().endsWith("'x'"));
    clob.free();
    assertTrue(clob.toString().endsWith("null"));

    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).truncate(0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).setAsciiStream(1);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).setString(1, "", 0, 1);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).position("", 0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).position((Clob) null, 0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, clob).getCharacterStream(1, 1);

    Blob blob = rs.getBlob(3);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).truncate(0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).setBytes(1, new byte[0], 0, 0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).position(new byte[1], 0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).position((Blob) null, 0);
    assertThrows(ErrorCode.FEATURE_NOT_SUPPORTED_1, blob).getBinaryStream(1, 1);
    assertTrue(blob.toString().endsWith("X'00'"));
    blob.free();
    assertTrue(blob.toString().endsWith("null"));

    stat.execute("drop table test");
    conn.close();
  }
  @Override
  public void releaseResources() {
    log.trace("Releasing JDBC resources");

    for (Map.Entry<Statement, Set<ResultSet>> entry : xref.entrySet()) {
      if (entry.getValue() != null) {
        closeAll(entry.getValue());
      }
      close(entry.getKey());
    }
    xref.clear();

    closeAll(unassociatedResultSets);

    if (blobs != null) {
      for (Blob blob : blobs) {
        try {
          blob.free();
        } catch (SQLException e) {
          log.debugf("Unable to free JDBC Blob reference [%s]", e.getMessage());
        }
      }
      blobs.clear();
    }

    if (clobs != null) {
      for (Clob clob : clobs) {
        try {
          clob.free();
        } catch (SQLException e) {
          log.debugf("Unable to free JDBC Clob reference [%s]", e.getMessage());
        }
      }
      clobs.clear();
    }

    if (nclobs != null) {
      for (NClob nclob : nclobs) {
        try {
          nclob.free();
        } catch (SQLException e) {
          log.debugf("Unable to free JDBC NClob reference [%s]", e.getMessage());
        }
      }
      nclobs.clear();
    }
  }
Ejemplo n.º 3
0
 public SerialBlob(final Blob other) throws SQLException {
   InputStream is = null;
   try {
     final ByteArrayOutputStream baos = new ByteArrayOutputStream();
     is = other.getBinaryStream();
     final byte[] buff = new byte[1024];
     int len;
     while ((len = is.read(buff)) > 0) {
       baos.write(buff, 0, len);
     }
     data = baos.toByteArray();
     other.free();
   } catch (final IOException e) {
     throw new SQLException("Can't retrieve contents of Blob", e.toString());
   } finally {
     StreamCloser.close(is);
   }
 }
  private byte[] getBytes(Blob blob) throws SQLException {
    if (blob == null) {
      LOGGER.log(Level.FINEST, "BLOB handler called with null BLOB");
      return new byte[0];
    }

    LOGGER.log(Level.FINEST, "BLOB handler called with BLOB of length {0}", blob.length());
    byte[] bytes = blob.getBytes(1, (int) blob.length());
    try {
      blob.free();
    } catch (SQLException e) {
      LOGGER.log(Level.WARNING, "Error freeing the BLOB", e);
    } catch (UnsupportedOperationException e) {
      // Check for JDBC drivers that don't support this JDBC 4.0 method.
      // This is an unusual exception to throw, but worth catching since
      // it's a RuntimeException that will otherwise terminate the monitor.
      LOGGER.log(Level.WARNING, "Error freeing the BLOB, try a newer JDBC 4.0 driver", e);
    } catch (LinkageError e) {
      // Check for JDBC drivers that were not compiled against Java 6.
      LOGGER.log(Level.WARNING, "Error freeing the BLOB, try a newer JDBC 4.0 driver", e);
    }
    return bytes;
  }
Ejemplo n.º 5
0
  /**
   * Gets the job configuration from the DDBB.
   *
   * @param jobId the job identification.
   * @return the {@link eu.aliada.ckancreation.model.JobConfiguration} which contains the
   *     configuration of the job.
   * @since 2.0
   */
  public JobConfiguration getJobConfiguration(final Integer jobId) {
    JobConfiguration jobConf = null;
    int datasetId = -1;
    int organisationId = -1;
    try {
      final Statement sta = getConnection().createStatement();
      String sql = "SELECT * FROM ckancreation_job_instances WHERE job_id=" + jobId;
      ResultSet resultSet = sta.executeQuery(sql);
      jobConf = new JobConfiguration();
      while (resultSet.next()) {
        jobConf = new JobConfiguration();
        jobConf.setId(jobId);
        jobConf.setCkanApiURL(resultSet.getString("ckan_api_url"));
        jobConf.setCkanApiKey(resultSet.getString("ckan_api_key"));
        jobConf.setTmpDir(resultSet.getString("tmp_dir"));
        jobConf.setStoreIp(resultSet.getString("store_ip"));
        jobConf.setStoreSqlPort(resultSet.getInt("store_sql_port"));
        jobConf.setSqlLogin(resultSet.getString("sql_login"));
        jobConf.setSqlPassword(resultSet.getString("sql_password"));
        jobConf.setIsqlCommandPath(resultSet.getString("isql_command_path"));
        jobConf.setIsqlCommandsGraphDumpFilename(
            resultSet.getString("isql_commands_file_graph_dump"));
        jobConf.setVirtHttpServRoot(resultSet.getString("virtuoso_http_server_root"));
        jobConf.setOntologyUri(resultSet.getString("aliada_ontology"));
        jobConf.setOrgName(resultSet.getString("org_name"));
        jobConf.setOrgTitle(resultSet.getString("org_name").toUpperCase());
        jobConf.setOrgDescription(resultSet.getString("org_description"));
        jobConf.setOrgHomePage(resultSet.getString("org_home_page"));
        datasetId = resultSet.getInt("datasetId");
        jobConf.setDatasetId(datasetId);
        organisationId = resultSet.getInt("organisationId");
      }
      resultSet.close();
      // Get dataset related information
      sql = "SELECT * FROM dataset WHERE datasetId=" + datasetId;
      resultSet = sta.executeQuery(sql);
      while (resultSet.next()) {
        jobConf.setDatasetAuthor(resultSet.getString("dataset_author"));
        jobConf.setDatasetAuthorEmail(resultSet.getString("dataset_author_email"));
        jobConf.setCkanDatasetName(resultSet.getString("ckan_dataset_name"));
        jobConf.setDatasetDesc(resultSet.getString("dataset_desc"));
        jobConf.setDatasetLongDesc(resultSet.getString("dataset_long_desc"));
        jobConf.setDatasetSourceURL(resultSet.getString("dataset_source_url"));
        jobConf.setSparqlEndpointUri(resultSet.getString("sparql_endpoint_uri"));
        jobConf.setSparqlLogin(resultSet.getString("sparql_endpoint_login"));
        jobConf.setSparqlPassword(resultSet.getString("sparql_endpoint_password"));
        jobConf.setPublicSparqlEndpointUri(resultSet.getString("public_sparql_endpoint_uri"));
        jobConf.setLicenseCKANId(resultSet.getString("license_ckan_id"));
        jobConf.setLicenseURL(resultSet.getString("license_url"));
        jobConf.setDomainName(resultSet.getString("domain_name"));
        jobConf.setVirtualHost(resultSet.getString("virtual_host"));
        jobConf.setUriIdPart(resultSet.getString("uri_id_part"));
        jobConf.setUriDocPart(resultSet.getString("uri_doc_part"));
        jobConf.setUriConceptPart(resultSet.getString("uri_concept_part"));
        jobConf.setUriSetPart(resultSet.getString("uri_set_part"));
      }
      resultSet.close();
      // Get subsets related information
      sql = "SELECT * FROM subset WHERE datasetId=" + datasetId;
      resultSet = sta.executeQuery(sql);
      while (resultSet.next()) {
        final Subset subset = new Subset();
        subset.setUriConceptPart(resultSet.getString("uri_concept_part"));
        subset.setDescription(resultSet.getString("subset_desc"));
        subset.setGraph(resultSet.getString("graph_uri"));
        subset.setLinksGraph(resultSet.getString("links_graph_uri"));
        subset.setDescription(resultSet.getString("subset_desc"));
        jobConf.setSubset(subset);
      }
      resultSet.close();
      // Get organisation LOGO from BLOB object in organisation table
      sql = "SELECT org_logo FROM organisation WHERE organisationId=" + organisationId;
      resultSet = sta.executeQuery(sql);
      if (resultSet.next() && resultSet.getBlob("org_logo") != null) {
        final Blob logo = resultSet.getBlob("org_logo");
        final int blobLength = (int) logo.length();
        byte[] blobAsBytes = null;
        blobAsBytes = logo.getBytes(1, blobLength);
        // Compose initial logo file name
        final String orgImagePathInit =
            jobConf.getTmpDir()
                + File.separator
                + "orgLogo"
                + "_"
                + System.currentTimeMillis()
                + ".jpeg";
        try {
          final FileOutputStream fos = new FileOutputStream(orgImagePathInit);
          fos.write(blobAsBytes);
          fos.close();
          jobConf.setOrgImagePath(orgImagePathInit);
        } catch (IOException exception) {
          LOGGER.error(MessageCatalog._00034_FILE_CREATION_FAILURE, exception, orgImagePathInit);
        }
        // release the blob and free up memory. (since JDBC 4.0)
        logo.free();
      }
      resultSet.close();
      sta.close();
    } catch (SQLException exception) {
      LOGGER.error(MessageCatalog._00024_DATA_ACCESS_FAILURE, exception);
      return null;
    }

    return jobConf;
  }
Ejemplo n.º 6
0
  //               1 "BibTeX.id",
  //               2 "BibTeX.createdBy",
  //               3 "BibTeX.abstract",
  //               4 "BibTeX.address",
  //               5 "BibTeX.annotation",
  //               6 "BibTeX.author",
  //               7 "BibTeX.bibType",
  //               8 "BibTeX.bookTitle",
  //               9 "BibTeX.chapter",
  //               10 "BibTeX.copyright",
  //               11 "BibTeX.crossref",
  //               12 "BibTeX.edition",
  //               13 "BibTeX.editor",
  //               14 "BibTeX.isbn",
  //               15 "BibTeX.issn",
  //               16 "BibTeX.journal",
  //               17 "BibTeX.bibkey",
  //               18 "BibTeX.keywords",
  //               19 "BibTeX.number",
  //               20 "BibTeX.pages",
  //               21 "BibTeX.series",
  //               22 "BibTeX.title",
  //               23 "BibTeX.url",
  //               24 "BibTeX.volume",
  //               25 "BibTeX.year",
  //               26 "uncompress(meta)"
  @Override
  public BibTeX next() throws DbException {
    BibTeX nextBibTeX = new BibTeX();
    try {
      String bibtexId = rs.getString("id");
      String createdBy = rs.getString("createdBy");
      String abstractBib = rs.getString("abstract");
      String address = rs.getString("address");
      String annotation = rs.getString("annotation");
      String author = rs.getString("author");
      String bibType = rs.getString("bibType");
      String bookTitle = rs.getString("bookTitle");
      String chapter = rs.getString("chapter");
      String copyright = rs.getString("copyright");
      String crossref = rs.getString("crossref");
      String edition = rs.getString("edition");
      String editor = rs.getString("editor");
      String isbn = rs.getString("isbn");
      String issn = rs.getString("issn");
      String journal = rs.getString("journal");
      String bibkey = rs.getString("bibkey");
      String keywords = rs.getString("keywords");
      String pages = rs.getString("pages");
      String series = rs.getString("series");
      String title = rs.getString("title");
      String url = rs.getString("url");

      String number = rs.getString("number");
      String volume = rs.getString("volume");
      String year = rs.getString("year");

      Blob metaInfoBlob = rs.getBlob(26);
      if (metaInfoBlob != null) {
        MetaInfoDeblobber mid = new MetaInfoDeblobber(metaInfoBlob);
        MetaInfo mi = mid.toMetaInfo();
        nextBibTeX.setMeta(mi);
        metaInfoBlob.free();
      }

      nextBibTeX.setUri(new VRI(baseUri).augment(bibtexId));
      nextBibTeX.setAbstract(abstractBib);
      nextBibTeX.setAddress(address);
      nextBibTeX.setAnnotation(annotation);
      nextBibTeX.setAuthor(author);

      BibTeX.BibTYPE bibTYPE = BibTeX.BibTYPE.Entry;
      if (bibType != null) {
        bibTYPE = BibTeX.BibTYPE.valueOf(bibType);
      }
      nextBibTeX.setBibType(bibTYPE);

      nextBibTeX.setBookTitle(bookTitle);
      nextBibTeX.setChapter(chapter);
      nextBibTeX.setCopyright(copyright);

      if (createdBy != null) {
        User user = usersCache.get(createdBy); // try to get the user from the cache.
        if (user == null) { // if user is not found in cache, create it and put it there!
          user = new User();
          user.setUid(createdBy);
          if (resolveUser) {
            FindUser fu = new FindUser();
            fu.setWhere("uid='" + createdBy + "'");
            IDbIterator<User> users = fu.list();
            if (users.hasNext()) {
              user = users.next();
            }
            users.close();
            fu.close();
          }
          usersCache.put(createdBy, user);
        }
        nextBibTeX.setCreatedBy(user);
      }

      nextBibTeX.setCrossref(crossref);
      nextBibTeX.setEdition(edition);
      nextBibTeX.setEditor(editor);
      nextBibTeX.setIsbn(isbn);
      nextBibTeX.setIssn(issn);
      nextBibTeX.setJournal(journal);
      nextBibTeX.setKey(bibkey);
      nextBibTeX.setKeywords(keywords);

      if (number == null) {
        nextBibTeX.setNumber(null);
      } else {
        nextBibTeX.setNumber(Integer.parseInt(number));
      }
      if (year == null) {
        nextBibTeX.setYear(null);
      } else {
        nextBibTeX.setYear(Integer.parseInt(year));
      }
      if (volume == null) {
        nextBibTeX.setVolume(null);
      } else {
        nextBibTeX.setVolume(Integer.parseInt(volume));
      }

      nextBibTeX.setPages(pages);
      nextBibTeX.setSeries(series);
      nextBibTeX.setTitle(title);
      nextBibTeX.setUrl(url);

    } catch (SQLException ex) {
      final String msg = "SQL-related exception thrown while reading bibtex data from the database";
      logger.warn(msg, ex);
      throw new DbException(msg, ex);
    }
    return nextBibTeX;
  }
Ejemplo n.º 7
0
  /**
   * @param rs
   * @param interpretLiteralBytes
   * @param payloadLength
   * @return
   * @throws HttpMalformedHeaderException
   * @throws SQLException
   * @throws DatabaseException
   */
  private List<WebSocketMessageDTO> buildMessageDTOs(
      ResultSet rs, boolean interpretLiteralBytes, int payloadLength)
      throws SQLException, DatabaseException {
    ArrayList<WebSocketMessageDTO> messages = new ArrayList<>();
    try {
      while (rs.next()) {
        WebSocketMessageDTO message;

        int channelId = rs.getInt("channel_id");
        WebSocketChannelDTO channel = getChannel(channelId);

        if (rs.getInt("fuzz_id") != 0) {
          WebSocketFuzzMessageDTO fuzzMessage = new WebSocketFuzzMessageDTO(channel);
          fuzzMessage.fuzzId = rs.getInt("fuzz_id");
          fuzzMessage.state = WebSocketFuzzMessageDTO.State.valueOf(rs.getString("state"));
          fuzzMessage.fuzz = rs.getString("fuzz");

          message = fuzzMessage;
        } else {
          message = new WebSocketMessageDTO(channel);
        }

        message.id = rs.getInt("message_id");
        message.setTime(rs.getTimestamp("timestamp"));
        message.opcode = rs.getInt("opcode");
        message.readableOpcode = WebSocketMessage.opcode2string(message.opcode);

        // read payload
        if (message.opcode == WebSocketMessage.OPCODE_BINARY) {
          if (payloadLength == -1) {
            // load all bytes
            message.payload = rs.getBytes("payload_bytes");
          } else {
            Blob blob = rs.getBlob("payload_bytes");
            int length = Math.min(payloadLength, (int) blob.length());
            message.payload = blob.getBytes(1, length);
            blob.free();
          }

          if (message.payload == null) {
            message.payload = new byte[0];
          }
        } else {
          if (payloadLength == -1) {
            // load all characters
            message.payload = rs.getString("payload_utf8");
          } else {
            Clob clob = rs.getClob("payload_utf8");
            int length = Math.min(payloadLength, (int) clob.length());
            message.payload = clob.getSubString(1, length);
            clob.free();
          }

          if (message.payload == null) {
            message.payload = "";
          }
        }

        message.isOutgoing = rs.getBoolean("is_outgoing");
        message.payloadLength = rs.getInt("payload_length");

        messages.add(message);
      }
    } finally {
      rs.close();
    }

    messages.trimToSize();

    return messages;
  }
Ejemplo n.º 8
0
  public static Object parseType(ResultSet result, Integer i, int type)
      throws SQLException, IOException, ParseException {
    logger.trace("i={} type={}", i, type);
    switch (type) {
        /**
         * The JDBC types CHAR, VARCHAR, and LONGVARCHAR are closely related. CHAR represents a
         * small, fixed-length character string, VARCHAR represents a small, variable-length
         * character string, and LONGVARCHAR represents a large, variable-length character string.
         */
      case Types.CHAR:
      case Types.VARCHAR:
      case Types.LONGVARCHAR:
        {
          return result.getString(i);
        }
      case Types.NCHAR:
      case Types.NVARCHAR:
      case Types.LONGNVARCHAR:
        {
          return result.getNString(i);
        }
        /**
         * The JDBC types BINARY, VARBINARY, and LONGVARBINARY are closely related. BINARY
         * represents a small, fixed-length binary value, VARBINARY represents a small,
         * variable-length binary value, and LONGVARBINARY represents a large, variable-length
         * binary value
         */
      case Types.BINARY:
      case Types.VARBINARY:
      case Types.LONGVARBINARY:
        {
          byte[] b = result.getBytes(i);
          return b;
        }
        /**
         * The JDBC type ARRAY represents the SQL3 type ARRAY.
         *
         * <p>An ARRAY value is mapped to an instance of the Array interface in the Java programming
         * language. If a driver follows the standard implementation, an Array object logically
         * points to an ARRAY value on the server rather than containing the elements of the ARRAY
         * object, which can greatly increase efficiency. The Array interface contains methods for
         * materializing the elements of the ARRAY object on the client in the form of either an
         * array or a ResultSet object.
         */
      case Types.ARRAY:
        {
          Array arr = result.getArray(i);
          return arr == null ? null : arr.getArray();
        }
        /**
         * The JDBC type BIGINT represents a 64-bit signed integer value between
         * -9223372036854775808 and 9223372036854775807.
         *
         * <p>The corresponding SQL type BIGINT is a nonstandard extension to SQL. In practice the
         * SQL BIGINT type is not yet currently implemented by any of the major databases, and we
         * recommend that its use be avoided in code that is intended to be portable.
         *
         * <p>The recommended Java mapping for the BIGINT type is as a Java long.
         */
      case Types.BIGINT:
        {
          Object o = result.getLong(i);
          return result.wasNull() ? null : o;
        }
        /**
         * The JDBC type BIT represents a single bit value that can be zero or one.
         *
         * <p>SQL-92 defines an SQL BIT type. However, unlike the JDBC BIT type, this SQL-92 BIT
         * type can be used as a parameterized type to define a fixed-length binary string.
         * Fortunately, SQL-92 also permits the use of the simple non-parameterized BIT type to
         * represent a single binary digit, and this usage corresponds to the JDBC BIT type.
         * Unfortunately, the SQL-92 BIT type is only required in "full" SQL-92 and is currently
         * supported by only a subset of the major databases. Portable code may therefore prefer to
         * use the JDBC SMALLINT type, which is widely supported.
         */
      case Types.BIT:
        {
          try {
            Object o = result.getInt(i);
            return result.wasNull() ? null : o;
          } catch (Exception e) {
            String exceptionClassName = e.getClass().getName();
            // postgresql can not handle boolean, it will throw PSQLException, something like "Bad
            // value for type int : t"
            if ("org.postgresql.util.PSQLException".equals(exceptionClassName)) {
              return "t".equals(result.getString(i));
            }
            throw new IOException(e);
          }
        }
        /**
         * The JDBC type BOOLEAN, which is new in the JDBC 3.0 API, maps to a boolean in the Java
         * programming language. It provides a representation of true and false, and therefore is a
         * better match than the JDBC type BIT, which is either 1 or 0.
         */
      case Types.BOOLEAN:
        {
          return result.getBoolean(i);
        }
        /**
         * The JDBC type BLOB represents an SQL3 BLOB (Binary Large Object).
         *
         * <p>A JDBC BLOB value is mapped to an instance of the Blob interface in the Java
         * programming language. If a driver follows the standard implementation, a Blob object
         * logically points to the BLOB value on the server rather than containing its binary data,
         * greatly improving efficiency. The Blob interface provides methods for materializing the
         * BLOB data on the client when that is desired.
         */
      case Types.BLOB:
        {
          Blob blob = result.getBlob(i);
          if (blob != null) {
            long n = blob.length();
            if (n > Integer.MAX_VALUE) {
              throw new IOException("can't process blob larger than Integer.MAX_VALUE");
            }
            byte[] tab = blob.getBytes(1, (int) n);
            blob.free();
            return tab;
          }
          break;
        }
        /**
         * The JDBC type CLOB represents the SQL3 type CLOB (Character Large Object).
         *
         * <p>A JDBC CLOB value is mapped to an instance of the Clob interface in the Java
         * programming language. If a driver follows the standard implementation, a Clob object
         * logically points to the CLOB value on the server rather than containing its character
         * data, greatly improving efficiency. Two of the methods on the Clob interface materialize
         * the data of a CLOB object on the client.
         */
      case Types.CLOB:
        {
          Clob clob = result.getClob(i);
          if (clob != null) {
            long n = clob.length();
            if (n > Integer.MAX_VALUE) {
              throw new IOException("can't process clob larger than Integer.MAX_VALUE");
            }
            String str = clob.getSubString(1, (int) n);
            clob.free();
            return str;
          }
          break;
        }
      case Types.NCLOB:
        {
          NClob nclob = result.getNClob(i);
          if (nclob != null) {
            long n = nclob.length();
            if (n > Integer.MAX_VALUE) {
              throw new IOException("can't process nclob larger than Integer.MAX_VALUE");
            }
            String str = nclob.getSubString(1, (int) n);
            nclob.free();
            return str;
          }
          break;
        }
        /**
         * The JDBC type DATALINK, new in the JDBC 3.0 API, is a column value that references a file
         * that is outside of a data source but is managed by the data source. It maps to the Java
         * type java.net.URL and provides a way to manage external files. For instance, if the data
         * source is a DBMS, the concurrency controls it enforces on its own data can be applied to
         * the external file as well.
         *
         * <p>A DATALINK value is retrieved from a ResultSet object with the ResultSet methods
         * getURL or getObject. If the Java platform does not support the type of URL returned by
         * getURL or getObject, a DATALINK value can be retrieved as a String object with the method
         * getString.
         *
         * <p>java.net.URL values are stored in a database using the method setURL. If the Java
         * platform does not support the type of URL being set, the method setString can be used
         * instead.
         */
      case Types.DATALINK:
        {
          return result.getURL(i);
        }
        /**
         * The JDBC DATE type represents a date consisting of day, month, and year. The
         * corresponding SQL DATE type is defined in SQL-92, but it is implemented by only a subset
         * of the major databases. Some databases offer alternative SQL types that support similar
         * semantics.
         */
      case Types.DATE:
        {
          try {
            Date d = result.getDate(i, calendar);
            return d != null ? formatDate(d.getTime()) : null;
          } catch (SQLException e) {
            return null;
          }
        }
      case Types.TIME:
        {
          try {
            Time t = result.getTime(i, calendar);
            return t != null ? formatDate(t.getTime()) : null;
          } catch (SQLException e) {
            return null;
          }
        }
      case Types.TIMESTAMP:
        {
          try {
            Timestamp t = result.getTimestamp(i, calendar);
            return t != null ? formatDate(t.getTime()) : null;
          } catch (SQLException e) {
            // java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column ... to
            // TIMESTAMP.
            return null;
          }
        }
        /**
         * The JDBC types DECIMAL and NUMERIC are very similar. They both represent fixed-precision
         * decimal values.
         *
         * <p>The corresponding SQL types DECIMAL and NUMERIC are defined in SQL-92 and are very
         * widely implemented. These SQL types take precision and scale parameters. The precision is
         * the total number of decimal digits supported, and the scale is the number of decimal
         * digits after the decimal point. For most DBMSs, the scale is less than or equal to the
         * precision. So for example, the value "12.345" has a precision of 5 and a scale of 3, and
         * the value ".11" has a precision of 2 and a scale of 2. JDBC requires that all DECIMAL and
         * NUMERIC types support both a precision and a scale of at least 15.
         *
         * <p>The sole distinction between DECIMAL and NUMERIC is that the SQL-92 specification
         * requires that NUMERIC types be represented with exactly the specified precision, whereas
         * for DECIMAL types, it allows an implementation to add additional precision beyond that
         * specified when the type was created. Thus a column created with type NUMERIC(12,4) will
         * always be represented with exactly 12 digits, whereas a column created with type
         * DECIMAL(12,4) might be represented by some larger number of digits.
         *
         * <p>The recommended Java mapping for the DECIMAL and NUMERIC types is
         * java.math.BigDecimal. The java.math.BigDecimal type provides math operations to allow
         * BigDecimal types to be added, subtracted, multiplied, and divided with other BigDecimal
         * types, with integer types, and with floating point types.
         *
         * <p>The method recommended for retrieving DECIMAL and NUMERIC values is
         * ResultSet.getBigDecimal. JDBC also allows access to these SQL types as simple Strings or
         * arrays of char. Thus, Java programmers can use getString to receive a DECIMAL or NUMERIC
         * result. However, this makes the common case where DECIMAL or NUMERIC are used for
         * currency values rather awkward, since it means that application writers have to perform
         * math on strings. It is also possible to retrieve these SQL types as any of the Java
         * numeric types.
         */
      case Types.DECIMAL:
      case Types.NUMERIC:
        {
          BigDecimal bd = null;
          try {
            // getBigDecimal() should get obsolete. Most seem to use getString/getObject anyway...
            bd = result.getBigDecimal(i);
          } catch (NullPointerException e) {
            // But is it true? JDBC NPE exists since 13 years?
            // http://forums.codeguru.com/archive/index.php/t-32443.html
            // Null values are driving us nuts in JDBC:
            // http://stackoverflow.com/questions/2777214/when-accessing-resultsets-in-jdbc-is-there-an-elegant-way-to-distinguish-betwee
          }
          if (bd == null || result.wasNull()) {
            return null;
          }
          int scale = 2;
          if (scale >= 0) {
            bd = bd.setScale(scale, BigDecimal.ROUND_UP);
            try {
              long l = bd.longValueExact();
              if (Long.toString(l).equals(result.getString(i))) {
                // convert to long if possible
                return l;
              } else {
                // convert to double (with precision loss)
                return bd.doubleValue();
              }
            } catch (ArithmeticException e) {
              return bd.doubleValue();
            }
          } else {
            return bd.toPlainString();
          }
        }
        /**
         * The JDBC type DOUBLE represents a "double precision" floating point number that supports
         * 15 digits of mantissa.
         *
         * <p>The corresponding SQL type is DOUBLE PRECISION, which is defined in SQL-92 and is
         * widely supported by the major databases. The SQL-92 standard leaves the precision of
         * DOUBLE PRECISION up to the implementation, but in practice all the major databases
         * supporting DOUBLE PRECISION support a mantissa precision of at least 15 digits.
         *
         * <p>The recommended Java mapping for the DOUBLE type is as a Java double.
         */
      case Types.DOUBLE:
        {
          String s = result.getString(i);
          if (result.wasNull() || s == null) {
            return null;
          }
          NumberFormat format = NumberFormat.getInstance(locale);
          Number number = format.parse(s);
          return number.doubleValue();
        }
        /**
         * The JDBC type FLOAT is basically equivalent to the JDBC type DOUBLE. We provided both
         * FLOAT and DOUBLE in a possibly misguided attempt at consistency with previous database
         * APIs. FLOAT represents a "double precision" floating point number that supports 15 digits
         * of mantissa.
         *
         * <p>The corresponding SQL type FLOAT is defined in SQL-92. The SQL-92 standard leaves the
         * precision of FLOAT up to the implementation, but in practice all the major databases
         * supporting FLOAT support a mantissa precision of at least 15 digits.
         *
         * <p>The recommended Java mapping for the FLOAT type is as a Java double. However, because
         * of the potential confusion between the double precision SQL FLOAT and the single
         * precision Java float, we recommend that JDBC programmers should normally use the JDBC
         * DOUBLE type in preference to FLOAT.
         */
      case Types.FLOAT:
        {
          String s = result.getString(i);
          if (result.wasNull() || s == null) {
            return null;
          }
          NumberFormat format = NumberFormat.getInstance(locale);
          Number number = format.parse(s);
          return number.doubleValue();
        }
        /**
         * The JDBC type JAVA_OBJECT, added in the JDBC 2.0 core API, makes it easier to use objects
         * in the Java programming language as values in a database. JAVA_OBJECT is simply a type
         * code for an instance of a class defined in the Java programming language that is stored
         * as a database object. The type JAVA_OBJECT is used by a database whose type system has
         * been extended so that it can store Java objects directly. The JAVA_OBJECT value may be
         * stored as a serialized Java object, or it may be stored in some vendor-specific format.
         *
         * <p>The type JAVA_OBJECT is one of the possible values for the column DATA_TYPE in the
         * ResultSet objects returned by various DatabaseMetaData methods, including getTypeInfo,
         * getColumns, and getUDTs. The method getUDTs, part of the new JDBC 2.0 core API, will
         * return information about the Java objects contained in a particular schema when it is
         * given the appropriate parameters. Having this information available facilitates using a
         * Java class as a database type.
         */
      case Types.OTHER:
      case Types.JAVA_OBJECT:
        {
          return result.getObject(i);
        }
        /**
         * The JDBC type REAL represents a "single precision" floating point number that supports
         * seven digits of mantissa.
         *
         * <p>The corresponding SQL type REAL is defined in SQL-92 and is widely, though not
         * universally, supported by the major databases. The SQL-92 standard leaves the precision
         * of REAL up to the implementation, but in practice all the major databases supporting REAL
         * support a mantissa precision of at least seven digits.
         *
         * <p>The recommended Java mapping for the REAL type is as a Java float.
         */
      case Types.REAL:
        {
          String s = result.getString(i);
          if (result.wasNull() || s == null) {
            return null;
          }
          NumberFormat format = NumberFormat.getInstance(locale);
          Number number = format.parse(s);
          return number.doubleValue();
        }
        /**
         * The JDBC type TINYINT represents an 8-bit integer value between 0 and 255 that may be
         * signed or unsigned.
         *
         * <p>The corresponding SQL type, TINYINT, is currently supported by only a subset of the
         * major databases. Portable code may therefore prefer to use the JDBC SMALLINT type, which
         * is widely supported.
         *
         * <p>The recommended Java mapping for the JDBC TINYINT type is as either a Java byte or a
         * Java short. The 8-bit Java byte type represents a signed value from -128 to 127, so it
         * may not always be appropriate for larger TINYINT values, whereas the 16-bit Java short
         * will always be able to hold all TINYINT values.
         */
        /**
         * The JDBC type SMALLINT represents a 16-bit signed integer value between -32768 and 32767.
         *
         * <p>The corresponding SQL type, SMALLINT, is defined in SQL-92 and is supported by all the
         * major databases. The SQL-92 standard leaves the precision of SMALLINT up to the
         * implementation, but in practice, all the major databases support at least 16 bits.
         *
         * <p>The recommended Java mapping for the JDBC SMALLINT type is as a Java short.
         */
        /**
         * The JDBC type INTEGER represents a 32-bit signed integer value ranging between
         * -2147483648 and 2147483647.
         *
         * <p>The corresponding SQL type, INTEGER, is defined in SQL-92 and is widely supported by
         * all the major databases. The SQL-92 standard leaves the precision of INTEGER up to the
         * implementation, but in practice all the major databases support at least 32 bits.
         *
         * <p>The recommended Java mapping for the INTEGER type is as a Java int.
         */
      case Types.TINYINT:
      case Types.SMALLINT:
      case Types.INTEGER:
        {
          try {
            Integer integer = result.getInt(i);
            return result.wasNull() ? null : integer;
          } catch (SQLDataException e) {
            Long l = result.getLong(i);
            return result.wasNull() ? null : l;
          }
        }

      case Types.SQLXML:
        {
          SQLXML xml = result.getSQLXML(i);
          return xml != null ? xml.getString() : null;
        }

      case Types.NULL:
        {
          return null;
        }
        /**
         * The JDBC type DISTINCT field (Types class)>DISTINCT represents the SQL3 type DISTINCT.
         *
         * <p>The standard mapping for a DISTINCT type is to the Java type to which the base type of
         * a DISTINCT object would be mapped. For example, a DISTINCT type based on a CHAR would be
         * mapped to a String object, and a DISTINCT type based on an SQL INTEGER would be mapped to
         * an int.
         *
         * <p>The DISTINCT type may optionally have a custom mapping to a class in the Java
         * programming language. A custom mapping consists of a class that implements the interface
         * SQLData and an entry in a java.util.Map object.
         */
      case Types.DISTINCT:
        {
          logger.warn("JDBC type not implemented: {}", type);
          return null;
        }
        /**
         * The JDBC type STRUCT represents the SQL99 structured type. An SQL structured type, which
         * is defined by a user with a CREATE TYPE statement, consists of one or more attributes.
         * These attributes may be any SQL data type, built-in or user-defined.
         *
         * <p>The standard mapping for the SQL type STRUCT is to a Struct object in the Java
         * programming language. A Struct object contains a value for each attribute of the STRUCT
         * value it represents.
         *
         * <p>A STRUCT value may optionally be custom mapped to a class in the Java programming
         * language, and each attribute in the STRUCT may be mapped to a field in the class. A
         * custom mapping consists of a class that implements the interface SQLData and an entry in
         * a java.util.Map object.
         */
      case Types.STRUCT:
        {
          logger.warn("JDBC type not implemented: {}", type);
          return null;
        }
      case Types.REF:
        {
          logger.warn("JDBC type not implemented: {}", type);
          return null;
        }
      case Types.ROWID:
        {
          logger.warn("JDBC type not implemented: {}", type);
          return null;
        }
      default:
        {
          logger.warn("unknown JDBC type ignored: {}", type);
          return null;
        }
    }
    return null;
  }