summaryrefslogtreecommitdiff
path: root/src/runtime/c/sg/sg.c
diff options
context:
space:
mode:
authorkrangelov <kr.angelov@gmail.com>2020-07-08 21:12:01 +0200
committerkrangelov <kr.angelov@gmail.com>2020-07-08 21:12:01 +0200
commit33818076ff553510b5e4a4d0295388d07ece2ec4 (patch)
treeb381152f5f8f8bb7847ed59ff75c0ae00af1f3ef /src/runtime/c/sg/sg.c
parent47d1da0845814b947113a6786555e6d2672f6533 (diff)
drop the SG library completely.
Diffstat (limited to 'src/runtime/c/sg/sg.c')
-rw-r--r--src/runtime/c/sg/sg.c2408
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);
-}