forked from GitHub/gf-core
storage for literals in libsg
This commit is contained in:
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
#include "sg/sg.h"
|
#include "sg/sg.h"
|
||||||
|
|
||||||
#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_TRIPLES "sg_triples"
|
#define SG_LITERALS "sg_literals"
|
||||||
|
#define SG_TRIPLES "sg_triples"
|
||||||
#define SG_TRIPLES_SPO "sg_triples_spo"
|
#define SG_TRIPLES_SPO "sg_triples_spo"
|
||||||
#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"
|
||||||
@@ -47,6 +48,7 @@ sg_open(const char *filename,
|
|||||||
|
|
||||||
rc = sqlite3_exec(db, "create table if not exists " SG_EXPRS "(fun not null, arg integer);"
|
rc = 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_LITERALS " on " SG_EXPRS "(fun) where arg = 0;"
|
||||||
"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_TRIPLES "(subj integer, pred integer, obj integer, state integer);"
|
"create table if not exists " SG_TRIPLES "(subj integer, pred integer, obj integer, state integer);"
|
||||||
"create unique index if not exists " SG_TRIPLES_SPO " on " SG_TRIPLES "(subj,pred,obj);"
|
"create unique index if not exists " SG_TRIPLES_SPO " on " SG_TRIPLES "(subj,pred,obj);"
|
||||||
@@ -123,6 +125,7 @@ typedef struct {
|
|||||||
BtCursor crsExprs;
|
BtCursor crsExprs;
|
||||||
BtCursor crsPairs;
|
BtCursor crsPairs;
|
||||||
BtCursor crsIdents;
|
BtCursor crsIdents;
|
||||||
|
BtCursor crsLiterals;
|
||||||
SgId key_seed;
|
SgId key_seed;
|
||||||
} ExprContext;
|
} ExprContext;
|
||||||
|
|
||||||
@@ -150,6 +153,12 @@ open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err)
|
|||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Index *literalsIdx = sqlite3HashFind(&db->aDb[0].pSchema->idxHash, SG_LITERALS);
|
||||||
|
if (!literalsIdx) {
|
||||||
|
sg_raise_err("Index " SG_LITERALS " is missing", err);
|
||||||
|
return SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
memset(&ctxt->crsExprs, 0, sizeof(ctxt->crsExprs));
|
memset(&ctxt->crsExprs, 0, sizeof(ctxt->crsExprs));
|
||||||
@@ -178,6 +187,15 @@ open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err)
|
|||||||
}
|
}
|
||||||
ctxt->n_cursors++;
|
ctxt->n_cursors++;
|
||||||
|
|
||||||
|
memset(&ctxt->crsLiterals, 0, sizeof(ctxt->crsLiterals));
|
||||||
|
KeyInfo *infLiterals = sqlite3KeyInfoAlloc(db, 1, 1);
|
||||||
|
rc = sqlite3BtreeCursor(db->aDb[0].pBt, literalsIdx->tnum, wrFlag, infLiterals, &ctxt->crsLiterals);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
sg_raise_sqlite(db, err);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
ctxt->n_cursors++;
|
||||||
|
|
||||||
if (wrFlag) {
|
if (wrFlag) {
|
||||||
int res;
|
int res;
|
||||||
rc = sqlite3BtreeLast(&ctxt->crsExprs, &res);
|
rc = sqlite3BtreeLast(&ctxt->crsExprs, &res);
|
||||||
@@ -201,6 +219,11 @@ open_exprs(sqlite3 *db, int wrFlag, ExprContext* ctxt, GuExn* err)
|
|||||||
static void
|
static void
|
||||||
close_exprs(ExprContext* ctxt)
|
close_exprs(ExprContext* ctxt)
|
||||||
{
|
{
|
||||||
|
if (ctxt->n_cursors >= 4) {
|
||||||
|
sqlite3KeyInfoUnref(ctxt->crsLiterals.pKeyInfo);
|
||||||
|
sqlite3BtreeCloseCursor(&ctxt->crsLiterals);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctxt->n_cursors >= 3) {
|
if (ctxt->n_cursors >= 3) {
|
||||||
sqlite3KeyInfoUnref(ctxt->crsIdents.pKeyInfo);
|
sqlite3KeyInfoUnref(ctxt->crsIdents.pKeyInfo);
|
||||||
sqlite3BtreeCloseCursor(&ctxt->crsIdents);
|
sqlite3BtreeCloseCursor(&ctxt->crsIdents);
|
||||||
@@ -228,6 +251,7 @@ store_expr(sqlite3* db,
|
|||||||
GuVariantInfo ei = gu_variant_open(expr);
|
GuVariantInfo ei = gu_variant_open(expr);
|
||||||
switch (ei.tag) {
|
switch (ei.tag) {
|
||||||
case PGF_EXPR_ABS: {
|
case PGF_EXPR_ABS: {
|
||||||
|
gu_impossible();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_APP: {
|
case PGF_EXPR_APP: {
|
||||||
@@ -314,9 +338,104 @@ store_expr(sqlite3* db,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_LIT: {
|
case PGF_EXPR_LIT: {
|
||||||
|
PgfExprLit* elit = ei.data;
|
||||||
|
|
||||||
|
Mem mem[2];
|
||||||
|
|
||||||
|
GuVariantInfo li = gu_variant_open(elit->lit);
|
||||||
|
switch (li.tag) {
|
||||||
|
case PGF_LITERAL_STR: {
|
||||||
|
PgfLiteralStr* lstr = li.data;
|
||||||
|
|
||||||
|
mem[0].flags = MEM_Str;
|
||||||
|
mem[0].n = strlen(lstr->val);
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PGF_LITERAL_FLT: {
|
||||||
|
PgfLiteralFlt* lflt = li.data;
|
||||||
|
|
||||||
|
mem[0].flags = MEM_Real;
|
||||||
|
mem[0].u.r = lflt->val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
gu_impossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
UnpackedRecord idxKey;
|
||||||
|
idxKey.pKeyInfo = ctxt->crsIdents.pKeyInfo;
|
||||||
|
idxKey.nField = 1;
|
||||||
|
idxKey.default_rc = 0;
|
||||||
|
idxKey.aMem = mem;
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
rc = sqlite3BtreeMovetoUnpacked(&ctxt->crsLiterals,
|
||||||
|
&idxKey, 0, 0, &res);
|
||||||
|
if (rc != SQLITE_OK) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == 0) {
|
||||||
|
rc = sqlite3VdbeIdxRowid(db, &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 = sqlite3VdbeSerialType(&mem[0], file_format);
|
||||||
|
int serial_type_lit_hdr_len = sqlite3VarintLen(serial_type_lit);
|
||||||
|
int serial_type_arg = sqlite3VdbeSerialType(&mem[1], file_format);
|
||||||
|
int serial_type_arg_hdr_len = sqlite3VarintLen(serial_type_arg);
|
||||||
|
|
||||||
|
unsigned char* buf = malloc(1+serial_type_lit_hdr_len+MAX(1,serial_type_arg_hdr_len)+mem[0].n+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 += sqlite3VdbeSerialPut(p, &mem[0], serial_type_lit);
|
||||||
|
p += sqlite3VdbeSerialPut(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 = sqlite3VdbeSerialType(&mem[1], file_format);
|
||||||
|
int serial_type_key_hdr_len = sqlite3VarintLen(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 += sqlite3VdbeSerialPut(p, &mem[0], serial_type_lit);
|
||||||
|
p += sqlite3VdbeSerialPut(p, &mem[1], serial_type_key);
|
||||||
|
rc = sqlite3BtreeInsert(&ctxt->crsLiterals, buf, p-buf,
|
||||||
|
0, *pKey, 0,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_META: {
|
case PGF_EXPR_META: {
|
||||||
|
gu_impossible();
|
||||||
}
|
}
|
||||||
case PGF_EXPR_FUN: {
|
case PGF_EXPR_FUN: {
|
||||||
PgfExprFun* fun = ei.data;
|
PgfExprFun* fun = ei.data;
|
||||||
@@ -390,12 +509,17 @@ free:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_VAR: {
|
case PGF_EXPR_VAR: {
|
||||||
|
gu_impossible();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_TYPED: {
|
case PGF_EXPR_TYPED: {
|
||||||
|
PgfExprTyped* etyped = ei.data;
|
||||||
|
rc = store_expr(db, ctxt, etyped->expr, pKey, wrFlag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PGF_EXPR_IMPL_ARG: {
|
case PGF_EXPR_IMPL_ARG: {
|
||||||
|
PgfExprImplArg* eimpl = ei.data;
|
||||||
|
rc = store_expr(db, ctxt, eimpl->expr, pKey, wrFlag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -482,8 +606,8 @@ load_expr(BtCursor* crsExprs, SgId key, PgfExpr *pExpr, GuPool* out_pool)
|
|||||||
Mem mem[2];
|
Mem mem[2];
|
||||||
row += sqlite3VdbeSerialGet(row, serial_type_fun, &mem[0]);
|
row += sqlite3VdbeSerialGet(row, serial_type_fun, &mem[0]);
|
||||||
row += sqlite3VdbeSerialGet(row, serial_type_arg, &mem[1]);
|
row += sqlite3VdbeSerialGet(row, serial_type_arg, &mem[1]);
|
||||||
|
|
||||||
if (serial_type_arg == 0) {
|
if (mem[1].flags & MEM_Null) {
|
||||||
u32 len = sqlite3VdbeSerialTypeLen(serial_type_fun);
|
u32 len = sqlite3VdbeSerialTypeLen(serial_type_fun);
|
||||||
|
|
||||||
PgfExprFun *efun =
|
PgfExprFun *efun =
|
||||||
@@ -493,6 +617,37 @@ load_expr(BtCursor* crsExprs, SgId key, PgfExpr *pExpr, GuPool* out_pool)
|
|||||||
pExpr, out_pool);
|
pExpr, out_pool);
|
||||||
memcpy(efun->fun, mem[0].z, len);
|
memcpy(efun->fun, mem[0].z, len);
|
||||||
efun->fun[len] = 0;
|
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 = sqlite3VdbeSerialTypeLen(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 {
|
} else {
|
||||||
PgfExprApp* papp =
|
PgfExprApp* papp =
|
||||||
gu_new_variant(PGF_EXPR_APP, PgfExprApp, pExpr, out_pool);
|
gu_new_variant(PGF_EXPR_APP, PgfExprApp, pExpr, out_pool);
|
||||||
@@ -1154,6 +1309,14 @@ sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
sg_triple_result_close(SgTripleResult* tres, GuExn* err)
|
sg_triple_result_close(SgTripleResult* tres, GuExn* err)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ int
|
|||||||
sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple,
|
sg_triple_result_fetch(SgTripleResult* tres, SgId* pKey, SgTriple triple,
|
||||||
GuPool* out_pool, GuExn* err);
|
GuPool* out_pool, GuExn* err);
|
||||||
|
|
||||||
|
void
|
||||||
|
sg_triple_result_get_query(SgTripleResult* tres, SgTriple triple);
|
||||||
|
|
||||||
void
|
void
|
||||||
sg_triple_result_close(SgTripleResult* tres, GuExn* err);
|
sg_triple_result_close(SgTripleResult* tres, GuExn* err);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user