aboutsummaryrefslogtreecommitdiff
path: root/ext/misc/json1.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-08-30 01:52:10 +0000
committerdrh <drh@noemail.net>2018-08-30 01:52:10 +0000
commite35fc302c3da49ac52edcda89a604a99ef898039 (patch)
tree7cbdf1ffd3bd9bd812058315619fd927ab2b82f3 /ext/misc/json1.c
parent9c1d7c6d4ce60c73e29daed1c005bb589f0cd74a (diff)
downloadsqlite-e35fc302c3da49ac52edcda89a604a99ef898039.tar.gz
sqlite-e35fc302c3da49ac52edcda89a604a99ef898039.zip
Improved JSON parser caching.
FossilOrigin-Name: 58078c0d2647a194279fa80e032670441b296ffc3acee692901faa5beca460b7
Diffstat (limited to 'ext/misc/json1.c')
-rw-r--r--ext/misc/json1.c74
1 files changed, 49 insertions, 25 deletions
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index f1b633d2c..51a519cf0 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -172,6 +172,7 @@ struct JsonParse {
u8 nErr; /* Number of errors seen */
u16 iDepth; /* Nesting depth */
int nJson; /* Length of the zJson string in bytes */
+ u32 iHold; /* Replace cache line with the lowest iHold value */
};
/*
@@ -976,7 +977,8 @@ static int jsonParseFindParents(JsonParse *pParse){
/*
** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
*/
-#define JSON_CACHE_ID (-429938)
+#define JSON_CACHE_ID (-429938) /* First cache entry */
+#define JSON_CACHE_SZ 4 /* Max number of cache entries */
/*
** Obtain a complete parse of the JSON found in the first argument
@@ -988,16 +990,42 @@ static int jsonParseFindParents(JsonParse *pParse){
*/
static JsonParse *jsonParseCached(
sqlite3_context *pCtx,
- sqlite3_value **argv
+ sqlite3_value **argv,
+ sqlite3_context *pErrCtx
){
const char *zJson = (const char*)sqlite3_value_text(argv[0]);
int nJson = sqlite3_value_bytes(argv[0]);
JsonParse *p;
+ JsonParse *pMatch = 0;
+ int iKey;
+ int iMinKey = 0;
+ u32 iMinHold = 0xffffffff;
+ u32 iMaxHold = 0;
if( zJson==0 ) return 0;
- p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID);
- if( p && p->nJson==nJson && memcmp(p->zJson,zJson,nJson)==0 ){
- p->nErr = 0;
- return p; /* The cached entry matches, so return it */
+ for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
+ p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
+ if( p==0 ){
+ iMinKey = iKey;
+ break;
+ }
+ if( pMatch==0
+ && p->nJson==nJson
+ && memcmp(p->zJson,zJson,nJson)==0
+ ){
+ p->nErr = 0;
+ pMatch = p;
+ }else if( p->iHold<iMinHold ){
+ iMinHold = p->iHold;
+ iMinKey = iKey;
+ }
+ if( p->iHold>iMaxHold ){
+ iMaxHold = p->iHold;
+ }
+ }
+ if( pMatch ){
+ pMatch->nErr = 0;
+ pMatch->iHold = iMaxHold+1;
+ return pMatch;
}
p = sqlite3_malloc( sizeof(*p) + nJson + 1 );
if( p==0 ){
@@ -1007,13 +1035,15 @@ static JsonParse *jsonParseCached(
memset(p, 0, sizeof(*p));
p->zJson = (char*)&p[1];
memcpy((char*)p->zJson, zJson, nJson+1);
- if( jsonParse(p, pCtx, p->zJson) ){
+ if( jsonParse(p, pErrCtx, p->zJson) ){
sqlite3_free(p);
return 0;
}
p->nJson = nJson;
- sqlite3_set_auxdata(pCtx, JSON_CACHE_ID, p, (void(*)(void*))jsonParseFree);
- return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID);
+ p->iHold = iMaxHold+1;
+ sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
+ (void(*)(void*))jsonParseFree);
+ return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
}
/*
@@ -1386,7 +1416,7 @@ static void jsonArrayLengthFunc(
u32 i;
JsonNode *pNode;
- p = jsonParseCached(ctx, argv);
+ p = jsonParseCached(ctx, argv, ctx);
if( p==0 ) return;
assert( p->nNode );
if( argc==2 ){
@@ -1427,7 +1457,7 @@ static void jsonExtractFunc(
int i;
if( argc<2 ) return;
- p = jsonParseCached(ctx, argv);
+ p = jsonParseCached(ctx, argv, ctx);
if( p==0 ) return;
jsonInit(&jx, ctx);
jsonAppendChar(&jx, '[');
@@ -1734,22 +1764,21 @@ static void jsonTypeFunc(
int argc,
sqlite3_value **argv
){
- JsonParse x; /* The parse */
+ JsonParse *p; /* The parse */
const char *zPath;
JsonNode *pNode;
- if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
- assert( x.nNode );
+ p = jsonParseCached(ctx, argv, ctx);
+ if( p==0 ) return;
if( argc==2 ){
zPath = (const char*)sqlite3_value_text(argv[1]);
- pNode = jsonLookup(&x, zPath, 0, ctx);
+ pNode = jsonLookup(p, zPath, 0, ctx);
}else{
- pNode = x.aNode;
+ pNode = p->aNode;
}
if( pNode ){
sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC);
}
- jsonParseReset(&x);
}
/*
@@ -1763,15 +1792,10 @@ static void jsonValidFunc(
int argc,
sqlite3_value **argv
){
- JsonParse x; /* The parse */
- int rc = 0;
-
+ JsonParse *p; /* The parse */
UNUSED_PARAM(argc);
- if( jsonParse(&x, 0, (const char*)sqlite3_value_text(argv[0]))==0 ){
- rc = 1;
- }
- jsonParseReset(&x);
- sqlite3_result_int(ctx, rc);
+ p = jsonParseCached(ctx, argv, 0);
+ sqlite3_result_int(ctx, p!=0);
}