mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-23 19:42:50 -06:00
API for storing triples in the semantic graph
This commit is contained in:
@@ -5,8 +5,8 @@
|
|||||||
#define SG_EXPRS "sg_exprs"
|
#define SG_EXPRS "sg_exprs"
|
||||||
#define SG_PAIRS "sg_pairs"
|
#define SG_PAIRS "sg_pairs"
|
||||||
#define SG_IDENTS "sg_idents"
|
#define SG_IDENTS "sg_idents"
|
||||||
#define SG_RELS "sg_rels"
|
|
||||||
#define SG_TRIPLES "sg_triples"
|
#define SG_TRIPLES "sg_triples"
|
||||||
|
#define SG_TRIPLES_SPO "sg_triples_spo"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
@@ -23,8 +23,8 @@ sg_create_tables(sqlite3 *db)
|
|||||||
return sqlite3_exec(db, "create table if not exists " SG_EXPRS "(fun not null, arg integer);"
|
return sqlite3_exec(db, "create table if not exists " SG_EXPRS "(fun not null, arg integer);"
|
||||||
"create unique index if not exists " SG_IDENTS " on " SG_EXPRS "(fun) where arg is null;"
|
"create unique index if not exists " SG_IDENTS " on " SG_EXPRS "(fun) where arg is null;"
|
||||||
"create unique index if not exists " SG_PAIRS " on " SG_EXPRS "(fun,arg) where arg is not null;"
|
"create unique index if not exists " SG_PAIRS " on " SG_EXPRS "(fun,arg) where arg is not null;"
|
||||||
"create table if not exists " SG_RELS "(rel varchar);"
|
"create table if not exists " SG_TRIPLES "(subj integer, pred integer, obj integer);"
|
||||||
"create table if not exists " SG_TRIPLES "(subj integer, rel integer, obj integer);",
|
"create unique index if not exists " SG_TRIPLES_SPO " on " SG_TRIPLES "(subj,pred,obj);",
|
||||||
NULL, NULL, NULL);
|
NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,6 +394,149 @@ rollback:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sg_insert_triple(sqlite3 *db, i64 subj, i64 pred, i64 obj, i64 *pKey)
|
||||||
|
{
|
||||||
|
Table *triplesTbl =
|
||||||
|
sqlite3HashFind(&db->aDb[0].pSchema->tblHash, SG_TRIPLES);
|
||||||
|
if (!triplesTbl) return SQLITE_ERROR;
|
||||||
|
|
||||||
|
Index *spoIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_TRIPLES_SPO);
|
||||||
|
if (!spoIdx) return SQLITE_ERROR;
|
||||||
|
|
||||||
|
int rc;
|
||||||
|
rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
BtCursor crsTriples;
|
||||||
|
memset(&crsTriples, 0, sizeof(crsTriples));
|
||||||
|
rc = sqlite3BtreeCursor(db->aDb[0].pBt, triplesTbl->tnum, 1, NULL, &crsTriples);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto rollback;
|
||||||
|
}
|
||||||
|
|
||||||
|
BtCursor crsSPO;
|
||||||
|
memset(&crsSPO, 0, sizeof(crsSPO));
|
||||||
|
KeyInfo *infSPO = sqlite3KeyInfoAlloc(db, 3, 0);
|
||||||
|
rc = sqlite3BtreeCursor(db->aDb[0].pBt, spoIdx->tnum, 1, infSPO, &crsSPO);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto close1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem mem[4];
|
||||||
|
mem[0].flags = MEM_Int;
|
||||||
|
mem[0].u.i = subj;
|
||||||
|
mem[1].flags = MEM_Int;
|
||||||
|
mem[1].u.i = pred;
|
||||||
|
mem[2].flags = MEM_Int;
|
||||||
|
mem[2].u.i = obj;
|
||||||
|
|
||||||
|
UnpackedRecord idxKey;
|
||||||
|
idxKey.pKeyInfo = crsSPO.pKeyInfo;
|
||||||
|
idxKey.nField = 3;
|
||||||
|
idxKey.default_rc = 0;
|
||||||
|
idxKey.aMem = mem;
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
rc = sqlite3BtreeMovetoUnpacked(&crsSPO,
|
||||||
|
&idxKey, 0, 0, &res);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
rc = sqlite3VdbeIdxRowid(db, &crsSPO, pKey);
|
||||||
|
} else {
|
||||||
|
rc = sqlite3BtreeLast(&crsTriples, &res);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto close;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sqlite3BtreeKeySize(&crsTriples, pKey);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto close;
|
||||||
|
}
|
||||||
|
(*pKey)++;
|
||||||
|
|
||||||
|
int file_format = db->aDb[0].pSchema->file_format;
|
||||||
|
|
||||||
|
unsigned char buf[41]; // enough for record with three integers
|
||||||
|
buf[0] = 5;
|
||||||
|
|
||||||
|
u32 serial_type;
|
||||||
|
unsigned char* p = buf+5;
|
||||||
|
|
||||||
|
serial_type = sqlite3VdbeSerialType(&mem[0], file_format);
|
||||||
|
buf[1] = serial_type;
|
||||||
|
p += sqlite3VdbeSerialPut(p, &mem[0], serial_type);
|
||||||
|
|
||||||
|
serial_type = sqlite3VdbeSerialType(&mem[1], file_format);
|
||||||
|
buf[2] = serial_type;
|
||||||
|
p += sqlite3VdbeSerialPut(p, &mem[1], serial_type);
|
||||||
|
|
||||||
|
serial_type = sqlite3VdbeSerialType(&mem[2], file_format);
|
||||||
|
buf[3] = serial_type;
|
||||||
|
p += sqlite3VdbeSerialPut(p, &mem[2], serial_type);
|
||||||
|
|
||||||
|
unsigned char* tmp = p;
|
||||||
|
|
||||||
|
mem[3].flags = MEM_Int;
|
||||||
|
mem[3].u.i = 1;
|
||||||
|
serial_type = sqlite3VdbeSerialType(&mem[3], file_format);
|
||||||
|
buf[4] = serial_type;
|
||||||
|
p += sqlite3VdbeSerialPut(p, &mem[3], serial_type);
|
||||||
|
|
||||||
|
rc = sqlite3BtreeInsert(&crsTriples, 0, *pKey,
|
||||||
|
buf, p-buf, 0,
|
||||||
|
0, 0);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = tmp;
|
||||||
|
|
||||||
|
mem[3].flags = MEM_Int;
|
||||||
|
mem[3].u.i = *pKey;
|
||||||
|
serial_type = sqlite3VdbeSerialType(&mem[3], file_format);
|
||||||
|
buf[4] = serial_type;
|
||||||
|
p += sqlite3VdbeSerialPut(p, &mem[3], serial_type);
|
||||||
|
|
||||||
|
rc = sqlite3BtreeInsert(&crsSPO, buf, p-buf,
|
||||||
|
0, *pKey, 0,
|
||||||
|
0, 0);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite3KeyInfoUnref(infSPO);
|
||||||
|
rc = sqlite3BtreeCloseCursor(&crsSPO);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto close1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sqlite3BtreeCloseCursor(&crsTriples);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
goto rollback;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sqlite3BtreeCommit(db->aDb[0].pBt);
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
close:
|
||||||
|
sqlite3KeyInfoUnref(infSPO);
|
||||||
|
sqlite3BtreeCloseCursor(&crsSPO);
|
||||||
|
|
||||||
|
close1:
|
||||||
|
sqlite3BtreeCloseCursor(&crsTriples);
|
||||||
|
|
||||||
|
rollback:
|
||||||
|
sqlite3BtreeRollback(db->aDb[0].pBt, SQLITE_ABORT_ROLLBACK, 0);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
sqlite3 *db = NULL;
|
sqlite3 *db = NULL;
|
||||||
@@ -417,6 +560,9 @@ void main()
|
|||||||
pgf_print_expr(e, NULL, 0, out, err);
|
pgf_print_expr(e, NULL, 0, out, err);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
sg_insert_triple(db, 2, 2, 2, &key);
|
||||||
|
printf("%d\n", (int) key);
|
||||||
|
|
||||||
gu_pool_free(tmp_pool);
|
gu_pool_free(tmp_pool);
|
||||||
|
|
||||||
sqlite3_close(db);
|
sqlite3_close(db);
|
||||||
|
|||||||
Reference in New Issue
Block a user