diff options
| author | krangelov <kr.angelov@gmail.com> | 2020-07-08 21:12:01 +0200 |
|---|---|---|
| committer | krangelov <kr.angelov@gmail.com> | 2020-07-08 21:12:01 +0200 |
| commit | 33818076ff553510b5e4a4d0295388d07ece2ec4 (patch) | |
| tree | b381152f5f8f8bb7847ed59ff75c0ae00af1f3ef /src/runtime/c/sg/sg.c | |
| parent | 47d1da0845814b947113a6786555e6d2672f6533 (diff) | |
drop the SG library completely.
Diffstat (limited to 'src/runtime/c/sg/sg.c')
| -rw-r--r-- | src/runtime/c/sg/sg.c | 2408 |
1 files changed, 0 insertions, 2408 deletions
diff --git a/src/runtime/c/sg/sg.c b/src/runtime/c/sg/sg.c deleted file mode 100644 index b5a473b99..000000000 --- a/src/runtime/c/sg/sg.c +++ /dev/null @@ -1,2408 +0,0 @@ -#include <stdlib.h> -#include "sqlite3Btree.h" - -#include "sg/sg.h" -#include "gu/mem.h" -#include "pgf/data.h" - -#define SG_EXPRS 1 -#define SG_PAIRS 2 -#define SG_IDENTS 3 -#define SG_LITERALS 4 -#define SG_TOKENS 5 -#define SG_TRIPLES 6 -#define SG_TRIPLES_SPO 7 -#define SG_TRIPLES_PO 8 -#define SG_TRIPLES_O 9 - -struct SgSG { - Btree *pBtree; - int exprsTNum; /* The page number for the table of expressions */ - int identsTNum; /* The page number for the index on identifiers */ - int literalsTNum; /* The page number for the index on literals */ - int pairsTNum; /* The page number for the index on application pairs */ - int tokensTNum; /* The page number for the index on linearization tokens */ - int triplesTNum; /* The page number for the table of triples */ - int triplesIdxTNum[3]; /* The page number for the three indexes on triples */ - int autoCommit; -}; - -void -sg_raise_sqlite(int rc, GuExn* err) -{ - const char *msg = sqlite3BtreeErrName(rc); - - GuExnData* err_data = gu_raise(err, SgError); - if (err_data) { - err_data->data = gu_malloc(err_data->pool, strlen(msg)+1); - strcpy(err_data->data, msg); - } -} - -void -sg_raise_err(GuString msg, GuExn* err) -{ - GuExnData* err_data = gu_raise(err, SgError); - if (err_data) { - err_data->data = (char*) msg; - } -} - -static int -sg_create_table(Btree* pBtree, BtCursor* crsSchema, int tblKey, int* pTNum, int flags) -{ - int rc; - int file_format = sqlite3BtreeFileFormat(pBtree); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(crsSchema, 0, tblKey, 0, &res); - if (rc != SQLITE_OK) { - return rc; - } - - Mem mem; - int serial_type; - - if (res == 0) { - u32 payloadSize; - rc = sqlite3BtreeDataSize(crsSchema, &payloadSize); - if (rc != SQLITE_OK) - return rc; - - u32 avail = 0; - const unsigned char* row = sqlite3BtreeDataFetch(crsSchema, &avail); - row++; - - row += getVarint32(row, serial_type); - row += sqlite3BtreeSerialGet(row, serial_type, &mem); - assert(mem.flags & MEM_Int); - - *pTNum = mem.u.i; - } else { - rc = sqlite3BtreeCreateTable(pBtree, pTNum, flags); - if (rc != SQLITE_OK) { - return rc; - } - - mem.flags = MEM_Int; - mem.u.i = *pTNum; - - unsigned char buf[32]; - unsigned char *p; - - buf[0] = 2; - serial_type = sqlite3BtreeSerialType(&mem, file_format); - buf[1] = serial_type; - - p = buf+2; - p += sqlite3BtreeSerialPut(buf+2, &mem, serial_type); - - rc = sqlite3BtreeInsert(crsSchema, 0, tblKey, - buf, p-buf, 0, - 0, 0); - if (rc != SQLITE_OK) - return rc; - } - - return SQLITE_OK; -} - -SgSG* -sg_open(const char *filename, - GuExn* err) -{ - int rc; - - Btree* pBtree; - rc = sqlite3BtreeOpen(0, filename, &pBtree, - 0, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return NULL; - } - - rc = sqlite3BtreeBeginTrans(pBtree, 1); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - sqlite3BtreeClose(pBtree); - return NULL; - } - - BtCursor* crsSchema = NULL; - rc = sqlite3BtreeCursor(pBtree, 1, 1, 0, 0, &crsSchema); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - sqlite3BtreeClose(pBtree); - return NULL; - } - - SgSG* sg = malloc(sizeof(SgSG)); - sg->pBtree = pBtree; - sg->autoCommit = 1; - - rc = sg_create_table(pBtree, crsSchema, SG_EXPRS, &sg->exprsTNum, BTREE_INTKEY); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_IDENTS, &sg->identsTNum, 0); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_LITERALS, &sg->literalsTNum, 0); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_PAIRS, &sg->pairsTNum, 0); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_TOKENS, &sg->tokensTNum, 0); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_TRIPLES, &sg->triplesTNum, BTREE_INTKEY); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_TRIPLES_SPO, &sg->triplesIdxTNum[0], 0); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_TRIPLES_PO, &sg->triplesIdxTNum[1], 0); - if (rc != SQLITE_OK) - goto fail; - - rc = sg_create_table(pBtree, crsSchema, SG_TRIPLES_O, &sg->triplesIdxTNum[2], 0); - if (rc != SQLITE_OK) - goto fail; - - sqlite3BtreeCloseCursor(crsSchema); - - rc = sqlite3BtreeCommit(pBtree); - if (rc != SQLITE_OK) - goto fail; - - return sg; - -fail: - sg_raise_sqlite(rc, err); - if (crsSchema != NULL) - sqlite3BtreeCloseCursor(crsSchema); - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - sqlite3BtreeClose(pBtree); - free(sg); - return NULL; -} - -void -sg_close(SgSG* sg, GuExn* err) -{ - sqlite3BtreeClose(sg->pBtree); -} - -void -sg_shutdown() -{ - sqlite3BtreeShutdown(); -} - -void -sg_begin_trans(SgSG* sg, GuExn* err) -{ - int rc = sqlite3BtreeBeginTrans(sg->pBtree, 1); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - sg->autoCommit = 0; -} - -void -sg_commit(SgSG* sg, GuExn* err) -{ - int rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - sg->autoCommit = 1; -} - -void -sg_rollback(SgSG* sg, GuExn* err) -{ - int rc = sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - sg->autoCommit = 1; -} - -typedef struct { - int n_cursors; - BtCursor* crsExprs; - BtCursor* crsIdents; - BtCursor* crsLiterals; - BtCursor* crsPairs; - SgId key_seed; -} ExprContext; - -static int -open_exprs(SgSG *sg, int wrFlag, bool identsOnly, - ExprContext* ctxt, GuExn* err) -{ - ctxt->n_cursors = 0; - - int rc; - - rc = sqlite3BtreeCursor(sg->pBtree, sg->exprsTNum, wrFlag, 0, 0, &ctxt->crsExprs); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - ctxt->n_cursors++; - - rc = sqlite3BtreeCursor(sg->pBtree, sg->identsTNum, wrFlag, 1, 1, &ctxt->crsIdents); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - ctxt->n_cursors++; - - if (!identsOnly) { - rc = sqlite3BtreeCursor(sg->pBtree, sg->literalsTNum, wrFlag, 1, 1, &ctxt->crsLiterals); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - ctxt->n_cursors++; - - rc = sqlite3BtreeCursor(sg->pBtree, sg->pairsTNum, wrFlag, 2, 0, &ctxt->crsPairs); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - ctxt->n_cursors++; - } - - if (wrFlag) { - int res; - rc = sqlite3BtreeLast(ctxt->crsExprs, &res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - - rc = sqlite3BtreeKeySize(ctxt->crsExprs, &ctxt->key_seed); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - } else { - ctxt->key_seed = 0; - } - - return SQLITE_OK; -} - -static void -close_exprs(ExprContext* ctxt) -{ - if (ctxt->n_cursors >= 4) { - sqlite3BtreeCloseCursor(ctxt->crsPairs); - } - - if (ctxt->n_cursors >= 3) { - sqlite3BtreeCloseCursor(ctxt->crsLiterals); - } - - if (ctxt->n_cursors >= 2) { - sqlite3BtreeCloseCursor(ctxt->crsIdents); - } - - if (ctxt->n_cursors >= 1) { - sqlite3BtreeCloseCursor(ctxt->crsExprs); - } - - ctxt->n_cursors = 0; -} - -static int -find_function_rowid(SgSG* sg, ExprContext* ctxt, - GuString fun, SgId* pKey, int wrFlag) -{ - int rc = SQLITE_OK; - int file_format = sqlite3BtreeFileFormat(sg->pBtree); - - Mem mem[2]; - mem[0].flags = MEM_Str; - mem[0].n = strlen(fun); - mem[0].z = (void*) fun; - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->crsIdents, 1, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->crsIdents, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) { - return rc; - } - - if (res == 0) { - rc = sqlite3BtreeIdxRowid(sg->pBtree, ctxt->crsIdents, pKey); - } else { - if (wrFlag == 0) { - *pKey = 0; - return SQLITE_OK; - } - - *pKey = ++ctxt->key_seed; - - int serial_type_fun = sqlite3BtreeSerialType(&mem[0], file_format); - int serial_type_fun_hdr_len = sqlite3BtreeVarintLen(serial_type_fun); - - mem[1].flags = MEM_Int; - mem[1].u.i = *pKey; - - int serial_type_key = sqlite3BtreeSerialType(&mem[1], file_format); - int serial_type_key_hdr_len = sqlite3BtreeVarintLen(serial_type_key); - - unsigned char* buf = malloc(1+serial_type_fun_hdr_len+(serial_type_key_hdr_len > 1 ? serial_type_key_hdr_len : 1)+mem[0].n+8); - unsigned char* p = buf; - *p++ = 1+serial_type_fun_hdr_len+1; - p += putVarint32(p, serial_type_fun); - *p++ = 0; - memcpy(p, fun, mem[0].n); - p += mem[0].n; - - rc = sqlite3BtreeInsert(ctxt->crsExprs, 0, *pKey, - buf, p-buf, 0, - 0, 0); - if (rc != SQLITE_OK) { - goto free; - } - - p = buf; - *p++ = 1+serial_type_fun_hdr_len+serial_type_key_hdr_len; - p += putVarint32(p, serial_type_fun); - p += putVarint32(p, serial_type_key); - memcpy(p, fun, mem[0].n); - p += mem[0].n; - p += sqlite3BtreeSerialPut(p, &mem[1], serial_type_key); - rc = sqlite3BtreeInsert(ctxt->crsIdents, buf, p-buf, - 0, *pKey, 0, - 0, 0); - -free: - free(buf); - } - - return rc; -} - -static int -store_expr(SgSG* sg, - ExprContext* ctxt, PgfExpr expr, SgId* pKey, int wrFlag) -{ - int rc = SQLITE_OK; - int file_format = sqlite3BtreeFileFormat(sg->pBtree); - - GuVariantInfo ei = gu_variant_open(expr); - switch (ei.tag) { - case PGF_EXPR_ABS: { - gu_impossible(); - break; - } - case PGF_EXPR_APP: { - PgfExprApp* app = ei.data; - - Mem mem[3]; - - mem[0].flags = MEM_Int; - rc = store_expr(sg, ctxt, app->fun, &mem[0].u.i, wrFlag); - if (rc != SQLITE_OK) - return rc; - if (wrFlag == 0 && mem[0].u.i == 0) { - *pKey = 0; - return SQLITE_OK; - } - - mem[1].flags = MEM_Int; - rc = store_expr(sg, ctxt, app->arg, &mem[1].u.i, wrFlag); - if (rc != SQLITE_OK) - return rc; - if (wrFlag == 0 && mem[1].u.i == 0) { - *pKey = 0; - return SQLITE_OK; - } - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->crsPairs, 2, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->crsPairs, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) { - return rc; - } - - if (res == 0) { - rc = sqlite3BtreeIdxRowid(sg->pBtree, ctxt->crsPairs, pKey); - } else { - if (wrFlag == 0) { - *pKey = 0; - return SQLITE_OK; - } - - *pKey = ++ctxt->key_seed; - - unsigned char buf[32]; // enough for a record with three integers - buf[1] = 3; - - u32 serial_type; - unsigned char* p = buf+4; - - serial_type = sqlite3BtreeSerialType(&mem[0], file_format); - buf[2] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[0], serial_type); - - serial_type = sqlite3BtreeSerialType(&mem[1], file_format); - buf[3] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[1], serial_type); - - rc = sqlite3BtreeInsert(ctxt->crsExprs, 0, *pKey, - buf+1, p-(buf+1), 0, - 0, 0); - if (rc != SQLITE_OK) { - return rc; - } - - buf[0] = 4; - buf[1] = buf[2]; - buf[2] = buf[3]; - - mem[2].flags = MEM_Int; - mem[2].u.i = *pKey; - serial_type = sqlite3BtreeSerialType(&mem[2], file_format); - buf[3] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[2], serial_type); - - rc = sqlite3BtreeInsert(ctxt->crsPairs, buf, p-buf, - 0, *pKey, 0, - 0, 0); - } - break; - } - case PGF_EXPR_LIT: { - PgfExprLit* elit = ei.data; - - Mem mem[2]; - size_t len = 0; - - GuVariantInfo li = gu_variant_open(elit->lit); - switch (li.tag) { - case PGF_LITERAL_STR: { - PgfLiteralStr* lstr = li.data; - - len = strlen(lstr->val); - - mem[0].flags = MEM_Str; - mem[0].n = len; - 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; - len = sizeof(mem[0].u.i); - break; - } - case PGF_LITERAL_FLT: { - PgfLiteralFlt* lflt = li.data; - - mem[0].flags = MEM_Real; - mem[0].u.r = lflt->val; - len = sizeof(mem[0].u.r); - break; - } - default: - gu_impossible(); - } - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->crsIdents, 1, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->crsLiterals, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) { - return rc; - } - - if (res == 0) { - rc = sqlite3BtreeIdxRowid(sg->pBtree, 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 = sqlite3BtreeSerialType(&mem[0], file_format); - int serial_type_lit_hdr_len = sqlite3BtreeVarintLen(serial_type_lit); - int serial_type_arg = sqlite3BtreeSerialType(&mem[1], file_format); - int serial_type_arg_hdr_len = sqlite3BtreeVarintLen(serial_type_arg); - - unsigned char* buf = malloc(1+serial_type_lit_hdr_len+(serial_type_arg_hdr_len > 1 ? serial_type_arg_hdr_len : 1)+len+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 += sqlite3BtreeSerialPut(p, &mem[0], serial_type_lit); - p += sqlite3BtreeSerialPut(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 = sqlite3BtreeSerialType(&mem[1], file_format); - int serial_type_key_hdr_len = sqlite3BtreeVarintLen(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 += sqlite3BtreeSerialPut(p, &mem[0], serial_type_lit); - p += sqlite3BtreeSerialPut(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; - rc = find_function_rowid(sg, ctxt, fun->fun, pKey, wrFlag); - break; - } - case PGF_EXPR_VAR: { - gu_impossible(); - break; - } - case PGF_EXPR_TYPED: { - PgfExprTyped* etyped = ei.data; - rc = store_expr(sg, ctxt, etyped->expr, pKey, wrFlag); - break; - } - case PGF_EXPR_IMPL_ARG: { - PgfExprImplArg* eimpl = ei.data; - rc = store_expr(sg, ctxt, eimpl->expr, pKey, wrFlag); - break; - } - default: - gu_impossible(); - } - - return rc; -} - -SgId -sg_insert_expr(SgSG *sg, PgfExpr expr, int wrFlag, GuExn* err) -{ - int rc; - - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, wrFlag); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return 0; - } - } - - ExprContext ctxt; - rc = open_exprs(sg, wrFlag, false, &ctxt, err); - if (rc != SQLITE_OK) - goto close; - - SgId key; - rc = store_expr(sg, &ctxt, expr, &key, wrFlag); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - close_exprs(&ctxt); - - if (sg->autoCommit) { - rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return 0; - } - } - - return key; - -close: - close_exprs(&ctxt); - - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - return 0; -} - -static int -load_expr(BtCursor* crsExprs, SgId key, PgfExpr *pExpr, GuPool* out_pool) -{ - int res; - int rc = sqlite3BtreeMovetoUnpacked(crsExprs, 0, key, 0, &res); - if (rc != SQLITE_OK) - return rc; - - if (res != 0) { - *pExpr = gu_null_variant; - return SQLITE_OK; - } - - u32 payloadSize; - rc = sqlite3BtreeDataSize(crsExprs, &payloadSize); - if (rc != SQLITE_OK) - return rc; - - u32 avail = 0; - const unsigned char* row = sqlite3BtreeDataFetch(crsExprs, &avail); - row++; - - int serial_type_fun, serial_type_arg; - row += getVarint32(row, serial_type_fun); - row += getVarint32(row, serial_type_arg); - - Mem mem[2]; - row += sqlite3BtreeSerialGet(row, serial_type_fun, &mem[0]); - row += sqlite3BtreeSerialGet(row, serial_type_arg, &mem[1]); - - if (mem[1].flags & MEM_Null) { - u32 len = sqlite3BtreeSerialTypeLen(serial_type_fun); - - PgfExprFun *efun = - gu_new_flex_variant(PGF_EXPR_FUN, - PgfExprFun, - fun, len+1, - 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 = sqlite3BtreeSerialTypeLen(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); - - rc = load_expr(crsExprs, mem[0].u.i, &papp->fun, out_pool); - if (rc != SQLITE_OK) - return rc; - - rc = load_expr(crsExprs, mem[1].u.i, &papp->arg, out_pool); - if (rc != SQLITE_OK) - return rc; - } - - return SQLITE_OK; -} - -PgfExpr -sg_get_expr(SgSG *sg, SgId key, GuPool* out_pool, GuExn* err) -{ - int rc; - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return gu_null_variant; - } - } - - BtCursor* crsExprs; - rc = sqlite3BtreeCursor(sg->pBtree, sg->exprsTNum, 0, 0, 0, &crsExprs); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto rollback; - } - - PgfExpr expr = gu_null_variant; - rc = load_expr(crsExprs, key, &expr, out_pool); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - rc = sqlite3BtreeCloseCursor(crsExprs); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto rollback; - } - - if (sg->autoCommit) { - rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto rollback; - } - } - - return expr; - -close: - sqlite3BtreeCloseCursor(crsExprs); - -rollback: - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - return gu_null_variant; -} - -// A query is compiled into a sequence of instructions with -// the following codes: -#define QI_PUSH 1 -#define QI_VAR 2 -#define QI_APPLY 3 -#define QI_RETURN 4 - -typedef struct { - int code; - SgId arg; -} QueryInstr; - -struct SgQueryExprResult { - ExprContext ectxt; - GuBuf* instrs; - GuBuf* queue; - size_t iState; - PgfMetaId min_meta_id; - PgfMetaId max_meta_id; -}; - -typedef struct QueryArg QueryArg; -struct QueryArg { - QueryArg* prev; - SgId arg; -}; - -typedef struct { - QueryArg* args; // a stack of arguments - int pc; // program counter -} QueryState; - -static int -build_expr_query(SgSG* sg, - SgQueryExprResult* ctxt, PgfExpr expr) -{ - int rc = SQLITE_OK; - - GuVariantInfo ei = gu_variant_open(expr); - switch (ei.tag) { - case PGF_EXPR_ABS: { - gu_impossible(); - break; - } - case PGF_EXPR_APP: { - PgfExprApp* app = ei.data; - - rc = build_expr_query(sg, ctxt, app->fun); - if (rc != SQLITE_OK) - return rc; - QueryInstr* first = - gu_buf_index_last(ctxt->instrs, QueryInstr); - - rc = build_expr_query(sg, ctxt, app->arg); - if (rc != SQLITE_OK) - return rc; - QueryInstr* second = - gu_buf_index_last(ctxt->instrs, QueryInstr); - - if (first->code == QI_PUSH && second->code == QI_PUSH && - second - first == 1) { - // we could directly combine the two expressions - - Mem mem[2]; - mem[0].flags = MEM_Int; - mem[0].u.i = first->arg; - mem[1].flags = MEM_Int; - mem[1].u.i = second->arg; - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->ectxt.crsPairs, 2, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->ectxt.crsPairs, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) - return rc; - if (res != 0) - return SQLITE_DONE; - - gu_buf_pop(ctxt->instrs, QueryInstr); - - rc = sqlite3BtreeIdxRowid(sg->pBtree, ctxt->ectxt.crsPairs, &first->arg); - } else if (gu_variant_tag(app->arg) != PGF_EXPR_META) { - QueryInstr* instr = gu_buf_extend(ctxt->instrs); - instr->code = QI_APPLY; - instr->arg = 0; - } - break; - } - case PGF_EXPR_LIT: { - PgfExprLit* elit = ei.data; - - Mem mem; - - GuVariantInfo li = gu_variant_open(elit->lit); - switch (li.tag) { - case PGF_LITERAL_STR: { - PgfLiteralStr* lstr = li.data; - - mem.flags = MEM_Str; - mem.n = strlen(lstr->val); - mem.z = lstr->val; - break; - } - case PGF_LITERAL_INT: { - PgfLiteralInt* lint = li.data; - - mem.flags = MEM_Int; - mem.u.i = lint->val; - break; - } - case PGF_LITERAL_FLT: { - PgfLiteralFlt* lflt = li.data; - - mem.flags = MEM_Real; - mem.u.r = lflt->val; - break; - } - default: - gu_impossible(); - } - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->ectxt.crsIdents, 1, 0, &mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->ectxt.crsLiterals, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) - return rc; - if (res != 0) - return SQLITE_DONE; - - QueryInstr* instr = gu_buf_extend(ctxt->instrs); - instr->code = QI_PUSH; - rc = sqlite3BtreeIdxRowid(sg->pBtree, ctxt->ectxt.crsLiterals, &instr->arg); - break; - } - case PGF_EXPR_META: { - PgfExprMeta* emeta = ei.data; - QueryInstr* instr = gu_buf_extend(ctxt->instrs); - instr->code = QI_VAR; - instr->arg = emeta->id; - - if (ctxt->min_meta_id > emeta->id) - ctxt->min_meta_id = emeta->id; - if (ctxt->max_meta_id < emeta->id) - ctxt->max_meta_id = emeta->id; - break; - } - case PGF_EXPR_FUN: { - PgfExprFun* fun = ei.data; - - QueryInstr* instr = gu_buf_extend(ctxt->instrs); - instr->code = QI_PUSH; - rc = find_function_rowid(sg, &ctxt->ectxt, fun->fun, &instr->arg, 0); - if (rc == SQLITE_OK && instr->arg == 0) - return SQLITE_DONE; - break; - } - case PGF_EXPR_VAR: { - gu_impossible(); - break; - } - case PGF_EXPR_TYPED: { - PgfExprTyped* etyped = ei.data; - rc = build_expr_query(sg, ctxt, etyped->expr); - break; - } - case PGF_EXPR_IMPL_ARG: { - PgfExprImplArg* eimpl = ei.data; - rc = build_expr_query(sg, ctxt, eimpl->expr); - break; - } - default: - gu_impossible(); - } - - return rc; -} - -static int -run_expr_query(SgSG* sg, SgQueryExprResult* ctxt, GuPool* pool) -{ - int rc; - - while (ctxt->iState < gu_buf_length(ctxt->queue)) { - QueryState* state = - gu_buf_index(ctxt->queue, QueryState, ctxt->iState); - QueryInstr* instr = - gu_buf_index(ctxt->instrs, QueryInstr, state->pc); - - switch (instr->code) { - case QI_PUSH: { - QueryArg* arg = gu_new(QueryArg, pool); - arg->arg = instr->arg; - arg->prev = state->args; - state->args = arg; - break; - } - case QI_VAR: { - assert(state->args != NULL); - - Mem mem; - mem.flags = MEM_Int; - mem.u.i = state->args->arg; - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->ectxt.crsPairs, 1, 1, &mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->ectxt.crsPairs, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) - return rc; - if (res < 0) { - rc = sqlite3BtreeNext(ctxt->ectxt.crsPairs, &res); - } - res = 0; - - while (res == 0) { - i64 szData; - const unsigned char *zData; - rc = sqlite3BtreeKeySize(ctxt->ectxt.crsPairs, &szData); - if (rc != SQLITE_OK) - return rc; - - u32 available = 0; - zData = sqlite3BtreeKeyFetch(ctxt->ectxt.crsPairs, &available); - if (szData > available) - gu_impossible(); - - idxKey.default_rc = 0; - res = sqlite3BtreeRecordCompare(available, zData, &idxKey); - if (res != 0) - break; - - QueryArg* arg = gu_new(QueryArg, pool); - arg->prev = state->args->prev; - - QueryState* state1 = gu_buf_extend(ctxt->queue); - state1->args = arg; - state1->pc = state->pc+1; - - rc = sqlite3BtreeIdxRowid(sg->pBtree, ctxt->ectxt.crsPairs, &arg->arg); - if (rc != SQLITE_OK) - return rc; - - sqlite3BtreeNext(ctxt->ectxt.crsPairs, &res); - if (rc != SQLITE_OK) - return rc; - } - - ctxt->iState++; - break; - } - case QI_APPLY: { - assert(state->args != NULL && state->args->prev); - - Mem mem[2]; - mem[0].flags = MEM_Int; - mem[0].u.i = state->args->prev->arg; - mem[1].flags = MEM_Int; - mem[1].u.i = state->args->arg; - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, ctxt->ectxt.crsPairs, 2, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(ctxt->ectxt.crsPairs, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) - return rc; - if (res != 0) { - ctxt->iState++; - continue; - } - - state->args = state->args->prev; - - rc = sqlite3BtreeIdxRowid(sg->pBtree, ctxt->ectxt.crsPairs, &state->args->arg); - if (rc != SQLITE_OK) - return rc; - break; - } - case QI_RETURN: - return SQLITE_OK; - } - - state->pc++; - } - - return SQLITE_DONE; -} - -SgQueryExprResult* -sg_query_expr(SgSG *sg, PgfExpr expr, GuPool* pool, GuExn* err) -{ - int rc; - - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return NULL; - } - } - - SgQueryExprResult* ctxt = gu_new(SgQueryExprResult, pool); - rc = open_exprs(sg, 0, false, &ctxt->ectxt, err); - if (rc != SQLITE_OK) - goto close; - - ctxt->instrs = gu_new_buf(QueryInstr, pool); - ctxt->queue = gu_new_buf(QueryState, pool); - ctxt->iState = 0; - ctxt->min_meta_id = INT_MAX; - ctxt->max_meta_id = INT_MIN; - - rc = build_expr_query(sg, ctxt, expr); - if (rc == SQLITE_OK) { - QueryInstr* instr = gu_buf_extend(ctxt->instrs); - instr->code = QI_RETURN; - instr->arg = 0; - - QueryState* state = gu_buf_extend(ctxt->queue); - state->args = NULL; - state->pc = 0; - } else if (rc != SQLITE_DONE) { - sg_raise_sqlite(rc, err); - goto close; - } - - return ctxt; - -close: - close_exprs(&ctxt->ectxt); - - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - return NULL; -} - -PgfExpr -sg_query_next(SgSG *sg, SgQueryExprResult* ctxt, SgId* pKey, GuPool* pool, GuExn* err) -{ - int rc; - - rc = run_expr_query(sg, ctxt, pool); - if (rc == SQLITE_DONE) - return gu_null_variant; - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return gu_null_variant; - } - - QueryState* state = - gu_buf_index(ctxt->queue, QueryState, ctxt->iState); - assert(state->args != NULL); - ctxt->iState++; - - PgfExpr expr; - rc = load_expr(ctxt->ectxt.crsExprs, state->args->arg, &expr, pool); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return gu_null_variant; - } - - *pKey = state->args->arg; - - return expr; -} - -void -sg_query_close(SgSG* sg, SgQueryExprResult* ctxt, GuExn* err) -{ - int rc; - - close_exprs(&ctxt->ectxt); - - if (sg->autoCommit) { - rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - } - } -} - -static int -insert_token(SgSG *sg, BtCursor* crsTokens, GuString tok, SgId key) -{ - int rc = SQLITE_OK; - int file_format = sqlite3BtreeFileFormat(sg->pBtree); - - Mem mem[2]; - mem[0].flags = MEM_Str; - mem[0].n = strlen(tok); - mem[0].z = (void*) tok; - - int serial_type_tok = sqlite3BtreeSerialType(&mem[0], file_format); - int serial_type_tok_hdr_len = sqlite3BtreeVarintLen(serial_type_tok); - - mem[1].flags = MEM_Int; - mem[1].u.i = key; - - int serial_type_key = sqlite3BtreeSerialType(&mem[1], file_format); - int serial_type_key_hdr_len = sqlite3BtreeVarintLen(serial_type_key); - - unsigned char* buf = malloc(1+serial_type_tok_hdr_len+serial_type_key_hdr_len+mem[0].n+8); - unsigned char* p = buf; - *p++ = 1+serial_type_tok_hdr_len+serial_type_key_hdr_len; - p += putVarint32(p, serial_type_tok); - p += putVarint32(p, serial_type_key); - memcpy(p, tok, mem[0].n); - p += mem[0].n; - p += sqlite3BtreeSerialPut(p, &mem[1], serial_type_key); - rc = sqlite3BtreeInsert(crsTokens, buf, p-buf, - 0, key, 0, - 0, 0); - free(buf); - - return rc; -} - -static int -insert_syms(SgSG *sg, BtCursor* crsTokens, PgfSymbols* syms, SgId key) -{ - int rc; - size_t n_syms = gu_seq_length(syms); - for (size_t sym_idx = 0; sym_idx < n_syms; sym_idx++) { - PgfSymbol sym = gu_seq_get(syms, PgfSymbol, sym_idx); - GuVariantInfo sym_i = gu_variant_open(sym); - switch (sym_i.tag) { - case PGF_SYMBOL_KS: { - PgfSymbolKS* ks = sym_i.data; - rc = insert_token(sg, crsTokens, ks->token, key); - if (rc != SQLITE_OK) - return rc; - break; - } - case PGF_SYMBOL_KP: { - PgfSymbolKP* kp = sym_i.data; - rc = insert_syms(sg, crsTokens, kp->default_form, key); - if (rc != SQLITE_OK) - return rc; - - for (size_t i = 0; i < kp->n_forms; i++) { - rc = insert_syms(sg, crsTokens, kp->forms[i].form, key); - if (rc != SQLITE_OK) - return rc; - } - break; - } - } - } - - return SQLITE_OK; -} - -void -sg_update_fts_index(SgSG* sg, PgfPGF* pgf, GuExn* err) -{ - int rc = SQLITE_OK; - - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 1); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - } - - ExprContext ctxt; - rc = open_exprs(sg, 1, true, &ctxt, err); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - rc = sqlite3BtreeClearTable(sg->pBtree, sg->tokensTNum, NULL); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - - BtCursor* crsTokens; - rc = sqlite3BtreeCursor(sg->pBtree, sg->tokensTNum, 1, 1, 1, &crsTokens); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - } - ctxt.n_cursors++; - - size_t n_concrs = gu_seq_length(pgf->concretes); - for (size_t i = 0; i < n_concrs; i++) { - PgfConcr* concr = gu_seq_index(pgf->concretes, PgfConcr, i); - - size_t n_funs = gu_seq_length(concr->cncfuns); - for (size_t funid = 0; funid < n_funs; funid++) { - PgfCncFun* cncfun = gu_seq_get(concr->cncfuns, PgfCncFun*, funid); - - SgId key = 0; - rc = find_function_rowid(sg, &ctxt, cncfun->absfun->name, &key, 1); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - for (size_t lin_idx = 0; lin_idx < cncfun->n_lins; lin_idx++) { - PgfSequence* seq = cncfun->lins[lin_idx]; - rc = insert_syms(sg, crsTokens, seq->syms, key); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - } - } - } - - if (ctxt.n_cursors >= 3) { - sqlite3BtreeCloseCursor(crsTokens); - ctxt.n_cursors--; - } - - close_exprs(&ctxt); - - if (sg->autoCommit) { - rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - } - } - - return; - -close: - if (ctxt.n_cursors >= 3) { - sqlite3BtreeCloseCursor(crsTokens); - ctxt.n_cursors--; - } - - close_exprs(&ctxt); - - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } -} - -GuSeq* -sg_query_linearization(SgSG *sg, GuString tok, GuPool *pool, GuExn* err) -{ - int rc; - - BtCursor* crsTokens; - rc = sqlite3BtreeCursor(sg->pBtree, sg->tokensTNum, 1, 1, 1, &crsTokens); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return NULL; - } - - Mem mem[1]; - mem[0].flags = MEM_Str; - mem[0].n = strlen(tok); - mem[0].z = (void*) tok; - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, crsTokens, 1, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(crsTokens, - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return NULL; - } - - GuBuf* ids = gu_new_buf(SgId, pool); - - while (res == 0) { - SgId key; - rc = sqlite3BtreeIdxRowid(sg->pBtree, crsTokens, &key); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - sqlite3BtreeClearCursor(crsTokens); - return NULL; - } - - gu_buf_push(ids, SgId, key); - - sqlite3BtreeNext(crsTokens, &res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - sqlite3BtreeClearCursor(crsTokens); - return NULL; - } - - i64 szData; - const unsigned char *zData; - rc = sqlite3BtreeKeySize(crsTokens, &szData); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - sqlite3BtreeClearCursor(crsTokens); - return NULL; - } - - u32 available = 0; - zData = sqlite3BtreeKeyFetch(crsTokens, &available); - if (szData > available) - gu_impossible(); - - res = sqlite3BtreeRecordCompare(available, zData, &idxKey); - if (res != 0) - break; - } - - sqlite3BtreeClearCursor(crsTokens); - return gu_buf_data_seq(ids); -} - -typedef struct { - int n_cursors; - BtCursor* cursor[4]; -} TripleContext; - -static int -open_triples(SgSG *sg, int wrFlag, TripleContext* ctxt, GuExn* err) -{ - int rc; - - ctxt->n_cursors = 0; - while (ctxt->n_cursors < 3) { - rc = sqlite3BtreeCursor(sg->pBtree, sg->triplesIdxTNum[ctxt->n_cursors], wrFlag, 3-ctxt->n_cursors, ctxt->n_cursors, &ctxt->cursor[ctxt->n_cursors]); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - ctxt->n_cursors++; - } - - rc = sqlite3BtreeCursor(sg->pBtree, sg->triplesTNum, wrFlag, 0, 0, &ctxt->cursor[ctxt->n_cursors]); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return rc; - } - ctxt->n_cursors++; - - return SQLITE_OK; -} - -static void -close_triples(TripleContext* ctxt) -{ - while (ctxt->n_cursors > 0) { - ctxt->n_cursors--; - sqlite3BtreeCloseCursor(ctxt->cursor[ctxt->n_cursors]); - } -} - -SgId -sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err) -{ - int rc; - - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 1); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return 0; - } - } - - TripleContext tctxt; - rc = open_triples(sg, 1, &tctxt, err); - if (rc != SQLITE_OK) - goto close; - - Mem mem[4]; - - ExprContext ectxt; - rc = open_exprs(sg, 1, false, &ectxt, err); - if (rc != SQLITE_OK) - goto close; - - for (size_t i = 0; i < 3; i++) { - mem[i].flags = MEM_Int; - - rc = store_expr(sg, &ectxt, triple[i], &mem[i].u.i, 1); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - } - - UnpackedRecord idxKey; - sqlite3BtreeInitUnpackedRecord(&idxKey, tctxt.cursor[0], 3, 0, mem); - - int res = 0; - rc = sqlite3BtreeMovetoUnpacked(tctxt.cursor[0], - &idxKey, 0, 0, &res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - SgId key = 0; - - if (res == 0) { - rc = sqlite3BtreeIdxRowid(sg->pBtree, tctxt.cursor[0], &key); - } else { - rc = sqlite3BtreeLast(tctxt.cursor[3], &res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - rc = sqlite3BtreeKeySize(tctxt.cursor[3], &key); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - key++; - - u32 serial_type; - unsigned char buf[41]; // enough for a record with three integers - int file_format = sqlite3BtreeFileFormat(sg->pBtree); - - unsigned char* p = buf+(buf[0] = 5); - - serial_type = sqlite3BtreeSerialType(&mem[0], file_format); - buf[1] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[0], serial_type); - - serial_type = sqlite3BtreeSerialType(&mem[1], file_format); - buf[2] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[1], serial_type); - - serial_type = sqlite3BtreeSerialType(&mem[2], file_format); - buf[3] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[2], serial_type); - - unsigned char* tmp = p; - - mem[3].flags = MEM_Int; - mem[3].u.i = 1; - serial_type = sqlite3BtreeSerialType(&mem[3], file_format); - buf[4] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[3], serial_type); - - rc = sqlite3BtreeInsert(tctxt.cursor[3], 0, key, - buf, p-buf, 0, - 0, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - mem[3].flags = MEM_Int; - mem[3].u.i = key; - - p = tmp; - serial_type = sqlite3BtreeSerialType(&mem[3], file_format); - buf[4] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[3], serial_type); - - rc = sqlite3BtreeInsert(tctxt.cursor[0], buf, p-buf, - 0, key, 0, - 0, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - p = buf+(buf[0] = 4); - - serial_type = sqlite3BtreeSerialType(&mem[1], file_format); - buf[1] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[1], serial_type); - - serial_type = sqlite3BtreeSerialType(&mem[2], file_format); - buf[2] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[2], serial_type); - - serial_type = sqlite3BtreeSerialType(&mem[3], file_format); - buf[3] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[3], serial_type); - - rc = sqlite3BtreeInsert(tctxt.cursor[1], buf, p-buf, - 0, key, 0, - 0, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - p = buf+(buf[0] = 3); - - serial_type = sqlite3BtreeSerialType(&mem[2], file_format); - buf[1] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[2], serial_type); - - serial_type = sqlite3BtreeSerialType(&mem[3], file_format); - buf[2] = serial_type; - p += sqlite3BtreeSerialPut(p, &mem[3], serial_type); - - rc = sqlite3BtreeInsert(tctxt.cursor[2], buf, p-buf, - 0, key, 0, - 0, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - } - -close: - close_exprs(&ectxt); - close_triples(&tctxt); - - if (sg->autoCommit) { - if (rc == SQLITE_OK || rc == SQLITE_DONE) { - rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return 0; - } - } else { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - } - - return key; -} - -static int -load_triple(BtCursor* crsTriples, BtCursor* crsExprs, SgTriple triple, - GuPool* out_pool) -{ - int rc; - - u32 payloadSize; - rc = sqlite3BtreeDataSize(crsTriples, &payloadSize); - if (rc != SQLITE_OK) - return rc; - - u32 avail = 0; - const unsigned char* row = sqlite3BtreeDataFetch(crsTriples, &avail); - row++; - - int serial_type_subj, serial_type_pred, serial_type_obj; - row += getVarint32(row, serial_type_subj); - row += getVarint32(row, serial_type_pred); - row += getVarint32(row, serial_type_obj); - row++; - - Mem mem[3]; - row += sqlite3BtreeSerialGet(row, serial_type_subj, &mem[0]); - row += sqlite3BtreeSerialGet(row, serial_type_pred, &mem[1]); - row += sqlite3BtreeSerialGet(row, serial_type_obj, &mem[2]); - - for (int i = 0; i < 3; i++) { - if (gu_variant_is_null(triple[i])) { - rc = load_expr(crsExprs, mem[i].u.i, &triple[i], out_pool); - if (rc != SQLITE_OK) - return rc; - } - } - - return SQLITE_OK; -} - -int -sg_get_triple(SgSG *sg, SgId key, SgTriple triple, - GuPool* out_pool, GuExn* err) -{ - triple[0] = gu_null_variant; - triple[1] = gu_null_variant; - triple[2] = gu_null_variant; - - int rc; - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return false; - } - } - - BtCursor* crsTriples; - rc = sqlite3BtreeCursor(sg->pBtree, sg->triplesTNum, 0, 0, 0, &crsTriples); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto rollback; - } - - BtCursor* crsExprs; - rc = sqlite3BtreeCursor(sg->pBtree, sg->exprsTNum, 0, 0, 0, &crsExprs); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close1; - } - - int res; - rc = sqlite3BtreeMovetoUnpacked(crsTriples, 0, key, 0, &res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - if (res == 0) { - rc = load_triple(crsTriples, crsExprs, triple, out_pool); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - } - - rc = sqlite3BtreeCloseCursor(crsExprs); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close1; - } - - rc = sqlite3BtreeCloseCursor(crsTriples); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto rollback; - } - - if (sg->autoCommit) { - rc = sqlite3BtreeCommit(sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return false; - } - } - - return (res == 0); - -close: - sqlite3BtreeCloseCursor(crsExprs); - -close1: - sqlite3BtreeCloseCursor(crsTriples); - -rollback: - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - return false; -} - -typedef struct { - TripleContext tctxt; - - BtCursor* cursor; - - int res; - Mem mem[3]; - UnpackedRecord idxKey; -} SgTripleResultInt; - -struct SgTripleResult { - SgSG *sg; - SgTriple triple; - ExprContext ectxt; - - SgTripleResultInt i; -}; - -static int -triple_result_init(SgSG *sg, SgTripleResultInt* tresi, GuExn* err) -{ - int rc; - - rc = open_triples(sg, 0, &tresi->tctxt, err); - if (rc != SQLITE_OK) - return rc; - - int i = 0; - while (i < 3) { - if (tresi->mem[i].flags != MEM_Null) - break; - i++; - } - - tresi->cursor = tresi->tctxt.cursor[i]; - sqlite3BtreeInitUnpackedRecord(&tresi->idxKey, tresi->cursor, 0, 0, &tresi->mem[i]); - tresi->res = 0; - - while (i+tresi->idxKey.nField < 3) { - tresi->idxKey.nField++; - - if (tresi->mem[i+tresi->idxKey.nField].flags == MEM_Null) - break; - } - - if (tresi->idxKey.nField > 0) { - tresi->idxKey.default_rc = 1; - rc = sqlite3BtreeMovetoUnpacked(tresi->cursor, - &tresi->idxKey, 0, 0, &tresi->res); - if (rc == SQLITE_OK) { - if (tresi->res < 0) { - rc = sqlite3BtreeNext(tresi->cursor, &tresi->res); - } - tresi->res = 0; - } - } else { - rc = sqlite3BtreeFirst(tresi->cursor, &tresi->res); - } - - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - } - - return rc; -} - -static bool -triple_result_fetch(SgSG* sg, - SgTripleResultInt* tresi, - SgId* pKey, GuExn* err) -{ - while (tresi->res == 0) { - int rc; - - if (tresi->idxKey.nField > 0) { - i64 szData; - const unsigned char *zData; - rc = sqlite3BtreeKeySize(tresi->cursor, &szData); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return false; - } - - u32 available = 0; - zData = sqlite3BtreeKeyFetch(tresi->cursor, &available); - if (szData > available) - gu_impossible(); - - tresi->idxKey.default_rc = 0; - tresi->res = sqlite3BtreeRecordCompare(available, zData, &tresi->idxKey); - if (tresi->res != 0) - return false; - - if (tresi->idxKey.aMem == &tresi->mem[0] && - tresi->idxKey.nField == 1 && - tresi->mem[2].flags != MEM_Null) { - int offset = - zData[0] + - sqlite3BtreeSerialTypeLen(zData[1]) + - sqlite3BtreeSerialTypeLen(zData[2]); - zData+offset; - Mem mem; - sqlite3BtreeSerialGet(zData+offset, zData[3], &mem); - if (mem.u.i != tresi->mem[2].u.i) { - sqlite3BtreeNext(tresi->cursor, &tresi->res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return false; - } - continue; - } - } - - rc = sqlite3BtreeIdxRowid(sg->pBtree, tresi->cursor, pKey); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return false; - } - - rc = sqlite3BtreeMovetoUnpacked(tresi->tctxt.cursor[3], 0, *pKey, 0, &tresi->res); - } else { - rc = sqlite3BtreeKeySize(tresi->cursor, pKey); - } - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return false; - } - - return true; - } - - return false; -} - -SgTripleResult* -sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err) -{ - int rc; - - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return NULL; - } - } - - SgTripleResult* tres = malloc(sizeof(SgTripleResult)); - tres->sg = sg; - tres->triple[0] = triple[0]; - tres->triple[1] = triple[1]; - tres->triple[2] = triple[2]; - - rc = open_exprs(sg, 0, false, &tres->ectxt, err); - if (rc != SQLITE_OK) - goto close; - - for (int i = 0; i < 3; i++) { - if (gu_variant_is_null(triple[i])) - tres->i.mem[i].flags = MEM_Null; - else { - tres->i.mem[i].flags = MEM_Int; - rc = store_expr(sg, &tres->ectxt, triple[i], &tres->i.mem[i].u.i, 0); - if (rc != SQLITE_OK) - goto close; - if (tres->i.mem[i].u.i == 0) { - tres->i.res = 1; - tres->i.tctxt.n_cursors = 0; // this is important since the triples are not initialized yet - return tres; - } - } - } - - rc = triple_result_init(sg, &tres->i, err); - if (rc != SQLITE_OK) { - return NULL; - } - - return tres; - -close: - close_exprs(&tres->ectxt); - - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - - free(tres); - return NULL; -} - -int -sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, - GuPool* out_pool, GuExn* err) -{ - int rc; - - triple[0] = tres->triple[0]; - triple[1] = tres->triple[1]; - triple[2] = tres->triple[2]; - - bool found = - triple_result_fetch(tres->sg, &tres->i, pKey, err); - if (!found) - return 0; - - rc = load_triple(tres->i.tctxt.cursor[3], tres->ectxt.crsExprs, - triple, out_pool); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return 0; - } - - sqlite3BtreeNext(tres->i.cursor, &tres->i.res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return 0; - } - - return 1; -} - -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) -{ - close_exprs(&tres->ectxt); - close_triples(&tres->i.tctxt); - - if (tres->sg->autoCommit) { - int rc = sqlite3BtreeCommit(tres->sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - } - - free(tres); -} - -typedef int SgPattern[3]; - -struct SgQueryResult { - SgSG* sg; - - size_t n_vars; - struct { - SgId id; - PgfExpr expr; - }* vars; - - size_t n_sels; - int* sels; - - ExprContext ectxt; - bool is_empty; - - size_t n_results; - size_t n_patterns; - struct { - SgPattern pattern; - SgTripleResultInt result; - } triples[]; -}; - -SgQueryResult* -sg_query(SgSG *sg, size_t n_triples, SgTriple* triples, GuExn* err) -{ - int rc; - - if (sg->autoCommit) { - rc = sqlite3BtreeBeginTrans(sg->pBtree, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return NULL; - } - } - - SgQueryResult* qres = malloc(GU_FLEX_SIZE(SgQueryResult, triples, n_triples)); - qres->sg = sg; - qres->is_empty = false; - qres->n_results = 0; - - qres->n_vars = 0; - qres->vars = malloc(sizeof(qres->vars[0])*n_triples*3); - - qres->n_sels = 0; - qres->sels = malloc(sizeof(int)*n_triples*3); - - rc = open_exprs(sg, 0, false, &qres->ectxt, err); - if (rc != SQLITE_OK) - goto close; - - qres->n_patterns = n_triples; - for (size_t i = 0; i < n_triples; i++) { - for (int k = 0; k < 3; k++) { - PgfExpr expr = triples[i][k]; - - size_t j = 0; - while (j < qres->n_vars) { - if (pgf_expr_eq(expr, qres->vars[j].expr)) - break; - j++; - } - if (j >= qres->n_vars) { - qres->vars[j].expr = expr; - - if (gu_variant_tag(expr) == PGF_EXPR_META) { - qres->vars[j].id = 0; - qres->sels[qres->n_sels++] = j; - qres->triples[i].result.mem[k].flags = MEM_Null; - } else { - rc = store_expr(sg, &qres->ectxt, expr, &qres->vars[j].id, 0); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - if (qres->vars[j].id == 0) - goto close; - - qres->triples[i].result.mem[k].flags = MEM_Int; - } - - qres->n_vars++; - } else { - qres->triples[i].result.mem[k].flags = MEM_Int; - } - - qres->triples[i].pattern[k] = j; - } - } - - return qres; - -close: - qres->is_empty = true; - - close_exprs(&qres->ectxt); - - if (sg->autoCommit) { - sqlite3BtreeRollback(sg->pBtree, SQLITE_ABORT_ROLLBACK, 0); - } - - return qres; -} - -size_t -sg_query_result_columns(SgQueryResult* qres) { - return qres->n_sels; -} - -static int -load_vars(SgQueryResult* qres, BtCursor* crsTriples, SgPattern pattern) -{ - int rc; - - u32 payloadSize; - rc = sqlite3BtreeDataSize(crsTriples, &payloadSize); - if (rc != SQLITE_OK) - return rc; - - u32 avail = 0; - const unsigned char* row = sqlite3BtreeDataFetch(crsTriples, &avail); - row++; - - int serial_type_subj, serial_type_pred, serial_type_obj; - row += getVarint32(row, serial_type_subj); - row += getVarint32(row, serial_type_pred); - row += getVarint32(row, serial_type_obj); - row++; - - Mem mem[3]; - row += sqlite3BtreeSerialGet(row, serial_type_subj, &mem[0]); - row += sqlite3BtreeSerialGet(row, serial_type_pred, &mem[1]); - row += sqlite3BtreeSerialGet(row, serial_type_obj, &mem[2]); - - for (int i = 0; i < 3; i++) { - qres->vars[pattern[i]].id = mem[i].u.i; - } - - return SQLITE_OK; -} - -int -query_result_next(SgQueryResult* qres, GuExn* err) -{ - if (qres->is_empty) - return 0; - - int rc; - - SgId key; - size_t i = (qres->n_results == 0) ? 0 : qres->n_results-1; - while (i < qres->n_patterns) { - if (i >= qres->n_results) { - for (int k = 0; k < 3; k++) { - qres->triples[i].result.mem[k].u.i = qres->vars[qres->triples[i].pattern[k]].id; - } - - rc = triple_result_init(qres->sg, &qres->triples[i].result, err); - if (rc != SQLITE_OK) { - goto close; - } - - qres->n_results++; - } - - bool found = - triple_result_fetch(qres->sg, - &qres->triples[i].result, - &key, err); - if (gu_exn_is_raised(err)) { - goto close; - } - - if (found) { - rc = sqlite3BtreeNext(qres->triples[i].result.cursor, &qres->triples[i].result.res); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - rc = load_vars(qres, qres->triples[i].result.tctxt.cursor[3], qres->triples[i].pattern); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - goto close; - } - - i++; - } else { - close_triples(&qres->triples[i].result.tctxt); - - if (i == 0) - goto close; - - i--; - qres->n_results--; - } - } - -close: - qres->is_empty = true; - return 0; -} - -int -sg_query_result_fetch(SgQueryResult* qres, PgfExpr* res, - GuPool* out_pool, GuExn* err) -{ - if (!query_result_next(qres, err)) - return 0; - - for (size_t i = 0; i < qres->n_sels; i++) { - int rc = load_expr(qres->ectxt.crsExprs, - qres->vars[qres->sels[i]].id, - &res[i], out_pool); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - qres->is_empty = true; - return 0; - } - } - - return 1; -} - -static PgfExpr -instantiate_expr(SgQueryResult* qres, PgfExpr expr, - GuPool* out_pool, GuExn* err) -{ - PgfExpr new_expr = gu_null_variant; - - GuVariantInfo ei = gu_variant_open(expr); - switch (ei.tag) { - case PGF_EXPR_ABS: { - PgfExprAbs* abs = ei.data; - - PgfExprAbs* new_abs = - gu_new_variant(PGF_EXPR_ABS, - PgfExprAbs, - &new_expr, out_pool); - new_abs->bind_type = abs->bind_type; - new_abs->id = gu_string_copy(abs->id, out_pool); - new_abs->body = instantiate_expr(qres, abs->body, out_pool, err); - break; - } - case PGF_EXPR_APP: { - PgfExprApp* app = ei.data; - - PgfExprApp* new_app = - gu_new_variant(PGF_EXPR_APP, - PgfExprApp, - &new_expr, out_pool); - new_app->fun = instantiate_expr(qres, app->fun, out_pool, err); - new_app->arg = instantiate_expr(qres, app->arg, out_pool, err); - break; - } - case PGF_EXPR_LIT: { - PgfExprLit* lit = ei.data; - - PgfExprLit* new_lit = - gu_new_variant(PGF_EXPR_LIT, - PgfExprLit, - &new_expr, out_pool); - - GuVariantInfo i = gu_variant_open(lit->lit); - switch (i.tag) { - case PGF_LITERAL_STR: { - PgfLiteralStr* lstr = i.data; - - PgfLiteralStr* new_lstr = - gu_new_flex_variant(PGF_LITERAL_STR, - PgfLiteralStr, - val, strlen(lstr->val)+1, - &new_lit->lit, out_pool); - strcpy(new_lstr->val, lstr->val); - break; - } - case PGF_LITERAL_INT: { - PgfLiteralInt* lint = i.data; - - PgfLiteralInt* new_lint = - gu_new_variant(PGF_LITERAL_INT, - PgfLiteralInt, - &new_lit->lit, out_pool); - new_lint->val = lint->val; - break; - } - case PGF_LITERAL_FLT: { - PgfLiteralFlt* lflt = i.data; - - PgfLiteralFlt* new_lflt = - gu_new_variant(PGF_LITERAL_FLT, - PgfLiteralFlt, - &new_lit->lit, out_pool); - new_lflt->val = lflt->val; - break; - } - default: - gu_impossible(); - } - - break; - } - case PGF_EXPR_META: { - new_expr = expr; - - size_t j = 0; - while (j < qres->n_vars) { - if (pgf_expr_eq(expr, qres->vars[j].expr)) { - - int rc = load_expr(qres->ectxt.crsExprs, - qres->vars[j].id, - &new_expr, out_pool); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - qres->is_empty = true; - return new_expr; - } - break; - } - j++; - } - - break; - } - case PGF_EXPR_FUN: { - PgfExprFun* fun = ei.data; - - PgfExprFun *new_fun = - gu_new_flex_variant(PGF_EXPR_FUN, - PgfExprFun, - fun, strlen(fun->fun)+1, - &new_expr, out_pool); - strcpy(new_fun->fun, fun->fun); - break; - } - case PGF_EXPR_VAR: { - PgfExprVar* var = ei.data; - - PgfExprVar* new_var = - gu_new_variant(PGF_EXPR_VAR, - PgfExprVar, - &new_expr, out_pool); - new_var->var = var->var; - break; - } - case PGF_EXPR_TYPED: { - break; - } - case PGF_EXPR_IMPL_ARG: { - PgfExprImplArg* impl = ei.data; - - PgfExprImplArg* new_impl = - gu_new_variant(PGF_EXPR_IMPL_ARG, - PgfExprImplArg, - &new_expr, out_pool); - new_impl->expr = instantiate_expr(qres, impl->expr, out_pool, err); - break; - } - default: - gu_impossible(); - } - - return new_expr; -} - -PgfExpr -sg_query_result_fetch_expr(SgQueryResult* qres, PgfExpr expr, - GuPool* out_pool, GuExn* err) -{ - if (!query_result_next(qres, err)) - return gu_null_variant; - - return instantiate_expr(qres, expr, out_pool, err); -} - -void -sg_query_result_close(SgQueryResult* qres, GuExn* err) -{ - while (qres->n_results > 0) { - close_triples(&qres->triples[qres->n_results-1].result.tctxt); - qres->n_results--; - } - - close_exprs(&qres->ectxt); - - if (qres->sg->autoCommit) { - int rc = sqlite3BtreeCommit(qres->sg->pBtree); - if (rc != SQLITE_OK) { - sg_raise_sqlite(rc, err); - return; - } - } - - free(qres->vars); - free(qres->sels); - free(qres); -} |
