summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/runtime/c/sg/sg.c523
-rw-r--r--src/runtime/c/sg/sg.h14
2 files changed, 330 insertions, 207 deletions
diff --git a/src/runtime/c/sg/sg.c b/src/runtime/c/sg/sg.c
index e1a52692a..88ac3f44d 100644
--- a/src/runtime/c/sg/sg.c
+++ b/src/runtime/c/sg/sg.c
@@ -11,15 +11,6 @@
#define SG_TRIPLES_PO "sg_triples_po"
#define SG_TRIPLES_O "sg_triples_o"
-typedef struct {
- sqlite3 *db;
- BtCursor* crsExprs;
- BtCursor* crsPairs;
- BtCursor* crsIdents;
- SgId key_seed;
- int file_format;
-} StoreContext;
-
void
sg_raise_sqlite(sqlite3* db, GuExn* err)
{
@@ -127,10 +118,112 @@ sg_rollback(SgSG* sg, GuExn* err)
db->autoCommit = 1;
}
+typedef struct {
+ int n_cursors;
+ BtCursor crsExprs;
+ BtCursor crsPairs;
+ BtCursor crsIdents;
+ SgId key_seed;
+} ExprContext;
+
static int
-store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
+open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err)
+{
+ ctxt->n_cursors = 0;
+
+ Table *exprsTbl =
+ sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_EXPRS);
+ if (!exprsTbl) {
+ sg_raise_err("Table " SG_EXPRS " is missing", err);
+ return SQLITE_ERROR;
+ }
+
+ Index *pairsIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_PAIRS);
+ if (!pairsIdx) {
+ sg_raise_err("Index " SG_PAIRS " is missing", err);
+ return SQLITE_ERROR;
+ }
+
+ Index *identsIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_IDENTS);
+ if (!identsIdx) {
+ sg_raise_err("Index " SG_IDENTS " is missing", err);
+ return SQLITE_ERROR;
+ }
+
+ int rc;
+
+ memset(&ctxt->crsExprs, 0, sizeof(ctxt->crsExprs));
+ rc = sqlite3BtreeCursor(db->aDb[0].pBt, exprsTbl->tnum, wrFlag, NULL, &ctxt->crsExprs);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return rc;
+ }
+ ctxt->n_cursors++;
+
+ memset(&ctxt->crsPairs, 0, sizeof(ctxt->crsPairs));
+ KeyInfo *infPairs = sqlite3KeyInfoAlloc(db, 2, 0);
+ rc = sqlite3BtreeCursor(db->aDb[0].pBt, pairsIdx->tnum, wrFlag, infPairs, &ctxt->crsPairs);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return rc;
+ }
+ ctxt->n_cursors++;
+
+ memset(&ctxt->crsIdents, 0, sizeof(ctxt->crsIdents));
+ KeyInfo *infIdents = sqlite3KeyInfoAlloc(db, 1, 1);
+ rc = sqlite3BtreeCursor(db->aDb[0].pBt, identsIdx->tnum, wrFlag, infIdents, &ctxt->crsIdents);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return rc;
+ }
+ ctxt->n_cursors++;
+
+ if (wrFlag) {
+ int res;
+ rc = sqlite3BtreeLast(&ctxt->crsExprs, &res);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return rc;
+ }
+
+ rc = sqlite3BtreeKeySize(&ctxt->crsExprs, &ctxt->key_seed);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return rc;
+ }
+ } else {
+ ctxt->key_seed = 0;
+ }
+
+ return SQLITE_OK;
+}
+
+static void
+close_exprs(ExprContext* ctxt)
+{
+ if (ctxt->n_cursors >= 3) {
+ sqlite3KeyInfoUnref(ctxt->crsIdents.pKeyInfo);
+ sqlite3BtreeCloseCursor(&ctxt->crsIdents);
+ }
+
+ if (ctxt->n_cursors >= 2) {
+ sqlite3KeyInfoUnref(ctxt->crsPairs.pKeyInfo);
+ sqlite3BtreeCloseCursor(&ctxt->crsPairs);
+ }
+
+ if (ctxt->n_cursors >= 1) {
+ sqlite3BtreeCloseCursor(&ctxt->crsExprs);
+ }
+
+ ctxt->n_cursors = 0;
+}
+
+static int
+store_expr(sqlite3* db,
+ ExprContext* ctxt, PgfExpr expr, SgId* pKey, int wrFlag)
{
int rc = SQLITE_OK;
+ int file_format = db->aDb[0].pSchema->file_format;
GuVariantInfo ei = gu_variant_open(expr);
switch (ei.tag) {
@@ -143,31 +236,44 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
Mem mem[3];
mem[0].flags = MEM_Int;
- rc = store_expr(ctxt, app->fun, &mem[0].u.i);
+ rc = store_expr(db, 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(ctxt, app->arg, &mem[1].u.i);
+ rc = store_expr(db, 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;
- idxKey.pKeyInfo = ctxt->crsPairs->pKeyInfo;
+ idxKey.pKeyInfo = ctxt->crsPairs.pKeyInfo;
idxKey.nField = 2;
idxKey.default_rc = 0;
idxKey.aMem = mem;
int res = 0;
- rc = sqlite3BtreeMovetoUnpacked(ctxt->crsPairs,
+ rc = sqlite3BtreeMovetoUnpacked(&ctxt->crsPairs,
&idxKey, 0, 0, &res);
if (rc != SQLITE_OK) {
return rc;
}
if (res == 0) {
- rc = sqlite3VdbeIdxRowid(ctxt->db, ctxt->crsPairs, pKey);
+ rc = sqlite3VdbeIdxRowid(db, &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
@@ -176,15 +282,15 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
u32 serial_type;
unsigned char* p = buf+4;
- serial_type = sqlite3VdbeSerialType(&mem[0], ctxt->file_format);
+ serial_type = sqlite3VdbeSerialType(&mem[0], file_format);
buf[2] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[0], serial_type);
- serial_type = sqlite3VdbeSerialType(&mem[1], ctxt->file_format);
+ serial_type = sqlite3VdbeSerialType(&mem[1], file_format);
buf[3] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[1], serial_type);
- rc = sqlite3BtreeInsert(ctxt->crsExprs, 0, *pKey,
+ rc = sqlite3BtreeInsert(&ctxt->crsExprs, 0, *pKey,
buf+1, p-(buf+1), 0,
0, 0);
if (rc != SQLITE_OK) {
@@ -197,11 +303,11 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
mem[2].flags = MEM_Int;
mem[2].u.i = *pKey;
- serial_type = sqlite3VdbeSerialType(&mem[2], ctxt->file_format);
+ serial_type = sqlite3VdbeSerialType(&mem[2], file_format);
buf[3] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[2], serial_type);
- rc = sqlite3BtreeInsert(ctxt->crsPairs, buf, p-buf,
+ rc = sqlite3BtreeInsert(&ctxt->crsPairs, buf, p-buf,
0, *pKey, 0,
0, 0);
}
@@ -221,30 +327,35 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
mem[0].z = fun->fun;
UnpackedRecord idxKey;
- idxKey.pKeyInfo = ctxt->crsIdents->pKeyInfo;
+ idxKey.pKeyInfo = ctxt->crsIdents.pKeyInfo;
idxKey.nField = 1;
idxKey.default_rc = 0;
idxKey.aMem = mem;
int res = 0;
- rc = sqlite3BtreeMovetoUnpacked(ctxt->crsIdents,
+ rc = sqlite3BtreeMovetoUnpacked(&ctxt->crsIdents,
&idxKey, 0, 0, &res);
if (rc != SQLITE_OK) {
return rc;
}
if (res == 0) {
- rc = sqlite3VdbeIdxRowid(ctxt->db, ctxt->crsIdents, pKey);
+ rc = sqlite3VdbeIdxRowid(db, &ctxt->crsIdents, pKey);
} else {
+ if (wrFlag == 0) {
+ *pKey = 0;
+ return SQLITE_OK;
+ }
+
*pKey = ++ctxt->key_seed;
- int serial_type_fun = sqlite3VdbeSerialType(&mem[0], ctxt->file_format);
+ int serial_type_fun = sqlite3VdbeSerialType(&mem[0], file_format);
int serial_type_fun_hdr_len = sqlite3VarintLen(serial_type_fun);
mem[1].flags = MEM_Int;
mem[1].u.i = *pKey;
- int serial_type_key = sqlite3VdbeSerialType(&mem[1], ctxt->file_format);
+ int serial_type_key = sqlite3VdbeSerialType(&mem[1], file_format);
int serial_type_key_hdr_len = sqlite3VarintLen(serial_type_key);
unsigned char* buf = malloc(1+serial_type_fun_hdr_len+MAX(1,serial_type_key_hdr_len)+mem[0].n+8);
@@ -255,7 +366,7 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
memcpy(p, fun->fun, mem[0].n);
p += mem[0].n;
- rc = sqlite3BtreeInsert(ctxt->crsExprs, 0, *pKey,
+ rc = sqlite3BtreeInsert(&ctxt->crsExprs, 0, *pKey,
buf, p-buf, 0,
0, 0);
if (rc != SQLITE_OK) {
@@ -269,7 +380,7 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
memcpy(p, fun->fun, mem[0].n);
p += mem[0].n;
p += sqlite3VdbeSerialPut(p, &mem[1], serial_type_key);
- rc = sqlite3BtreeInsert(ctxt->crsIdents, buf, p-buf,
+ rc = sqlite3BtreeInsert(&ctxt->crsIdents, buf, p-buf,
0, *pKey, 0,
0, 0);
@@ -299,26 +410,8 @@ sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err)
{
sqlite3 *db = (sqlite3 *) sg;
- Table *exprsTbl =
- sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_EXPRS);
- if (!exprsTbl) {
- sg_raise_err("Table " SG_EXPRS " is missing", err);
- return 0;
- }
-
- Index *pairsIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_PAIRS);
- if (!pairsIdx) {
- sg_raise_err("Index " SG_PAIRS " is missing", err);
- return 0;
- }
-
- Index *identsIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_IDENTS);
- if (!identsIdx) {
- sg_raise_err("Index " SG_IDENTS " is missing", err);
- return 0;
- }
-
int rc;
+
if (db->autoCommit) {
rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1);
if (rc != SQLITE_OK) {
@@ -327,78 +420,19 @@ sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err)
}
}
- BtCursor crsExprs;
- memset(&crsExprs, 0, sizeof(crsExprs));
- rc = sqlite3BtreeCursor(db->aDb[0].pBt, exprsTbl->tnum, 1, NULL, &crsExprs);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto rollback;
- }
-
- BtCursor crsPairs;
- memset(&crsPairs, 0, sizeof(crsPairs));
- KeyInfo *infPairs = sqlite3KeyInfoAlloc(db, 2, 0);
- rc = sqlite3BtreeCursor(db->aDb[0].pBt, pairsIdx->tnum, 1, infPairs, &crsPairs);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto close1;
- }
-
- BtCursor crsIdents;
- memset(&crsIdents, 0, sizeof(crsIdents));
- KeyInfo *infIdents = sqlite3KeyInfoAlloc(db, 1, 1);
- rc = sqlite3BtreeCursor(db->aDb[0].pBt, identsIdx->tnum, 1, infIdents, &crsIdents);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto close2;
- }
-
- int res;
- rc = sqlite3BtreeLast(&crsExprs, &res);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
+ ExprContext ctxt;
+ rc = open_exprs(db, 1, &ctxt, err);
+ if (rc != SQLITE_OK)
goto close;
- }
- SgId key = 0;
- rc = sqlite3BtreeKeySize(&crsExprs, &key);
+ SgId key;
+ rc = store_expr(db, &ctxt, expr, &key, 1);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
goto close;
}
- StoreContext ctxt;
- ctxt.db = db;
- ctxt.crsExprs = &crsExprs;
- ctxt.crsPairs = &crsPairs;
- ctxt.crsIdents = &crsIdents;
- ctxt.key_seed = key;
- ctxt.file_format = db->aDb[0].pSchema->file_format;
- rc = store_expr(&ctxt, expr, &key);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto close;
- }
-
- sqlite3KeyInfoUnref(infIdents);
- rc = sqlite3BtreeCloseCursor(&crsIdents);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto close2;
- }
-
- sqlite3KeyInfoUnref(infPairs);
- rc = sqlite3BtreeCloseCursor(&crsPairs);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto close1;
- }
-
- rc = sqlite3BtreeCloseCursor(&crsExprs);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- goto rollback;
- }
+ close_exprs(&ctxt);
if (db->autoCommit) {
rc = sqlite3BtreeCommit(db->aDb[0].pBt);
@@ -411,17 +445,8 @@ sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err)
return key;
close:
- sqlite3KeyInfoUnref(infIdents);
- sqlite3BtreeCloseCursor(&crsIdents);
-
-close2:
- sqlite3KeyInfoUnref(infPairs);
- sqlite3BtreeCloseCursor(&crsPairs);
+ close_exprs(&ctxt);
-close1:
- sqlite3BtreeCloseCursor(&crsExprs);
-
-rollback:
if (db->autoCommit) {
sqlite3BtreeRollback(db->aDb[0].pBt, SQLITE_ABORT_ROLLBACK, 0);
}
@@ -485,7 +510,7 @@ load_expr(BtCursor* crsExprs, SgId key, PgfExpr *pExpr, GuPool* out_pool)
}
PgfExpr
-sg_select_expr(SgSG *sg, SgId key, GuPool* out_pool, GuExn* err)
+sg_get_expr(SgSG *sg, SgId key, GuPool* out_pool, GuExn* err)
{
sqlite3 *db = (sqlite3 *) sg;
@@ -546,8 +571,13 @@ rollback:
return gu_null_variant;
}
+typedef struct {
+ int n_cursors;
+ BtCursor cursor[4];
+} TripleContext;
+
static int
-open_triples(sqlite3 *db, int wrFlag, BtCursor cursor[], int *n_cursors, GuExn* err)
+open_triples(sqlite3 *db, int wrFlag, TripleContext* ctxt, GuExn* err)
{
Index *idx[3];
idx[0] = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_TRIPLES_SPO);
@@ -576,58 +606,39 @@ open_triples(sqlite3 *db, int wrFlag, BtCursor cursor[], int *n_cursors, GuExn*
}
int rc;
- if (db->autoCommit) {
- rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, wrFlag);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- return rc;
- }
- }
- memset(cursor, 0, sizeof(BtCursor)*4);
+ memset(ctxt->cursor, 0, sizeof(ctxt->cursor));
- *n_cursors = 0;
- while (*n_cursors < 3) {
- KeyInfo *inf = sqlite3KeyInfoAlloc(db, 3-*n_cursors, *n_cursors);
- rc = sqlite3BtreeCursor(db->aDb[0].pBt, idx[*n_cursors]->tnum, wrFlag, inf, &cursor[*n_cursors]);
+ ctxt->n_cursors = 0;
+ while (ctxt->n_cursors < 3) {
+ KeyInfo *inf = sqlite3KeyInfoAlloc(db, 3-ctxt->n_cursors, ctxt->n_cursors);
+ rc = sqlite3BtreeCursor(db->aDb[0].pBt, idx[ctxt->n_cursors]->tnum, wrFlag, inf, &ctxt->cursor[ctxt->n_cursors]);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
return rc;
}
- (*n_cursors)++;
+ ctxt->n_cursors++;
}
- rc = sqlite3BtreeCursor(db->aDb[0].pBt, triplesTbl->tnum, wrFlag, NULL, &cursor[*n_cursors]);
+ rc = sqlite3BtreeCursor(db->aDb[0].pBt, triplesTbl->tnum, wrFlag, NULL, &ctxt->cursor[ctxt->n_cursors]);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
return rc;
}
- (*n_cursors)++;
-
+ ctxt->n_cursors++;
+
return SQLITE_OK;
}
static void
-close_triples(sqlite3 *db, BtCursor cursor[], int *n_cursors, int rc, GuExn* err)
+close_triples(TripleContext* ctxt)
{
- while (*n_cursors > 0) {
- (*n_cursors)--;
- if (cursor[*n_cursors].pKeyInfo != NULL) {
- sqlite3KeyInfoUnref(cursor[*n_cursors].pKeyInfo);
- }
- sqlite3BtreeCloseCursor(&cursor[*n_cursors]);
- }
-
- if (db->autoCommit) {
- if (rc == SQLITE_OK || rc == SQLITE_DONE) {
- rc = sqlite3BtreeCommit(db->aDb[0].pBt);
- if (rc != SQLITE_OK) {
- sg_raise_sqlite(db, err);
- return;
- }
- } else {
- sqlite3BtreeRollback(db->aDb[0].pBt, SQLITE_ABORT_ROLLBACK, 0);
+ while (ctxt->n_cursors > 0) {
+ ctxt->n_cursors--;
+ if (ctxt->cursor[ctxt->n_cursors].pKeyInfo != NULL) {
+ sqlite3KeyInfoUnref(ctxt->cursor[ctxt->n_cursors].pKeyInfo);
}
+ sqlite3BtreeCloseCursor(&ctxt->cursor[ctxt->n_cursors]);
}
}
@@ -638,29 +649,44 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
int rc;
- BtCursor cursor[4];
- int n_cursors = 0;
- rc = open_triples(db, 1, cursor, &n_cursors, err);
- if (rc != SQLITE_OK) {
- goto close;
+ if (db->autoCommit) {
+ rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return 0;
+ }
}
+ TripleContext tctxt;
+ rc = open_triples(db, 1, &tctxt, err);
+ if (rc != SQLITE_OK)
+ goto close;
+
Mem mem[4];
- mem[0].flags = MEM_Int;
- mem[0].u.i = triple[0];
- mem[1].flags = MEM_Int;
- mem[1].u.i = triple[1];
- mem[2].flags = MEM_Int;
- mem[2].u.i = triple[2];
+
+ ExprContext ectxt;
+ rc = open_exprs(db, 1, &ectxt, err);
+ if (rc != SQLITE_OK)
+ goto close;
+
+ for (size_t i = 0; i < 3; i++) {
+ mem[i].flags = MEM_Int;
+
+ rc = store_expr(db, &ectxt, triple[i], &mem[i].u.i, 1);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ goto close;
+ }
+ }
UnpackedRecord idxKey;
- idxKey.pKeyInfo = cursor[0].pKeyInfo;
+ idxKey.pKeyInfo = tctxt.cursor[0].pKeyInfo;
idxKey.nField = 3;
idxKey.default_rc = 0;
idxKey.aMem = mem;
int res = 0;
- rc = sqlite3BtreeMovetoUnpacked(&cursor[0],
+ rc = sqlite3BtreeMovetoUnpacked(&tctxt.cursor[0],
&idxKey, 0, 0, &res);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
@@ -670,15 +696,15 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
SgId key = 0;
if (res == 0) {
- rc = sqlite3VdbeIdxRowid(db, &cursor[0], &key);
+ rc = sqlite3VdbeIdxRowid(db, &tctxt.cursor[0], &key);
} else {
- rc = sqlite3BtreeLast(&cursor[3], &res);
+ rc = sqlite3BtreeLast(&tctxt.cursor[3], &res);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
goto close;
}
- rc = sqlite3BtreeKeySize(&cursor[3], &key);
+ rc = sqlite3BtreeKeySize(&tctxt.cursor[3], &key);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
goto close;
@@ -711,7 +737,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[4] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], serial_type);
- rc = sqlite3BtreeInsert(&cursor[3], 0, key,
+ rc = sqlite3BtreeInsert(&tctxt.cursor[3], 0, key,
buf, p-buf, 0,
0, 0);
if (rc != SQLITE_OK) {
@@ -727,7 +753,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[4] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], serial_type);
- rc = sqlite3BtreeInsert(&cursor[0], buf, p-buf,
+ rc = sqlite3BtreeInsert(&tctxt.cursor[0], buf, p-buf,
0, key, 0,
0, 0);
if (rc != SQLITE_OK) {
@@ -749,7 +775,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[3] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], serial_type);
- rc = sqlite3BtreeInsert(&cursor[1], buf, p-buf,
+ rc = sqlite3BtreeInsert(&tctxt.cursor[1], buf, p-buf,
0, key, 0,
0, 0);
if (rc != SQLITE_OK) {
@@ -767,7 +793,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[2] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], serial_type);
- rc = sqlite3BtreeInsert(&cursor[2], buf, p-buf,
+ rc = sqlite3BtreeInsert(&tctxt.cursor[2], buf, p-buf,
0, key, 0,
0, 0);
if (rc != SQLITE_OK) {
@@ -777,12 +803,27 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
}
close:
- close_triples(db, cursor, &n_cursors, rc, err);
+ close_exprs(&ectxt);
+ close_triples(&tctxt);
+
+ if (db->autoCommit) {
+ if (rc == SQLITE_OK || rc == SQLITE_DONE) {
+ rc = sqlite3BtreeCommit(db->aDb[0].pBt);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return 0;
+ }
+ } else {
+ sqlite3BtreeRollback(db->aDb[0].pBt, SQLITE_ABORT_ROLLBACK, 0);
+ }
+ }
+
return key;
}
static int
-load_triple(BtCursor* crsTriples, SgTriple triple)
+load_triple(BtCursor* crsTriples, BtCursor* crsExprs, SgTriple triple,
+ GuPool* out_pool)
{
int rc;
@@ -806,18 +847,27 @@ load_triple(BtCursor* crsTriples, SgTriple triple)
row += sqlite3VdbeSerialGet(row, serial_type_pred, &mem[1]);
row += sqlite3VdbeSerialGet(row, serial_type_obj, &mem[2]);
- triple[0] = mem[0].u.i;
- triple[1] = mem[1].u.i;
- triple[2] = mem[2].u.i;
-
+ 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;
}
-bool
-sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
+int
+sg_get_triple(SgSG *sg, SgId key, SgTriple triple,
+ GuPool* out_pool, GuExn* err)
{
sqlite3 *db = (sqlite3 *) sg;
+ triple[0] = gu_null_variant;
+ triple[1] = gu_null_variant;
+ triple[2] = gu_null_variant;
+
Table *triplesTbl =
sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_TRIPLES);
if (!triplesTbl) {
@@ -825,6 +875,13 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
return false;
}
+ Table *exprsTbl =
+ sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_EXPRS);
+ if (!exprsTbl) {
+ sg_raise_err("Table " SG_EXPRS " is missing", err);
+ return false;
+ }
+
int rc;
if (db->autoCommit) {
rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 0);
@@ -842,6 +899,14 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
goto rollback;
}
+ BtCursor crsExprs;
+ memset(&crsExprs, 0, sizeof(crsExprs));
+ rc = sqlite3BtreeCursor(db->aDb[0].pBt, exprsTbl->tnum, 0, NULL, &crsExprs);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ goto close1;
+ }
+
int res;
rc = sqlite3BtreeMovetoUnpacked(&crsTriples, 0, key, 0, &res);
if (rc != SQLITE_OK) {
@@ -850,13 +915,19 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
}
if (res == 0) {
- rc = load_triple(&crsTriples, triple);
+ rc = load_triple(&crsTriples, &crsExprs, triple, out_pool);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
goto close;
}
}
+ rc = sqlite3BtreeCloseCursor(&crsExprs);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ goto close1;
+ }
+
rc = sqlite3BtreeCloseCursor(&crsTriples);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
@@ -874,6 +945,9 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
return (res == 0);
close:
+ sqlite3BtreeCloseCursor(&crsExprs);
+
+close1:
sqlite3BtreeCloseCursor(&crsTriples);
rollback:
@@ -885,9 +959,11 @@ rollback:
struct SgTripleResult {
sqlite3 *db;
+ SgTriple triple;
+
+ ExprContext ectxt;
+ TripleContext tctxt;
- int n_cursors;
- BtCursor cursors[4];
BtCursor* cursor;
int res;
@@ -902,30 +978,51 @@ sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err)
int rc;
+ if (db->autoCommit) {
+ rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 0);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(db, err);
+ return NULL;
+ }
+ }
+
SgTripleResult* tres = malloc(sizeof(SgTripleResult));
tres->db = db;
+ tres->triple[0] = triple[0];
+ tres->triple[1] = triple[1];
+ tres->triple[2] = triple[2];
- rc = open_triples(db, 0, tres->cursors, &tres->n_cursors, err);
+ rc = open_triples(db, 0, &tres->tctxt, err);
+ if (rc != SQLITE_OK)
+ goto close;
+
+ rc = open_exprs(db, 0, &tres->ectxt, err);
if (rc != SQLITE_OK)
goto close;
for (int i = 0; i < 3; i++) {
- if (triple[i] == 0)
+ if (gu_variant_is_null(triple[i]))
tres->mem[i].flags = MEM_Null;
else {
tres->mem[i].flags = MEM_Int;
- tres->mem[i].u.i = triple[i];
+ rc = store_expr(db, &tres->ectxt, triple[i], &tres->mem[i].u.i, 0);
+ if (rc != SQLITE_OK)
+ goto close;
+ if (tres->mem[i].u.i == 0) {
+ tres->res = 1;
+ return tres;
+ }
}
}
int i = 0;
while (i < 3) {
- if (triple[i] != 0)
+ if (!gu_variant_is_null(triple[i]))
break;
i++;
}
- tres->cursor = &tres->cursors[i];
+ tres->cursor = &tres->tctxt.cursor[i];
tres->idxKey.pKeyInfo = tres->cursor->pKeyInfo;
tres->idxKey.nField = 0;
tres->idxKey.aMem = &tres->mem[i];
@@ -960,14 +1057,25 @@ sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err)
return tres;
close:
- close_triples(db, tres->cursors, &tres->n_cursors, rc, err);
+ close_exprs(&tres->ectxt);
+ close_triples(&tres->tctxt);
+
+ if (db->autoCommit) {
+ sqlite3BtreeRollback(db->aDb[0].pBt, SQLITE_ABORT_ROLLBACK, 0);
+ }
+
free(tres);
return NULL;
}
-bool
-sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn* err)
+int
+sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple,
+ GuPool* out_pool, GuExn* err)
{
+ triple[0] = tres->triple[0];
+ triple[1] = tres->triple[1];
+ triple[2] = tres->triple[2];
+
while (tres->res == 0) {
int rc;
@@ -990,7 +1098,9 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
if (tres->res != 0)
return false;
- if (tres->idxKey.nField == 1 && tres->mem[2].flags != MEM_Null) {
+ if (tres->idxKey.aMem == &tres->mem[0] &&
+ tres->idxKey.nField == 1 &&
+ tres->mem[2].flags != MEM_Null) {
int offset =
zData[0] +
sqlite3VdbeSerialTypeLen(zData[1]) +
@@ -1016,7 +1126,7 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
return false;
}
- rc = sqlite3BtreeMovetoUnpacked(&tres->cursors[3], 0, *pKey, 0, &tres->res);
+ rc = sqlite3BtreeMovetoUnpacked(&tres->tctxt.cursor[3], 0, *pKey, 0, &tres->res);
} else {
rc = sqlite3BtreeKeySize(tres->cursor, pKey);
}
@@ -1025,7 +1135,8 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
return false;
}
- rc = load_triple(&tres->cursors[3], triple);
+ rc = load_triple(&tres->tctxt.cursor[3], &tres->ectxt.crsExprs,
+ triple, out_pool);
if (rc != SQLITE_OK) {
sg_raise_sqlite(tres->db, err);
return false;
@@ -1046,7 +1157,17 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
void
sg_triple_result_close(SgTripleResult* tres, GuExn* err)
{
- close_triples(tres->db, tres->cursors, &tres->n_cursors, SQLITE_OK, err);
+ close_exprs(&tres->ectxt);
+ close_triples(&tres->tctxt);
+
+ if (tres->db->autoCommit) {
+ int rc = sqlite3BtreeCommit(tres->db->aDb[0].pBt);
+ if (rc != SQLITE_OK) {
+ sg_raise_sqlite(tres->db, err);
+ return;
+ }
+ }
+
free(tres);
}
@@ -1086,7 +1207,7 @@ sg_query_result_fetch(SgQueryResult* qres, SgId* res, GuExn* err)
SgId key;
for (;;) {
- bool found = sg_triple_result_fetch(qres->results[i], &key, triple, err);
+ bool found = sg_triple_result_fetch(qres->results[i], &key, triple, NULL, err);
if (gu_exn_is_raised(err)) {
return false;
}
diff --git a/src/runtime/c/sg/sg.h b/src/runtime/c/sg/sg.h
index 67084876f..4f1c40562 100644
--- a/src/runtime/c/sg/sg.h
+++ b/src/runtime/c/sg/sg.h
@@ -28,24 +28,26 @@ SgId
sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err);
PgfExpr
-sg_select_expr(SgSG *sg, SgId key, GuPool* out_pool, GuExn* err);
+sg_get_expr(SgSG *sg, SgId key, GuPool* out_pool, GuExn* err);
-typedef SgId SgTriple[3];
+typedef PgfExpr SgTriple[3];
SgId
sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err);
-bool
-sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err);
+int
+sg_get_triple(SgSG *sg, SgId key, SgTriple triple,
+ GuPool* out_pool, GuExn* err);
typedef struct SgTripleResult SgTripleResult;
SgTripleResult*
sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err);
-bool
-sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn* err);
+int
+sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple,
+ GuPool* out_pool, GuExn* err);
void
sg_triple_result_close(SgTripleResult* tres, GuExn* err);