Changeset: 0566e1f2e779 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/0566e1f2e779
Added Files:
        sql/backends/monet5/dict.c
        sql/backends/monet5/dict.h
Modified Files:
        sql/backends/monet5/CMakeLists.txt
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/sql.c
        sql/backends/monet5/sql_statement.c
        sql/backends/monet5/sql_statement.h
        sql/include/sql_catalog.h
        sql/storage/bat/bat_storage.c
        sql/storage/bat/bat_storage.h
        sql/storage/sql_storage.h
Branch: dict
Log Message:

v1 dictionary compression


diffs (truncated from 642 to 300 lines):

diff --git a/sql/backends/monet5/CMakeLists.txt 
b/sql/backends/monet5/CMakeLists.txt
--- a/sql/backends/monet5/CMakeLists.txt
+++ b/sql/backends/monet5/CMakeLists.txt
@@ -151,6 +151,7 @@ target_sources(sql
   sql_rank.c sql_rank.h
   sql_subquery.c sql_subquery.h
   opt_backend.h
+  dict.c dict.h
   ${MONETDB_CURRENT_SQL_SOURCES}
   PUBLIC
   ${sql_public_headers})
diff --git a/sql/backends/monet5/dict.c b/sql/backends/monet5/dict.c
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/dict.c
@@ -0,0 +1,178 @@
+
+#include "monetdb_config.h"
+#include "sql.h"
+#include "mal.h"
+#include "mal_client.h"
+
+#include "dict.h"
+
+str
+DICTcompress(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+       (void)mb;
+       /* always assume one result */
+       str msg = MAL_SUCCEED;
+       const char *sname = *getArgReference_str(stk, pci, 1);
+       const char *tname = *getArgReference_str(stk, pci, 2);
+       const char *cname = *getArgReference_str(stk, pci, 3);
+       backend *be = NULL;
+       sql_trans *tr = NULL;
+
+       if (!sname || !tname || !cname)
+               throw(SQL, "sql.dict_compress", SQLSTATE(3F000) "dict compress: 
invalid column name");
+       if ((msg = getBackendContext(cntxt, &be)) != MAL_SUCCEED)
+               return msg;
+       tr = be->mvc->session->tr;
+
+       sql_schema *s = find_sql_schema(tr, sname);
+       assert(s);
+       sql_table *t = find_sql_table(tr, s, tname);
+       assert(t);
+       sql_column *c = find_sql_column(t, cname);
+       assert(c);
+
+       sqlstore *store = tr->store;
+       BAT *b = store->storage_api.bind_col(tr, c, RDONLY);
+
+       /* for now use all rows */
+       BAT *u = BATunique(b, NULL);
+       if (!u)
+               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+
+       BUN cnt = BATcount(u);
+       /* create hash on u */
+       int tt = (cnt<256)?TYPE_bte:(cnt<(64*1024))?TYPE_sht:TYPE_int;
+       if (cnt > 2L*1024*1024*1024) {
+               bat_destroy(u);
+               bat_destroy(b);
+               throw(SQL, "sql.dict_compress", SQLSTATE(3F000) "dict compress: 
too many values");
+       }
+       BAT *uv = BATproject(u, b); /* get values */
+       bat_destroy(u);
+       if (!uv) {
+               bat_destroy(b);
+               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+       }
+    BAT *uu = COLcopy(uv, uv->ttype, true, PERSISTENT);
+       if (!uu) {
+               bat_destroy(uv);
+               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+       }
+       bat_destroy(uv);
+       u = uu;
+
+       BAT *o = COLnew(0, tt, BATcount(b), PERSISTENT);
+       if (!o || BAThash(u) != GDK_SUCCEED) {
+               bat_destroy(u);
+               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+       }
+       BUN p, q;
+       BATiter bi = bat_iterator(b);
+       BATiter ui = bat_iterator_nolock(u);
+       if (tt == TYPE_bte) {
+               bte *op = (bte*)Tloc(o, 0);
+               BATloop(b, p, q) {
+                       BUN up = 0;
+                       HASHloop(ui, ui.b->thash, up, BUNtail(bi, p)) {
+                               op[p] = up;
+                       }
+               }
+               BATsetcount(o, BATcount(b));
+               o->tsorted = (u->tsorted && b->tsorted);
+               o->trevsorted = false;
+               o->tnil = b->tnil;
+               o->tnonil = b->tnonil;
+               o->tkey = b->tkey;
+               if (sql_trans_alter_storage(tr, c, "DICT") != LOG_OK || 
store->storage_api.col_dict(tr, c, o, u) != LOG_OK)
+                       throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
"alter_storage failed");
+       } else if (tt == TYPE_sht) {
+               sht *op = (sht*)Tloc(o, 0);
+               BATloop(b, p, q) {
+                       BUN up = 0;
+                       HASHloop(ui, ui.b->thash, up, BUNtail(bi, p)) {
+                               op[p] = up;
+                       }
+               }
+               BATsetcount(o, BATcount(b));
+               o->tsorted = (u->tsorted && b->tsorted);
+               o->trevsorted = false;
+               o->tnil = b->tnil;
+               o->tnonil = b->tnonil;
+               o->tkey = b->tkey;
+               if (sql_trans_alter_storage(tr, c, "DICT") != LOG_OK || 
store->storage_api.col_dict(tr, c, o, u) != LOG_OK)
+                       throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
"alter_storage failed");
+       } else {
+               printf("implement int cases \n");
+       }
+       bat_iterator_end(&bi);
+       bat_destroy(b);
+       bat_destroy(u);
+       bat_destroy(o);
+       return MAL_SUCCEED;
+}
+
+
+str
+DICTdecompress(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+       /* b = project(o:bat[:bte], u) */
+       /* b = project(o:bat[:sht], u) */
+       /* b = project(o:bat[:int], u) */
+       (void)cntxt;
+       (void)mb;
+       bat *r = getArgReference_bat(stk, pci, 0);
+       bat O = *getArgReference_bat(stk, pci, 1);
+       bat U = *getArgReference_bat(stk, pci, 2);
+
+       BAT *o = BATdescriptor(O);
+       BAT *u = BATdescriptor(U);
+       if (!o || !u) {
+               bat_destroy(o);
+               bat_destroy(o);
+               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+       }
+       BAT *b = COLnew(0, u->ttype, BATcount(o), TRANSIENT);
+
+       BUN p, q;
+       BATiter oi = bat_iterator(o);
+       BATiter ui = bat_iterator_nolock(u);
+       //if (ATOMvarsized(u->ttype)) {
+       if (o->ttype == TYPE_bte) {
+               bte *op = Tloc(o, 0);
+               BATloop(o, p, q) {
+                       BUN up = op[p];
+               if (BUNappend(b, BUNtail(ui, up), false) != GDK_SUCCEED) {
+                               bat_iterator_end(&oi);
+                               bat_destroy(b);
+                               bat_destroy(o);
+                               bat_destroy(u);
+                               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       }
+               }
+       } else if (o->ttype == TYPE_sht) {
+               sht *op = Tloc(o, 0);
+               BATloop(o, p, q) {
+                       BUN up = op[p];
+               if (BUNappend(b, BUNtail(ui, up), false) != GDK_SUCCEED) {
+                               bat_iterator_end(&oi);
+                               bat_destroy(b);
+                               bat_destroy(o);
+                               bat_destroy(u);
+                               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+                       }
+               }
+       } else if (o->ttype == TYPE_int) {
+               assert(0);
+       } else {
+               bat_iterator_end(&oi);
+               bat_destroy(b);
+               bat_destroy(o);
+               bat_destroy(u);
+               throw(SQL, "sql.dict_compress", SQLSTATE(HY013) "unknown offset 
type");
+       }
+       bat_iterator_end(&oi);
+       BBPkeepref(*r = b->batCacheid);
+       bat_destroy(o);
+       bat_destroy(u);
+       return MAL_SUCCEED;
+}
diff --git a/sql/backends/monet5/dict.h b/sql/backends/monet5/dict.h
new file mode 100644
--- /dev/null
+++ b/sql/backends/monet5/dict.h
@@ -0,0 +1,11 @@
+
+#ifndef _DICT_H
+#define _DICT_H
+
+#include "sql.h"
+
+extern str DICTcompress(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
+extern str DICTdecompress(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr 
pci);
+
+#endif /* _DICT_H */
+
diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1576,6 +1576,10 @@ stmt_col( backend *be, sql_column *c, st
                sc = stmt_project_delta(be, sc, u);
                if (del)
                        sc = stmt_project(be, del, sc);
+               if (c->storage_type) {
+                       stmt *v = stmt_bat(be, c, RD_DICT, part);
+                       sc = stmt_dict(be, sc, v);
+               }
        } else if (del) { /* always handle the deletes */
                sc = stmt_project(be, del, sc);
        }
diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -5037,6 +5037,7 @@ finalize:
 #include "sql_subquery.h"
 #include "sql_statistics.h"
 #include "sql_transaction.h"
+#include "dict.h"
 #include "mel.h"
 static mel_func sql_init_funcs[] = {
  pattern("sql", "shutdown", SQLshutdown_wrap, false, "", args(1,3, 
arg("",str),arg("delay",bte),arg("force",bit))),
@@ -5167,6 +5168,8 @@ static mel_func sql_init_funcs[] = {
  pattern("sql", "prepared_statements_args", 
SQLsession_prepared_statements_args, false, "Available prepared statements' 
arguments in the current session", args(9,9, 
batarg("statementid",int),batarg("type",str),batarg("digits",int),batarg("scale",int),batarg("inout",bte),batarg("number",int),batarg("schema",str),batarg("table",str),batarg("column",str))),
  pattern("sql", "copy_rejects", COPYrejects, false, "", args(4,4, 
batarg("rowid",lng),batarg("fldid",int),batarg("msg",str),batarg("inp",str))),
  pattern("sql", "copy_rejects_clear", COPYrejects_clear, true, "", noargs),
+ pattern("sql", "dict_compress", DICTcompress, false, "compress a sql column", 
args(0, 3, arg("schema", str), arg("table", str), arg("column", str))),
+ pattern("sql", "dict_decompress", DICTdecompress, false, "decompress a 
dictionary compressed (sub)column", args(1, 3, batargany("", 1), batargany("o", 
0), batargany("u", 1))),
  command("calc", "dec_round", bte_dec_round_wrap, false, "round off the value 
v to nearests multiple of r", args(1,3, arg("",bte),arg("v",bte),arg("r",bte))),
  pattern("batcalc", "dec_round", bte_bat_dec_round_wrap, false, "round off the 
value v to nearests multiple of r", args(1,3, 
batarg("",bte),batarg("v",bte),arg("r",bte))),
  pattern("batcalc", "dec_round", bte_bat_dec_round_wrap, false, "round off the 
value v to nearests multiple of r", args(1,4, 
batarg("",bte),batarg("v",bte),arg("r",bte),batarg("s",oid))),
diff --git a/sql/backends/monet5/sql_statement.c 
b/sql/backends/monet5/sql_statement.c
--- a/sql/backends/monet5/sql_statement.c
+++ b/sql/backends/monet5/sql_statement.c
@@ -579,6 +579,12 @@ stmt_bat(backend *be, sql_column *c, int
        q = newStmtArgs(mb, sqlRef, bindRef, 9);
        if (q == NULL)
                return NULL;
+       if (c->storage_type && access != RD_DICT) {
+               sql_trans *tr = be->mvc->session->tr;
+               sqlstore *store = tr->store;
+               BAT *b = store->storage_api.bind_col(tr, c, QUICK);
+               tt = b->ttype;
+       }
        if (access == RD_UPD_ID) {
                q = pushReturn(mb, q, newTmpVariable(mb, newBatType(tt)));
        } else {
@@ -2257,6 +2263,39 @@ stmt_left_project(backend *be, stmt *op1
 }
 
 stmt *
+stmt_dict(backend *be, stmt *op1, stmt *op2)
+{
+       MalBlkPtr mb = be->mb;
+       InstrPtr q = NULL;
+
+       if (op1->nr < 0 || op2->nr < 0)
+               return NULL;
+
+       q = newStmt(mb, sqlRef, "dict_decompress");
+       q = pushArgument(mb, q, op1->nr);
+       q = pushArgument(mb, q, op2->nr);
+
+       if (q) {
+               stmt *s = stmt_create(be->mvc->sa, st_join);
+               if (s == NULL) {
+                       freeInstruction(q);
+                       return NULL;
+               }
+
+               s->op1 = op1;
+               s->op2 = op2;
+               s->flag = cmp_project;
+               s->key = 0;
+               s->nrcols = MAX(op1->nrcols,op2->nrcols);
+               s->nr = getDestVar(q);
+               s->q = q;
+               s->tname = op1->tname;
+               s->cname = op1->cname;
+               return s;
+       }
+       return NULL;
+}
+stmt *
 stmt_join2(backend *be, stmt *l, stmt *ra, stmt *rb, int cmp, int anti, int 
symmetric, int swapped)
 {
        InstrPtr q = select2_join2(be, l, ra, rb, cmp, NULL, anti, symmetric, 
swapped, st_join2, 1/*reduce semantics*/);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to