Changeset: e49aa2d54dde for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=e49aa2d54dde
Added Files:
        monetdb5/extras/rapi/converters.c
        tools/embedded/rpackage/tests/testthat/test_dbi.R
Removed Files:
        monetdb5/extras/rapi/converters.h
Modified Files:
        clients/R/MonetDB.R/R/dbi.R
        monetdb5/extras/rapi/rapi.c
        tools/embedded/embedded.c
Branch: embedded
Log Message:

DBI test cases for embedded branch. All passing.


diffs (truncated from 386 to 300 lines):

diff --git a/clients/R/MonetDB.R/R/dbi.R b/clients/R/MonetDB.R/R/dbi.R
--- a/clients/R/MonetDB.R/R/dbi.R
+++ b/clients/R/MonetDB.R/R/dbi.R
@@ -92,7 +92,9 @@ setMethod("dbConnect", "MonetDBDriver", 
       stop("MonetDB package required for embedded mode")
     }
     monetdb_embedded_startup(embedded, !getOption("monetdb.debug.embedded", 
FALSE))
-    return(new("MonetDBEmbeddedConnection"))
+    connenv <- new.env(parent=emptyenv())
+    connenv$open <- TRUE
+    return(new("MonetDBEmbeddedConnection", connenv=connenv))
   }
   
   if (getOption("monetdb.debug.mapi", F)) message("II: Connecting to MonetDB 
on host ", host, " at "
@@ -135,7 +137,7 @@ setMethod("dbConnect", "MonetDBDriver", 
   }
 
   # if (getOption("monetdb.profile", T)) .profiler_enable(conn)
-  return(conn)
+  conn
 }, 
 valueClass="MonetDBConnection")
 
@@ -144,7 +146,7 @@ valueClass="MonetDBConnection")
 setClass("MonetDBConnection", representation("DBIConnection", socket="ANY", 
                                              connenv="environment"))
 
-setClass("MonetDBEmbeddedConnection", representation("MonetDBConnection"))
+setClass("MonetDBEmbeddedConnection", representation("MonetDBConnection", 
connenv="environment"))
 
 
 setMethod("dbGetInfo", "MonetDBConnection", def=function(dbObj, ...) {
@@ -152,7 +154,7 @@ setMethod("dbGetInfo", "MonetDBConnectio
   ll <- as.list(envdata$value)
   names(ll) <- envdata$name
   ll$name <- "MonetDBConnection"
-  return(ll)
+  ll
 })
 
 setMethod("dbIsValid", "MonetDBConnection", def=function(dbObj, ...) {
@@ -161,7 +163,12 @@ setMethod("dbIsValid", "MonetDBConnectio
 
 setMethod("dbDisconnect", "MonetDBConnection", def=function(conn, ...) {
   .mapiDisconnect(conn@socket)
-  return(invisible(TRUE))
+  invisible(TRUE)
+})
+
+setMethod("dbDisconnect", "MonetDBEmbeddedConnection", def=function(conn, ...) 
{
+  conn@connenv$open <- FALSE
+  invisible(TRUE)
 })
 
 setMethod("dbListTables", "MonetDBConnection", def=function(conn, ..., 
sys_tables=F, schema_names=F) {
@@ -174,7 +181,7 @@ setMethod("dbListTables", "MonetDBConnec
     df$sn <- quoteIfNeeded(conn, df$sn, warn=F)
     res <- paste0(df$sn, ".", df$tn)
   }
-  return(as.character(res))
+  as.character(res)
 })
 
 if (is.null(getGeneric("dbTransaction"))) setGeneric("dbTransaction", 
function(conn, ...) 
@@ -296,6 +303,9 @@ setMethod("dbSendQuery", signature(conn=
 # This one does all the work in this class
 setMethod("dbSendQuery", signature(conn="MonetDBEmbeddedConnection", 
statement="character"),  
           def=function(conn, statement, ..., list=NULL) {   
+  if (!conn@connenv$open) {
+    stop("This connection was closed.")
+  }
   if(!is.null(list) || length(list(...))){
     if (length(list(...))) statement <- .bindParameters(statement, list(...))
     if (!is.null(list)) statement <- .bindParameters(statement, list)
@@ -313,14 +323,13 @@ setMethod("dbSendQuery", signature(conn=
   if (resp$type == Q_TABLE) {
     meta <- new.env(parent=emptyenv())
     meta$type  <- Q_TABLE
-    meta$id    <- 42
+    meta$id    <- -1
     meta$rows  <- NROW(resp$tuples)
     meta$cols  <- NCOL(resp$tuples)
     meta$index <- 0
     meta$names <- names(resp$tuples)
 
     env$info <- meta
-
     env$success = TRUE
     env$conn <- conn
     env$resp <- resp
@@ -381,10 +390,6 @@ quoteIfNeeded <- function(conn, x, warn=
   x
 }
 
-# # overload as per DBI documentation
-# setMethod("dbQuoteIdentifier", c("MonetDBConnection", "SQL"), function(conn, 
x, ...) {x})
-
-# adapted from RMonetDB, very useful...
 setMethod("dbWriteTable", "MonetDBConnection", def=function(conn, name, value, 
overwrite=FALSE, 
   append=FALSE, csvdump=FALSE, transaction=TRUE,...) {
   if (is.vector(value) && !is.list(value)) value <- data.frame(x=value)
@@ -413,6 +418,8 @@ setMethod("dbWriteTable", "MonetDBConnec
     dbSendUpdate(conn, ct)
   }
   if (length(value[[1]])) {
+    # TODO: special handling for embedded mode
+
     if (csvdump) {
       tmp <- tempfile(fileext = ".csv")
       write.table(value, tmp, sep = ",", quote = TRUE, row.names = FALSE, 
col.names = FALSE,na="")
@@ -673,19 +680,13 @@ setMethod("dbFetch", signature(res="Mone
   if (!dbIsValid(res)) {
     stop("Cannot fetch results from closed response.")
   }
-
   if (n > -1) {
-    stop("Cannot do partial fetch")
+    stop("No partial fetch, entire result already available")
   }
   res@env$delivered <- res@env$info$rows
   res@env$resp$tuples
 })
 
-setMethod("dbClearResult", "MonetDBEmbeddedResult", def = function(res, ...) {
-  # no need to do anything here
-  return(invisible(TRUE))
-}, valueClass = "logical")
-
 setMethod("dbClearResult", "MonetDBResult", def = function(res, ...) {
   if (res@env$info$type == Q_TABLE) {
     resid <- res@env$info$id
@@ -697,6 +698,13 @@ setMethod("dbClearResult", "MonetDBResul
   return(invisible(TRUE))
 }, valueClass = "logical")
 
+setMethod("dbClearResult", "MonetDBEmbeddedResult", def = function(res, ...) {
+  if (res@env$info$type == Q_TABLE) {
+    res@env$open <- FALSE
+  }
+  return(invisible(TRUE))
+}, valueClass = "logical")
+
 setMethod("dbHasCompleted", "MonetDBResult", def = function(res, ...) {
   if (res@env$info$type == Q_TABLE) {
     return(res@env$delivered == res@env$info$rows)
@@ -712,12 +720,19 @@ setMethod("dbIsValid", signature(dbObj="
 })
 
 setMethod("dbColumnInfo", "MonetDBResult", def = function(res, ...) {
-  return(data.frame(field.name=res@env$info$names, 
field.type=res@env$info$types, 
+  data.frame(field.name=res@env$info$names, field.type=res@env$info$types, 
                     data.type=monetTypes[res@env$info$types], 
r.data.type=monetTypes[res@env$info$types], 
-                    monetdb.data.type=res@env$info$types))     
+                    monetdb.data.type=res@env$info$types, stringsAsFactors=F)  
 }, 
 valueClass = "data.frame")
 
+setMethod("dbColumnInfo", "MonetDBEmbeddedResult", def = function(res, ...) {
+  data.frame(field.name=res@env$info$names, stringsAsFactors=F)  
+  # TODO: also export SQL types? Do we need this?
+}, 
+valueClass = "data.frame")
+
+
 setMethod("dbGetInfo", "MonetDBResult", def=function(dbObj, ...) {
   return(list(statement=dbObj@env$query, rows.affected=0, 
row.count=dbObj@env$info$rows, 
               has.completed=dbHasCompleted(dbObj), is.select=TRUE))    
diff --git a/monetdb5/extras/rapi/converters.h 
b/monetdb5/extras/rapi/converters.c
rename from monetdb5/extras/rapi/converters.h
rename to monetdb5/extras/rapi/converters.c
diff --git a/monetdb5/extras/rapi/rapi.c b/monetdb5/extras/rapi/rapi.c
--- a/monetdb5/extras/rapi/rapi.c
+++ b/monetdb5/extras/rapi/rapi.c
@@ -37,7 +37,8 @@
 
 //#define _RAPI_DEBUG_
 
-#include "converters.h"
+/* we need the BAT-SEXP-BAT conversion in two places, here and in 
tools/embedded */
+#include "converters.c"
 
 const char* rapi_enableflag = "embedded_r";
 
diff --git a/tools/embedded/embedded.c b/tools/embedded/embedded.c
--- a/tools/embedded/embedded.c
+++ b/tools/embedded/embedded.c
@@ -211,7 +211,8 @@ void monetdb_cleanup_result(void* output
        (*res_table_destroy_ptr)((res_table*) output);
 }
 
-#include "converters.h"
+/* we need the BAT-SEXP-BAT conversion in two places, here and in RAPI */
+#include "converters.c"
 
 SEXP monetdb_query_R(SEXP query) {
        res_table* output = NULL;
diff --git a/tools/embedded/rpackage/tests/testthat/test_dbi.R 
b/tools/embedded/rpackage/tests/testthat/test_dbi.R
new file mode 100644
--- /dev/null
+++ b/tools/embedded/rpackage/tests/testthat/test_dbi.R
@@ -0,0 +1,185 @@
+library(testthat)
+library(MonetDB)
+library(MonetDB.R)
+
+tname <- "monetdbtest"
+data(iris)
+tsize <- function(conn, tname) 
+       as.integer(dbGetQuery(conn, paste0("SELECT COUNT(*) FROM ",tname))[[1]])
+
+test_that("db starts up and accepts queries", {
+       con <<- dbConnect(MonetDB.R::MonetDB.R(), embedded=tempdir())
+       expect_is(con, "MonetDBEmbeddedConnection")
+       expect_true(dbIsValid(con))
+       res <- dbGetQuery(con, "SELECT 42")
+       expect_equal(res$single_value, 42)
+       expect_is(res, "data.frame")
+})
+
+test_that("raw sql handling", {
+       dbSendUpdate(con, "CREATE TABLE monetdbtest (a varchar(10),b integer,c 
blob)")
+       expect_equal(dbExistsTable(con, tname), TRUE)
+       dbSendUpdate(con, "INSERT INTO monetdbtest VALUES ('one',1,'1111')")
+       dbSendUpdate(con, "INSERT INTO monetdbtest VALUES ('two',2,'22222222')")
+       expect_equal(dbGetQuery(con,"SELECT count(*) FROM monetdbtest")[[1]], 2)
+       #expect_equal(dbReadTable(con, "monetdbtest")[[3]], 
list(charToRaw("1111"), charToRaw("22222222")))
+       # why does this not work?
+       dbRemoveTable(con, tname)
+       expect_false(dbExistsTable(con, tname))
+})
+
+test_that("import export", {
+       data(iris)
+       dbWriteTable(con, tname, iris)
+
+       expect_true(dbExistsTable(con, tname))
+       expect_false(dbExistsTable(con, "monetdbtest2"))
+
+       expect_true(tname %in% dbListTables(con))
+       expect_equal(dbListFields(con, tname), names(iris))
+
+       iris2 <- dbReadTable(con, tname)
+       expect_equal(dim(iris), dim(iris2))
+
+       res <- dbSendQuery(con, "SELECT \"Species\", \"Sepal.Width\" FROM 
monetdbtest")
+       expect_true(dbIsValid(res))
+       expect_is(res, "MonetDBEmbeddedResult")
+       expect_true(res@env$success)
+       expect_equal(dbColumnInfo(res)[[1,1]], "Species")
+       expect_equal(dbColumnInfo(res)[[2,1]], "Sepal.Width")
+       expect_equal(dbGetInfo(res)$row.count, 150)
+       expect_equal(res@env$info$rows, 150)
+       expect_error(dbFetch(res,10))
+
+       data2 <- dbFetch(res,-1)
+       expect_equal(dim(data2)[[1]], 150)
+       expect_true(dbHasCompleted(res))
+       expect_true(dbIsValid(res))
+       dbClearResult(res)
+       expect_false(dbIsValid(res))
+
+       dbRemoveTable(con, tname)
+       expect_false(dbExistsTable(con, tname))
+       expect_error(dbFetch(res))
+})
+
+test_that("csv import", {
+       tf <- tempfile()
+       on.exit(unlink(tf))
+
+       write.table(iris, tf, sep=",", row.names=FALSE)
+       tname2 <- "Need to quote this table name"
+       monetdb.read.csv(con, tf, tname)
+       monetdb.read.csv(con, tf, tname2)
+       expect_true(dbExistsTable(con, tname))
+       expect_true(dbExistsTable(con,tname2))
+
+       iris3 <- dbReadTable(con, tname)
+       iris4 <- dbReadTable(con, tname2)
+       expect_equal(dim(iris), dim(iris3))
+       expect_equal(dim(iris), dim(iris4))
+       expect_equal(dbListFields(con,tname), names(iris))
+       expect_equal(dbListFields(con,tname2), names(iris)) 
+
+       dbRemoveTable(con, tname)
+       dbRemoveTable(con, tname2)
+       expect_false(dbExistsTable(con, tname))
+       expect_false(dbExistsTable(con, tname2))
+})
+
+test_that("write table with complications", {
+       # make sure table is gone before we start
+       if (dbExistsTable(con,tname))
+               dbRemoveTable(con,tname)
+
+       # table does not exist, append=F, overwrite=F, this should work
+       dbWriteTable(con, tname, mtcars, append=F, overwrite=F)
+       expect_true(dbExistsTable(con, tname))
+       expect_equal(nrow(mtcars), tsize(con, tname))
+
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to