Changeset: 21143fb53227 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=21143fb53227
Modified Files:
clients/R/MonetDB.R/DESCRIPTION
clients/R/MonetDB.R/NEWS
clients/R/MonetDB.R/R/dbi.R
clients/R/MonetDB.R/R/mapi.R
clients/R/MonetDB.R/src/mapisplit.c
clients/R/Tests/dbi.R
Branch: default
Log Message:
R Connector: Progress bar, MAPI parser overhaul
diffs (truncated from 487 to 300 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
@@ -1,5 +1,5 @@
Package: MonetDB.R
-Version: 0.9.6
+Version: 0.9.7
Title: Connect MonetDB to R
Authors@R: c(person("Hannes Muehleisen", role = c("aut", "cre"),email =
"[email protected]"),
person("Thomas Lumley", role = "ctb"),
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,3 +1,9 @@
+0.9.7
+- monetdb.read.csv TODO (thanks, Duncan)
+- dbWriteTable encoding checks TODO (thanks, Anthony)
+- deprecated nrows parameter to monetdb.read.csv, not neccessary any more
because of upgrades to MonetDB
+- added query progress bar (counting MAL statements) for MonetDB releases
following Oct2014, enable with options(monetdb.profile=T)
+
0.9.6
- Fixed non-ASCII character handling (thanks, Roman!)
- Fully removed C-based socket code
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
@@ -125,6 +125,15 @@ setMethod("dbConnect", "MonetDBDriver",
message("MonetDB: Switching to single-threaded query execution.")
dbSendQuery(conn, "set optimizer='sequential_pipe'")
}
+
+ # enable profiler, we use a MAL connection for this
+ if (getOption("monetdb.profile", F)) {
+ msocket <- .mapiConnect(host, port, timeout)
+ .mapiAuthenticate(msocket, dbname, user, password, language="mal")
+ .profiler_enable(msocket)
+ .mapiDisconnect(msocket);
+ message("Enabled profiler")
+ }
return(conn)
@@ -222,64 +231,64 @@ setMethod("dbReadTable", "MonetDBConnect
setMethod("dbSendQuery", signature(conn="MonetDBConnection",
statement="character"),
def=function(conn, statement, ..., list=NULL, async=FALSE) {
- if(!is.null(list) || length(list(...))){
- if (length(list(...))) statement <- .bindParameters(statement,
list(...))
- if (!is.null(list)) statement <- .bindParameters(statement, list)
- }
- conn@connenv$exception <- list()
- env <- NULL
- # Auto-convert?
- # statement <- enc2utf8(statement)
- if (getOption("monetdb.debug.query", F)) message("QQ: '",
statement, "'")
- resp <- .mapiParseResponse(.mapiRequest(conn, paste0("s",
statement, "\n;"), async=async))
-
- env <- new.env(parent=emptyenv())
-
- if (resp$type == Q_TABLE) {
- # we have to pass this as an environment to make conn object
available to result for fetching
- env$success = TRUE
- env$conn <- conn
- env$data <- resp$tuples
- resp$tuples <- NULL # clean up
- env$info <- resp
- env$delivered <- 0
- env$query <- statement
- env$open <- TRUE
- }
- if (resp$type == Q_UPDATE || resp$type == Q_CREATE || resp$type ==
MSG_ASYNC_REPLY) {
- env$success = TRUE
- env$conn <- conn
- env$query <- statement
- env$info <- resp
+ if(!is.null(list) || length(list(...))){
+ if (length(list(...))) statement <- .bindParameters(statement, list(...))
+ if (!is.null(list)) statement <- .bindParameters(statement, list)
+ }
+ conn@connenv$exception <- list()
+ env <- NULL
+ if (getOption("monetdb.debug.query", F)) message("QQ: '", statement, "'")
+ # the actual request
+ mresp <- .mapiRequest(conn, paste0("s", statement, "\n;"), async=async)
+ resp <- .mapiParseResponse(mresp)
- }
- if (resp$type == MSG_MESSAGE) {
- env$success = FALSE
- env$conn <- conn
- env$query <- statement
- env$info <- resp
- env$message <- resp$message
- }
-
- if (!env$success) {
- sp <- strsplit(env$message, "!", fixed=T)[[1]]
- # truncate statement to not hide actual error message
- if (nchar(statement) > 100) { statement <-
paste0(substring(statement, 1, 100), "...") }
- if (length(sp) == 3) {
- errno <- sp[[2]]
- errmsg <- sp[[3]]
- conn@connenv$exception <- list(errNum=errno, errMsg=errmsg)
- stop("Unable to execute statement '", statement, "'.\nServer
says '", errmsg, "' [#",
- errno, "].")
- }
- else {
- conn@connenv$exception <- list(errNum=NA, errMsg=env$message)
- stop("Unable to execute statement '", statement, "'.\nServer
says '", env$message, "'.")
- }
- }
-
- return(new("MonetDBResult", env=env))
- })
+ env <- new.env(parent=emptyenv())
+
+ if (resp$type == Q_TABLE) {
+ # we have to pass this as an environment to make conn object available to
result for fetching
+ env$success = TRUE
+ env$conn <- conn
+ env$data <- resp$tuples
+ resp$tuples <- NULL # clean up
+ env$info <- resp
+ env$delivered <- 0
+ env$query <- statement
+ env$open <- TRUE
+ }
+ if (resp$type == Q_UPDATE || resp$type == Q_CREATE || resp$type ==
MSG_ASYNC_REPLY) {
+ env$success = TRUE
+ env$conn <- conn
+ env$query <- statement
+ env$info <- resp
+
+ }
+ if (resp$type == MSG_MESSAGE) {
+ env$success = FALSE
+ env$conn <- conn
+ env$query <- statement
+ env$info <- resp
+ env$message <- resp$message
+ }
+
+ if (!env$success) {
+ sp <- strsplit(env$message, "!", fixed=T)[[1]]
+ # truncate statement to not hide actual error message
+ if (nchar(statement) > 100) { statement <- paste0(substring(statement, 1,
100), "...") }
+ if (length(sp) == 3) {
+ errno <- sp[[2]]
+ errmsg <- sp[[3]]
+ conn@connenv$exception <- list(errNum=errno, errMsg=errmsg)
+ stop("Unable to execute statement '", statement, "'.\nServer says '",
errmsg, "' [#",
+ errno, "].")
+ }
+ else {
+ conn@connenv$exception <- list(errNum=NA, errMsg=env$message)
+ stop("Unable to execute statement '", statement, "'.\nServer says '",
env$message, "'.")
+ }
+ }
+
+ return(new("MonetDBResult", env=env))
+ })
@@ -323,7 +332,7 @@ setMethod("dbWriteTable", "MonetDBConnec
if (length(value[[1]])) {
if (csvdump) {
tmp <- tempfile(fileext = ".csv")
- write.table(value, tmp, sep = ",", quote = TRUE,row.names = FALSE,
col.names = FALSE,na="")
+ write.table(value, tmp, sep = ",", quote = TRUE, row.names = FALSE,
col.names = FALSE,na="")
dbSendQuery(conn, paste0("COPY ",format(nrow(value), scientific=FALSE),"
RECORDS INTO ", qname,
" FROM '", tmp, "' USING DELIMITERS ',','\\n','\"' NULL AS ''"))
file.remove(tmp)
@@ -528,7 +537,7 @@ setMethod("dbFetch", signature(res="Mone
# convert tuple string vector into matrix so we can access a single column
efficiently
# call to a faster C implementation for the annoying task of splitting
everyting into fields
- parts <- .Call("mapiSplit", res@env$data[1:n], as.integer(info$cols),
PACKAGE=C_LIBRARY)
+ parts <- .Call("mapi_split", res@env$data[1:n], as.integer(info$cols),
PACKAGE=C_LIBRARY)
# convert values column by column
for (j in seq.int(info$cols)) {
@@ -610,13 +619,17 @@ setMethod("dbGetInfo", "MonetDBResult",
has.completed=dbHasCompleted(dbObj), is.select=TRUE))
}, valueClass="list")
-# copied from RMonetDB, no java-specific things in here...
-monet.read.csv <- monetdb.read.csv <- function(conn, files, tablename, nrows,
header=TRUE,
+# adapted from RMonetDB, no java-specific things in here...
+monet.read.csv <- monetdb.read.csv <- function(conn, files, tablename,
nrows=NA, header=TRUE,
locked=FALSE, na.strings="",
nrow.check=500, delim=",", newline="\\n", quote="\"", ...){
if (length(na.strings)>1) stop("na.strings must be of length 1")
headers <- lapply(files, read.csv, sep=delim, na.strings=na.strings,
quote=quote, nrows=nrow.check,
...)
+
+ if (!missing(nrows)) {
+ warning("monetdb.read.csv(): nrows parameter is not neccessary any more
and deprecated.")
+ }
if (length(files)>1){
nn <- sapply(headers, ncol)
@@ -631,19 +644,18 @@ monet.read.csv <- monetdb.read.csv <- fu
delimspec <- paste0("USING DELIMITERS '", delim, "','", newline, "','",
quote, "'")
- if(header || !missing(nrows)){
- if (length(nrows)==1) nrows <- rep(nrows, length(files))
+ if(header){
for(i in seq_along(files)) {
thefile <- normalizePath(files[i])
- dbSendUpdate(conn, paste("COPY", format(nrows[i], scientific=FALSE),
"OFFSET 2 RECORDS INTO",
- tablename, "FROM", paste("'", thefile, "'",
sep=""), delimspec, "NULL as", paste("'",
-
na.strings[1], "'", sep=""), if(locked)
"LOCKED"))
+ dbSendUpdate(conn, paste("COPY OFFSET 2 INTO",
+ tablename, "FROM", paste("'", thefile, "'", sep=""), delimspec, "NULL
as", paste("'",
+ na.strings[1], "'", sep=""), if(locked) "LOCKED"))
}
} else {
for(i in seq_along(files)) {
thefile <- normalizePath(files[i])
dbSendUpdate(conn, paste0("COPY INTO ", tablename, " FROM ", paste("'",
thefile, "'", sep=""),
- delimspec, "NULL as ", paste("'",
na.strings[1], "'", sep=""), if(locked) " LOCKED "))
+ delimspec, "NULL as ", paste("'", na.strings[1], "'", sep=""),
if(locked) " LOCKED "))
}
}
dbGetQuery(conn, paste("select count(*) from", tablename))
diff --git a/clients/R/MonetDB.R/R/mapi.R b/clients/R/MonetDB.R/R/mapi.R
--- a/clients/R/MonetDB.R/R/mapi.R
+++ b/clients/R/MonetDB.R/R/mapi.R
@@ -315,7 +315,7 @@ REPLY_SIZE <- 100 # Apparently, -1 me
protocol <- redirect[[1]][1]
if (protocol == "merovingian") {
# retry auth on same connection, we will get a new challenge
- .mapiAuthenticate(con, dbname, user, password, endhashfunc)
+ .mapiAuthenticate(con, dbname, user, password, endhashfunc, language)
}
if (protocol == "monetdb") {
stop("Forwarding to another server (", link, ") not supported.")
@@ -327,8 +327,10 @@ REPLY_SIZE <- 100 # Apparently, -1 me
} else {
if (getOption("monetdb.debug.mapi", F)) message("II: Authentication
successful.")
# setting some server parameters...not sure if this should happen here
- .mapiWrite(con, paste0("Xreply_size ", REPLY_SIZE)); .mapiRead(con)
- .mapiWrite(con, "Xauto_commit 1"); .mapiRead(con)
+ if (language == "sql") {
+ .mapiWrite(con, paste0("Xreply_size ", REPLY_SIZE)); .mapiRead(con)
+ .mapiWrite(con, "Xauto_commit 1"); .mapiRead(con)
+ }
}
}
diff --git a/clients/R/MonetDB.R/src/mapisplit.c
b/clients/R/MonetDB.R/src/mapisplit.c
--- a/clients/R/MonetDB.R/src/mapisplit.c
+++ b/clients/R/MonetDB.R/src/mapisplit.c
@@ -1,36 +1,74 @@
-/*
- * The contents of this file are subject to the MonetDB Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.monetdb.org/Legal/MonetDBLicense
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is the MonetDB Database System.
- *
- * The Initial Developer of the Original Code is CWI.
- * Portions created by CWI are Copyright (C) 1997-July 2008 CWI.
- * Copyright August 2008-2015 MonetDB B.V.
- * All Rights Reserved.
- */
-
-#include <R.h>
-#include <Rdefines.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
+#include <R.h>
+#include <Rdefines.h>
+
typedef enum {
INQUOTES, ESCAPED, INTOKEN, INCRAP
-} chrstate;
+} mapi_line_chrstate;
+
+void mapi_line_split(char* line, char** out, size_t ncols) {
+ int cCol = 0;
+ int tokenStart = 2;
+ int endQuote = 0;
+ int curPos;
+
+ int linelen = strlen(line);
+ mapi_line_chrstate state = INCRAP;
+
+ for (curPos = 2; curPos < linelen - 1; curPos++) {
+ char chr = line[curPos];
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list