/ Check-in [6adc7de7]
Login

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

Overview
Comment:Fix the json_tree() scan for the case when a path is supplied. Add new json1 test cases.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6adc7de76acee6cfb5ff761739e7a8de7b5bf4b2
User & Date: drh 2015-09-10 03:29:11
Context
2015-09-10
04:17
Attempt to declare sqlite3MemoryBarrier() correctly for all possible build configurations. check-in: da8a288f user: drh tags: trunk
03:29
Fix the json_tree() scan for the case when a path is supplied. Add new json1 test cases. check-in: 6adc7de7 user: drh tags: trunk
01:22
No-op the sqlite3_memory_alarm() interface in a different way, that does not break legacy memory behavior. This is a re-do of check-in [5d3f5df4da9f40d5]. check-in: 8250e2a4 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/misc/json1.c.

    79     79   */
    80     80   #define JNODE_RAW     0x01         /* Content is raw, not JSON encoded */
    81     81   #define JNODE_ESCAPE  0x02         /* Content is text with \ escapes */
    82     82   #define JNODE_REMOVE  0x04         /* Do not output */
    83     83   #define JNODE_REPLACE 0x08         /* Replace with JsonNode.iVal */
    84     84   #define JNODE_APPEND  0x10         /* More ARRAY/OBJECT entries at u.iAppend */
    85     85   #define JNODE_JSON    0x20         /* Treat REPLACE as JSON text */
           86  +#define JNODE_LABEL   0x40         /* Is a label of an object */
    86     87   
    87     88   
    88     89   /* A single node of parsed JSON
    89     90   */
    90     91   struct JsonNode {
    91     92     u8 eType;              /* One of the JSON_ type values */
    92     93     u8 jnFlags;            /* JNODE flags */
................................................................................
   579    580   ** non-whitespace character is ']'.
   580    581   */
   581    582   static int jsonParseValue(JsonParse *pParse, u32 i){
   582    583     char c;
   583    584     u32 j;
   584    585     int iThis;
   585    586     int x;
          587  +  JsonNode *pNode;
   586    588     while( isspace(pParse->zJson[i]) ){ i++; }
   587    589     if( (c = pParse->zJson[i])==0 ) return 0;
   588    590     if( c=='{' ){
   589    591       /* Parse object */
   590    592       iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
   591    593       if( iThis<0 ) return -1;
   592    594       for(j=i+1;;j++){
................................................................................
   593    595         while( isspace(pParse->zJson[j]) ){ j++; }
   594    596         x = jsonParseValue(pParse, j);
   595    597         if( x<0 ){
   596    598           if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
   597    599           return -1;
   598    600         }
   599    601         if( pParse->oom ) return -1;
   600         -      if( pParse->aNode[pParse->nNode-1].eType!=JSON_STRING ) return -1;
          602  +      pNode = &pParse->aNode[pParse->nNode-1];
          603  +      if( pNode->eType!=JSON_STRING ) return -1;
          604  +      pNode->jnFlags |= JNODE_LABEL;
   601    605         j = x;
   602    606         while( isspace(pParse->zJson[j]) ){ j++; }
   603    607         if( pParse->zJson[j]!=':' ) return -1;
   604    608         j++;
   605    609         x = jsonParseValue(pParse, j);
   606    610         if( x<0 ) return -1;
   607    611         j = x;
................................................................................
  1032   1036     u32 i;
  1033   1037   
  1034   1038     assert( argc==1 );
  1035   1039     if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
  1036   1040     jsonParseFindParents(&x);
  1037   1041     jsonInit(&s, ctx);
  1038   1042     for(i=0; i<x.nNode; i++){
  1039         -    jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%d\n",
  1040         -               i, jsonType[x.aNode[i].eType], x.aNode[i].n, x.aUp[i]);
         1043  +    const char *zType;
         1044  +    if( x.aNode[i].jnFlags & JNODE_LABEL ){
         1045  +      assert( x.aNode[i].eType==JSON_STRING );
         1046  +      zType = "label";
         1047  +    }else{
         1048  +      zType = jsonType[x.aNode[i].eType];
         1049  +    }
         1050  +    jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
         1051  +               i, zType, x.aNode[i].n, x.aUp[i]);
  1041   1052       if( x.aNode[i].u.zJContent!=0 ){
  1042         -      jsonAppendRaw(&s, "    text: ", 10);
         1053  +      jsonAppendRaw(&s, " ", 1);
  1043   1054         jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
  1044         -      jsonAppendRaw(&s, "\n", 1);
  1045   1055       }
         1056  +    jsonAppendRaw(&s, "\n", 1);
  1046   1057     }
  1047   1058     jsonParseReset(&x);
  1048   1059     jsonResult(&s);
  1049   1060   }
  1050   1061   
  1051   1062   /*
  1052   1063   ** The json_test1(JSON) function parses and rebuilds the JSON string.
................................................................................
  1423   1434   /****************************************************************************
  1424   1435   ** The json_each virtual table
  1425   1436   ****************************************************************************/
  1426   1437   typedef struct JsonEachCursor JsonEachCursor;
  1427   1438   struct JsonEachCursor {
  1428   1439     sqlite3_vtab_cursor base;  /* Base class - must be first */
  1429   1440     u32 iRowid;                /* The rowid */
         1441  +  u32 iBegin;                /* The first node of the scan */
  1430   1442     u32 i;                     /* Index in sParse.aNode[] of current row */
  1431   1443     u32 iEnd;                  /* EOF when i equals or exceeds this value */
  1432   1444     u8 eType;                  /* Type of top-level element */
  1433   1445     u8 bRecursive;             /* True for json_tree().  False for json_each() */
  1434   1446     char *zJson;               /* Input JSON */
  1435   1447     char *zPath;               /* Path by which to filter zJson */
  1436   1448     JsonParse sParse;          /* Parse of the input JSON */
................................................................................
  1530   1542     return p->i >= p->iEnd;
  1531   1543   }
  1532   1544   
  1533   1545   /* Advance the cursor to the next element for json_tree() */
  1534   1546   static int jsonEachNext(sqlite3_vtab_cursor *cur){
  1535   1547     JsonEachCursor *p = (JsonEachCursor*)cur;
  1536   1548     if( p->bRecursive ){
  1537         -    if( p->i==0 ){
  1538         -      p->i = 1;
  1539         -    }else{
  1540         -      u32 iUp = p->sParse.aUp[p->i];
  1541         -      JsonNode *pUp = &p->sParse.aNode[iUp];
  1542         -      p->i++;
  1543         -      if( pUp->eType==JSON_OBJECT && (pUp->n + iUp >= p->i) ) p->i++;
  1544         -    }
         1549  +    if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
         1550  +    p->i++;
  1545   1551       p->iRowid++;
  1546         -    if( p->i<p->sParse.nNode ){
         1552  +    if( p->i<p->iEnd ){
  1547   1553         u32 iUp = p->sParse.aUp[p->i];
  1548   1554         JsonNode *pUp = &p->sParse.aNode[iUp];
  1549   1555         p->eType = pUp->eType;
  1550   1556         if( pUp->eType==JSON_ARRAY ){
  1551   1557           if( iUp==p->i-1 ){
  1552   1558             pUp->u.iKey = 0;
  1553   1559           }else{
................................................................................
  1593   1599     jsonEachComputePath(p, pStr, iUp);
  1594   1600     pNode = &p->sParse.aNode[i];
  1595   1601     pUp = &p->sParse.aNode[iUp];
  1596   1602     if( pUp->eType==JSON_ARRAY ){
  1597   1603       jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
  1598   1604     }else{
  1599   1605       assert( pUp->eType==JSON_OBJECT );
  1600         -    if( pNode->eType>=JSON_ARRAY ) pNode--;
         1606  +    if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
  1601   1607       assert( pNode->eType==JSON_STRING );
         1608  +    assert( pNode->jnFlags & JNODE_LABEL );
  1602   1609       jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
  1603   1610     }
  1604   1611   }
  1605   1612   
  1606   1613   /* Return the value of a column */
  1607   1614   static int jsonEachColumn(
  1608   1615     sqlite3_vtab_cursor *cur,   /* The cursor */
................................................................................
  1625   1632             iKey = p->iRowid;
  1626   1633           }
  1627   1634           sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
  1628   1635         }
  1629   1636         break;
  1630   1637       }
  1631   1638       case JEACH_VALUE: {
  1632         -      if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
         1639  +      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
  1633   1640         jsonReturn(pThis, ctx, 0);
  1634   1641         break;
  1635   1642       }
  1636   1643       case JEACH_TYPE: {
  1637         -      if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
         1644  +      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
  1638   1645         sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
  1639   1646         break;
  1640   1647       }
  1641   1648       case JEACH_ATOM: {
  1642         -      if( p->eType==JSON_OBJECT && p->i>0 ) pThis++;
         1649  +      if( pThis->jnFlags & JNODE_LABEL ) pThis++;
  1643   1650         if( pThis->eType>=JSON_ARRAY ) break;
  1644   1651         jsonReturn(pThis, ctx, 0);
  1645   1652         break;
  1646   1653       }
  1647   1654       case JEACH_ID: {
  1648         -      sqlite3_result_int64(ctx, (sqlite3_int64)p->i + (p->eType==JSON_OBJECT));
         1655  +      sqlite3_result_int64(ctx, 
         1656  +         (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
  1649   1657         break;
  1650   1658       }
  1651   1659       case JEACH_PARENT: {
  1652         -      if( p->i>0 && p->bRecursive ){
         1660  +      if( p->i>p->iBegin && p->bRecursive ){
  1653   1661           sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
  1654   1662         }
  1655   1663         break;
  1656   1664       }
  1657   1665       case JEACH_FULLKEY: {
  1658   1666         JsonString x;
  1659   1667         jsonInit(&x, ctx);
................................................................................
  1790   1798     }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
  1791   1799       jsonEachCursorReset(p);
  1792   1800       return SQLITE_NOMEM;
  1793   1801     }else{
  1794   1802       JsonNode *pNode;
  1795   1803       if( idxNum==3 ){
  1796   1804         const char *zErr = 0;
  1797         -      p->bRecursive = 0;
  1798   1805         n = sqlite3_value_bytes(argv[1]);
  1799   1806         p->zPath = sqlite3_malloc64( n+1 );
  1800   1807         if( p->zPath==0 ) return SQLITE_NOMEM;
  1801   1808         memcpy(p->zPath, zPath, (size_t)n+1);
  1802   1809         pNode = jsonLookupStep(&p->sParse, 0, p->zPath+1, 0, &zErr);
  1803   1810         if( p->sParse.nErr ){
  1804   1811           sqlite3_free(cur->pVtab->zErrMsg);
................................................................................
  1807   1814           return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
  1808   1815         }else if( pNode==0 ){
  1809   1816           return SQLITE_OK;
  1810   1817         }
  1811   1818       }else{
  1812   1819         pNode = p->sParse.aNode;
  1813   1820       }
  1814         -    p->i = (int)(pNode - p->sParse.aNode);
         1821  +    p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
  1815   1822       p->eType = pNode->eType;
  1816   1823       if( p->eType>=JSON_ARRAY ){
  1817   1824         pNode->u.iKey = 0;
  1818   1825         p->iEnd = p->i + pNode->n + 1;
  1819         -      if( !p->bRecursive ) p->i++;
         1826  +      if( p->bRecursive ){
         1827  +        if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
         1828  +          p->i--;
         1829  +        }
         1830  +      }else{
         1831  +        p->i++;
         1832  +      }
  1820   1833       }else{
  1821   1834         p->iEnd = p->i+1;
  1822   1835       }
  1823   1836     }
  1824   1837     return p->sParse.oom ? SQLITE_NOMEM : SQLITE_OK;
  1825   1838   }
  1826   1839   

Added test/json102.test.

            1  +# 2015-08-12
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements tests for JSON SQL functions extension to the
           12  +# SQLite library.
           13  +#
           14  +# This file contains tests automatically generated from the json1
           15  +# documentation.
           16  +#
           17  +
           18  +set testdir [file dirname $argv0]
           19  +source $testdir/tester.tcl
           20  +
           21  +load_static_extension db json
           22  +do_execsql_test json102-100 {
           23  +  SELECT json_array(1,2,'3',4);
           24  +} {{[1,2,"3",4]}}
           25  +do_execsql_test json102-110 {
           26  +  SELECT json_array('[1,2]');
           27  +} {{["[1,2]"]}}
           28  +do_execsql_test json102-120 {
           29  +  SELECT json_array(1,null,'3','[4,5]','{"six":7.7}');
           30  +} {{[1,null,"3","[4,5]","{\"six\":7.7}"]}}
           31  +do_execsql_test json102-130 {
           32  +  SELECT json_array_length('[1,2,3,4]');
           33  +} {{4}}
           34  +do_execsql_test json102-140 {
           35  +  SELECT json_array_length('{"one":[1,2,3]}');
           36  +} {{0}}
           37  +do_execsql_test json102-150 {
           38  +  SELECT json_array_length('{"one":[1,2,3]}', '$.one');
           39  +} {{3}}
           40  +do_execsql_test json102-160 {
           41  +  SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$');
           42  +} {{{"a":2,"c":[4,5,{"f":7}]}}}
           43  +do_execsql_test json102-170 {
           44  +  SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c');
           45  +} {{[4,5,{"f":7}]}}
           46  +do_execsql_test json102-180 {
           47  +  SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2]');
           48  +} {{{"f":7}}}
           49  +do_execsql_test json102-190 {
           50  +  SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.c[2].f');
           51  +} {{7}}
           52  +do_execsql_test json102-200 {
           53  +  SELECT json_extract('{"a":2,"c":[4,5],"f":7}','$.c','$.a');
           54  +} {{[[4,5],2]}}
           55  +do_execsql_test json102-210 {
           56  +  SELECT json_extract('{"a":2,"c":[4,5,{"f":7}]}', '$.x');
           57  +} {{}}
           58  +do_execsql_test json102-220 {
           59  +  SELECT json_insert('{"a":2,"c":4}', '$.a', 99);
           60  +} {{{"a":2,"c":4}}}
           61  +do_execsql_test json102-230 {
           62  +  SELECT json_insert('{"a":2,"c":4}', '$.e', 99);
           63  +} {{{"a":2,"c":4,"e":99}}}
           64  +do_execsql_test json102-240 {
           65  +  SELECT json_replace('{"a":2,"c":4}', '$.a', 99);
           66  +} {{{"a":99,"c":4}}}
           67  +do_execsql_test json102-250 {
           68  +  SELECT json_replace('{"a":2,"c":4}', '$.e', 99);
           69  +} {{{"a":2,"c":4}}}
           70  +do_execsql_test json102-260 {
           71  +  SELECT json_set('{"a":2,"c":4}', '$.a', 99);
           72  +} {{{"a":99,"c":4}}}
           73  +do_execsql_test json102-270 {
           74  +  SELECT json_set('{"a":2,"c":4}', '$.e', 99);
           75  +} {{{"a":2,"c":4,"e":99}}}
           76  +do_execsql_test json102-280 {
           77  +  SELECT json_object('a',2,'c',4);
           78  +} {{{"a":2,"c":4}}}
           79  +do_execsql_test json102-290 {
           80  +  SELECT json_object('a',2,'c','{e:5}');
           81  +} {{{"a":2,"c":"{e:5}"}}}
           82  +do_execsql_test json102-300 {
           83  +  SELECT json_remove('[0,1,2,3,4]','$[2]');
           84  +} {{[0,1,3,4]}}
           85  +do_execsql_test json102-310 {
           86  +  SELECT json_remove('[0,1,2,3,4]','$[2]','$[0]');
           87  +} {{[1,3,4]}}
           88  +do_execsql_test json102-320 {
           89  +  SELECT json_remove('[0,1,2,3,4]','$[0]','$[2]');
           90  +} {{[1,2,4]}}
           91  +do_execsql_test json102-330 {
           92  +  SELECT json_remove('{"x":25,"y":42}');
           93  +} {{{"x":25,"y":42}}}
           94  +do_execsql_test json102-340 {
           95  +  SELECT json_remove('{"x":25,"y":42}','$.z');
           96  +} {{{"x":25,"y":42}}}
           97  +do_execsql_test json102-350 {
           98  +  SELECT json_remove('{"x":25,"y":42}','$.y');
           99  +} {{{"x":25}}}
          100  +do_execsql_test json102-360 {
          101  +  SELECT json_remove('{"x":25,"y":42}','$');
          102  +} {{}}
          103  +do_execsql_test json102-370 {
          104  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}');
          105  +} {{object}}
          106  +do_execsql_test json102-380 {
          107  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$');
          108  +} {{object}}
          109  +do_execsql_test json102-390 {
          110  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a');
          111  +} {{array}}
          112  +do_execsql_test json102-400 {
          113  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[0]');
          114  +} {{integer}}
          115  +do_execsql_test json102-410 {
          116  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[1]');
          117  +} {{real}}
          118  +do_execsql_test json102-420 {
          119  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[2]');
          120  +} {{true}}
          121  +do_execsql_test json102-430 {
          122  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[3]');
          123  +} {{false}}
          124  +do_execsql_test json102-440 {
          125  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[4]');
          126  +} {{null}}
          127  +do_execsql_test json102-450 {
          128  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[5]');
          129  +} {{text}}
          130  +do_execsql_test json102-460 {
          131  +  SELECT json_type('{"a":[2,3.5,true,false,null,"x"]}','$.a[6]');
          132  +} {{}}
          133  +do_execsql_test json102-470 {
          134  +  SELECT json_valid('{"x":35}');
          135  +} {{1}}
          136  +do_execsql_test json102-480 {
          137  +  SELECT json_valid('{"x":35'); -- }
          138  +} {{0}}
          139  +
          140  +do_execsql_test json102-500 {
          141  +  CREATE TABLE user(name,phone);
          142  +  INSERT INTO user(name,phone) VALUES
          143  +     ('Alice','["919-555-2345","804-555-3621"]'),
          144  +     ('Bob','["201-555-8872"]'),
          145  +     ('Cindy','["704-555-9983"]'),
          146  +     ('Dave','["336-555-8421","704-555-4321","803-911-4421"]');
          147  +  SELECT DISTINCT user.name
          148  +    FROM user, json_each(user.phone)
          149  +   WHERE json_each.value LIKE '704-%'
          150  +   ORDER BY 1;
          151  +} {Cindy Dave}
          152  +
          153  +do_execsql_test json102-510 {
          154  +  UPDATE user
          155  +     SET phone=json_extract(phone,'$[0]')
          156  +   WHERE json_array_length(phone)<2;
          157  +  SELECT name, substr(phone,1,5) FROM user ORDER BY name;
          158  +} {Alice {["919} Bob 201-5 Cindy 704-5 Dave {["336}}
          159  +do_execsql_test json102-511 {
          160  +  SELECT name FROM user WHERE phone LIKE '704-%'
          161  +  UNION
          162  +  SELECT user.name
          163  +    FROM user, json_each(user.phone)
          164  +   WHERE json_valid(user.phone)
          165  +     AND json_each.value LIKE '704-%';
          166  +} {Cindy Dave}
          167  +
          168  +do_execsql_test json102-600 {
          169  +  CREATE TABLE big(json JSON);
          170  +  INSERT INTO big(json) VALUES('{
          171  +    "id":123,
          172  +    "stuff":[1,2,3,4],
          173  +    "partlist":[
          174  +       {"uuid":"bb108722-572e-11e5-9320-7f3b63a4ca74"},
          175  +       {"uuid":"c690dc14-572e-11e5-95f9-dfc8861fd535"},
          176  +       {"subassembly":[
          177  +          {"uuid":"6fa5181e-5721-11e5-a04e-57f3d7b32808"}
          178  +       ]}
          179  +    ]
          180  +  }');
          181  +  INSERT INTO big(json) VALUES('{
          182  +    "id":456,
          183  +    "stuff":["hello","world","xyzzy"],
          184  +    "partlist":[
          185  +       {"uuid":false},
          186  +       {"uuid":"c690dc14-572e-11e5-95f9-dfc8861fd535"}
          187  +    ]
          188  +  }');
          189  +} {}
          190  +set correct_answer [list \
          191  +    1 {$.id} 123 \
          192  +    1 {$.stuff[0]} 1 \
          193  +    1 {$.stuff[1]} 2 \
          194  +    1 {$.stuff[2]} 3 \
          195  +    1 {$.stuff[3]} 4 \
          196  +    1 {$.partlist[0].uuid} bb108722-572e-11e5-9320-7f3b63a4ca74 \
          197  +    1 {$.partlist[1].uuid} c690dc14-572e-11e5-95f9-dfc8861fd535 \
          198  +    1 {$.partlist[2].subassembly[0].uuid} 6fa5181e-5721-11e5-a04e-57f3d7b32808 \
          199  +    2 {$.id} 456 \
          200  +    2 {$.stuff[0]} hello \
          201  +    2 {$.stuff[1]} world \
          202  +    2 {$.stuff[2]} xyzzy \
          203  +    2 {$.partlist[0].uuid} 0 \
          204  +    2 {$.partlist[1].uuid} c690dc14-572e-11e5-95f9-dfc8861fd535]
          205  +do_execsql_test json102-610 {
          206  +  SELECT big.rowid, fullkey, value
          207  +    FROM big, json_tree(big.json)
          208  +   WHERE json_tree.type NOT IN ('object','array')
          209  +   ORDER BY +big.rowid, +json_tree.id
          210  +} $correct_answer
          211  +do_execsql_test json102-620 {
          212  +  SELECT big.rowid, fullkey, atom
          213  +    FROM big, json_tree(big.json)
          214  +   WHERE atom IS NOT NULL
          215  +   ORDER BY +big.rowid, +json_tree.id
          216  +} $correct_answer
          217  +
          218  +do_execsql_test json102-630 {
          219  +  SELECT DISTINCT json_extract(big.json,'$.id')
          220  +    FROM big, json_tree(big.json,'$.partlist')
          221  +   WHERE json_tree.key='uuid'
          222  +     AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
          223  +} {123}
          224  +do_execsql_test json102-631 {
          225  +  SELECT DISTINCT json_extract(big.json,'$.id')
          226  +    FROM big, json_tree(big.json,'$')
          227  +   WHERE json_tree.key='uuid'
          228  +     AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
          229  +} {123}
          230  +do_execsql_test json102-632 {
          231  +  SELECT DISTINCT json_extract(big.json,'$.id')
          232  +    FROM big, json_tree(big.json)
          233  +   WHERE json_tree.key='uuid'
          234  +     AND json_tree.value='6fa5181e-5721-11e5-a04e-57f3d7b32808';
          235  +} {123}
          236  +
          237  +
          238  +finish_test