diff options
author | drh <drh@noemail.net> | 2018-08-30 01:52:10 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2018-08-30 01:52:10 +0000 |
commit | e35fc302c3da49ac52edcda89a604a99ef898039 (patch) | |
tree | 7cbdf1ffd3bd9bd812058315619fd927ab2b82f3 /ext/misc/json1.c | |
parent | 9c1d7c6d4ce60c73e29daed1c005bb589f0cd74a (diff) | |
download | sqlite-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.c | 74 |
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); } |