the new triples API in libsg now always works with expressions

This commit is contained in:
krasimir
2015-09-04 10:01:19 +00:00
parent 32f18b515e
commit e9f7aa0e33
2 changed files with 333 additions and 210 deletions

View File

@@ -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;
}
ExprContext ctxt;
rc = open_exprs(db, 1, &ctxt, err);
if (rc != SQLITE_OK)
goto close;
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);
SgId key;
rc = store_expr(db, &ctxt, expr, &key, 1);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
goto close;
}
SgId key = 0;
rc = sqlite3BtreeKeySize(&crsExprs, &key);
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);
close_exprs(&ctxt);
close2:
sqlite3KeyInfoUnref(infPairs);
sqlite3BtreeCloseCursor(&crsPairs);
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);
memset(ctxt->cursor, 0, sizeof(ctxt->cursor));
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;
}
ctxt->n_cursors++;
}
memset(cursor, 0, sizeof(BtCursor)*4);
*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]);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
return rc;
}
(*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;
}

View File

@@ -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);