Changeset: 5d4b4ab2be35 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5d4b4ab2be35
Modified Files:
        clients/mapilib/mapi.c
        common/utils/conversion.c
        common/utils/conversion.h
        monetdb5/modules/atoms/blob.c
        sql/backends/monet5/sql_result.c
Branch: protocol
Log Message:

Binary transfer of blobs.


diffs (truncated from 343 to 300 lines):

diff --git a/clients/mapilib/mapi.c b/clients/mapilib/mapi.c
--- a/clients/mapilib/mapi.c
+++ b/clients/mapilib/mapi.c
@@ -837,6 +837,7 @@ struct MapiColumn {
        void *null_value;
        char* buffer_ptr;
        char *dynamic_write_buf;
+       size_t dynamic_write_bufsiz;
        char write_buf[COLBUFSIZ];
        mapi_converter converter;
 };
@@ -4139,6 +4140,25 @@ static char* mapi_convert_timestamptz(st
        return (char*) col->write_buf;
 }
 
+static char* mapi_convert_blob(struct MapiColumn *col) {
+       lng length = *((lng*) col->buffer_ptr);
+       if (length < 0) {
+               return NULL;
+       }
+       if (24 + 3 * length > col->dynamic_write_bufsiz) {
+               col->dynamic_write_bufsiz = (size_t) 24 + 3 * length;
+               if (col->dynamic_write_buf) free(col->dynamic_write_buf);
+               col->dynamic_write_buf = malloc(col->dynamic_write_bufsiz);
+               if (!col->dynamic_write_buf) {
+                       return NULL;
+               }
+       }
+       if (conversion_blob_to_string(col->dynamic_write_buf, 
col->dynamic_write_bufsiz, col->buffer_ptr + sizeof(lng), length) < 0) {
+               return NULL;
+       }
+       return (char*) col->dynamic_write_buf;
+}
+
 static char* mapi_convert_null(struct MapiColumn *col) {
        (void) col;
        return NULL;
@@ -4271,14 +4291,18 @@ read_into_cache(MapiHdl hdl, int lookahe
                                result->fields[i].typelen = typelen;
                                result->fields[i].columnlength = (int) 
column_print_length;
                                result->fields[i].dynamic_write_buf = NULL;
+                               result->fields[i].dynamic_write_bufsiz = 0;
                                result->fields[i].converter = NULL;
 
-                               if (result->fields[i].null_value == NULL) {
+                               if (strcasecmp(type_sql_name, "blob") == 0) {
+                                       result->fields[i].converter = 
(mapi_converter) mapi_convert_blob;
+                               } else if (result->fields[i].null_value == 
NULL) {
                                        result->fields[i].converter = 
(mapi_converter) mapi_convert_null;
                                } else if (strcasecmp(type_sql_name, "varchar") 
== 0 || strcasecmp(type_sql_name, "char") == 0) {
                                        if (typelen > 0) {
                                                result->fields[i].converter = 
(mapi_converter) mapi_convert_varchar;
-                                               
result->fields[i].dynamic_write_buf = malloc(result->fields[i].typelen * 
sizeof(char));
+                                               
result->fields[i].dynamic_write_bufsiz = result->fields[i].typelen * 
sizeof(char);
+                                               
result->fields[i].dynamic_write_buf = 
malloc(result->fields[i].dynamic_write_bufsiz);
                                        } else {
                                                result->fields[i].converter = 
(mapi_converter) mapi_convert_clob;
                                        }
@@ -5562,7 +5586,9 @@ mapi_fetch_row(MapiHdl hdl)
        mapi_hdl_check(hdl, "mapi_fetch_row");
        if (result && result->prot10_resultset) {
                char* buf;
+               // check if we are done reading this result set
                if (result->rows_read >= result->row_count) {
+                       // if we are done, check if there is another result set 
we have to read
                        do {
                                if ((reply = mapi_fetch_line(hdl)) == NULL)
                                        return 0;
@@ -5573,15 +5599,14 @@ mapi_fetch_row(MapiHdl hdl)
                        }
                        return 0;
                }
-               // if not, check if our cache is empty
+               // if we are not done, check if our cache is empty
                if (result->rows_read >= result->tuple_count) {
                        // if our cache is empty, we read data from the socket
                        lng nrows = -1;
                        result->cur_row = 1;
 
+#ifdef CONTINUATION_MESSAGE
                        // first we write a prompt to the server indicating 
that we want another block of the result set
-
-#ifdef CONTINUATION_MESSAGE
                        if (!mnstr_writeChr(hdl->mid->to, 42) || 
mnstr_flush(hdl->mid->to)) {
                                return hdl->mid->error;
                        }
@@ -5649,11 +5674,25 @@ mapi_fetch_row(MapiHdl hdl)
                                bs2_resetbuf(hdl->mid->from);
                        }
                } else {
+                       // the requested row is in the cache, simply move each 
column pointer to the next row
                        for (i = 0; i < (size_t) result->fieldcnt; i++) {
                                if (result->fields[i].typelen < 0) {
                                        // variable-length column
-                                       result->fields[i].buffer_ptr += 
strlen(result->fields[i].buffer_ptr) + 1;
+                                       if (result->fields[i].converter == 
(mapi_converter) mapi_convert_blob) {
+                                               // blobs are prefixed by their 
length
+                                               // so we can read the length to 
know how to get to the next blob
+                                               lng length = *((lng*) 
result->fields[i].buffer_ptr);
+                                               result->fields[i].buffer_ptr += 
sizeof(lng);
+                                               if (length > 0) {
+                                                       
result->fields[i].buffer_ptr += length;
+                                               }
+                                       } else {
+                                               // strings are null-terminated
+                                               // so we call strlen to figure 
out how far to jump
+                                               result->fields[i].buffer_ptr += 
strlen(result->fields[i].buffer_ptr) + 1;
+                                       }
                                } else {
+                                       // fixed-length column, so we just jump 
forward typelen
                                        result->fields[i].buffer_ptr += 
result->fields[i].typelen;
                                }
                        }
diff --git a/common/utils/conversion.c b/common/utils/conversion.c
--- a/common/utils/conversion.c
+++ b/common/utils/conversion.c
@@ -350,4 +350,38 @@ conversion_epoch_tz_to_string(char *dst,
        return conversion_epoch_optional_tz_to_string(dst, len, src, 
null_value, 1, timezone_diff);
 }
 
+static char hexit[] = "0123456789ABCDEF";
 
+int
+conversion_blob_to_string(char *dst, int len, const char *blobdata, size_t 
nitems)
+{
+       char *s;
+       size_t i;
+       size_t expectedlen;
+
+       if (nitems == ~(size_t) 0)
+               expectedlen = 4;
+       else
+               expectedlen = 24 + (nitems * 3);
+
+       if (len < expectedlen) return -1;
+
+       if (nitems == ~(size_t) 0) {
+               strcpy(dst, NULL_STRING);
+               return 3;
+       }
+
+       strcpy(dst, "\0");
+       s = dst;
+
+       for (i = 0; i < nitems; i++) {
+               int val = (blobdata[i] >> 4) & 15;
+
+               *s++ = hexit[val];
+               val = blobdata[i] & 15;
+               *s++ = hexit[val];
+       }
+       *s = '\0';
+       return (int) (s - dst); /* 64bit: check for overflow */
+}
+
diff --git a/common/utils/conversion.h b/common/utils/conversion.h
--- a/common/utils/conversion.h
+++ b/common/utils/conversion.h
@@ -70,4 +70,5 @@ int conversion_epoch_to_string(char *dst
 // *src is time since epoch in ms
 int conversion_epoch_tz_to_string(char *dst, int len, const lng *src, lng 
null_value, int timezone_diff);
 
+int conversion_blob_to_string(char *dst, int len, const char *blobdata, size_t 
nitems);
 #endif
diff --git a/monetdb5/modules/atoms/blob.c b/monetdb5/modules/atoms/blob.c
--- a/monetdb5/modules/atoms/blob.c
+++ b/monetdb5/modules/atoms/blob.c
@@ -226,23 +226,26 @@ sqlblob_tostr(str *tostr, int *l, const 
                        return 0;
                *l = (int) expectedlen;
        }
-       if (p->nitems == ~(size_t) 0) {
-               strcpy(*tostr, "nil");
-               return 3;
-       }
 
-       strcpy(*tostr, "\0");
-       s = *tostr;
+       return conversion_blob_to_string(*tostr, expectedlen, p->data, 
p->nitems);
 
-       for (i = 0; i < p->nitems; i++) {
-               int val = (p->data[i] >> 4) & 15;
+       // if (p->nitems == ~(size_t) 0) {
+       //      strcpy(*tostr, "nil");
+       //      return 3;
+       // }
 
-               *s++ = hexit[val];
-               val = p->data[i] & 15;
-               *s++ = hexit[val];
-       }
-       *s = '\0';
-       return (int) (s - *tostr); /* 64bit: check for overflow */
+       // strcpy(*tostr, "\0");
+       // s = *tostr;
+
+       // for (i = 0; i < p->nitems; i++) {
+       //      int val = (p->data[i] >> 4) & 15;
+
+       //      *s++ = hexit[val];
+       //      val = p->data[i] & 15;
+       //      *s++ = hexit[val];
+       // }
+       // *s = '\0';
+       // return (int) (s - *tostr); /* 64bit: check for overflow */
 }
 
 static int
diff --git a/sql/backends/monet5/sql_result.c b/sql/backends/monet5/sql_result.c
--- a/sql/backends/monet5/sql_result.c
+++ b/sql/backends/monet5/sql_result.c
@@ -1828,6 +1828,7 @@ static int type_supports_binary_transfer
                type->eclass == EC_CHAR || 
                type->eclass == EC_STRING ||
                type->eclass == EC_DEC || 
+               type->eclass == EC_BLOB ||
                type->eclass == EC_FLT || 
                type->eclass == EC_NUM || 
                type->eclass == EC_DATE || 
@@ -1938,6 +1939,10 @@ int mvc_export_resultset_prot10(mvc *m, 
                        goto cleanup;
                }
 
+               if (type->eclass == EC_BLOB) {
+                       nil_len = 0;
+               }
+
                // write NULL values for this column to the stream
                // NULL values are encoded as <size:int> <NULL value> (<size> 
is always <typelen> for fixed size columns)
                if (!mnstr_writeInt(s, nil_len)) {
@@ -1959,40 +1964,42 @@ int mvc_export_resultset_prot10(mvc *m, 
                        iterators[i] = bat_iterator(BATdescriptor(ret));
                }
 
-               switch(ATOMstorage(mtype)) {
-                       case TYPE_str:
-                               retval = write_str_term(s, str_nil);
-                               break;
-                       case TYPE_bit:
-                       case TYPE_bte:
-                               retval = mnstr_writeBte(s, bte_nil);
-                               break;
-                       case TYPE_sht:
-                               retval = mnstr_writeSht(s, sht_nil);
-                               break;
-                       case TYPE_int:
-                               retval = mnstr_writeInt(s, int_nil);
-                               break;
-                       case TYPE_lng:
-                               retval = mnstr_writeLng(s, lng_nil);
-                               break;
-                       case TYPE_flt:
-                               retval = mnstr_writeFlt(s, flt_nil);
-                               break;
-                       case TYPE_dbl:
-                               retval = mnstr_writeDbl(s, dbl_nil);
-                               break;
-#ifdef HAVE_HGE
-                       case TYPE_hge:
-                               retval = mnstr_writeHge(s, hge_nil);
-                               break;
-#endif
-                       case TYPE_void:
-                               break;
-                       default:
-                               assert(0);
-                               fres = -1;
-                               goto cleanup;
+               if (type->eclass != EC_BLOB) {
+                       switch(ATOMstorage(mtype)) {
+                               case TYPE_str:
+                                       retval = write_str_term(s, str_nil);
+                                       break;
+                               case TYPE_bit:
+                               case TYPE_bte:
+                                       retval = mnstr_writeBte(s, bte_nil);
+                                       break;
+                               case TYPE_sht:
+                                       retval = mnstr_writeSht(s, sht_nil);
+                                       break;
+                               case TYPE_int:
+                                       retval = mnstr_writeInt(s, int_nil);
+                                       break;
+                               case TYPE_lng:
+                                       retval = mnstr_writeLng(s, lng_nil);
+                                       break;
+                               case TYPE_flt:
+                                       retval = mnstr_writeFlt(s, flt_nil);
+                                       break;
+                               case TYPE_dbl:
+                                       retval = mnstr_writeDbl(s, dbl_nil);
+                                       break;
+       #ifdef HAVE_HGE
+                               case TYPE_hge:
+                                       retval = mnstr_writeHge(s, hge_nil);
+                                       break;
+       #endif
+                               case TYPE_void:
+                                       break;
+                               default:
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to