Changeset: e9939515dd04 for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=e9939515dd04 Added Files: clients/R/MonetDB.R/R/dbapply.R clients/R/Tests/dbapply.R clients/R/Tests/dbapply.stable.err clients/R/Tests/dbapply.stable.out Modified Files: clients/R/MonetDB.R/DESCRIPTION clients/R/MonetDB.R/NAMESPACE clients/R/MonetDB.R/NEWS clients/R/Tests/All Branch: default Log Message:
R Connector: Autmatic code shipping diffs (272 lines): diff --git a/clients/R/MonetDB.R/DESCRIPTION b/clients/R/MonetDB.R/DESCRIPTION --- a/clients/R/MonetDB.R/DESCRIPTION +++ b/clients/R/MonetDB.R/DESCRIPTION @@ -12,3 +12,4 @@ Description: Allows to pull data from Mo License: MPL (== 1.1) URL: http://monetr.r-forge.r-project.org SystemRequirements: MonetDB, available from http://www.monetdb.org +Collate: mapi.R dbi.R dbapply.R dplyr.R control.R \ No newline at end of file diff --git a/clients/R/MonetDB.R/NAMESPACE b/clients/R/MonetDB.R/NAMESPACE --- a/clients/R/MonetDB.R/NAMESPACE +++ b/clients/R/MonetDB.R/NAMESPACE @@ -1,10 +1,10 @@ -import(DBI,digest,methods) +import(DBI,digest,methods,codetools) # export only driver constructor, everything else is DBI stuff.. export(MonetDB,MonetR,MonetDBR,MonetDB.R) export(monet.read.csv,monetdb.read.csv) # this one is not in the DBI -exportMethods(dbSendUpdate,dbSendUpdateAsync,dbTransaction) +exportMethods(dbSendUpdate,dbSendUpdateAsync,dbTransaction,dbApply) # shorthands export(mc,mq) useDynLib(MonetDB.R) diff --git a/clients/R/MonetDB.R/NEWS b/clients/R/MonetDB.R/NEWS --- a/clients/R/MonetDB.R/NEWS +++ b/clients/R/MonetDB.R/NEWS @@ -1,5 +1,6 @@ 0.9.9 - dbWriteTable now quotes table/column names if necessary, and outputs warnings if it did +- New dbApply function to automatically create embedded R functions in MonetDB 0.9.8 - Added support for esoteric data types such as MONTH_INTERVAL (Thanks, Roman) diff --git a/clients/R/MonetDB.R/R/dbapply.R b/clients/R/MonetDB.R/R/dbapply.R new file mode 100644 --- /dev/null +++ b/clients/R/MonetDB.R/R/dbapply.R @@ -0,0 +1,66 @@ +.encodeGlobals <- function(name) { + vars <- findGlobals(name,merge=F)$variables + if (length(vars) < 1) { + return(NA) + } + if (getOption("monetdb.debug.query",FALSE)) + message("Variable(s) ",paste0(vars,collapse=", ")) + + # TODO: optionally inline serialized context for remote dbs + res <- tempfile() + save(list=vars,file=res,envir=environment(name),compress=T) + return(res) +} + +if (is.null(getGeneric("dbApply"))) setGeneric("dbApply", function(conn, ...) + standardGeneric("dbApply")) + +setMethod("dbApply", signature(conn="MonetDBConnection"), def=function(conn, table, rettype, fun) { + # generate unique function name + dbfunname <- "__r_dapply_autogen_" + while (dbGetQuery(conn,paste0("select count(*) from functions where name='",dbfunname,"'"))[[1]] > 0) + dbfunname <- paste0(dbfunname,sample(letters,1)) + + # test R integration with dummy function + dbBegin(conn) + dbSendQuery(conn,paste0("CREATE FUNCTION ",dbfunname,"() RETURNS TABLE(d INTEGER) LANGUAGE R {1L}")) + res <- dbGetQuery(conn,paste0("SELECT * FROM ",dbfunname,"()"))[[1]] + dbRollback(conn) + + # now generate the UDF + # find packages loaded here and load them on the server as well + toloadpkgs <- setdiff(unique(sapply(strsplit(grep("^package:",search(),value=T),":"),function(x) x[[2]])),c("base","stats","methods","utils","codetools","graphics","grDevices","datasets")) + dbrcode <- '' + if (length(toloadpkgs) > 0) { + if (getOption("monetdb.debug.query",FALSE)) + message("Package(s) ",paste0(toloadpkgs,collapse=", ")) + dbrcode <- paste0('# loading packages\ninvisible(lapply(setdiff(', + paste0(deparse(toloadpkgs),collapse=""), + ',unique(sapply(strsplit(grep("^package:", search(), value=T),":"), function(x) x[[2]]))), function(pname) library(pname, character.only=T, quietly=T)))\n') + } + # serialize global variables into ascii string, and add the code to scan it again into the current env + sfilename <- .encodeGlobals(fun) + if (!is.na(sfilename)) { + dbrcode <- paste0(dbrcode,'# load serialized global variables\nload("',sfilename,'")\n') + } + # get source of user function and append + dbrcode <- paste0(dbrcode,"# user-supplied function\n.userfun <- ",paste0(deparse(fun),collapse="\n"),"\n# calling user function\nreturn(.userfun(.dbdata))\n") + + # find out things about the table, then wrap the r function + res <- dbSendQuery(conn,paste0("SELECT * FROM ",table," LIMIT 1")) + dbnames <- res@env$info$names + dbtypes <- res@env$info$dbtypes + dbfun <- paste0("CREATE FUNCTION ",dbfunname,"(",paste0(dbnames," ", dbtypes, collapse=", "), + ") \nRETURNS TABLE(retval ",rettype,") LANGUAGE R {\n# rename arguments\n.dbdata <- data.frame(", + paste0(dbnames, collapse=", "),")\n",dbrcode,"};\n") + # call the function we just created + dbsel <- paste0("SELECT * FROM ", dbfunname, "( (SELECT * FROM ", table, " AS t) );\n") + # ok, talk to DB (EZ) + dbBegin(conn) + dbSendQuery(conn,dbfun) + res <- dbGetQuery(conn,dbsel) + dbRollback(conn) + return(res[,1]) +}) + + diff --git a/clients/R/Tests/All b/clients/R/Tests/All --- a/clients/R/Tests/All +++ b/clients/R/Tests/All @@ -2,5 +2,6 @@ HAVE_LIBR?install HAVE_LIBR?dbi HAVE_LIBR?survey HAVE_LIBR?dplyr +HAVE_LIBR?dbapply diff --git a/clients/R/Tests/dbapply.R b/clients/R/Tests/dbapply.R new file mode 100644 --- /dev/null +++ b/clients/R/Tests/dbapply.R @@ -0,0 +1,58 @@ +ll <- NULL +if (Sys.getenv("TSTTRGDIR") != "") { + ll <- paste0(Sys.getenv("TSTTRGDIR"),"/rlibdir") +} +library(MonetDB.R,quietly=T,lib.loc=ll) + +args <- commandArgs(trailingOnly = TRUE) +dbport <- 50000 +dbname <- "mTests_clients_R" +if (length(args) > 0) + dbport <- args[[1]] +if (length(args) > 1) + dbname <- args[[2]] + +options(monetdb.insert.splitsize=10) +options(monetdb.profile=F) + + +tname <- "monetdbtest" + +con <- dbConnect(MonetDB(), port=dbport, dbname=dbname, wait=T) +stopifnot(dbIsValid(con)) + +# make sure embedded R is working in general +dbBegin(con) +dbSendQuery(con, "CREATE FUNCTION fuuu() RETURNS TABLE(i INTEGER) LANGUAGE R {42L}") +res <- dbGetQuery(con, "SELECT * FROM fuuu();") +print(res$i[[1]]) +stopifnot(identical(42L, res$i[[1]])) +dbRollback(con) + +data(mtcars) +dbWriteTable(con,tname,mtcars, overwrite=T) +stopifnot(identical(TRUE, dbExistsTable(con,tname))) + +res <- dbApply(con, tname, "double", function(d) { + d$mpg +}) +stopifnot(identical(res, mtcars$mpg)) + +res <- dbApply(con, tname, "double", function(d) { + min(d$mpg) +}) +stopifnot(identical(res, min(mtcars$mpg))) + +# model fitting / in-db application +fitted <- lm(mpg~.,data=mtcars) +predictions <- dbApply(con,tname,"double",function(d) { + predict(fitted, newdata=d) +}) +stopifnot(identical(unname(predict(fitted, newdata=mtcars)), predictions)) + +dbRemoveTable(con,tname) +stopifnot(identical(FALSE, dbExistsTable(con,tname))) + + + +print("SUCCESS") diff --git a/clients/R/Tests/dbapply.stable.err b/clients/R/Tests/dbapply.stable.err new file mode 100644 --- /dev/null +++ b/clients/R/Tests/dbapply.stable.err @@ -0,0 +1,37 @@ +stderr of test 'dbapply` in directory 'clients/R` itself: + + +# 11:43:10 > +# 11:43:10 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "mapi_open=true" "--set" "mapi_port=35780" "--set" "mapi_usock=/var/tmp/mtest-66645/.s.monetdb.35780" "--set" "monet_prompt=" "--forcemito" "--set" "mal_listing=2" "--dbpath=/Users/hannes/monetdb-install/var/MonetDB/mTests_clients_R" "--set" "mal_listing=0" "--set" "embedded_r=yes" +# 11:43:10 > + +# builtin opt gdk_dbpath = /Users/hannes/monetdb-install/var/monetdb5/dbfarm/demo +# builtin opt gdk_debug = 0 +# builtin opt gdk_vmtrim = no +# builtin opt monet_prompt = > +# builtin opt monet_daemon = no +# builtin opt mapi_port = 50000 +# builtin opt mapi_open = false +# builtin opt mapi_autosense = false +# builtin opt sql_optimizer = default_pipe +# builtin opt sql_debug = 0 +# cmdline opt gdk_nr_threads = 0 +# cmdline opt mapi_open = true +# cmdline opt mapi_port = 35780 +# cmdline opt mapi_usock = /var/tmp/mtest-66645/.s.monetdb.35780 +# cmdline opt monet_prompt = +# cmdline opt mal_listing = 2 +# cmdline opt gdk_dbpath = /Users/hannes/monetdb-install/var/MonetDB/mTests_clients_R +# cmdline opt mal_listing = 0 +# cmdline opt embedded_r = yes +# cmdline opt gdk_debug = 536870922 + +# 11:43:14 > +# 11:43:14 > "R" "--vanilla" "--slave" "--args" "35780" +# 11:43:14 > + + +# 11:43:21 > +# 11:43:21 > "Done." +# 11:43:21 > + diff --git a/clients/R/Tests/dbapply.stable.out b/clients/R/Tests/dbapply.stable.out new file mode 100644 --- /dev/null +++ b/clients/R/Tests/dbapply.stable.out @@ -0,0 +1,46 @@ +stdout of test 'dbapply` in directory 'clients/R` itself: + + +# 11:43:10 > +# 11:43:10 > "mserver5" "--debug=10" "--set" "gdk_nr_threads=0" "--set" "mapi_open=true" "--set" "mapi_port=35780" "--set" "mapi_usock=/var/tmp/mtest-66645/.s.monetdb.35780" "--set" "monet_prompt=" "--forcemito" "--set" "mal_listing=2" "--dbpath=/Users/hannes/monetdb-install/var/MonetDB/mTests_clients_R" "--set" "mal_listing=0" "--set" "embedded_r=yes" +# 11:43:10 > + +# MonetDB 5 server v11.22.0 +# This is an unreleased version +# Serving database 'mTests_clients_R', using 4 threads +# Compiled for x86_64-apple-darwin14.3.0/64bit with 64bit OIDs and 128bit integers dynamically linked +# Found 16.000 GiB available main-memory. +# Copyright (c) 1993-July 2008 CWI. +# Copyright (c) August 2008-2015 MonetDB B.V., all rights reserved +# Visit http://www.monetdb.org/ for further information +# Listening for connection requests on mapi:monetdb://dakar.da.cwi.nl.hhk.dk:35780/ +# Listening for UNIX domain connection requests on mapi:monetdb:///var/tmp/mtest-66645/.s.monetdb.35780 +# MonetDB/GIS module loaded +# Start processing logs sql/sql_logs version 52200 +# Start reading the write-ahead log 'sql_logs/sql/log.5' +# Finished reading the write-ahead log 'sql_logs/sql/log.5' +# Finished processing logs sql/sql_logs +# MonetDB/SQL module loaded +# MonetDB/R module loaded + +Ready. + +# 11:43:14 > +# 11:43:14 > "R" "--vanilla" "--slave" "--args" "35780" +# 11:43:14 > + +[1] TRUE +An object of class "MonetDBResult" +Slot "env": +<environment: 0x7fa0e4a984e8> + +[1] 42 +[1] TRUE +[1] TRUE +[1] TRUE +[1] "SUCCESS" + +# 11:43:21 > +# 11:43:21 > "Done." +# 11:43:21 > + _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list