Changeset: 9b54d2a5e9b8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/9b54d2a5e9b8
Modified Files:
        monetdb5/modules/mal/tablet.c
        monetdb5/modules/mal/tablet.h
        sql/backends/monet5/sql_result.c
Branch: directappend
Log Message:

Refactor away most of the SQLinsert_val logic

So we can start inlining it into the main functions.

This was surprisingly tricky to get right, hope it's ok now.


diffs (192 lines):

diff --git a/monetdb5/modules/mal/tablet.c b/monetdb5/modules/mal/tablet.c
--- a/monetdb5/modules/mal/tablet.c
+++ b/monetdb5/modules/mal/tablet.c
@@ -637,6 +637,9 @@ typedef struct {
        bte *rowerror;
        int errorcnt;
        LoadOps *loadops;
+       char scratch_buffer[3];
+       char *scratch;
+       size_t scratch_len;
 } READERtask;
 
 static void
@@ -798,6 +801,70 @@ SQLload_error(READERtask *task, lng idx,
 static void report_append_failed(READERtask *task, Column *fmt, int idx, lng 
col);
 static int report_conversion_failed(READERtask *task, Column *fmt, int idx, 
lng col, char *s);
 
+static inline void
+make_it_nil(Column *fmt)
+{
+       if (fmt->data == NULL)
+               return;
+       assert(fmt->len >= fmt->nil_len);
+       memcpy(fmt->data, fmt->nildata, fmt->nil_len);
+       if (fmt->c)
+               fmt->c->tnonil = false;
+}
+
+
+static inline int
+SQLconvert_val(READERtask *task, int col, int idx) {
+       Column *fmt = &task->as->format[col];
+       char *s = task->fields[col][idx];
+
+       if (s == NULL) {
+               make_it_nil(fmt);
+               return 0;
+       }
+       size_t slen = strlen(s);
+
+       char *unescaped;
+       if (!task->escape) {
+               unescaped = s;
+       } else {
+               // reallocate scratch space if necessary
+               size_t needed = slen + 1;
+               if (needed > task->scratch_len) {
+                       // add some margin
+                       size_t new_len = needed + needed / 2;
+                       if (task->scratch != NULL && task->scratch != 
task->scratch_buffer)
+                               GDKfree(task->scratch);
+                       task->scratch = GDKmalloc(new_len);
+                       if (!task->scratch) {
+                               task->scratch = task->scratch_buffer;
+                               task->scratch_len = 
sizeof(task->scratch_buffer);
+                               int ret = report_conversion_failed(task, fmt, 
idx, col + 1, "ALLOCATION FAILURE");
+                               make_it_nil(fmt);
+                               return ret;
+                       }
+                       task->scratch_len = new_len;
+               }
+               // unescape into the scratch space
+               if (GDKstrFromStr((unsigned char*)task->scratch, (unsigned 
char*)s, slen) < 0) {
+                       int ret = report_conversion_failed(task, fmt, idx, col 
+ 1, s);
+                       make_it_nil(fmt);
+                       return ret;
+               }
+               unescaped = task->scratch;
+       }
+
+       // Now parse the value into fmt->data.
+       void *p = fmt->frstr(fmt, fmt->adt, unescaped);
+       if (p == NULL) {
+               int ret = report_conversion_failed(task, fmt, idx, col + 1, s);
+               make_it_nil(fmt);
+               return ret;
+       }
+
+       return 0;
+}
+
 /*
  * The parsing of the individual values is straightforward. If the value 
represents
  * the null-replacement string then we grab the underlying nil.
@@ -813,55 +880,26 @@ SQLinsert_val(READERtask *task, int col,
 {
        Column *fmt = task->as->format + col;
        const void *adt;
-       char buf[BUFSIZ];
-       char *s = task->fields[col][idx];
-       int ret = 0;
 
-       /* include testing on the terminating null byte !! */
-       if (s == 0) {
-               adt = fmt->nildata;
-               if (fmt->c)
-                       fmt->c->tnonil = false;
-               if (fmt->data)
-                       memcpy(fmt->data, adt, fmt->len);
-       } else {
-               if (task->escape) {
-                       size_t slen = strlen(s) + 1;
-                       char *data = slen <= sizeof(buf) ? buf : 
GDKmalloc(strlen(s) + 1);
-                       if (data == NULL ||
-                               GDKstrFromStr((unsigned char *) data, (unsigned 
char *) s, strlen(s)) < 0)
-                               adt = NULL;
-                       else
-                               adt = fmt->frstr(fmt, fmt->adt, data);
-                       if (data != buf)
-                               GDKfree(data);
-               } else
-                       adt = fmt->frstr(fmt, fmt->adt, s);
-       }
+       void *orig = fmt->data;
+       if (SQLconvert_val(task, col, idx) < 0)
+               return -1;
+       assert(one_by_one || fmt->data == orig);
 
-       /* col is zero-based, but for error messages it needs to be one-based. 
*/
-       lng colno = col + 1;
-
-       if (adt == NULL) {
-               ret = report_conversion_failed(task, fmt, idx, colno, s);
-               /* replace it with a nil */
-               adt = fmt->nildata;
-               if (fmt->c)
-                       fmt->c->tnonil = false;
-       }
+       adt = fmt->data ? fmt->data : fmt->nildata;
 
        if (task->loadops) {
                if (!one_by_one)
-                       return ret;
+                       return 0;
                // Simple fixed size types will be appended in bulk.
                // Here we deal with the more messy ones
                str msg = task->loadops->append_one(task->loadops->state, idx, 
adt, fmt->appendcol);
                if (msg == MAL_SUCCEED)
-                       return ret;
+                       return 0;
        } else if (bunfastapp(fmt->c, adt) == GDK_SUCCEED)
-               return ret;
+               return 0;
 
-       report_append_failed(task, fmt, idx, colno);
+       report_append_failed(task, fmt, idx, col + 1);
        return -1;
 }
 
@@ -1790,6 +1828,8 @@ SQLload_file(Client cntxt, Tablet *as, b
                        for (j = 0; j < threads; j++)
                                ptask[j].workers = threads;
                }
+               ptask[j].scratch = ptask[j].scratch_buffer;
+               ptask[j].scratch_len = sizeof(ptask[j].scratch_buffer);
        }
        if (threads == 0) {
                /* no threads started */
@@ -2071,6 +2111,11 @@ SQLload_file(Client cntxt, Tablet *as, b
        GDKfree(task.rowerror);
        for (i = 0; i < MAXWORKERS; i++)
                GDKfree(ptask[i].cols);
+       for (int t = 0; t < threads; t++) {
+               char *scratch = ptask[t].scratch;
+               if (scratch != NULL && scratch != ptask[t].scratch_buffer)
+                       GDKfree(scratch);
+       }
 #ifdef MLOCK_TST
        munlockall();
 #endif
diff --git a/monetdb5/modules/mal/tablet.h b/monetdb5/modules/mal/tablet.h
--- a/monetdb5/modules/mal/tablet.h
+++ b/monetdb5/modules/mal/tablet.h
@@ -49,6 +49,7 @@ typedef struct Column_t {
        bit ws;                                         /* if set we need to 
skip white space */
        char quote;                                     /* if set use this 
character for string quotes */
        const void *nildata;
+       size_t nil_len;
        int size;
        void *appendcol;                        /* temporary, can probably use 
Columnt_t.extra in the future */
 } Column;
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
@@ -1054,6 +1054,7 @@ mvc_import_table(Client cntxt, BAT ***ba
                        fmt[i].nullstr = ns;
                        fmt[i].null_length = strlen(ns);
                        fmt[i].nildata = ATOMnilptr(fmt[i].adt);
+                       fmt[i].nil_len = ATOMlen(fmt[i].adt, fmt[i].nildata);
                        fmt[i].skip = (col->base.name[0] == '%');
                        if (col->type.type->eclass == EC_DEC) {
                                fmt[i].tostr = &dec_tostr;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to