~hrbrmstr/sergeant-caffeinated

36383232bec8506b725c680e3bc0b3531fcfc37c — boB Rudis 2 years ago 2bfe549
Better query error messages
M DESCRIPTION => DESCRIPTION +4 -3
@@ 1,6 1,6 @@
Package: sergeant.caffeinated
Title: Tools to Transform and Query Data with 'Apache' 'Drill' ('JDBC')
Version: 0.1.0
Version: 0.2.0
Authors@R: c(
      person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), 
             comment = c(ORCID = "0000-0001-5670-2640"))


@@ 25,9 25,10 @@ Imports:
    RJDBC (>= 0.2-5),
    utils,
    methods,
    magrittr
    magrittr,
    bit64
Suggests:
    rJava (>= 0.9-8),
    testthat (>= 1.0.2),
    covr (>= 3.0.0)
RoxygenNote: 6.0.1.9000
RoxygenNote: 6.1.1

M NAMESPACE => NAMESPACE +1 -0
@@ 18,6 18,7 @@ exportMethods(dbConnect)
exportMethods(dbDataType)
exportMethods(dbSendQuery)
import(DBI)
import(bit64)
import(methods)
import(utils)
importClassesFrom(RJDBC,JDBCConnection)

M R/jdbc.r => R/jdbc.r +8 -7
@@ 84,7 84,7 @@ setMethod(

    }

    .verify.JDBC.result(jc, "Unable to connect JDBC to ",url)
    .verify.JDBC.result(jc, "Unable to connect JDBC to ",url, , conn=NULL)

    new("DrillJDBCConnection", jc=jc, identifier.quote=drv@identifier.quote)



@@ 240,6 240,7 @@ db_data_type.DrillJDBCConnection <- function(con, fields, ...) {
  data_type <- function(x) {
    switch(
      class(x)[1],
      integer64 = "BIGINT",
      logical = "BOOLEAN",
      integer = "INTEGER",
      numeric = "DOUBLE",


@@ 277,23 278,23 @@ setMethod(
    ## if the statement starts with {call or {?= call then we use CallableStatement
    if (isTRUE(as.logical(grepl("^\\{(call|\\?= *call)", statement)))) {
      s <- rJava::.jcall(conn@jc, "Ljava/sql/CallableStatement;", "prepareCall", statement, check=FALSE)
      .verify.JDBC.result(s, "Unable to execute JDBC callable statement ",statement)
      .verify.JDBC.result(s, "Unable to execute JDBC callable statement ",statement, conn=conn)
      if (length(list(...))) .fillStatementParameters(s, list(...))
      if (!is.null(list)) .fillStatementParameters(s, list)
      r <- rJava::.jcall(s, "Ljava/sql/ResultSet;", "executeQuery", check=FALSE)
      .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",statement)
      .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",statement, conn=conn)
    } else if (length(list(...)) || length(list)) { ## use prepared statements if there are additional arguments
      s <- rJava::.jcall(conn@jc, "Ljava/sql/PreparedStatement;", "prepareStatement", statement, check=FALSE)
      .verify.JDBC.result(s, "Unable to execute JDBC prepared statement ", statement)
      .verify.JDBC.result(s, "Unable to execute JDBC prepared statement ", statement, conn=conn)
      if (length(list(...))) .fillStatementParameters(s, list(...))
      if (!is.null(list)) .fillStatementParameters(s, list)
      r <- rJava::.jcall(s, "Ljava/sql/ResultSet;", "executeQuery", check=FALSE)
      .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",statement)
      .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",statement, conn=conn)
    } else { ## otherwise use a simple statement some DBs fail with the above)
      s <- rJava::.jcall(conn@jc, "Ljava/sql/Statement;", "createStatement")
      .verify.JDBC.result(s, "Unable to create simple JDBC statement ",statement)
      .verify.JDBC.result(s, "Unable to create simple JDBC statement ",statement, conn=conn)
      r <- rJava::.jcall(s, "Ljava/sql/ResultSet;", "executeQuery", as.character(statement)[1], check=FALSE)
      .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",statement)
      .verify.JDBC.result(r, "Unable to retrieve JDBC result set for ",statement, conn=conn)
    }
    md <- rJava::.jcall(r, "Ljava/sql/ResultSetMetaData;", "getMetaData", check=FALSE)
    .verify.JDBC.result(md, "Unable to retrieve JDBC result set meta data for ",statement, " in dbSendQuery")

M R/sergeant-caffeinated-package.R => R/sergeant-caffeinated-package.R +2 -3
@@ 30,14 30,13 @@
#' @references \href{https://drill.apache.org/docs/}{Drill documentation}
#' @docType package
#' @author Bob Rudis (bob@@rud.is)
#' @importFrom scales comma
#' @importFrom dplyr mutate select left_join bind_cols bind_rows data_frame tbl filter
#' @importFrom dplyr db_desc src db_data_type db_explain sql_translate_env copy_to %>%
#' @importFrom dplyr db_query_fields src_tbls sql_escape_ident
#' @importFrom dbplyr build_sql sql_prefix sql_quote src_sql tbl_sql
#' @importFrom dbplyr win_recycled win_current_group base_win base_agg base_scalar win_over sql
#' @import utils
#' @import DBI methods
#' @importFrom scales comma
#' @import utils DBI methods bit64
#' @importClassesFrom RJDBC JDBCDriver JDBCConnection JDBCResult
NULL


M R/utils.r => R/utils.r +45 -4
@@ 1,11 1,52 @@
.verify.JDBC.result <- function (result, ...) {
.verify.JDBC.result <- function(result, ..., conn=NULL) {

  if (rJava::is.jnull(result)) {

    x <- rJava::.jgetEx(TRUE)
    if (rJava::is.jnull(x))

    if (rJava::is.jnull(x)) {
      stop(...)
    else
      stop(...," (",rJava::.jcall(x, "S", "getMessage"),")")
    } else if (is.null(conn)) {
      stop(...)
    } else {

      jr <- unlist(rJava::.jcall(x, "S", "getMessage"))

      resp <- unlist(list(...))

      jdbc_err <- resp[1]
      oq <- resp[2]

      resp <- unlist(strsplit(jr, "\n"))

      err <- resp[grepl("Error Id", resp)]

      resp <- resp[resp != ""]
      resp <- resp[!grepl("Error Id", resp)]

      err <- sub("^.*: ", "", err)
      err <- unlist(strsplit(err, "[[:space:]]+"))[1]

      oq <- unlist(strsplit(oq, "\n"))

      c(
        sprintf("%s:\n", jdbc_err),
        sprintf("%3d: %s", 1:length(oq), oq),
        " ",
        resp,
        sprintf(
          "\nQuery Profile Error Id: %s", err
        )
      ) -> resp

      resp <- paste0(resp, collapse="\n")

      stop(resp, call.=FALSE)

    }

  }

}



M man/dbConnect-DrillJDBCDriver-method.Rd => man/dbConnect-DrillJDBCDriver-method.Rd +2 -2
@@ 5,8 5,8 @@
\alias{dbConnect,DrillJDBCDriver-method}
\title{Connect to Drill JDBC with your own connection string}
\usage{
\S4method{dbConnect}{DrillJDBCDriver}(drv, url, user = "", password = "",
  ...)
\S4method{dbConnect}{DrillJDBCDriver}(drv, url, user = "",
  password = "", ...)
}
\arguments{
\item{drv}{what you get back from \code{\link[=DrillJDBC]{DrillJDBC()}}}

M man/drill_jdbc.Rd => man/drill_jdbc.Rd +4 -4
@@ 6,11 6,11 @@
\alias{tbl.src_drill_jdbc}
\title{Connect to Drill using JDBC}
\usage{
drill_jdbc(nodes = "localhost:2181", cluster_id = NULL, schema = NULL,
  use_zk = TRUE)
drill_jdbc(nodes = "localhost:2181", cluster_id = NULL,
  schema = NULL, use_zk = TRUE)

src_drill_jdbc(nodes = "localhost:2181", cluster_id = NULL, schema = NULL,
  use_zk = TRUE)
src_drill_jdbc(nodes = "localhost:2181", cluster_id = NULL,
  schema = NULL, use_zk = TRUE)

\method{tbl}{src_drill_jdbc}(src, from, ...)
}