From: drh Date: Thu, 23 Mar 2017 00:13:52 +0000 (+0000) Subject: Various fixes to the json_merge_patch() function. X-Git-Tag: version-3.18.0~11^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb7aa2d85e684d0db13c93c1e6dbb0e2f3bfb1ab;p=thirdparty%2Fsqlite.git Various fixes to the json_merge_patch() function. FossilOrigin-Name: f49fd2554b0723eb7cf2fd765d655c6820833ee7e5f7d7629d98c27a6fffa1d9 --- diff --git a/ext/misc/json1.c b/ext/misc/json1.c index c037525c45..f03bdc6652 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1364,7 +1364,7 @@ static JsonNode *jsonMergePatch( JsonNode *pPatch /* The PATCH */ ){ int i, j; - int iApnd; + int iRoot; JsonNode *pTarget; if( pPatch->eType!=JSON_OBJECT ){ return pPatch; @@ -1373,14 +1373,14 @@ static JsonNode *jsonMergePatch( pTarget = &pParse->aNode[iTarget]; assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); if( pTarget->eType!=JSON_OBJECT ){ - for(i=2; in; i += jsonNodeSize(&pPatch[i])+1){ + for(i=2; i<=pPatch->n; i += jsonNodeSize(&pPatch[i])+1){ if( pPatch[i].eType==JSON_NULL ){ - pPatch[i-1].jnFlags |= JNODE_REMOVE; + pPatch[i].jnFlags |= JNODE_REMOVE; } } return pPatch; } - iApnd = iTarget; + iRoot = iTarget; for(i=1; in; i += jsonNodeSize(&pPatch[i+1])+1){ int nKey; const char *zKey; @@ -1388,21 +1388,19 @@ static JsonNode *jsonMergePatch( assert( pPatch[i].jnFlags & JNODE_LABEL ); nKey = pPatch[i].n; zKey = pPatch[i].u.zJContent; - if( (pPatch[i].jnFlags & JNODE_RAW)==0 ){ - assert( nKey>=2 && zKey[0]=='"' && zKey[nKey-1]=='"' ); - nKey -= 2; - zKey ++; - } + assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); for(j=1; jn; j += jsonNodeSize(&pTarget[j+1])+1 ){ assert( pTarget[j].eType==JSON_STRING ); assert( pTarget[j].jnFlags & JNODE_LABEL ); - if( jsonLabelCompare(&pTarget[j], zKey, nKey) - && (pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH))==0 + assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); + if( (pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH))==0 + && pTarget[j].n==nKey + && strncmp(pTarget[j].u.zJContent, zKey, nKey)==0 ){ if( pPatch[i+1].eType==JSON_NULL ){ pTarget[j+1].jnFlags |= JNODE_REMOVE; }else{ - JsonNode *pNew = jsonMergePatch(pParse, j+1, &pPatch[i+1]); + JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]); if( pNew==0 ) return 0; pTarget = &pParse->aNode[iTarget]; if( pNew!=&pTarget[j+1] ){ @@ -1413,16 +1411,16 @@ static JsonNode *jsonMergePatch( break; } } - if( j>=pTarget->n ){ + if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){ int iStart, iPatch; iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0); jsonParseAddNode(pParse, JSON_STRING, nKey, zKey); iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0); if( pParse->oom ) return 0; pTarget = &pParse->aNode[iTarget]; - pParse->aNode[iApnd].jnFlags |= JNODE_APPEND; - pParse->aNode[iApnd].u.iAppend = iStart; - iApnd = iStart; + pParse->aNode[iRoot].jnFlags |= JNODE_APPEND; + pParse->aNode[iRoot].u.iAppend = iStart - iRoot; + iRoot = iStart; pParse->aNode[iPatch].jnFlags |= JNODE_PATCH; pParse->aNode[iPatch].u.pPatch = &pPatch[i+1]; } @@ -1442,13 +1440,20 @@ static void jsonMergePatchFunc( ){ JsonParse x; /* The JSON that is being patched */ JsonParse y; /* The patch */ + JsonNode *pResult; /* The result of the merge */ if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ jsonParseReset(&x); return; } - jsonReturnJson(jsonMergePatch(&x, 0, y.aNode), ctx, 0); + pResult = jsonMergePatch(&x, 0, y.aNode); + assert( pResult!=0 || x.oom ); + if( pResult ){ + jsonReturnJson(pResult, ctx, 0); + }else{ + sqlite3_result_error_nomem(ctx); + } jsonParseReset(&x); jsonParseReset(&y); } diff --git a/manifest b/manifest index 8c6f009d42..31881bdb35 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sname\sof\sthe\snew\sfunction\sto\s"json_merge_patch()". -D 2017-03-22T21:45:20.759 +C Various\sfixes\sto\sthe\sjson_merge_patch()\sfunction. +D 2017-03-23T00:13:52.903 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 1faf9f06aadc9284c212dea7bbc7c0dea7e8337f0287c81001eff500912c790a @@ -218,7 +218,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c be1032c54498ae8d884b7c430da876a0f895dfc734ac3255336014ce79e3f219 +F ext/misc/json1.c 8a8ba23a0715858ff393aa890e379912759712518afa4d28de6308a79287cb61 F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e @@ -913,7 +913,7 @@ F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa F test/json101.test c0897616f32d95431f37fd291cb78742181980ac F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0 -F test/json104.test 66d3dfc9f76e413c7c957d897325b17b9d1bbdf471225310dbf47279e36f1937 +F test/json104.test 9f8358fd4ec94eca27b31d4ad7f75482edf24c865df378e5129c0b3107c9664e F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff F test/kvtest.c b9a9822dda05a1aa481215a52e2fc93cd8b22ee5 F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63 @@ -1568,7 +1568,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a267444039af519f088dd8f8ee33f686cc3071c087677075af2364ebc2587514 -R f0982f12ae9e098efe5bc17c4edc8338 +P 53bf70f37bbca319ea35f70849e2a34ae628a504486158fdad5c4bb7431c68e0 +R 7c38ec8ac02c81967ed35b7b062ffaf6 U drh -Z 17fdf70c56513cf2488f301085ed16e1 +Z e95ab9d86e57fcad88a27a5fb020f800 diff --git a/manifest.uuid b/manifest.uuid index ea9e24d51d..23d86ab688 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -53bf70f37bbca319ea35f70849e2a34ae628a504486158fdad5c4bb7431c68e0 \ No newline at end of file +f49fd2554b0723eb7cf2fd765d655c6820833ee7e5f7d7629d98c27a6fffa1d9 \ No newline at end of file diff --git a/test/json104.test b/test/json104.test index be041c5da8..b5a45bc525 100644 --- a/test/json104.test +++ b/test/json104.test @@ -54,6 +54,13 @@ do_execsql_test json104-110 { }, "tags": [ "example" ] }'); -} {{{"title":"Hello!","author":{"givenName":"John"},"tags":["example"],"content":"This will be unchanged",phoneNumber:"+01-123-456-7890"}}} +} {{{"title":"Hello!","author":{"givenName":"John"},"tags":["example"],"content":"This will be unchanged","phoneNumber":"+01-123-456-7890"}}} + +do_execsql_test json104-200 { + SELECT json_merge_patch('[1,2,3]','{"x":null}'); +} {{{}}} +do_execsql_test json104-210 { + SELECT json_merge_patch('[1,2,3]','{"x":null,"y":1,"z":null}'); +} {{{"y":1}}} finish_test