diff -ur perl/DBD/monetdb.pm perl-2/DBD/monetdb.pm
--- perl/DBD/monetdb.pm	2014-01-14 00:56:23.000000000 -0800
+++ perl-2/DBD/monetdb.pm	2015-01-12 12:37:03.970915612 -0800
@@ -1,8 +1,8 @@
 package DBD::monetdb;
 
 use strict;
-use sigtrap;
 use DBI();
+use Encode();
 use MonetDB::CLI();
 
 our $VERSION = '0.10';
@@ -99,11 +99,11 @@
     return $dbh->{monetdb_language} eq 'sql' ? 'NULL' : 'nil'
         unless defined $value;
 
+    $value = Encode::encode_utf8($value);
+
     for ($value) {
-      s/	/\\t/g;
       s/\\/\\\\/g;
       s/\n/\\n/g;
-      s/\r/\\r/g;
       s/"/\\"/g;
       s/'/''/g;
     }
@@ -122,22 +122,15 @@
 
 
 sub _count_param {
-    my @statement = split //, shift;
+    my $statement = shift;
     my $num = 0;
 
-    while (defined(my $c = shift @statement)) {
-        if ($c eq '"' || $c eq "'") {
-            my $end = $c;
-            while (defined(my $c = shift @statement)) {
-                last if $c eq $end;
-                @statement = splice @statement, 2 if $c eq '\\';
-            }
-        }
-        elsif ($c eq '?') {
-            $num++;
-        }
-    }
-    return $num;
+    $statement =~ s{
+        ' (?: \\. | [^\\']++ )*+ ' |
+        " (?: \\. | [^\\"]++ )*+ '
+    }{}gx;
+
+    return $statement =~ tr/?/?/;
 }
 
 
@@ -614,7 +607,7 @@
         $sth->set_err(-1, $@) if $@;
         return;
     }
-    my @row = map $hdl->field($_), 0 .. $field_count-1;
+    my @row = map $hdl->{currow}[$_], 0 .. $field_count-1; # encapsulation break but saves a microsecond per cell
     map { s/\s+$// } @row if $sth->FETCH('ChopBlanks');
 
     $sth->{monetdb_rows}++;
diff -ur perl/Mapi.pm perl-2/Mapi.pm
--- perl/Mapi.pm	2014-11-20 00:22:36.000000000 -0800
+++ perl-2/Mapi.pm	2015-01-12 13:07:28.783916175 -0800
@@ -96,7 +96,8 @@
         PeerPort => $port,
         Proto    => 'tcp'
   ) || die "!ERROR can't connect to $host:$port $!";
-  $self->{piggyback} = "";
+  $self->{piggyback} = [];
+  $self->{skip_in} = 0;
 
   #binmode($self->{socket},":utf8");
 
@@ -236,7 +237,7 @@
 sub getRow {
   my ($self)= @_;
   my $row = $self->{lines}[$self->{next}++];
-  my @chars = split(//, $row);
+  my @chars = split(//, $row,3);
 
   if ($chars[0] eq '!') { 
     $self->error($row);
@@ -278,6 +279,11 @@
   my $block = $self->getblock();
   @{$self->{lines}} = split(/\n/, $block);
 
+  # skip diagnostic messages before the header
+  shift @{$self->{lines}} while @{$self->{lines}} && $self->{lines}[0] =~ /\A#/;
+
+  die "implausible return from MonetDB: $self->{lines}[0]\n" if $self->{lines}[0] =~ /\A[^ -~]/;
+
   my $header = $self->{lines}[0];
   my @chars = split(//, $header);
 
@@ -309,7 +315,7 @@
       }
       # for now skip table header information
       my $i = 1;
-      while ($self->{lines}[$i] =~ '%') {
+      while ($self->{lines}[$i] =~ /\A%/) {
         $self->{hdrs}[$i - 1] = $self->{lines}[$i];
         $i++;
       }
@@ -365,8 +371,10 @@
     return $self->getBlock();
   } else {
     # close large results, but only send on next query
-    $self->{piggyback} .= "Xclose $self->{id}" 
-      if ($self->{id} > 0 && $self->{count} != $self->{replysize});
+    if ($self->{id} > 0 && $self->{count} != $self->{replysize}) {
+      push @{$self->{piggyback}}, "Xclose $self->{id}";
+      $self->{skip_in}++;
+    }
     $self->{active} = 0;
   } 
   return $self->{active};
@@ -414,33 +422,45 @@
       print "getblock: $data\n" if ($self->{trace});
     }
   } while ( !$last_block );
+  print "IN:\n$result\n" if $ENV{MAPI_TRACE};
+
+  if ($self->{skip_in}) {
+    $self->{skip_in}--;
+    goto &getblock;
+  }
+
   return $result;
 }
 
 sub putblock {
-  my ($self,$blk) = @_;
-
-  my $pos        = 0;
-  my $last_block = 0;
-  my $blocksize  = 0xffff >> 1;       # max len per block
-  my $data;
+  my $self = shift;
 
   # there maybe something in the piggyback buffer
-  $blk = $self->{piggyback} . $blk if ($self->{piggyback} ne "");
-  $self->{piggyback} = "";
+  my @blocks = (\(@{ $self->{piggyback} }), \(@_));
+  @{ $self->{piggyback} } = ();
 
   # create blocks of data with max 0xffff length,
   # then loop over the data and send it.
-  while ( $data = substr( $blk, $pos, $blocksize ) ) {
-    my $len = length($data);
-    # set last-block-flag
-    $last_block = 1 if ( $len < $blocksize );    
-    my $flag = pack( 'v', ( $len << 1 ) + $last_block );
-    print "putblock: $last_block ".$data."\n" if ($self->{trace});
-    $self->{socket}->syswrite($flag);  # len<<1 + last-block-flag
-    $self->{socket}->syswrite($data);  # send it
-    $pos += $len;    # next block
+  my $out = '';
+  for my $blk (@blocks) {
+    print "OUT:\n$$blk\n" if $ENV{MAPI_TRACE};
+    utf8::downgrade($$blk); # deny wide chars
+    my $pos        = 0;
+    my $last_block = 0;
+    my $blocksize  = 0x7fff >> 1;       # max len per block
+    my $data;
+
+    while ( !$last_block ) {
+      my $data = substr($$blk, 0, $blocksize, "");
+      my $len = length($data);
+      # set last-block-flag
+      $last_block = 1 if !length $$blk;
+      my $flag = pack( 'v', ( $len << 1 ) + $last_block );
+      print "putblock: $last_block ".$data."\n" if ($self->{trace});
+      $out .= $flag . $data;
+    }
   }
+  $self->{socket}->syswrite($out); #send it
 }
 
 1;
diff -ur perl/MonetDB-CLI-MapiPP/MonetDB/CLI/MapiPP.pm perl-2/MonetDB-CLI-MapiPP/MonetDB/CLI/MapiPP.pm
--- perl/MonetDB-CLI-MapiPP/MonetDB/CLI/MapiPP.pm	2014-01-14 00:56:23.000000000 -0800
+++ perl-2/MonetDB-CLI-MapiPP/MonetDB/CLI/MapiPP.pm	2015-01-12 12:37:51.036029960 -0800
@@ -1,6 +1,7 @@
 package MonetDB::CLI::MapiPP;
 
 use Text::ParseWords();
+use Encode ();
 use Mapi;
 use strict;
 use warnings;
@@ -12,19 +13,15 @@
 
 sub unquote
 {
-  my ($class, $v) = @_;
+  if (!defined($_) || $_ eq 'NULL' || $_ eq 'nil') { $_ = undef; return; }
 
-  return undef if !defined($v) || $v eq 'NULL' || $v eq 'nil';
-
-  if ( $v =~ /^["']/) {
-    $v =~ s/^["']//;
-    $v =~ s/["']$//;
-    $v =~ s/\\(.)/$unescape{$1}||$1/eg;
+  if ( /^["']/) {
+    s/^["']//;
+    s/["']$//;
+    s/\\([0-7]{3}|.)/length($1) == 3 ? chr(oct($1)) : ($unescape{$1} || $1)/eg;
   }
-  return $v;
 }
 
-
 sub connect
 {
   my ($class, $host, $port, $user, $pass, $lang, $db) = @_;
@@ -106,14 +103,15 @@
       # TODO: table_name
     }
     # we must pre-fetch if this is not an SQL result-set
-    if (!$h->{count}) {
+    if (!defined $h->{count}) {
       do {
+        utf8::decode($self->{h}->{row});
         my @cols = split(/,\t */, $h->{row});
         my $i = -1;
-        while (++$i < @cols) {
-          $cols[$i] =~ s/^\[ //;
-          $cols[$i] =~ s/[ \t]+\]$//;
-          $cols[$i] = MonetDB::CLI::MapiPP->unquote($cols[$i]);
+        for (@cols) {
+          s/^\[ //;
+          s/[ \t]+\]$//;
+          MonetDB::CLI::MapiPP::unquote();
         }
         push(@{$self->{rows}}, [@cols]);
       } while (($tpe = $h->getReply()) > 0);
@@ -185,12 +183,13 @@
   return if ++$self->{i} >= $self->{affrows};
   
   if ($self->{id}) {
+    utf8::decode($self->{h}->{row});
     my @cols = split(/,\t */, $self->{h}->{row});
     my $i = -1;
-    while (++$i < @cols) {
-      $cols[$i] =~ s/^\[ //;
-      $cols[$i] =~ s/[ \t]+\]$//;
-      $cols[$i] = MonetDB::CLI::MapiPP->unquote($cols[$i]);
+    $cols[0] =~ s/^\[ //;
+    $cols[-1] =~ s/[ \t]+\]$//;
+    for (@cols) {
+      MonetDB::CLI::MapiPP::unquote();
     }
     $self->{currow} = [@cols];
     $self->{h}->getReply();
