From ab086e7cb39d6d4ce263d8d7a8b9057a27be8552 Mon Sep 17 00:00:00 2001 From: krasimir Date: Fri, 4 Sep 2015 14:45:18 +0000 Subject: [PATCH] storage for literals in libsg --- src/runtime/c/sg/sg.c | 175 ++++++++++++++++++++++++++++++++++++++++-- src/runtime/c/sg/sg.h | 3 + 2 files changed, 172 insertions(+), 6 deletions(-) diff --git a/src/runtime/c/sg/sg.c b/src/runtime/c/sg/sg.c index 88ac3f44d..c0f8f5dda 100644 --- a/src/runtime/c/sg/sg.c +++ b/src/runtime/c/sg/sg.c @@ -3,10 +3,11 @@ #include "sg/sg.h" -#define SG_EXPRS "sg_exprs" -#define SG_PAIRS "sg_pairs" -#define SG_IDENTS "sg_idents" -#define SG_TRIPLES "sg_triples" +#define SG_EXPRS "sg_exprs" +#define SG_PAIRS "sg_pairs" +#define SG_IDENTS "sg_idents" +#define SG_LITERALS "sg_literals" +#define SG_TRIPLES "sg_triples" #define SG_TRIPLES_SPO "sg_triples_spo" #define SG_TRIPLES_PO "sg_triples_po" #define SG_TRIPLES_O "sg_triples_o" @@ -47,6 +48,7 @@ sg_open(const char *filename, rc = sqlite3_exec(db, "create table if not exists " SG_EXPRS "(fun not null, arg integer);" "create unique index if not exists " SG_IDENTS " on " SG_EXPRS "(fun) where arg is null;" + "create unique index if not exists " SG_LITERALS " on " SG_EXPRS "(fun) where arg = 0;" "create unique index if not exists " SG_PAIRS " on " SG_EXPRS "(fun,arg) where arg is not null;" "create table if not exists " SG_TRIPLES "(subj integer, pred integer, obj integer, state integer);" "create unique index if not exists " SG_TRIPLES_SPO " on " SG_TRIPLES "(subj,pred,obj);" @@ -123,6 +125,7 @@ typedef struct { BtCursor crsExprs; BtCursor crsPairs; BtCursor crsIdents; + BtCursor crsLiterals; SgId key_seed; } ExprContext; @@ -150,6 +153,12 @@ open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err) return SQLITE_ERROR; } + Index *literalsIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_LITERALS); + if (!literalsIdx) { + sg_raise_err("Index " SG_LITERALS " is missing", err); + return SQLITE_ERROR; + } + int rc; memset(&ctxt->crsExprs, 0, sizeof(ctxt->crsExprs)); @@ -178,6 +187,15 @@ open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err) } ctxt->n_cursors++; + memset(&ctxt->crsLiterals, 0, sizeof(ctxt->crsLiterals)); + KeyInfo *infLiterals = sqlite3KeyInfoAlloc(db, 1, 1); + rc = sqlite3BtreeCursor(db->aDb[0].pBt, literalsIdx->tnum, wrFlag, infLiterals, &ctxt->crsLiterals); + if (rc != SQLITE_OK) { + sg_raise_sqlite(db, err); + return rc; + } + ctxt->n_cursors++; + if (wrFlag) { int res; rc = sqlite3BtreeLast(&ctxt->crsExprs, &res); @@ -201,6 +219,11 @@ open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err) static void close_exprs(ExprContext* ctxt) { + if (ctxt->n_cursors >= 4) { + sqlite3KeyInfoUnref(ctxt->crsLiterals.pKeyInfo); + sqlite3BtreeCloseCursor(&ctxt->crsLiterals); + } + if (ctxt->n_cursors >= 3) { sqlite3KeyInfoUnref(ctxt->crsIdents.pKeyInfo); sqlite3BtreeCloseCursor(&ctxt->crsIdents); @@ -228,6 +251,7 @@ store_expr(sqlite3* db, GuVariantInfo ei = gu_variant_open(expr); switch (ei.tag) { case PGF_EXPR_ABS: { + gu_impossible(); break; } case PGF_EXPR_APP: { @@ -314,9 +338,104 @@ store_expr(sqlite3* db, break; } case PGF_EXPR_LIT: { + PgfExprLit* elit = ei.data; + + Mem mem[2]; + + GuVariantInfo li = gu_variant_open(elit->lit); + switch (li.tag) { + case PGF_LITERAL_STR: { + PgfLiteralStr* lstr = li.data; + + mem[0].flags = MEM_Str; + mem[0].n = strlen(lstr->val); + mem[0].z = lstr->val; + break; + } + case PGF_LITERAL_INT: { + PgfLiteralInt* lint = li.data; + + mem[0].flags = MEM_Int; + mem[0].u.i = lint->val; + break; + } + case PGF_LITERAL_FLT: { + PgfLiteralFlt* lflt = li.data; + + mem[0].flags = MEM_Real; + mem[0].u.r = lflt->val; + break; + } + default: + gu_impossible(); + } + + UnpackedRecord idxKey; + idxKey.pKeyInfo = ctxt->crsIdents.pKeyInfo; + idxKey.nField = 1; + idxKey.default_rc = 0; + idxKey.aMem = mem; + + int res = 0; + rc = sqlite3BtreeMovetoUnpacked(&ctxt->crsLiterals, + &idxKey, 0, 0, &res); + if (rc != SQLITE_OK) { + return rc; + } + + if (res == 0) { + rc = sqlite3VdbeIdxRowid(db, &ctxt->crsLiterals, pKey); + } else { + if (wrFlag == 0) { + *pKey = 0; + return SQLITE_OK; + } + + *pKey = ++ctxt->key_seed; + + mem[1].flags = MEM_Int; + mem[1].u.i = 0; + + int serial_type_lit = sqlite3VdbeSerialType(&mem[0], file_format); + int serial_type_lit_hdr_len = sqlite3VarintLen(serial_type_lit); + int serial_type_arg = sqlite3VdbeSerialType(&mem[1], file_format); + int serial_type_arg_hdr_len = sqlite3VarintLen(serial_type_arg); + + unsigned char* buf = malloc(1+serial_type_lit_hdr_len+MAX(1,serial_type_arg_hdr_len)+mem[0].n+8); + unsigned char* p = buf; + *p++ = 1+serial_type_lit_hdr_len+serial_type_arg_hdr_len; + p += putVarint32(p, serial_type_lit); + p += putVarint32(p, serial_type_arg); + p += sqlite3VdbeSerialPut(p, &mem[0], serial_type_lit); + p += sqlite3VdbeSerialPut(p, &mem[1], serial_type_arg); + + rc = sqlite3BtreeInsert(&ctxt->crsExprs, 0, *pKey, + buf, p-buf, 0, + 0, 0); + if (rc == SQLITE_OK) { + mem[1].flags = MEM_Int; + mem[1].u.i = *pKey; + + int serial_type_key = sqlite3VdbeSerialType(&mem[1], file_format); + int serial_type_key_hdr_len = sqlite3VarintLen(serial_type_key); + + p = buf; + *p++ = 1+serial_type_lit_hdr_len+serial_type_key_hdr_len; + p += putVarint32(p, serial_type_lit); + p += putVarint32(p, serial_type_key); + p += sqlite3VdbeSerialPut(p, &mem[0], serial_type_lit); + p += sqlite3VdbeSerialPut(p, &mem[1], serial_type_key); + rc = sqlite3BtreeInsert(&ctxt->crsLiterals, buf, p-buf, + 0, *pKey, 0, + 0, 0); + } + + free(buf); + } break; } case PGF_EXPR_META: { + gu_impossible(); } case PGF_EXPR_FUN: { PgfExprFun* fun = ei.data; @@ -390,12 +509,17 @@ free: break; } case PGF_EXPR_VAR: { + gu_impossible(); break; } case PGF_EXPR_TYPED: { + PgfExprTyped* etyped = ei.data; + rc = store_expr(db, ctxt, etyped->expr, pKey, wrFlag); break; } case PGF_EXPR_IMPL_ARG: { + PgfExprImplArg* eimpl = ei.data; + rc = store_expr(db, ctxt, eimpl->expr, pKey, wrFlag); break; } default: @@ -482,8 +606,8 @@ load_expr(BtCursor* crsExprs, SgId key, PgfExpr *pExpr, GuPool* out_pool) Mem mem[2]; row += sqlite3VdbeSerialGet(row, serial_type_fun, &mem[0]); row += sqlite3VdbeSerialGet(row, serial_type_arg, &mem[1]); - - if (serial_type_arg == 0) { + + if (mem[1].flags & MEM_Null) { u32 len = sqlite3VdbeSerialTypeLen(serial_type_fun); PgfExprFun *efun = @@ -493,6 +617,37 @@ load_expr(BtCursor* crsExprs, SgId key, PgfExpr *pExpr, GuPool* out_pool) pExpr, out_pool); memcpy(efun->fun, mem[0].z, len); efun->fun[len] = 0; + } else if (mem[1].u.i == 0) { + PgfExprLit *elit = + gu_new_variant(PGF_EXPR_LIT, + PgfExprLit, + pExpr, out_pool); + + if (mem[0].flags & MEM_Str) { + u32 len = sqlite3VdbeSerialTypeLen(serial_type_fun); + + PgfLiteralStr *lstr = + gu_new_flex_variant(PGF_LITERAL_STR, + PgfLiteralStr, + val, len+1, + &elit->lit, out_pool); + memcpy(lstr->val, mem[0].z, len); + lstr->val[len] = 0; + } else if (mem[0].flags & MEM_Int) { + PgfLiteralInt *lint = + gu_new_variant(PGF_LITERAL_INT, + PgfLiteralInt, + &elit->lit, out_pool); + lint->val = mem[0].u.i; + } else if (mem[0].flags & MEM_Real) { + PgfLiteralFlt *lflt = + gu_new_variant(PGF_LITERAL_FLT, + PgfLiteralFlt, + &elit->lit, out_pool); + lflt->val = mem[0].u.r; + } else { + gu_impossible(); + } } else { PgfExprApp* papp = gu_new_variant(PGF_EXPR_APP, PgfExprApp, pExpr, out_pool); @@ -1154,6 +1309,14 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, return false; } +void +sg_triple_result_get_query(SgTripleResult* tres, SgTriple triple) +{ + triple[0] = tres->triple[0]; + triple[1] = tres->triple[1]; + triple[2] = tres->triple[2]; +} + void sg_triple_result_close(SgTripleResult* tres, GuExn* err) { diff --git a/src/runtime/c/sg/sg.h b/src/runtime/c/sg/sg.h index 4f1c40562..3bf0cb8c5 100644 --- a/src/runtime/c/sg/sg.h +++ b/src/runtime/c/sg/sg.h @@ -49,6 +49,9 @@ int sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuPool* out_pool, GuExn* err); +void +sg_triple_result_get_query(SgTripleResult* tres, SgTriple triple); + void sg_triple_result_close(SgTripleResult* tres, GuExn* err);