SQLite

Check-in [afe02a398a]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Clarify ownership of the various objects involved in parsing JSON.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | json-opt-rcstr
Files: files | file ages | folders
SHA3-256: afe02a398a16d51bd7482b6fbe2fbd15d9ac4fd9cdbc9d2bf81f38b3391fc567
User & Date: drh 2023-07-25 20:26:47.054
Context
2023-07-26
00:48
Add the JsonParse.zAlt field to old revised JSON text after a change. Demonstrate that this elminates the need for reparsing after a change by using it in the json_remove() function. This is an incremental check-in containing lots of cruft. (check-in: f930b139d6 user: drh tags: json-opt-rcstr)
2023-07-25
20:26
Clarify ownership of the various objects involved in parsing JSON. (check-in: afe02a398a user: drh tags: json-opt-rcstr)
18:28
Incremental improvements to JSON parsing - trying to fold in the RCStr object. (check-in: 4cb15d934a user: drh tags: json-opt-rcstr)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/json.c.
167
168
169
170
171
172
173











174
175
176
177
178
179
180
*/
#define JSON_MAX_DEPTH  1000

/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/












/* Set the JsonString object to an empty string
*/
static void jsonZero(JsonString *p){
  p->zBuf = p->zSpace;
  p->nAlloc = sizeof(p->zSpace);
  p->nUsed = 0;
  p->bStatic = 1;







>
>
>
>
>
>
>
>
>
>
>







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
*/
#define JSON_MAX_DEPTH  1000

/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/

#if 0
/*
** This is a destructor for JSON strings.  We make it a separate function
** so that the sqlite3ValueIsOfClass() function can be used to unambiguously
** identify sqlite3_value objects that are known JSON strings.
*/
static void jsonStringClass(void *p){
  sqlite3RCStrUnref((char*)p);
}
#endif

/* Set the JsonString object to an empty string
*/
static void jsonZero(JsonString *p){
  p->zBuf = p->zSpace;
  p->nAlloc = sizeof(p->zSpace);
  p->nUsed = 0;
  p->bStatic = 1;
1696
1697
1698
1699
1700
1701
1702








1703
1704
1705
1706
1707

1708
1709
1710
1711
1712


1713
1714
1715
1716
1717
1718
1719

/*
** Parse a complete JSON string.  Return 0 on success or non-zero if there
** are any errors.  If an error occurs, free all memory associated with
** pParse.
**
** pParse is uninitialized when this routine is called.








*/
static int jsonParse(
  JsonParse *pParse,           /* Initialize and fill this JsonParse object */
  sqlite3_context *pCtx,       /* Report errors here */
  char *zJson                  /* Input JSON text to be parsed */

){
  int i;
  memset(pParse, 0, sizeof(*pParse));
  if( zJson==0 ) return 1;
  pParse->zJson = zJson;


  i = jsonParseValue(pParse, 0);
  if( pParse->oom ) i = -1;
  if( i>0 ){
    assert( pParse->iDepth==0 );
    while( fast_isspace(zJson[i]) ) i++;
    if( zJson[i] ){
      i += json5Whitespace(&zJson[i]);







>
>
>
>
>
>
>
>




|
>





>
>







1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741

/*
** Parse a complete JSON string.  Return 0 on success or non-zero if there
** are any errors.  If an error occurs, free all memory associated with
** pParse.
**
** pParse is uninitialized when this routine is called.
**
** pParse->nJPRef set to 1.  The caller becomes the owner of the 
** the JsonParse object.
**
** pParse->bOwnsJson is to bTakeJson.  If bTakeJson is 1, the newly initialized
** JsonParse object will become the own the zJson input string.  If bTakeJson
** is 0, then the caller is responsible for preserving zJson for the lifetime
** of the JsonParse object.
*/
static int jsonParse(
  JsonParse *pParse,           /* Initialize and fill this JsonParse object */
  sqlite3_context *pCtx,       /* Report errors here */
  char *zJson,                 /* Input JSON text to be parsed */
  int bTakeJson                /* Assume ownership of zJson if true */
){
  int i;
  memset(pParse, 0, sizeof(*pParse));
  if( zJson==0 ) return 1;
  pParse->zJson = zJson;
  pParse->bOwnsJson = bTakeJson;
  pParse->nJPRef = 1;
  i = jsonParseValue(pParse, 0);
  if( pParse->oom ) i = -1;
  if( i>0 ){
    assert( pParse->iDepth==0 );
    while( fast_isspace(zJson[i]) ) i++;
    if( zJson[i] ){
      i += json5Whitespace(&zJson[i]);
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
    }
    jsonParseReset(pParse);
    return 1;
  }
  return 0;
}

#if 0
/*
** This is a destructor for JSON strings.  We make it a separate function
** so that the sqlite3ValueIsOfClass() function can be used to unambiguously
** identify sqlite3_value objects that are known JSON strings.
*/
static void jsonClass(void *p){
  sqlite3RCStrUnref((char*)p);
}
#endif

#if 0
/*
** Process SQL function argument pJson as a JSON string.  Return a pointer
** to its parse.
**
** If any error is encountered, return a NULL pointer and leave an error
** message in pCtx.
*/
static JsonParse *jsonParseFromFunctionArg(
  sqlite3_value *pJson,       /* An SQL function argument containing JSON */
  sqlite3_context *pCtx,      /* For accessing the cache */
  sqlite3_context *pErrCtx,   /* For reporting errors */
  int bUnchng                 /* Only accept cached parse that are unchanged */
){
  JsonParse *pParse;
  char *zJson;
  int nJson;
  JsonParse *pMatch = 0;
  int iKey;
  int iMinKey = 0;
  u32 iMinHold = 0xffffffff;
  u32 iMaxHold = 0;

  char *zJson = (char*)sqlite3_value_text(pJson);
  int nJson = sqlite3_value_bytes(pJson);
  if( zJson==0 ) goto json_parse_value_nomem;
  if( sqlite3ValueIsOfClass(pJson, jsonClass) ){
    assert( zJson!=0 );
    (void)sqlite3RCStrRef(zJson);
    pParse = sqlite3RCStrGetAttachment(zJson, (void(*)(void*)jsonParseFree);
    if( pParse ){
      return pParse;
    }
  }else{
    char *z = zJson;
    zJson = sqlite3RCStrNew( nJson );
    if( zJson==0 ) goto json_parse_value_nomem;
    assert( strlen(z)==nJson );
    memcpy(zJson, z, nJson+1);
  }

  /* At this point zJson is an RCStr object that does not yet have a
  ** parse.  This procedure is holding its own reference to that zJson
  ** and needs to release it, or hand it off, prior to returning.
  **
  ** The next step is to try to find a parse of the JSON that already
  ** exists in cache.
  */
  for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
    JsonParse *p;
    p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
    if( p==0 ){
      iMinKey = iKey;
      break;
    }
    if( pMatch==0
     && p->nJson==nJson
     && (p->isMod==0 || bUnchng==0)
     && 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 ){
    pParse = pMatch;
    pParse->iHold = iMaxHold+1;
  }else{
    /* No parse of zJson could be found in cache.  So parse it afresh.
    */
    pParse = sqlite3_malloc64( sizeof(JsonParse) );
    if( pParse==0 ) goto json_parse_value_nomem;
    if( jsonParse(pParse, pCtx, zJson) ){
      sqlite3_free(pParse);
      sqlite3RCStrUnref(zJson);
      return 0;
    }
    pParse->bOwnsJson = 1;
    pParse->nJson = nJson;
    pParse->nJPRef = 1;
    pParse->iHold = iMaxHold+1;
    sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, pParse,
                        (void(*)(void*))jsonParseFree);
    pParse = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
  }
  if( pParse ){
    pParse->nJPRef++;  /* The caller will own this object */
  }
  return pParse;

json_parse_value_nomem:
  if( zJson ) sqlite3RCStrUnref(zJson);
  if( pErrCtx ) sqlite3_result_error_nomem(pCtx);
  return 0;
}
#endif

/* Mark node i of pParse as being a child of iParent.  Call recursively
** to fill in all the descendants of node i.
*/
static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
  JsonNode *pNode = &pParse->aNode[i];
  u32 j;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1756
1757
1758
1759
1760
1761
1762


















































































































1763
1764
1765
1766
1767
1768
1769
    }
    jsonParseReset(pParse);
    return 1;
  }
  return 0;
}




















































































































/* Mark node i of pParse as being a child of iParent.  Call recursively
** to fill in all the descendants of node i.
*/
static void jsonParseFillInParentage(JsonParse *pParse, u32 i, u32 iParent){
  JsonNode *pNode = &pParse->aNode[i];
  u32 j;
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914




1915
1916
1917
1918
1919







1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933

1934
1935
1936
1937
1938
1939
1940
#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
** of the argv array.  Use the sqlite3_get_auxdata() cache for this
** parse if it is available.  If the cache is not available or if it
** is no longer valid, parse the JSON again and return the new parse,
** and also register the new parse so that it will be available for
** future sqlite3_get_auxdata() calls.
**
** If an error occurs and pErrCtx!=0 then report the error on pErrCtx
** and return NULL.
**




** If an error occurs and pErrCtx==0 then return the Parse object with
** JsonParse.nErr non-zero.  If the caller invokes this routine with
** pErrCtx==0 and it gets back a JsonParse with nErr!=0, then the caller
** is responsible for invoking jsonParseFree() on the returned value.
** But the caller may invoke jsonParseFree() *only* if pParse->nErr!=0.







*/
static JsonParse *jsonParseCached(
  sqlite3_context *pCtx,
  sqlite3_value *pJson,
  sqlite3_context *pErrCtx
){
  char *zJson = (char*)sqlite3_value_text(pJson);
  int nJson = sqlite3_value_bytes(pJson);
  JsonParse *p;
  JsonParse *pMatch = 0;
  int iKey;
  int iMinKey = 0;
  u32 iMinHold = 0xffffffff;
  u32 iMaxHold = 0;

  if( zJson==0 ) return 0;
  for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
    p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
    if( p==0 ){
      iMinKey = iKey;
      break;
    }







|
|





>
>
>
>
|
|
<
|
|
>
>
>
>
>
>
>














>







1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
#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
** of the argv array.  Use the sqlite3_get_auxdata() cache for this
** parse if it is available.  If the cache is not available or if it
** is no longer valid, parse the JSON again and return the new parse.
** Also register the new parse so that it will be available for
** future sqlite3_get_auxdata() calls.
**
** If an error occurs and pErrCtx!=0 then report the error on pErrCtx
** and return NULL.
**
** The returned pointer (if it is not NULL) is owned by the cache in
** most cases, not the caller.  The caller does NOT need to invoke
** jsonParseFree(), in most cases.
**
** Except, if an error occurs and pErrCtx==0 then return the JsonParse
** object with JsonParse.nErr non-zero and the caller will own the JsonParse

** object.  In that case, it will be the responsibility of the caller to
** invoke jsonParseFree().  To summarize:
**
**   pErrCtx!=0 || p->nErr==0      ==>   Return value p is owned by the
**                                       cache.  Call does not need to
**                                       free it.
**
**   pErrCtx==0 && p->nErr!=0      ==>   Return value is owned by the caller
**                                       and so the caller must free it.
*/
static JsonParse *jsonParseCached(
  sqlite3_context *pCtx,
  sqlite3_value *pJson,
  sqlite3_context *pErrCtx
){
  char *zJson = (char*)sqlite3_value_text(pJson);
  int nJson = sqlite3_value_bytes(pJson);
  JsonParse *p;
  JsonParse *pMatch = 0;
  int iKey;
  int iMinKey = 0;
  u32 iMinHold = 0xffffffff;
  u32 iMaxHold = 0;

  if( zJson==0 ) return 0;
  for(iKey=0; iKey<JSON_CACHE_SZ; iKey++){
    p = (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iKey);
    if( p==0 ){
      iMinKey = iKey;
      break;
    }
1951
1952
1953
1954
1955
1956
1957

1958
1959
1960
1961
1962
1963
1964
1965

1966




1967

1968
1969
1970

1971
1972
1973
1974
1975
1976
1977
1978

1979
1980
1981
1982
1983
1984
1985
    if( p->iHold>iMaxHold ){
      iMaxHold = p->iHold;
    }
  }
  if( pMatch ){
    pMatch->nErr = 0;
    pMatch->iHold = iMaxHold+1;

    return pMatch;
  }
  p = sqlite3_malloc64( sizeof(*p) + nJson + 1 );
  if( p==0 ){
    sqlite3_result_error_nomem(pCtx);
    return 0;
  }
  memset(p, 0, sizeof(*p));

  p->zJson = (char*)&p[1];




  memcpy((char*)p->zJson, zJson, nJson+1);

  if( jsonParse(p, pErrCtx, p->zJson) ){
    if( pErrCtx==0 ){
      p->nErr = 1;

      return p;
    }
    sqlite3_free(p);
    return 0;
  }
  p->nJPRef = 1;
  p->nJson = nJson;
  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);
}

/*
** Compare the OBJECT label at pNode against zKey,nKey.  Return true on







>


|





>
|
>
>
>
>
|
>
|


>


|


<


>







1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902

1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
    if( p->iHold>iMaxHold ){
      iMaxHold = p->iHold;
    }
  }
  if( pMatch ){
    pMatch->nErr = 0;
    pMatch->iHold = iMaxHold+1;
    assert( pMatch->nJPRef>0 ); /* pMatch is owned by the cache */
    return pMatch;
  }
  p = sqlite3_malloc64( sizeof(*p) );
  if( p==0 ){
    sqlite3_result_error_nomem(pCtx);
    return 0;
  }
  memset(p, 0, sizeof(*p));
  p->zJson = sqlite3RCStrNew( nJson );
  if( p->zJson==0 ){
    sqlite3_free(p);
    sqlite3_result_error_nomem(pCtx);
    return 0;
  }
  memcpy(p->zJson, zJson, nJson);
  p->zJson[nJson] = 0;
  if( jsonParse(p, pErrCtx, p->zJson, 1) ){
    if( pErrCtx==0 ){
      p->nErr = 1;
      assert( p->nJPRef==1 ); /* Caller will own the new JsonParse object p */
      return p;
    }
    jsonParseFree(p);
    return 0;
  }

  p->nJson = nJson;
  p->iHold = iMaxHold+1;
  /* Transfer ownership of the new JsonParse to the cache */
  sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p,
                      (void(*)(void*))jsonParseFree);
  return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey);
}

/*
** Compare the OBJECT label at pNode against zKey,nKey.  Return true on
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
  sqlite3_value **argv
){
  JsonString s;       /* Output string - not real JSON */
  JsonParse x;        /* The parse */
  u32 i;

  assert( argc==1 );
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0])) ) return;
  jsonParseFindParents(&x);
  jsonInit(&s, ctx);
  for(i=0; i<x.nNode; i++){
    const char *zType;
    if( x.aNode[i].jnFlags & JNODE_LABEL ){
      assert( x.aNode[i].eType==JSON_STRING );
      zType = "label";







|







2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
  sqlite3_value **argv
){
  JsonString s;       /* Output string - not real JSON */
  JsonParse x;        /* The parse */
  u32 i;

  assert( argc==1 );
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0]), 0) ) return;
  jsonParseFindParents(&x);
  jsonInit(&s, ctx);
  for(i=0; i<x.nNode; i++){
    const char *zType;
    if( x.aNode[i].jnFlags & JNODE_LABEL ){
      assert( x.aNode[i].eType==JSON_STRING );
      zType = "label";
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
  sqlite3_value **argv
){
  JsonParse x;     /* The JSON that is being patched */
  JsonParse y;     /* The patch */
  JsonNode *pResult;   /* The result of the merge */

  UNUSED_PARAMETER(argc);
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0])) ) return;
  if( jsonParse(&y, ctx, (char*)sqlite3_value_text(argv[1])) ){
    jsonParseReset(&x);
    return;
  }
  pResult = jsonMergePatch(&x, 0, y.aNode);
  assert( pResult!=0 || x.oom );
  if( pResult && x.oom==0 ){
    jsonDebugPrintParse(&x);







|
|







2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
  sqlite3_value **argv
){
  JsonParse x;     /* The JSON that is being patched */
  JsonParse y;     /* The patch */
  JsonNode *pResult;   /* The result of the merge */

  UNUSED_PARAMETER(argc);
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0]), 0) ) return;
  if( jsonParse(&y, ctx, (char*)sqlite3_value_text(argv[1]), 0) ){
    jsonParseReset(&x);
    return;
  }
  pResult = jsonMergePatch(&x, 0, y.aNode);
  assert( pResult!=0 || x.oom );
  if( pResult && x.oom==0 ){
    jsonDebugPrintParse(&x);
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;

  if( argc<1 ) return;
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i++){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    if( zPath==0 ) goto remove_done;
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto remove_done;
    if( pNode ) pNode->jnFlags |= JNODE_REMOVE;







|







2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
){
  JsonParse x;          /* The parse */
  JsonNode *pNode;
  const char *zPath;
  u32 i;

  if( argc<1 ) return;
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0]), 0) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i++){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    if( zPath==0 ) goto remove_done;
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto remove_done;
    if( pNode ) pNode->jnFlags |= JNODE_REMOVE;
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
  u32 i;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, "replace");
    return;
  }
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto replace_err;
    if( pNode ){
      jsonReplaceNode(ctx, &x, (u32)(pNode - x.aNode), argv[i+1]);







|







2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
  u32 i;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, "replace");
    return;
  }
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0]), 0) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    pNode = jsonLookup(&x, zPath, 0, ctx);
    if( x.nErr ) goto replace_err;
    if( pNode ){
      jsonReplaceNode(ctx, &x, (u32)(pNode - x.aNode), argv[i+1]);
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
  int bIsSet = sqlite3_user_data(ctx)!=0;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
    return;
  }
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0])) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    bApnd = 0;
    pNode = jsonLookup(&x, zPath, &bApnd, ctx);
    if( x.oom ){
      sqlite3_result_error_nomem(ctx);







|







2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
  int bIsSet = sqlite3_user_data(ctx)!=0;

  if( argc<1 ) return;
  if( (argc&1)==0 ) {
    jsonWrongNumArgs(ctx, bIsSet ? "set" : "insert");
    return;
  }
  if( jsonParse(&x, ctx, (char*)sqlite3_value_text(argv[0]), 0) ) return;
  assert( x.nNode );
  for(i=1; i<(u32)argc; i+=2){
    zPath = (const char*)sqlite3_value_text(argv[i]);
    bApnd = 0;
    pNode = jsonLookup(&x, zPath, &bApnd, ctx);
    if( x.oom ){
      sqlite3_result_error_nomem(ctx);
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
    sqlite3_result_error_nomem(ctx);
    sqlite3_free(p);
  }else if( p->nErr==0 ){
    sqlite3_result_int(ctx, 0);
  }else{
    int n = 1;
    u32 i;
    const char *z = p->zJson;
    for(i=0; i<p->iErr && ALWAYS(z[i]); i++){
      if( (z[i]&0xc0)!=0x80 ) n++;
    }
    sqlite3_result_int(ctx, n);
    jsonParseFree(p);
  }
}







|







2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
    sqlite3_result_error_nomem(ctx);
    sqlite3_free(p);
  }else if( p->nErr==0 ){
    sqlite3_result_int(ctx, 0);
  }else{
    int n = 1;
    u32 i;
    const char *z = (const char*)sqlite3_value_text(argv[0]);
    for(i=0; i<p->iErr && ALWAYS(z[i]); i++){
      if( (z[i]&0xc0)!=0x80 ) n++;
    }
    sqlite3_result_int(ctx, n);
    jsonParseFree(p);
  }
}
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
  if( idxNum==0 ) return SQLITE_OK;
  z = (const char*)sqlite3_value_text(argv[0]);
  if( z==0 ) return SQLITE_OK;
  n = sqlite3_value_bytes(argv[0]);
  p->zJson = sqlite3_malloc64( n+1 );
  if( p->zJson==0 ) return SQLITE_NOMEM;
  memcpy(p->zJson, z, (size_t)n+1);
  if( jsonParse(&p->sParse, 0, p->zJson) ){
    int rc = SQLITE_NOMEM;
    if( p->sParse.oom==0 ){
      sqlite3_free(cur->pVtab->zErrMsg);
      cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
      if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
    }
    jsonEachCursorReset(p);







|







3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
  if( idxNum==0 ) return SQLITE_OK;
  z = (const char*)sqlite3_value_text(argv[0]);
  if( z==0 ) return SQLITE_OK;
  n = sqlite3_value_bytes(argv[0]);
  p->zJson = sqlite3_malloc64( n+1 );
  if( p->zJson==0 ) return SQLITE_NOMEM;
  memcpy(p->zJson, z, (size_t)n+1);
  if( jsonParse(&p->sParse, 0, p->zJson, 0) ){
    int rc = SQLITE_NOMEM;
    if( p->sParse.oom==0 ){
      sqlite3_free(cur->pVtab->zErrMsg);
      cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
      if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
    }
    jsonEachCursorReset(p);
Changes to src/printf.c.
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
**
** The reference count is initially 1.  Call sqlite3RCStrUnref() to free the
** newly allocated string.
**
** This routine returns 0 on an OOM.
*/
char *sqlite3RCStrNew(u64 N){
  RCStr *p = sqlite3_malloc64( N + sizeof(*p) );
  if( p==0 ) return 0;
  p->nRCRef = 1;
  p->xFree = 0;
  p->pAttach = 0;
#ifdef SQLITE_DEBUG
  p->uMagic = SQLITE_RCSTR_MAGIC;
#endif







|







1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
**
** The reference count is initially 1.  Call sqlite3RCStrUnref() to free the
** newly allocated string.
**
** This routine returns 0 on an OOM.
*/
char *sqlite3RCStrNew(u64 N){
  RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 );
  if( p==0 ) return 0;
  p->nRCRef = 1;
  p->xFree = 0;
  p->pAttach = 0;
#ifdef SQLITE_DEBUG
  p->uMagic = SQLITE_RCSTR_MAGIC;
#endif