diff options
Diffstat (limited to 'src/json.c')
-rw-r--r-- | src/json.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/src/json.c b/src/json.c index e66c4b132..fa7913d94 100644 --- a/src/json.c +++ b/src/json.c @@ -2465,11 +2465,21 @@ static JsonNode *jsonLookupAppend( } /* -** Return the text of a syntax error message on a JSON path. Space is -** obtained from sqlite3_malloc(). +** Compute the text of an error in JSON path syntax. +** +** If ctx is not NULL then push the error message into ctx and return NULL. +* If ctx is NULL, then return the text of the error message. */ -static char *jsonPathSyntaxError(const char *zErr){ - return sqlite3_mprintf("JSON path error near '%q'", zErr); +static char *jsonPathSyntaxError(const char *zErr, sqlite3_context *ctx){ + char *zMsg = sqlite3_mprintf("JSON path error near '%q'", zErr); + if( ctx==0 ) return zMsg; + if( zMsg==0 ){ + sqlite3_result_error_nomem(ctx); + }else{ + sqlite3_result_error(ctx, zMsg, -1); + sqlite3_free(zMsg); + } + return 0; } /* @@ -2490,7 +2500,6 @@ static JsonNode *jsonLookup( ){ const char *zErr = 0; JsonNode *pNode = 0; - char *zMsg; if( zPath==0 ) return 0; if( zPath[0]!='$' ){ @@ -2504,13 +2513,7 @@ static JsonNode *jsonLookup( lookup_err: pParse->nErr++; assert( zErr!=0 && pCtx!=0 ); - zMsg = jsonPathSyntaxError(zErr); - if( zMsg ){ - sqlite3_result_error(pCtx, zMsg, -1); - sqlite3_free(zMsg); - }else{ - sqlite3_result_error_nomem(pCtx); - } + jsonPathSyntaxError(zErr, pCtx); return 0; } @@ -3814,11 +3817,15 @@ static u32 jsonbArrayCount(JsonParse *pParse, u32 iRoot){ */ static void jsonAfterEditSizeAdjust(JsonParse *pParse, u32 iRoot){ u32 sz = 0; + u32 nBlob; assert( pParse->delta!=0 ); + assert( pParse->nBlobAlloc >= pParse->nBlob ); + nBlob = pParse->nBlob; + pParse->nBlob = pParse->nBlobAlloc; (void)jsonbPayloadSize(pParse, iRoot, &sz); + pParse->nBlob = nBlob; sz += pParse->delta; jsonBlobChangePayloadSize(pParse, iRoot, sz); - pParse->nBlob += pParse->delta; } /* @@ -3857,6 +3864,7 @@ static u32 jsonLookupBlobStep( memmove(&pParse->aBlob[iRoot], &pParse->aBlob[iRoot+sz], pParse->nBlob - (iRoot+sz)); pParse->delta = -(int)sz; + pParse->nBlob -= sz; }else if( pParse->eEdit==JEDIT_INS ){ /* Already exists, so json_insert() is a no-op */ }else{ @@ -3871,6 +3879,7 @@ static u32 jsonLookupBlobStep( memmove(&pParse->aBlob[iRoot+pParse->nIns], &pParse->aBlob[iRoot+sz], pParse->nBlob - iRoot - sz); + pParse->nBlob += d; } memcpy(&pParse->aBlob[iRoot], pParse->aIns, pParse->nIns); } @@ -3981,6 +3990,7 @@ static u32 jsonLookupBlobStep( pParse->nBlob - j); memcpy(&pParse->aBlob[j], pParse->aIns, pParse->nIns); pParse->delta = pParse->nIns; + pParse->nBlob += pParse->nIns; jsonAfterEditSizeAdjust(pParse, iRoot); return j; } @@ -4254,6 +4264,7 @@ static void jsonRemoveFromBlob( ){ int i; u32 rc; + const char *zPath = 0; JsonParse px; memset(&px, 0, sizeof(px)); px.nBlob = sqlite3_value_bytes(argv[0]); @@ -4261,21 +4272,25 @@ static void jsonRemoveFromBlob( if( px.aBlob==0 ) return; for(i=1; i<argc; i++){ const char *zPath = (const char*)sqlite3_value_text(argv[i]); - if( zPath==0 ) goto jsonRemoveFromBlob_error; - if( zPath[0]!='$' ) goto jsonRemoveFromBlob_error; + if( zPath==0 ) goto jsonRemoveFromBlob_patherror; + if( zPath[0]!='$' ) goto jsonRemoveFromBlob_patherror; + if( zPath[1]==0 ){ + if( px.nBlobAlloc ) sqlite3_free(px.aBlob); + return; /* return NULL if $ is removed */ + } px.eEdit = JEDIT_DEL; rc = jsonLookupBlobStep(&px, 0, zPath+1, 0); if( rc==JSON_BLOB_NOTFOUND ) continue; - if( JSON_BLOB_ISERROR(rc) ) goto jsonRemoveFromBlob_error; + if( JSON_BLOB_ISERROR(rc) ) goto jsonRemoveFromBlob_patherror; } sqlite3_result_blob(ctx, px.aBlob, px.nBlob, - px.nBlobAlloc>0 ? sqlite3_free : SQLITE_DYNAMIC); + px.nBlobAlloc>0 ? SQLITE_DYNAMIC : SQLITE_TRANSIENT); return; -jsonRemoveFromBlob_error: +jsonRemoveFromBlob_patherror: if( px.nBlobAlloc ) sqlite3_free(px.aBlob); + jsonPathSyntaxError(zPath, ctx); return; - } /**************************************************************************** @@ -5814,7 +5829,7 @@ static int jsonEachFilter( } if( zErr ){ sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr); + cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr, 0); jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; }else if( pNode==0 ){ |