]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove the vestigal JsonNode logic from json_tree() and json_each().
authordrh <>
Sat, 25 Nov 2023 20:59:03 +0000 (20:59 +0000)
committerdrh <>
Sat, 25 Nov 2023 20:59:03 +0000 (20:59 +0000)
FossilOrigin-Name: 66c2ab9ebbf90477742e6be0d30e061d827c409de038f2a5b73479ed9448c4a6

manifest
manifest.uuid
src/json.c

index 8851c060f1a2c1c6081759626ede9c0e64eaf054..1f18d635130836cc3a29b246e261096748564198 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Almost\sworking.\s\sPath\sis\sstill\snot\sexactly\sright\swhen\sRoot\sis\sdefined\son\njson_tree().
-D 2023-11-25T19:28:44.393
+C Remove\sthe\svestigal\sJsonNode\slogic\sfrom\sjson_tree()\sand\sjson_each().
+D 2023-11-25T20:59:03.008
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -688,7 +688,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
-F src/json.c 617eaedbe44c139f0144f04ecbfa240721462f45d76e715eaacc99e172bf43b0
+F src/json.c 211c4e1b8fd886c97d3224105bfef9d4cc04db2e3f1daca1e95c52343df4e85c
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
 F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9
@@ -2145,8 +2145,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P ffaa468ab8871906121df9ee5ef3dc00129a0086ed9c18831ecda69bf7f71455
-R b82a578143acb9c5e1a084b85e2e99b7
+P 92258246916a9c0d72785964513113848a850dec78bdade8b3f274e410df4e7e
+R 43fba60a847876455ec8abde78205ef3
 U drh
-Z 1f6ed13fcc3b9ce0d1d8c376c125c482
+Z d0660c039b12ecd1fe4ffd828711a405
 # Remove this line to create a well-formed Fossil manifest.
index 78ef7d1413fbdc9f7b86e95593456e7de1159f3c..3b93842124a02b48a8d1356dfdc9868a0402d1df 100644 (file)
@@ -1 +1 @@
-92258246916a9c0d72785964513113848a850dec78bdade8b3f274e410df4e7e
\ No newline at end of file
+66c2ab9ebbf90477742e6be0d30e061d827c409de038f2a5b73479ed9448c4a6
\ No newline at end of file
index 2de4c61a12bb705d017c3f29a3b92faaa4bf8457..cc4eb83c5b070f5ea3e5aa6fda8d2ab8279f599e 100644 (file)
@@ -329,7 +329,6 @@ struct JsonParse {
   JsonNode *aNode;   /* Array of nodes containing the parse */
   char *zJson;       /* Original JSON string (before edits) */
   char *zAlt;        /* Revised and/or mimified JSON */
-  u32 *aUp;          /* Index of parent of each node */
   JsonCleanup *pClup;/* Cleanup operations prior to freeing this object */
   u16 iDepth;        /* Nesting depth */
   u8 nErr;           /* Number of errors seen */
@@ -860,10 +859,6 @@ static void jsonParseReset(JsonParse *pParse){
   }
   pParse->nNode = 0;
   pParse->nAlloc = 0;
-  if( pParse->aUp ){
-    sqlite3_free(pParse->aUp);
-    pParse->aUp = 0;
-  }
   if( pParse->bJsonIsRCStr ){
     sqlite3RCStrUnref(pParse->zJson);
     pParse->zJson = 0;
@@ -2013,33 +2008,6 @@ json_parse_restart:
   } /* End switch(z[i]) */
 }
 
-/* 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;
-  pParse->aUp[i] = iParent;
-  switch( pNode->eType ){
-    case JSON_ARRAY: {
-      for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j)){
-        jsonParseFillInParentage(pParse, i+j, i);
-      }
-      break;
-    }
-    case JSON_OBJECT: {
-      for(j=1; j<=pNode->n; j += jsonNodeSize(pNode+j+1)+1){
-        pParse->aUp[i+j] = i;
-        jsonParseFillInParentage(pParse, i+j+1, i);
-      }
-      break;
-    }
-    default: {
-      break;
-    }
-  }
-}
-
 /*
 ** Parse JSON (either pure RFC-8259 JSON text, or JSON-5 text, or a JSONB
 ** blob) into the JsonNode representation.
@@ -2090,21 +2058,6 @@ static int jsonParse(
   return 0;
 }
 
-/*
-** Compute the parentage of all nodes in a completed parse.
-*/
-static int jsonParseFindParents(JsonParse *pParse){
-  u32 *aUp;
-  assert( pParse->aUp==0 );
-  aUp = pParse->aUp = sqlite3_malloc64( sizeof(u32)*pParse->nNode );
-  if( aUp==0 ){
-    pParse->oom = 1;
-    return SQLITE_NOMEM;
-  }
-  jsonParseFillInParentage(pParse, 0, 0);
-  return SQLITE_OK;
-}
-
 /*
 ** Magic number used for the JSON parse cache in sqlite3_get_auxdata()
 */
@@ -3257,7 +3210,7 @@ static int jsonConvertTextToBlob(
     }
   }
   if( i<=0 ){
-    if( ALWAYS(pCtx!=0) ){
+    if( pCtx!=0 ){
       if( pParse->oom ){
         sqlite3_result_error_nomem(pCtx);
       }else{
@@ -5767,47 +5720,7 @@ static void jsonAppendPathName(JsonEachCursor *p){
 /* Advance the cursor to the next element for json_tree() */
 static int jsonEachNext(sqlite3_vtab_cursor *cur){
   JsonEachCursor *p = (JsonEachCursor*)cur;
-  if( p->sParse.aNode ){
-    /* LEGACY */
-    if( p->bRecursive ){
-      if( p->sParse.aNode[p->i].jnFlags & JNODE_LABEL ) p->i++;
-      p->i++;
-      p->iRowid++;
-      if( p->i<p->iEnd ){
-        u32 iUp = p->sParse.aUp[p->i];
-        JsonNode *pUp = &p->sParse.aNode[iUp];
-        p->eType = pUp->eType;
-        if( pUp->eType==JSON_ARRAY ){
-          assert( pUp->eU==0 || pUp->eU==3 );
-          testcase( pUp->eU==3 );
-          JSON_VVA( pUp->eU = 3 );
-          if( iUp==p->i-1 ){
-            pUp->u.iKey = 0;
-          }else{
-            pUp->u.iKey++;
-          }
-        }
-      }
-    }else{
-      switch( p->eType ){
-        case JSON_ARRAY: {
-          p->i += jsonNodeSize(&p->sParse.aNode[p->i]);
-          p->iRowid++;
-          break;
-        }
-        case JSON_OBJECT: {
-          p->i += 1 + jsonNodeSize(&p->sParse.aNode[p->i+1]);
-          p->iRowid++;
-          break;
-        }
-        default: {
-          p->i = p->iEnd;
-          break;
-        }
-      }
-    }
-    return SQLITE_OK;
-  }else if( p->bRecursive ){
+  if( p->bRecursive ){
     u8 x;
     u8 levelChange = 0;
     u32 n, sz = 0;
@@ -5866,70 +5779,6 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){
   return SQLITE_OK;
 }
 
-/* Append an object label to the JSON Path being constructed
-** in pStr.
-*/
-static void jsonAppendObjectPathElementOfNode(
-  JsonString *pStr,
-  JsonNode *pNode
-){
-  int nn;
-  const char *z;
-  int bNeedQuote = 0;
-  assert( pNode->eType==JSON_STRING );
-  assert( pNode->jnFlags & JNODE_LABEL );
-  assert( pNode->eU==1 );
-  z = pNode->u.zJContent;
-  nn = pNode->n;
-  if( pNode->jnFlags & JNODE_RAW ){
-    /* no-op */
-  }else if( nn==0 || !sqlite3Isalpha(z[0]) ){
-    bNeedQuote = 1;
-  }else{
-    int jj;
-    for(jj=1; jj<nn && sqlite3Isalnum(z[jj]); jj++){}
-    bNeedQuote = jj<nn;
-  }
-  if( bNeedQuote ){
-    jsonPrintf(nn+4, pStr, ".\"%.*s\"", nn, z);
-  }else{
-    jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
-  }
-}
-
-/* Append the name of the path for element i to pStr
-*/
-static void jsonEachComputePath(
-  JsonEachCursor *p,       /* The cursor */
-  JsonString *pStr,        /* Write the path here */
-  u32 i                    /* Path to this element */
-){
-  JsonNode *pNode, *pUp;
-  u32 iUp;
-  if( i==0 ){
-    jsonAppendChar(pStr, '$');
-    return;
-  }
-  if( p->sParse.aNode ){
-    /* LEGACY */
-    assert( p->sParse.aUp );
-    iUp = p->sParse.aUp[i];
-    jsonEachComputePath(p, pStr, iUp);
-    pNode = &p->sParse.aNode[i];
-    pUp = &p->sParse.aNode[iUp];
-    if( pUp->eType==JSON_ARRAY ){
-      assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
-      testcase( pUp->eU==0 );
-      jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
-    }else{
-      assert( pUp->eType==JSON_OBJECT );
-      if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
-      jsonAppendObjectPathElementOfNode(pStr, pNode);
-    }
-    return;
-  }
-}
-
 /* Return the value of a column */
 static int jsonEachColumn(
   sqlite3_vtab_cursor *cur,   /* The cursor */
@@ -5937,173 +5786,73 @@ static int jsonEachColumn(
   int iColumn                 /* Which column to return */
 ){
   JsonEachCursor *p = (JsonEachCursor*)cur;
-  if( p->sParse.aNode!=0 ){
-    /* LEGACY */
-    JsonNode *pThis = &p->sParse.aNode[p->i];
-    switch( iColumn ){
-      case JEACH_KEY: {
-        if( p->i==0 ) break;
-        if( p->eType==JSON_OBJECT ){
-          jsonReturnFromNode(&p->sParse, pThis, ctx, 0);
-        }else if( p->eType==JSON_ARRAY ){
-          u32 iKey;
-          if( p->bRecursive ){
-            if( p->iRowid==0 ) break;
-            assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 );
-            iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
-          }else{
-            iKey = p->iRowid;
-          }
-          sqlite3_result_int64(ctx, (sqlite3_int64)iKey);
-        }
-        break;
-      }
-      case JEACH_VALUE: {
-        if( pThis->jnFlags & JNODE_LABEL ) pThis++;
-        jsonReturnFromNode(&p->sParse, pThis, ctx, 0);
-        break;
-      }
-      case JEACH_TYPE: {
-        if( pThis->jnFlags & JNODE_LABEL ) pThis++;
-        sqlite3_result_text(ctx, jsonType[pThis->eType], -1, SQLITE_STATIC);
-        break;
-      }
-      case JEACH_ATOM: {
-        if( pThis->jnFlags & JNODE_LABEL ) pThis++;
-        if( pThis->eType>=JSON_ARRAY ) break;
-        jsonReturnFromNode(&p->sParse, pThis, ctx, 0);
-        break;
-      }
-      case JEACH_ID: {
-        sqlite3_result_int64(ctx,
-           (sqlite3_int64)p->i + ((pThis->jnFlags & JNODE_LABEL)!=0));
-        break;
-      }
-      case JEACH_PARENT: {
-        if( p->i>p->iBegin && p->bRecursive ){
-          sqlite3_result_int64(ctx, (sqlite3_int64)p->sParse.aUp[p->i]);
-        }
-        break;
-      }
-      case JEACH_FULLKEY: {
-        JsonString x;
-        jsonStringInit(&x, ctx);
-        if( p->bRecursive ){
-          jsonEachComputePath(p, &x, p->i);
-        }else{
-          if( p->zRoot ){
-            jsonAppendRaw(&x, p->zRoot, (int)strlen(p->zRoot));
-          }else{
-            jsonAppendChar(&x, '$');
-          }
-          if( p->eType==JSON_ARRAY ){
-            jsonPrintf(30, &x, "[%d]", p->iRowid);
-          }else if( p->eType==JSON_OBJECT ){
-            jsonAppendObjectPathElementOfNode(&x, pThis);
-          }
-        }
-        jsonReturnString(&x);
-        break;
-      }
-      case JEACH_PATH: {
-        if( p->bRecursive ){
-          JsonString x;
-          jsonStringInit(&x, ctx);
-          jsonEachComputePath(p, &x, p->sParse.aUp[p->i]);
-          jsonReturnString(&x);
-          break;
-        }
-        /* For json_each() path and root are the same so fall through
-        ** into the root case */
-        /* no break */ deliberate_fall_through
-      }
-      default: {
-        const char *zRoot = p->zRoot;
-        if( zRoot==0 ) zRoot = "$";
-        sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
-        break;
-      }
-      case JEACH_JSON: {
-        if( p->sParse.isBinary ){
-          sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
-                              SQLITE_STATIC);
-        }else{
-          sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
-        }
-        break;
+  switch( iColumn ){
+    case JEACH_KEY: {
+      if( p->nParent==0 ) break;
+      if( p->eType==JSONB_OBJECT ){
+        jsonReturnFromBlob(&p->sParse, p->i, ctx, 1);
+      }else{
+        assert( p->eType==JSONB_ARRAY );
+        sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey);
       }
+      break;
     }
-  }else{
-    /* Blob scan */
-    switch( iColumn ){
-      case JEACH_KEY: {
-        if( p->nParent==0 ) break;
-        if( p->eType==JSONB_OBJECT ){
-          jsonReturnFromBlob(&p->sParse, p->i, ctx, 1);
-        }else{
-          assert( p->eType==JSONB_ARRAY );
-          sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iKey);
-        }
-        break;
-      }
-      case JEACH_VALUE: {
-        u32 i = jsonSkipLabel(p);
+    case JEACH_VALUE: {
+      u32 i = jsonSkipLabel(p);
+      jsonReturnFromBlob(&p->sParse, i, ctx, 1);
+      break;
+    }
+    case JEACH_TYPE: {
+      u32 i = jsonSkipLabel(p);
+      u8 eType = eType = p->sParse.aBlob[i] & 0x0f;
+      sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC);
+      break;
+    }
+    case JEACH_ATOM: {
+      u32 i = jsonSkipLabel(p);
+      if( (p->sParse.aBlob[i] & 0x0f)<JSONB_ARRAY ){
         jsonReturnFromBlob(&p->sParse, i, ctx, 1);
-        break;
       }
-      case JEACH_TYPE: {
-        u32 i = jsonSkipLabel(p);
-        u8 eType = eType = p->sParse.aBlob[i] & 0x0f;
-        sqlite3_result_text(ctx, jsonbType[eType], -1, SQLITE_STATIC);
-        break;
-      }
-      case JEACH_ATOM: {
-        u32 i = jsonSkipLabel(p);
-        if( (p->sParse.aBlob[i] & 0x0f)<JSONB_ARRAY ){
-          jsonReturnFromBlob(&p->sParse, i, ctx, 1);
-        }
-        break;
-      }
-      case JEACH_ID: {
-        sqlite3_result_int64(ctx, (sqlite3_int64)p->i);
-        break;
-      }
-      case JEACH_PARENT: {
-        if( p->nParent>0 ){
-          sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead);
-        }
-        break;
-      }
-      case JEACH_FULLKEY: {
-        u64 nBase = p->path.nUsed;
-        if( p->nParent ) jsonAppendPathName(p);
-        sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
-                              SQLITE_TRANSIENT, SQLITE_UTF8);
-        p->path.nUsed = nBase;
-        break;
-      }
-      case JEACH_PATH: {
-        sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
-                              SQLITE_TRANSIENT, SQLITE_UTF8);
-        break;
-      }
-      default: {
-        const char *zRoot = p->zRoot;
-        if( zRoot==0 ) zRoot = "$";
-        sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
-        break;
+      break;
+    }
+    case JEACH_ID: {
+      sqlite3_result_int64(ctx, (sqlite3_int64)p->i);
+      break;
+    }
+    case JEACH_PARENT: {
+      if( p->nParent>0 ){
+        sqlite3_result_int64(ctx, p->aParent[p->nParent-1].iHead);
       }
-      case JEACH_JSON: {
-        if( p->sParse.isBinary ){
-          sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
-                              SQLITE_STATIC);
-        }else{
-          sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
-        }
-        break;
+      break;
+    }
+    case JEACH_FULLKEY: {
+      u64 nBase = p->path.nUsed;
+      if( p->nParent ) jsonAppendPathName(p);
+      sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
+                            SQLITE_TRANSIENT, SQLITE_UTF8);
+      p->path.nUsed = nBase;
+      break;
+    }
+    case JEACH_PATH: {
+      sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
+                            SQLITE_TRANSIENT, SQLITE_UTF8);
+      break;
+    }
+    default: {
+      const char *zRoot = p->zRoot;
+      if( zRoot==0 ) zRoot = "$";
+      sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
+      break;
+    }
+    case JEACH_JSON: {
+      if( p->sParse.isBinary ){
+        sqlite3_result_blob(ctx, p->sParse.aBlob, p->sParse.nBlob,
+                            SQLITE_STATIC);
+      }else{
+        sqlite3_result_text(ctx, p->sParse.zJson, -1, SQLITE_STATIC);
       }
+      break;
     }
-
   }
   return SQLITE_OK;
 }
@@ -6192,10 +5941,8 @@ static int jsonEachFilter(
   int argc, sqlite3_value **argv
 ){
   JsonEachCursor *p = (JsonEachCursor*)cur;
-  const char *z;
   const char *zRoot = 0;
-  sqlite3_int64 n;
-  int isBinary;
+  u32 i, n, sz;
 
   UNUSED_PARAMETER(idxStr);
   UNUSED_PARAMETER(argc);
@@ -6204,136 +5951,71 @@ static int jsonEachFilter(
   memset(&p->sParse, 0, sizeof(p->sParse));
   p->sParse.nJPRef = 1;
   if( jsonFuncArgMightBeBinary(argv[0]) ){
-    u32 i, n, sz;
     p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
     p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
     if( p->sParse.aBlob==0 ){
       return SQLITE_NOMEM;
     }
-    if( idxNum==3 ){
-      zRoot = (const char*)sqlite3_value_text(argv[1]);
-      if( zRoot==0 ) return SQLITE_OK;
-      if( zRoot[0]!='$' ){
-        sqlite3_free(cur->pVtab->zErrMsg);
-        cur->pVtab->zErrMsg = jsonPathSyntaxError(zRoot, 0);
-        jsonEachCursorReset(p);
-        return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
-      }
-      if( zRoot[1]==0 ){
-        i = p->i = 0;
-        p->eType = 0;
-      }else{
-        i = jsonLookupBlobStep(&p->sParse, 0, zRoot+1, 0);
-        if( JSON_BLOB_ISERROR(i) ){
-          p->i = 0;
-          p->eType = 0;
-          p->iEnd = 0;
-          return SQLITE_OK;
-        }
-        if( p->sParse.iLabel ){
-          p->i = p->sParse.iLabel;
-          p->eType = JSONB_OBJECT;
-        }else{
-          p->i = i;
-          p->eType = JSONB_ARRAY;
-        }
+  }else{
+    p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
+    p->sParse.nJson = sqlite3_value_bytes(argv[0]);
+    if( p->sParse.zJson==0 || jsonConvertTextToBlob(&p->sParse, 0) ){
+      if( p->sParse.oom ){
+        return SQLITE_NOMEM;
       }
-      jsonAppendRaw(&p->path, zRoot, sqlite3Strlen30(zRoot));
-    }else{
-      i = p->i = 0;
-      p->eType = 0;
-      jsonAppendRaw(&p->path, "$", 1);
+      p->i = p->iEnd = 0;
+      return SQLITE_OK;
     }
-    p->nParent = 0;
-    p->sParse.isBinary = 1;
-    n = jsonbPayloadSize(&p->sParse, i, &sz);
-    p->iEnd = i+n+sz;
-    if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){
-      p->i = i + n;
-      p->eType = p->sParse.aBlob[i] & 0x0f;
-      p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent));
-      if( p->aParent==0 ) return SQLITE_NOMEM;
-      p->nParent = 1;
-      p->nParentAlloc = 1;
-      p->aParent[0].iKey = 0;
-      p->aParent[0].iEnd = p->iEnd;
-      p->aParent[0].iHead = p->i;
-      p->aParent[0].iValue = i;
-    }
-    return SQLITE_OK;
-  }else{
-    z = (const char*)sqlite3_value_text(argv[0]);
-    isBinary = 0;
   }
-  if( z==0 ) return SQLITE_OK;
-  if( sqlite3ValueIsOfClass(argv[0], sqlite3RCStrUnref) ){
-    p->sParse.zJson = sqlite3RCStrRef((char*)z);
-  }else{
-    n = sqlite3_value_bytes(argv[0]);
-    p->sParse.zJson = sqlite3RCStrNew( n+1 );
-    if( p->sParse.zJson==0 ) return SQLITE_NOMEM;
-    memcpy(p->sParse.zJson, z, (size_t)n+(isBinary==0));
-    p->sParse.nJson = n;
-  }
-  p->sParse.bJsonIsRCStr = 1;
-  p->sParse.isBinary = isBinary;
-  p->zJson = p->sParse.zJson;
-  if( jsonParse(&p->sParse, 0) ){
-    int rc = SQLITE_NOMEM;
-    if( p->sParse.oom==0 ){
+  if( idxNum==3 ){
+    zRoot = (const char*)sqlite3_value_text(argv[1]);
+    if( zRoot==0 ) return SQLITE_OK;
+    if( zRoot[0]!='$' ){
       sqlite3_free(cur->pVtab->zErrMsg);
-      cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON");
-      if( cur->pVtab->zErrMsg ) rc = SQLITE_ERROR;
-    }
-    jsonEachCursorReset(p);
-    return rc;
-  }else if( p->bRecursive && jsonParseFindParents(&p->sParse) ){
-    jsonEachCursorReset(p);
-    return SQLITE_NOMEM;
-  }else{
-    JsonNode *pNode = 0;
-    if( idxNum==3 ){
-      const char *zErr = 0;
-      zRoot = (const char*)sqlite3_value_text(argv[1]);
-      if( zRoot==0 ) return SQLITE_OK;
-      n = sqlite3_value_bytes(argv[1]);
-      p->zRoot = sqlite3_malloc64( n+1 );
-      if( p->zRoot==0 ) return SQLITE_NOMEM;
-      memcpy(p->zRoot, zRoot, (size_t)n+1);
-      if( zRoot[0]!='$' ){
-        zErr = zRoot;
-      }else{
-        pNode = jsonLookupStep(&p->sParse, 0, p->zRoot+1, 0, &zErr);
-      }
-      if( zErr ){
-        sqlite3_free(cur->pVtab->zErrMsg);
-        cur->pVtab->zErrMsg = jsonPathSyntaxError(zErr, 0);
-        jsonEachCursorReset(p);
-        return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
-      }else if( pNode==0 ){
+      cur->pVtab->zErrMsg = jsonPathSyntaxError(zRoot, 0);
+      jsonEachCursorReset(p);
+      return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM;
+    }
+    if( zRoot[1]==0 ){
+      i = p->i = 0;
+      p->eType = 0;
+    }else{
+      i = jsonLookupBlobStep(&p->sParse, 0, zRoot+1, 0);
+      if( JSON_BLOB_ISERROR(i) ){
+        p->i = 0;
+        p->eType = 0;
+        p->iEnd = 0;
         return SQLITE_OK;
       }
-    }else{
-      pNode = p->sParse.aNode;
-    }
-    p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
-    p->eType = pNode->eType;
-    if( p->eType>=JSON_ARRAY ){
-      assert( pNode->eU==0 );
-      JSON_VVA( pNode->eU = 3 );
-      pNode->u.iKey = 0;
-      p->iEnd = p->i + pNode->n + 1;
-      if( p->bRecursive ){
-        p->eType = p->sParse.aNode[p->sParse.aUp[p->i]].eType;
-        if( p->i>0 && (p->sParse.aNode[p->i-1].jnFlags & JNODE_LABEL)!=0 ){
-          p->i--;
-        }
+      if( p->sParse.iLabel ){
+        p->i = p->sParse.iLabel;
+        p->eType = JSONB_OBJECT;
       }else{
-        p->i++;
+        p->i = i;
+        p->eType = JSONB_ARRAY;
       }
-    }else{
-      p->iEnd = p->i+1;
     }
+    jsonAppendRaw(&p->path, zRoot, sqlite3Strlen30(zRoot));
+  }else{
+    i = p->i = 0;
+    p->eType = 0;
+    jsonAppendRaw(&p->path, "$", 1);
+  }
+  p->nParent = 0;
+  p->sParse.isBinary = 1;
+  n = jsonbPayloadSize(&p->sParse, i, &sz);
+  p->iEnd = i+n+sz;
+  if( (p->sParse.aBlob[i] & 0x0f)>=JSONB_ARRAY && !p->bRecursive ){
+    p->i = i + n;
+    p->eType = p->sParse.aBlob[i] & 0x0f;
+    p->aParent = sqlite3DbMallocZero(p->db, sizeof(JsonParent));
+    if( p->aParent==0 ) return SQLITE_NOMEM;
+    p->nParent = 1;
+    p->nParentAlloc = 1;
+    p->aParent[0].iKey = 0;
+    p->aParent[0].iEnd = p->iEnd;
+    p->aParent[0].iHead = p->i;
+    p->aParent[0].iValue = i;
   }
   return SQLITE_OK;
 }