Changeset: 1d9f1593a744 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=1d9f1593a744
Modified Files:
        clients/R/MonetDB.R/NEWS
        clients/R/MonetDB.R/R/mapi.R
        clients/R/Tests/dbi.R
Branch: Oct2014
Log Message:

R Connector: Fix for non-ASCII strings


diffs (97 lines):

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,6 @@
+0.9.6
+- Fixed non-ASCII character handling (thanks, Roman!)
+
 0.9.5
 - Removed package date (Thanks, Dimitar)
 - Added sys. schema name to internal queries, so SET SCHEMA xx would not break 
things (Thanks again, Dimitar)
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
@@ -117,7 +117,7 @@ REPLY_SIZE    <- 100 # Apparently, -1 me
     if (getOption("monetdb.debug.mapi", F)) {
       dstr <- respstr
       if (nchar(dstr) > 300) {
-        dstr <- paste0(substring(dstr, 1, 200), "...", substring(dstr, 
nchar(dstr)-100, nchar(dstr))) 
+        dstr <- paste0(substring(dstr, 1, 200), "...", substring(dstr, 
nchar(dstr) -100, nchar(dstr))) 
       } 
       message("RX: '", dstr, "'")
     }
@@ -128,21 +128,22 @@ REPLY_SIZE    <- 100 # Apparently, -1 me
       stop("I can only be called with a MonetDB connection object as 
parameter.")
     resp <- list()
     repeat {
-      unpacked <- 
readBin(con,"integer",n=1,size=2,signed=FALSE,endian="little")
+      unpacked <- readBin(con, "integer", n=1, size=2, signed=FALSE, 
endian="little")
       
       if (length(unpacked) == 0) {
         stop("Empty response from MonetDB server, probably a timeout. You can 
increase the time to wait for responses with the 'timeout' parameter to 
'dbConnect()'.")
       }
-      
-      length <- bitwShiftR(unpacked,1)
-      final  <- bitwAnd(unpacked,1)
+
+      length <- bitwShiftR(unpacked, 1)
+      final  <- bitwAnd(unpacked, 1)
           
       if (length == 0) break
-      resp <- c(resp,readChar(con, length, useBytes = TRUE))    
+      # no raw handling here (see .mapiWrite), since server tells us the 
length in bytes already
+      resp <- c(resp, readChar(con, length, useBytes = TRUE))    
       if (final == 1) break
     }
-    if (getOption("monetdb.debug.mapi", F)) cat(paste("RX: 
'",substring(paste0(resp,collapse=""),1,200),"'\n",sep=""))
-    return(paste0("",resp,collapse=""))
+    if (getOption("monetdb.debug.mapi", F)) cat(paste("RX: '", 
substring(paste0(resp, collapse=""), 1, 200), "'\n", sep=""))
+    return(paste0("", resp, collapse=""))
   }
 }
 
@@ -161,15 +162,18 @@ REPLY_SIZE    <- 100 # Apparently, -1 me
       stop("I can only be called with a MonetDB connection object as 
parameter.")
     final <- FALSE
     pos <- 0
-    if (getOption("monetdb.debug.mapi", F))  message("TX: '",msg,"'\n",sep="")
-    while (!final) {    
-      req <- substring(msg,pos+1,min(MAX_PACKET_SIZE, nchar(msg))+pos)
-      bytes <- nchar(req)
+    if (getOption("monetdb.debug.mapi", F))  message("TX: '", msg, "'\n", 
sep="")
+    # convert to raw byte array, otherwise multibyte characters are 'difficult'
+    msgr <- charToRaw(msg)
+    msglen <- length(msgr)
+    while (!final) {
+      reqr <- msgr[pos+1 : min(MAX_PACKET_SIZE, msglen) + pos]
+      bytes <- length(reqr)
       pos <- pos + bytes
-      final <- max(nchar(msg) - pos,0) == 0            
-      header <- as.integer(bitwOr(bitwShiftL(bytes,1),as.numeric(final)))
-      writeBin(header, con, 2,endian="little")
-      writeChar(req,con,bytes,useBytes=TRUE,eos=NULL)
+      final <- max(msglen - pos, 0) == 0            
+      header <- as.integer(bitwOr(bitwShiftL(bytes, 1), as.numeric(final)))
+      writeBin(header, con, 2, endian="little")
+      writeBin(reqr, con, endian="little")
     }
     flush(con)
   }
diff --git a/clients/R/Tests/dbi.R b/clients/R/Tests/dbi.R
--- a/clients/R/Tests/dbi.R
+++ b/clients/R/Tests/dbi.R
@@ -156,6 +156,14 @@ dbCommit(conn)
 stopifnot(identical(1L, tsize(conn, tname)))
 dbRemoveTable(conn,tname)
 
+# funny characters in strings
+stopifnot(dbIsValid(conn))
+dbBegin(conn)
+sq <- dbSendQuery(conn,"create table monetdbtest (a string)")
+sq <- dbSendQuery(conn,"INSERT INTO monetdbtest VALUES ('Роман Mühleisen')")
+stopifnot(identical("Роман Mühleisen", dbGetQuery(conn,"SELECT a FROM 
monetdbtest")$a[[1]]))
+dbRollback(conn)
+
 stopifnot(dbIsValid(conn))
 #thrice to catch null pointer errors
 stopifnot(identical(dbDisconnect(con),TRUE))
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to