1
0
forked from GitHub/gf-core

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_PO "sg_triples_po"
#define SG_TRIPLES_O "sg_triples_o" #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 void
sg_raise_sqlite(sqlite3* db, GuExn* err) sg_raise_sqlite(sqlite3* db, GuExn* err)
{ {
@@ -127,10 +118,112 @@ sg_rollback(SgSG* sg, GuExn* err)
db->autoCommit = 1; db->autoCommit = 1;
} }
typedef struct {
int n_cursors;
BtCursor crsExprs;
BtCursor crsPairs;
BtCursor crsIdents;
SgId key_seed;
} ExprContext;
static int 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 rc = SQLITE_OK;
int file_format = db->aDb[0].pSchema->file_format;
GuVariantInfo ei = gu_variant_open(expr); GuVariantInfo ei = gu_variant_open(expr);
switch (ei.tag) { switch (ei.tag) {
@@ -143,31 +236,44 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
Mem mem[3]; Mem mem[3];
mem[0].flags = MEM_Int; 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) if (rc != SQLITE_OK)
return rc; return rc;
if (wrFlag == 0 && mem[0].u.i == 0) {
*pKey = 0;
return SQLITE_OK;
}
mem[1].flags = MEM_Int; 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) if (rc != SQLITE_OK)
return rc; return rc;
if (wrFlag == 0 && mem[1].u.i == 0) {
*pKey = 0;
return SQLITE_OK;
}
UnpackedRecord idxKey; UnpackedRecord idxKey;
idxKey.pKeyInfo = ctxt->crsPairs->pKeyInfo; idxKey.pKeyInfo = ctxt->crsPairs.pKeyInfo;
idxKey.nField = 2; idxKey.nField = 2;
idxKey.default_rc = 0; idxKey.default_rc = 0;
idxKey.aMem = mem; idxKey.aMem = mem;
int res = 0; int res = 0;
rc = sqlite3BtreeMovetoUnpacked(ctxt->crsPairs, rc = sqlite3BtreeMovetoUnpacked(&ctxt->crsPairs,
&idxKey, 0, 0, &res); &idxKey, 0, 0, &res);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
return rc; return rc;
} }
if (res == 0) { if (res == 0) {
rc = sqlite3VdbeIdxRowid(ctxt->db, ctxt->crsPairs, pKey); rc = sqlite3VdbeIdxRowid(db, &ctxt->crsPairs, pKey);
} else { } else {
if (wrFlag == 0) {
*pKey = 0;
return SQLITE_OK;
}
*pKey = ++ctxt->key_seed; *pKey = ++ctxt->key_seed;
unsigned char buf[32]; // enough for a record with three integers 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; u32 serial_type;
unsigned char* p = buf+4; unsigned char* p = buf+4;
serial_type = sqlite3VdbeSerialType(&mem[0], ctxt->file_format); serial_type = sqlite3VdbeSerialType(&mem[0], file_format);
buf[2] = serial_type; buf[2] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[0], 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; buf[3] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[1], 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, buf+1, p-(buf+1), 0,
0, 0); 0, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -197,11 +303,11 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
mem[2].flags = MEM_Int; mem[2].flags = MEM_Int;
mem[2].u.i = *pKey; mem[2].u.i = *pKey;
serial_type = sqlite3VdbeSerialType(&mem[2], ctxt->file_format); serial_type = sqlite3VdbeSerialType(&mem[2], file_format);
buf[3] = serial_type; buf[3] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[2], 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, *pKey, 0,
0, 0); 0, 0);
} }
@@ -221,30 +327,35 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
mem[0].z = fun->fun; mem[0].z = fun->fun;
UnpackedRecord idxKey; UnpackedRecord idxKey;
idxKey.pKeyInfo = ctxt->crsIdents->pKeyInfo; idxKey.pKeyInfo = ctxt->crsIdents.pKeyInfo;
idxKey.nField = 1; idxKey.nField = 1;
idxKey.default_rc = 0; idxKey.default_rc = 0;
idxKey.aMem = mem; idxKey.aMem = mem;
int res = 0; int res = 0;
rc = sqlite3BtreeMovetoUnpacked(ctxt->crsIdents, rc = sqlite3BtreeMovetoUnpacked(&ctxt->crsIdents,
&idxKey, 0, 0, &res); &idxKey, 0, 0, &res);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
return rc; return rc;
} }
if (res == 0) { if (res == 0) {
rc = sqlite3VdbeIdxRowid(ctxt->db, ctxt->crsIdents, pKey); rc = sqlite3VdbeIdxRowid(db, &ctxt->crsIdents, pKey);
} else { } else {
if (wrFlag == 0) {
*pKey = 0;
return SQLITE_OK;
}
*pKey = ++ctxt->key_seed; *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); int serial_type_fun_hdr_len = sqlite3VarintLen(serial_type_fun);
mem[1].flags = MEM_Int; mem[1].flags = MEM_Int;
mem[1].u.i = *pKey; 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); 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); 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); memcpy(p, fun->fun, mem[0].n);
p += mem[0].n; p += mem[0].n;
rc = sqlite3BtreeInsert(ctxt->crsExprs, 0, *pKey, rc = sqlite3BtreeInsert(&ctxt->crsExprs, 0, *pKey,
buf, p-buf, 0, buf, p-buf, 0,
0, 0); 0, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -269,7 +380,7 @@ store_expr(StoreContext* ctxt, PgfExpr expr, SgId* pKey)
memcpy(p, fun->fun, mem[0].n); memcpy(p, fun->fun, mem[0].n);
p += mem[0].n; p += mem[0].n;
p += sqlite3VdbeSerialPut(p, &mem[1], serial_type_key); 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, *pKey, 0,
0, 0); 0, 0);
@@ -299,26 +410,8 @@ sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err)
{ {
sqlite3 *db = (sqlite3 *) sg; 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; int rc;
if (db->autoCommit) { if (db->autoCommit) {
rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1); rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -327,78 +420,19 @@ sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err)
} }
} }
BtCursor crsExprs; ExprContext ctxt;
memset(&crsExprs, 0, sizeof(crsExprs)); rc = open_exprs(db, 1, &ctxt, err);
rc = sqlite3BtreeCursor(db->aDb[0].pBt, exprsTbl->tnum, 1, NULL, &crsExprs); if (rc != SQLITE_OK)
if (rc != SQLITE_OK) { goto close;
sg_raise_sqlite(db, err);
goto rollback;
}
BtCursor crsPairs; SgId key;
memset(&crsPairs, 0, sizeof(crsPairs)); rc = store_expr(db, &ctxt, expr, &key, 1);
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) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
goto close; goto close;
} }
SgId key = 0; close_exprs(&ctxt);
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;
}
if (db->autoCommit) { if (db->autoCommit) {
rc = sqlite3BtreeCommit(db->aDb[0].pBt); rc = sqlite3BtreeCommit(db->aDb[0].pBt);
@@ -411,17 +445,8 @@ sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err)
return key; return key;
close: close:
sqlite3KeyInfoUnref(infIdents); close_exprs(&ctxt);
sqlite3BtreeCloseCursor(&crsIdents);
close2:
sqlite3KeyInfoUnref(infPairs);
sqlite3BtreeCloseCursor(&crsPairs);
close1:
sqlite3BtreeCloseCursor(&crsExprs);
rollback:
if (db->autoCommit) { if (db->autoCommit) {
sqlite3BtreeRollback(db->aDb[0].pBt, SQLITE_ABORT_ROLLBACK, 0); 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 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; sqlite3 *db = (sqlite3 *) sg;
@@ -546,8 +571,13 @@ rollback:
return gu_null_variant; return gu_null_variant;
} }
typedef struct {
int n_cursors;
BtCursor cursor[4];
} TripleContext;
static int 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]; Index *idx[3];
idx[0] = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_TRIPLES_SPO); 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; 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) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
return rc; return rc;
} }
ctxt->n_cursors++;
} }
memset(cursor, 0, sizeof(BtCursor)*4); rc = sqlite3BtreeCursor(db->aDb[0].pBt, triplesTbl->tnum, wrFlag, NULL, &ctxt->cursor[ctxt->n_cursors]);
*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]);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
return rc; return rc;
} }
(*n_cursors)++; ctxt->n_cursors++;
return SQLITE_OK; return SQLITE_OK;
} }
static void static void
close_triples(sqlite3 *db, BtCursor cursor[], int *n_cursors, int rc, GuExn* err) close_triples(TripleContext* ctxt)
{ {
while (*n_cursors > 0) { while (ctxt->n_cursors > 0) {
(*n_cursors)--; ctxt->n_cursors--;
if (cursor[*n_cursors].pKeyInfo != NULL) { if (ctxt->cursor[ctxt->n_cursors].pKeyInfo != NULL) {
sqlite3KeyInfoUnref(cursor[*n_cursors].pKeyInfo); sqlite3KeyInfoUnref(ctxt->cursor[ctxt->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);
} }
sqlite3BtreeCloseCursor(&ctxt->cursor[ctxt->n_cursors]);
} }
} }
@@ -638,29 +649,44 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
int rc; int rc;
BtCursor cursor[4]; if (db->autoCommit) {
int n_cursors = 0; rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1);
rc = open_triples(db, 1, cursor, &n_cursors, err); if (rc != SQLITE_OK) {
if (rc != SQLITE_OK) { sg_raise_sqlite(db, err);
goto close; return 0;
}
} }
TripleContext tctxt;
rc = open_triples(db, 1, &tctxt, err);
if (rc != SQLITE_OK)
goto close;
Mem mem[4]; Mem mem[4];
mem[0].flags = MEM_Int;
mem[0].u.i = triple[0]; ExprContext ectxt;
mem[1].flags = MEM_Int; rc = open_exprs(db, 1, &ectxt, err);
mem[1].u.i = triple[1]; if (rc != SQLITE_OK)
mem[2].flags = MEM_Int; goto close;
mem[2].u.i = triple[2];
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; UnpackedRecord idxKey;
idxKey.pKeyInfo = cursor[0].pKeyInfo; idxKey.pKeyInfo = tctxt.cursor[0].pKeyInfo;
idxKey.nField = 3; idxKey.nField = 3;
idxKey.default_rc = 0; idxKey.default_rc = 0;
idxKey.aMem = mem; idxKey.aMem = mem;
int res = 0; int res = 0;
rc = sqlite3BtreeMovetoUnpacked(&cursor[0], rc = sqlite3BtreeMovetoUnpacked(&tctxt.cursor[0],
&idxKey, 0, 0, &res); &idxKey, 0, 0, &res);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
@@ -670,15 +696,15 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
SgId key = 0; SgId key = 0;
if (res == 0) { if (res == 0) {
rc = sqlite3VdbeIdxRowid(db, &cursor[0], &key); rc = sqlite3VdbeIdxRowid(db, &tctxt.cursor[0], &key);
} else { } else {
rc = sqlite3BtreeLast(&cursor[3], &res); rc = sqlite3BtreeLast(&tctxt.cursor[3], &res);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
goto close; goto close;
} }
rc = sqlite3BtreeKeySize(&cursor[3], &key); rc = sqlite3BtreeKeySize(&tctxt.cursor[3], &key);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
goto close; goto close;
@@ -711,7 +737,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[4] = serial_type; buf[4] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], 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, buf, p-buf, 0,
0, 0); 0, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -727,7 +753,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[4] = serial_type; buf[4] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], 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, key, 0,
0, 0); 0, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -749,7 +775,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[3] = serial_type; buf[3] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[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, key, 0,
0, 0); 0, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -767,7 +793,7 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
buf[2] = serial_type; buf[2] = serial_type;
p += sqlite3VdbeSerialPut(p, &mem[3], 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, key, 0,
0, 0); 0, 0);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -777,12 +803,27 @@ sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err)
} }
close: 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; return key;
} }
static int static int
load_triple(BtCursor* crsTriples, SgTriple triple) load_triple(BtCursor* crsTriples, BtCursor* crsExprs, SgTriple triple,
GuPool* out_pool)
{ {
int rc; 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_pred, &mem[1]);
row += sqlite3VdbeSerialGet(row, serial_type_obj, &mem[2]); row += sqlite3VdbeSerialGet(row, serial_type_obj, &mem[2]);
triple[0] = mem[0].u.i; for (int i = 0; i < 3; i++) {
triple[1] = mem[1].u.i; if (gu_variant_is_null(triple[i])) {
triple[2] = mem[2].u.i; rc = load_expr(crsExprs, mem[i].u.i, &triple[i], out_pool);
if (rc != SQLITE_OK)
return rc;
}
}
return SQLITE_OK; return SQLITE_OK;
} }
bool int
sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err) sg_get_triple(SgSG *sg, SgId key, SgTriple triple,
GuPool* out_pool, GuExn* err)
{ {
sqlite3 *db = (sqlite3 *) sg; sqlite3 *db = (sqlite3 *) sg;
triple[0] = gu_null_variant;
triple[1] = gu_null_variant;
triple[2] = gu_null_variant;
Table *triplesTbl = Table *triplesTbl =
sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_TRIPLES); sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_TRIPLES);
if (!triplesTbl) { if (!triplesTbl) {
@@ -825,6 +875,13 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
return false; 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; int rc;
if (db->autoCommit) { if (db->autoCommit) {
rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 0); rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 0);
@@ -842,6 +899,14 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
goto rollback; 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; int res;
rc = sqlite3BtreeMovetoUnpacked(&crsTriples, 0, key, 0, &res); rc = sqlite3BtreeMovetoUnpacked(&crsTriples, 0, key, 0, &res);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
@@ -850,13 +915,19 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
} }
if (res == 0) { if (res == 0) {
rc = load_triple(&crsTriples, triple); rc = load_triple(&crsTriples, &crsExprs, triple, out_pool);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
goto close; goto close;
} }
} }
rc = sqlite3BtreeCloseCursor(&crsExprs);
if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err);
goto close1;
}
rc = sqlite3BtreeCloseCursor(&crsTriples); rc = sqlite3BtreeCloseCursor(&crsTriples);
if (rc != SQLITE_OK) { if (rc != SQLITE_OK) {
sg_raise_sqlite(db, err); sg_raise_sqlite(db, err);
@@ -874,6 +945,9 @@ sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err)
return (res == 0); return (res == 0);
close: close:
sqlite3BtreeCloseCursor(&crsExprs);
close1:
sqlite3BtreeCloseCursor(&crsTriples); sqlite3BtreeCloseCursor(&crsTriples);
rollback: rollback:
@@ -885,9 +959,11 @@ rollback:
struct SgTripleResult { struct SgTripleResult {
sqlite3 *db; sqlite3 *db;
SgTriple triple;
ExprContext ectxt;
TripleContext tctxt;
int n_cursors;
BtCursor cursors[4];
BtCursor* cursor; BtCursor* cursor;
int res; int res;
@@ -902,30 +978,51 @@ sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err)
int rc; 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)); SgTripleResult* tres = malloc(sizeof(SgTripleResult));
tres->db = db; 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) if (rc != SQLITE_OK)
goto close; goto close;
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
if (triple[i] == 0) if (gu_variant_is_null(triple[i]))
tres->mem[i].flags = MEM_Null; tres->mem[i].flags = MEM_Null;
else { else {
tres->mem[i].flags = MEM_Int; 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; int i = 0;
while (i < 3) { while (i < 3) {
if (triple[i] != 0) if (!gu_variant_is_null(triple[i]))
break; break;
i++; i++;
} }
tres->cursor = &tres->cursors[i]; tres->cursor = &tres->tctxt.cursor[i];
tres->idxKey.pKeyInfo = tres->cursor->pKeyInfo; tres->idxKey.pKeyInfo = tres->cursor->pKeyInfo;
tres->idxKey.nField = 0; tres->idxKey.nField = 0;
tres->idxKey.aMem = &tres->mem[i]; tres->idxKey.aMem = &tres->mem[i];
@@ -960,14 +1057,25 @@ sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err)
return tres; return tres;
close: 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); free(tres);
return NULL; return NULL;
} }
bool int
sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn* err) 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) { while (tres->res == 0) {
int rc; int rc;
@@ -990,7 +1098,9 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
if (tres->res != 0) if (tres->res != 0)
return false; 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 = int offset =
zData[0] + zData[0] +
sqlite3VdbeSerialTypeLen(zData[1]) + sqlite3VdbeSerialTypeLen(zData[1]) +
@@ -1016,7 +1126,7 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
return false; return false;
} }
rc = sqlite3BtreeMovetoUnpacked(&tres->cursors[3], 0, *pKey, 0, &tres->res); rc = sqlite3BtreeMovetoUnpacked(&tres->tctxt.cursor[3], 0, *pKey, 0, &tres->res);
} else { } else {
rc = sqlite3BtreeKeySize(tres->cursor, pKey); rc = sqlite3BtreeKeySize(tres->cursor, pKey);
} }
@@ -1025,7 +1135,8 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
return false; 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) { if (rc != SQLITE_OK) {
sg_raise_sqlite(tres->db, err); sg_raise_sqlite(tres->db, err);
return false; return false;
@@ -1046,7 +1157,17 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn*
void void
sg_triple_result_close(SgTripleResult* tres, GuExn* err) 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); free(tres);
} }
@@ -1086,7 +1207,7 @@ sg_query_result_fetch(SgQueryResult* qres, SgId* res, GuExn* err)
SgId key; SgId key;
for (;;) { 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)) { if (gu_exn_is_raised(err)) {
return false; return false;
} }

View File

@@ -28,24 +28,26 @@ SgId
sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err); sg_insert_expr(SgSG *sg, PgfExpr expr, GuExn* err);
PgfExpr 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 SgId
sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err); sg_insert_triple(SgSG *sg, SgTriple triple, GuExn* err);
bool int
sg_select_triple(SgSG *sg, SgId key, SgTriple triple, GuExn* err); sg_get_triple(SgSG *sg, SgId key, SgTriple triple,
GuPool* out_pool, GuExn* err);
typedef struct SgTripleResult SgTripleResult; typedef struct SgTripleResult SgTripleResult;
SgTripleResult* SgTripleResult*
sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err); sg_query_triple(SgSG *sg, SgTriple triple, GuExn* err);
bool int
sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple, GuExn* err); sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple,
GuPool* out_pool, GuExn* err);
void void
sg_triple_result_close(SgTripleResult* tres, GuExn* err); sg_triple_result_close(SgTripleResult* tres, GuExn* err);