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

Append simple types in batch


diffs (195 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
@@ -806,7 +806,7 @@ SQLload_error(READERtask *task, lng idx,
  * either case an entry is added to the error table.
  */
 static inline int
-SQLinsert_val(READERtask *task, int col, int idx)
+SQLinsert_val(READERtask *task, int col, int idx, bool one_by_one)
 {
        Column *fmt = task->as->format + col;
        const void *adt;
@@ -896,6 +896,10 @@ SQLinsert_val(READERtask *task, int col,
                        fmt->c->tnonil = false;
        }
        if (task->loadops) {
+               if (!one_by_one)
+                       return ret;
+               // 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;
@@ -923,6 +927,65 @@ SQLinsert_val(READERtask *task, int col,
 }
 
 static int
+SQLworker_directappend_column(READERtask *task, int col)
+{
+       Column *c = &task->as->format[col];
+       int count = task->top[task->cur];
+
+       int type = c->adt;
+       size_t width = ATOMsize(type);
+       bool batch_mode = !ATOMvarsized(type);
+
+       if (!batch_mode) {
+               for (int i = 0; i < count; i++) {
+                       if (SQLinsert_val(task, col, i, true) < 0)
+                               return -1;
+               }
+               return 0;
+       }
+
+       size_t allocation_size = count * width;
+       GDKfree(c->data);
+       c->data = GDKmalloc(allocation_size);
+       if (c->data) {
+               c->len = allocation_size;
+       } else {
+               tablet_error(task, lng_nil, lng_nil, int_nil, "cannot allocate 
memory", "");
+               return -1;
+       }
+
+       char * const allocation = c->data;
+       char *cursor = c->data;
+       for (int i = 0; i < count; i++) {
+               // We have to be careful here, c->data is not pointing at the 
beginning
+               // of a malloc'ed area, but into the middle. If SQLinsert_val 
tries to
+               // reallocate it we're screwed. However, c->len is sufficient 
so it
+               // shouldn't try to reallocate.
+               c->data = cursor;
+               c->len = width;
+               if (SQLinsert_val(task, col, i, false) < 0) {
+                       // We don't free our allocation here, it can probably 
be reused for the next block.
+                       c->data = allocation;
+                       c->len = allocation_size;
+                       return -1;
+               }
+               cursor += width;
+       }
+       // We don't free our allocation here, it can probably be reused for the 
next block.
+       c->data = allocation;
+       c->len = allocation_size;
+
+       // Now insert it.
+       str msg = task->loadops->append_batch(task->loadops->state, c->data, 
count, width, c->appendcol);
+       if (msg != MAL_SUCCEED) {
+               tablet_error(task, lng_nil, lng_nil, col, "bulk insert failed", 
msg);
+               return -1;
+       }
+
+       return 0;
+}
+
+static int
 SQLworker_column(READERtask *task, int col)
 {
        int i;
@@ -932,11 +995,7 @@ SQLworker_column(READERtask *task, int c
                return 0;
 
        if (task->loadops) {
-               for (i = 0; i < task->top[task->cur]; i++) {
-                       if (SQLinsert_val(task, col, i) < 0)
-                               return -1;
-               }
-               return 0;
+               return SQLworker_directappend_column(task, col);
        }
 
        /* watch out for concurrent threads */
@@ -951,7 +1010,7 @@ SQLworker_column(READERtask *task, int c
        MT_lock_unset(&mal_copyLock);
 
        for (i = 0; i < task->top[task->cur]; i++) {
-               if (!fmt[col].skip && SQLinsert_val(task, col, i) < 0) {
+               if (!fmt[col].skip && SQLinsert_val(task, col, i, true) < 0) {
                        BATsetcount(fmt[col].c, BATcount(fmt[col].c));
                        return -1;
                }
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
@@ -74,11 +74,13 @@ typedef struct Table_t {
 // SQLload_file doesn't know how to manipulate the sql transaction 
bookkeeping, caller does.
 typedef str (*loadfile_claim_fptr)(void *state, size_t nrows, size_t ncols, 
Column *cols[]);
 typedef str (*loadfile_append_one_fptr)(void *state, size_t idx, const void 
*data, void *col);
+typedef str (*loadfile_append_batch_fptr)(void *state, const void *data, BUN 
count, int width, void *col);
 typedef BAT *(*loadfile_get_offsets_bat_fptr)(void *state);
 typedef struct LoadOps {
        void *state;
        loadfile_claim_fptr claim;
        loadfile_append_one_fptr append_one;
+       loadfile_append_batch_fptr append_batch;
        loadfile_get_offsets_bat_fptr get_offsets;
 } LoadOps;
 
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
@@ -876,8 +876,6 @@ directappend_get_offsets_bat(void *state
        return state->all_offsets;
 }
 
-// Currently we're appending the values one by one but we need to switch to
-// a bulk interface.
 static str
 directappend_append_one(void *state_, size_t idx, const void *const_data, void 
*col)
 {
@@ -907,6 +905,46 @@ directappend_append_one(void *state_, si
        return MAL_SUCCEED;
 }
 
+static str
+directappend_append_batch(void *state_, const void *const_data, BUN count, int 
width, void *col)
+{
+       struct directappend *state = state_;
+       sqlstore *store = state->mvc->session->tr->store;
+       sql_column *c = col;
+       int tpe = c->type.type->localtype;
+
+       (void)width;
+       assert(width== ATOMsize(tpe));
+
+       BUN scattered_count = state->new_offsets ? BATcount(state->new_offsets) 
: 0;
+
+       int ret = LOG_OK;
+
+       if (scattered_count > 0) {
+               BUN dummy_offset = GDK_oid_max;
+               ret = store->storage_api.append_col(
+                                       state->mvc->session->tr, c,
+                                       dummy_offset, state->new_offsets,
+                                       (void*)const_data, scattered_count, tpe
+               );
+       }
+
+       if (ret == LOG_OK && count > scattered_count) {
+               char *remaining_data = (char*)const_data + scattered_count * 
width;
+               BUN remaining_count = count - scattered_count;
+               ret = store->storage_api.append_col(
+                                       state->mvc->session->tr, c,
+                                       state->offset, NULL,
+                                       remaining_data, remaining_count, tpe
+               );
+       }
+       if (ret != LOG_OK) {
+               throw(SQL, "sql.append", SQLSTATE(42000) "Append failed%s", ret 
== LOG_CONFLICT ? " due to conflict with another transaction" : "");
+       }
+
+       return MAL_SUCCEED;
+}
+
 str
 mvc_import_table(Client cntxt, BAT ***bats, mvc *m, bstream *bs, sql_table *t, 
const char *sep, const char *rsep, const char *ssep, const char *ns, lng sz, 
lng offset, int best, bool from_stdin, bool escape, bool append_directly)
 {
@@ -922,6 +960,7 @@ mvc_import_table(Client cntxt, BAT ***ba
                .state = NULL,
                .claim = directappend_claim,
                .append_one = directappend_append_one,
+               .append_batch = directappend_append_batch,
                .get_offsets = directappend_get_offsets_bat,
        };
        LoadOps *loadops = NULL;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to