aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2023-11-30 19:06:27 +0000
committerdrh <>2023-11-30 19:06:27 +0000
commit66795962b59af6deab38b178a8a3b03f223c309a (patch)
tree174fa58e5119433f77b6373a8a4343d1022d0ffe /src
parent7394a6ef571081ed4f8bd88f77121b0b9338fa70 (diff)
downloadsqlite-66795962b59af6deab38b178a8a3b03f223c309a.tar.gz
sqlite-66795962b59af6deab38b178a8a3b03f223c309a.zip
Enhance json_set() and json_insert() so that they create missing
substructure. FossilOrigin-Name: cc7a641ab5ae739d31c24f0ad0caeb15a481a63fa8f13720718ea922c25862ff
Diffstat (limited to 'src')
-rw-r--r--src/json.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/src/json.c b/src/json.c
index b3b4f993e..b8b01bf45 100644
--- a/src/json.c
+++ b/src/json.c
@@ -3154,6 +3154,7 @@ static u32 jsonLookupBlobStep(
u32 i, j, k, nKey, sz, n, iEnd, rc;
const char *zKey;
u8 x;
+ static const u8 emptyObject[] = { JSONB_ARRAY, JSONB_OBJECT };
if( zPath[0]==0 ){
if( pParse->eEdit && jsonBlobMakeEditable(pParse, pParse->nIns) ){
@@ -3225,25 +3226,44 @@ static u32 jsonLookupBlobStep(
}
if( j>iEnd ) return JSON_BLOB_ERROR;
if( pParse->eEdit>=JEDIT_INS ){
- u32 nIns;
- u8 aLabel[16];
- JsonParse ix;
+ u32 nIns; /* Total bytes to insert (label+value) */
+ JsonParse v; /* BLOB encoding of the value to be inserted */
+ JsonParse ix; /* Header of the label to be inserted */
+ u8 aLabel[16]; /* Buffer space for ix */
testcase( pParse->eEdit==JEDIT_INS );
testcase( pParse->eEdit==JEDIT_SET );
memset(&ix, 0, sizeof(ix));
ix.aBlob = aLabel;
ix.nBlobAlloc = sizeof(aLabel);
jsonBlobAppendNodeType(&ix,JSONB_TEXTRAW, nKey);
- if( jsonBlobMakeEditable(pParse, ix.nBlob+nKey+pParse->nIns) ){
- nIns = ix.nBlob + nKey + pParse->nIns;
+ memset(&v, 0, sizeof(v));
+ if( zPath[i]==0 ){
+ v.nBlob = pParse->nIns;
+ v.aBlob = pParse->aIns;
+ }else{
+ v.nBlob = 1;
+ v.aBlob = (u8*)&emptyObject[zPath[i]=='.'];
+ v.eEdit = pParse->eEdit;
+ v.nIns = pParse->nIns;
+ v.aIns = pParse->aIns;
+ rc = jsonLookupBlobStep(&v, 0, &zPath[i], 0);
+ if( JSON_BLOB_ISERROR(rc) || v.oom ){
+ pParse->oom |= v.oom;
+ jsonParseReset(&v);
+ return rc;
+ }
+ }
+ if( jsonBlobMakeEditable(pParse, ix.nBlob+nKey+v.nBlob) ){
+ nIns = ix.nBlob + nKey + v.nBlob;
jsonBlobEdit(pParse, j, 0, 0, nIns);
memcpy(&pParse->aBlob[j], ix.aBlob, ix.nBlob);
k = j + ix.nBlob;
memcpy(&pParse->aBlob[k], zKey, nKey);
k += nKey;
- memcpy(&pParse->aBlob[k], pParse->aIns, pParse->nIns);
+ memcpy(&pParse->aBlob[k], v.aBlob, v.nBlob);
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
}
+ jsonParseReset(&v);
return j;
}
}else if( zPath[0]=='[' ){
@@ -3292,12 +3312,31 @@ static u32 jsonLookupBlobStep(
}
if( j>iEnd ) return JSON_BLOB_ERROR;
if( k>0 ) return JSON_BLOB_NOTFOUND;
- if( pParse->eEdit>=JEDIT_INS
- && jsonBlobMakeEditable(pParse, pParse->nIns)
- ){
+ if( pParse->eEdit>=JEDIT_INS ){
+ JsonParse v;
testcase( pParse->eEdit==JEDIT_INS );
testcase( pParse->eEdit==JEDIT_SET );
- jsonBlobEdit(pParse, j, 0, pParse->aIns, pParse->nIns);
+ memset(&v, 0, sizeof(v));
+ if( zPath[i+1]==0 ){
+ v.aBlob = pParse->aIns;
+ v.nBlob = pParse->nIns;
+ }else{
+ v.nBlob = 1;
+ v.aBlob = (u8*)&emptyObject[zPath[i+1]=='.'];
+ v.eEdit = pParse->eEdit;
+ v.nIns = pParse->nIns;
+ v.aIns = pParse->aIns;
+ rc = jsonLookupBlobStep(&v, 0, &zPath[i+1], 0);
+ if( JSON_BLOB_ISERROR(rc) || v.oom ){
+ pParse->oom |= v.oom;
+ jsonParseReset(&v);
+ return rc;
+ }
+ }
+ if( jsonBlobMakeEditable(pParse, v.nBlob) ){
+ jsonBlobEdit(pParse, j, 0, v.aBlob, v.nBlob);
+ }
+ jsonParseReset(&v);
if( pParse->delta ) jsonAfterEditSizeAdjust(pParse, iRoot);
return j;
}
@@ -3754,6 +3793,10 @@ static void jsonReturnParse(
JsonParse *p
){
int flgs;
+ if( p->oom ){
+ sqlite3_result_error_nomem(ctx);
+ return;
+ }
flgs = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx));
if( flgs & JSON_BLOB ){
sqlite3_result_blob(ctx, p->aBlob, p->nBlob,