/ Check-in [fc1b24f3]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Fixes to json_each() and json_tree(). Improved json_parse() debugging output.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fc1b24f316af07a64672f6edc14ebcff487dffbb
User & Date: drh 2015-08-23 02:42:30
Context
2015-08-23
20:44
Fix minor glitches in the json1.c extension, mostly having to do with OOM behavior. check-in: cc520414 user: drh tags: trunk
02:42
Fixes to json_each() and json_tree(). Improved json_parse() debugging output. check-in: fc1b24f3 user: drh tags: trunk
2015-08-22
19:39
Add the json_valid() function to the json1.c extension. Fix various minor problems in the json1.c extension. check-in: 380a9734 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/json1.c.

   191    191     if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return;
   192    192     va_start(ap, zFormat);
   193    193     sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap);
   194    194     va_end(ap);
   195    195     p->nUsed += (int)strlen(p->zBuf+p->nUsed);
   196    196   }
   197    197   
   198         -#ifdef SQLITE_DEBUG
   199         -/* Append the zero-terminated string zIn
   200         -*/
   201         -static void jsonAppend(JsonString *p, const char *zIn){
   202         -  jsonAppendRaw(p, zIn, (u32)strlen(zIn));
   203         -}
   204         -#endif
   205         -
   206    198   /* Append a single character
   207    199   */
   208    200   static void jsonAppendChar(JsonString *p, char c){
   209    201     if( p->nUsed>=p->nAlloc && jsonGrow(p,1)!=0 ) return;
   210    202     p->zBuf[p->nUsed++] = c;
   211    203   }
   212    204   
................................................................................
   464    456             char c = z[i];
   465    457             if( c!='\\' && z[i+1] ){
   466    458               zOut[j++] = c;
   467    459             }else{
   468    460               c = z[++i];
   469    461               if( c=='u' && z[1] ){
   470    462                 u32 v = 0, k;
   471         -              z++;
   472         -              for(k=0; k<4 && z[k]; k++){
   473         -                c = z[0];
          463  +              for(k=0; k<4 && z[i+1]; i++, k++){
          464  +                c = z[i+1];
   474    465                   if( c>='0' && c<='9' ) v = v*16 + c - '0';
   475    466                   else if( c>='A' && c<='F' ) v = v*16 + c - 'A' + 10;
   476    467                   else if( c>='a' && c<='f' ) v = v*16 + c - 'a' + 10;
   477    468                   else break;
   478         -                z++;
   479    469                 }
   480    470                 if( v<=0x7f ){
   481    471                   zOut[j++] = v;
   482    472                 }else if( v<=0x7ff ){
   483    473                   zOut[j++] = 0xc0 | (v>>6);
   484    474                   zOut[j++] = 0x80 | (v&0x3f);
   485    475                 }else if( v<=0xffff ){
................................................................................
   674    664           continue;
   675    665         }
   676    666         if( c=='e' || c=='E' ){
   677    667           if( pParse->zJson[j-1]<'0' ) return -1;
   678    668           if( seenE ) return -1;
   679    669           seenDP = seenE = 1;
   680    670           c = pParse->zJson[j+1];
   681         -        if( c=='+' || c=='-' ) j++;
          671  +        if( c=='+' || c=='-' ){
          672  +          j++;
          673  +          c = pParse->zJson[j+1];
          674  +        }
          675  +        if( c<'0' || c>'0' ) return -1;
   682    676           continue;
   683    677         }
   684    678         break;
   685    679       }
   686    680       if( pParse->zJson[j-1]<'0' ) return -1;
   687    681       jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT,
   688    682                           j - i, &pParse->zJson[i]);
................................................................................
   833    827         return pNode;
   834    828       }
   835    829     }else if( zPath[0]=='[' && isdigit(zPath[1]) ){
   836    830       if( pRoot->eType!=JSON_ARRAY ) return 0;
   837    831       i = 0;
   838    832       zPath++;
   839    833       while( isdigit(zPath[0]) ){
   840         -      i = i + zPath[0] - '0';
          834  +      i = i*10 + zPath[0] - '0';
   841    835         zPath++;
   842    836       }
   843    837       if( zPath[0]!=']' ) return 0;
   844    838       zPath++;
   845    839       j = 1;
   846    840       for(;;){
   847    841         while( j<=pRoot->n && (i>0 || (pRoot[j].jnFlags & JNODE_REMOVE)!=0) ){
................................................................................
   926    920     sqlite3_context *ctx,
   927    921     int argc,
   928    922     sqlite3_value **argv
   929    923   ){
   930    924     JsonString s;       /* Output string - not real JSON */
   931    925     JsonParse x;        /* The parse */
   932    926     u32 i;
   933         -  char zBuf[100];
   934    927   
   935    928     assert( argc==1 );
   936    929     if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
          930  +  jsonParseFindParents(&x);
   937    931     jsonInit(&s, ctx);
   938    932     for(i=0; i<x.nNode; i++){
   939         -    sqlite3_snprintf(sizeof(zBuf), zBuf, "node %3u: %7s n=%d\n",
   940         -                     i, jsonType[x.aNode[i].eType], x.aNode[i].n);
   941         -    jsonAppend(&s, zBuf);
          933  +    jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%d\n",
          934  +               i, jsonType[x.aNode[i].eType], x.aNode[i].n, x.aUp[i]);
   942    935       if( x.aNode[i].u.zJContent!=0 ){
   943    936         jsonAppendRaw(&s, "    text: ", 10);
   944    937         jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
   945    938         jsonAppendRaw(&s, "\n", 1);
   946    939       }
   947    940     }
   948    941     jsonParseReset(&x);
................................................................................
  1414   1407   
  1415   1408   /* Advance the cursor to the next element for json_tree() */
  1416   1409   static int jsonEachNext(sqlite3_vtab_cursor *cur){
  1417   1410     JsonEachCursor *p = (JsonEachCursor*)cur;
  1418   1411     if( p->bRecursive ){
  1419   1412       if( p->i==0 ){
  1420   1413         p->i = 1;
  1421         -    }else if( p->sParse.aNode[p->sParse.aUp[p->i]].eType==JSON_OBJECT ){
  1422         -      p->i += 2;
  1423   1414       }else{
         1415  +      u32 iUp = p->sParse.aUp[p->i];
         1416  +      JsonNode *pUp = &p->sParse.aNode[iUp];
  1424   1417         p->i++;
         1418  +      if( pUp->eType==JSON_OBJECT && (pUp->n + iUp >= p->i) ) p->i++;
  1425   1419       }
  1426   1420       p->iRowid++;
  1427   1421       if( p->i<p->sParse.nNode ){
  1428         -      JsonNode *pUp = &p->sParse.aNode[p->sParse.aUp[p->i]];
         1422  +      u32 iUp = p->sParse.aUp[p->i];
         1423  +      JsonNode *pUp = &p->sParse.aNode[iUp];
  1429   1424         p->eType = pUp->eType;
  1430         -      if( pUp->eType==JSON_ARRAY ) pUp->u.iKey++;
  1431         -      if( p->sParse.aNode[p->i].eType==JSON_ARRAY ){
  1432         -        p->sParse.aNode[p->i].u.iKey = 0;
         1425  +      if( pUp->eType==JSON_ARRAY ){
         1426  +        if( iUp==p->i-1 ){
         1427  +          pUp->u.iKey = 0;
         1428  +        }else{
         1429  +          pUp->u.iKey++;
         1430  +        }
  1433   1431         }
  1434   1432       }
  1435   1433     }else{
  1436   1434       switch( p->eType ){
  1437   1435         case JSON_ARRAY: {
  1438   1436           p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
  1439   1437           p->iRowid++;
................................................................................
  1486   1484     sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
  1487   1485     int i                       /* Which column to return */
  1488   1486   ){
  1489   1487     JsonEachCursor *p = (JsonEachCursor*)cur;
  1490   1488     JsonNode *pThis = &p->sParse.aNode[p->i];
  1491   1489     switch( i ){
  1492   1490       case JEACH_KEY: {
         1491  +      if( p->i==0 ) break;
  1493   1492         if( p->eType==JSON_OBJECT ){
  1494   1493           jsonReturn(pThis, ctx, 0);
  1495   1494         }else if( p->eType==JSON_ARRAY ){
  1496   1495           u32 iKey;
  1497   1496           if( p->bRecursive ){
  1498   1497             if( p->iRowid==0 ) break;
  1499         -          iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey - 1;
         1498  +          iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
  1500   1499           }else{
  1501   1500             iKey = p->iRowid;
  1502   1501           }
  1503   1502           sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
  1504   1503         }
  1505   1504         break;
  1506   1505       }
  1507   1506       case JEACH_VALUE: {
  1508         -      if( p->eType==JSON_OBJECT ) pThis++;
         1507  +      if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
  1509   1508         jsonReturn(pThis, ctx, 0);
  1510   1509         break;
  1511   1510       }
  1512   1511       case JEACH_TYPE: {
  1513   1512         if( p->eType==JSON_OBJECT ) pThis++;
  1514   1513         sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
  1515   1514         break;
................................................................................
  1668   1667         }
  1669   1668       }else{
  1670   1669         pNode = p->sParse.aNode;
  1671   1670       }
  1672   1671       p->i = (int)(pNode - p->sParse.aNode);
  1673   1672       p->eType = pNode->eType;
  1674   1673       if( p->eType>=JSON_ARRAY ){
  1675         -      p->i++;
         1674  +      pNode->u.iKey = 0;
         1675  +      if( !p->bRecursive ) p->i++;
  1676   1676         p->iEnd = p->i + pNode->n;
  1677   1677       }else{
  1678   1678         p->iEnd = p->i+1;
  1679   1679       }
  1680   1680     }
  1681   1681     return p->sParse.oom ? SQLITE_NOMEM : SQLITE_OK;
  1682   1682   }