-C Handle\sthe\spath\sargument\sto\sjson_tree()\sand\sjson_each().
-D 2023-11-25T13:40:19.363
+C Generate\sthe\sfullkey\sand\spath\scolumns\sof\sjson_tree().
+D 2023-11-25T18:11:11.468
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
-F src/json.c ff48d52463493f5f40d6e1e14ac3dc9277c40290df140a52bd17e7a562f766ea
+F src/json.c 9a5ff28f7b55e83b92eeab9285eb4b0132f11526620565e2d5b81fb84d4e8611
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 3df891cb11feee65e239ee2506eda34a9688341f05210d7c2e25a05338cb71ad
-R 86973d4c807995bd645f2f5dbc7eac48
+P fded888469565b2a4687185a926bd23fccfbf167c8bebe6c10696fc7f972f41e
+R 90c664426338898baffedf8dcba41bea
U drh
-Z e2d0e1a86b5ddc3117954e8a28079ed7
+Z e9b6e925dfee6d388855b55f2b458a4c
# Remove this line to create a well-formed Fossil manifest.
}
}
-
/* Make the text in p (which is probably a generated JSON text string)
** the result of the SQL function.
**
u32 iHead; /* Start of object or array */
u32 iValue; /* Start of the value */
u32 iEnd; /* First byte past the end */
+ u32 nPath; /* Length of path */
i64 iKey; /* Key for JSONB_ARRAY */
};
char *zJson; /* Input JSON */
char *zRoot; /* Path by which to filter zJson */
sqlite3 *db; /* Database connection */
+ JsonString path; /* Current path */
JsonParse sParse; /* Parse of the input JSON */
};
typedef struct JsonEachConnection JsonEachConnection;
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = pVtab->db;
+ jsonStringZero(&pCur->path);
*ppCursor = &pCur->base;
return SQLITE_OK;
}
static void jsonEachCursorReset(JsonEachCursor *p){
sqlite3_free(p->zRoot);
jsonParseReset(&p->sParse);
+ jsonStringReset(&p->path);
sqlite3DbFree(p->db, p->aParent);
p->iRowid = 0;
p->i = 0;
static int jsonEachClose(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
jsonEachCursorReset(p);
+
sqlite3_free(cur);
return SQLITE_OK;
}
}
}
+/*
+** Append the path name for the current element.
+*/
+static void jsonAppendPathName(JsonEachCursor *p){
+ assert( p->nParent>0 );
+ assert( p->eType==JSONB_ARRAY || p->eType==JSONB_OBJECT );
+ if( p->eType==JSONB_ARRAY ){
+ jsonPrintf(30, &p->path, "[%lld]", p->aParent[p->nParent-1].iKey);
+ }else{
+ u32 n, sz = 0, k, i;
+ const char *z;
+ int needQuote = 0;
+ n = jsonbPayloadSize(&p->sParse, p->i, &sz);
+ k = p->i + n;
+ z = (const char*)&p->sParse.aBlob[k];
+ if( sz==0 || !sqlite3Isalpha(z[0]) ){
+ needQuote = 1;
+ }else{
+ for(i=0; i<sz; i++){
+ if( !sqlite3Isalnum(z[i]) ){
+ needQuote = 1;
+ break;
+ }
+ }
+ }
+ if( needQuote ){
+ jsonPrintf(sz+4,&p->path,".\"%.*s\"", sz, z);
+ }else{
+ jsonPrintf(sz+2,&p->path,".%.*s", sz, z);
+ }
+ }
+}
+
/* Advance the cursor to the next element for json_tree() */
static int jsonEachNext(sqlite3_vtab_cursor *cur){
JsonEachCursor *p = (JsonEachCursor*)cur;
p->aParent = pNew;
}
levelChange = 1;
- pParent = &p->aParent[p->nParent++];
+ pParent = &p->aParent[p->nParent];
pParent->iHead = p->i;
pParent->iValue = i;
pParent->iEnd = i + n + sz;
pParent->iKey = -1;
+ pParent->nPath = (u32)p->path.nUsed;
+ if( p->eType && p->nParent ) jsonAppendPathName(p);
+ p->nParent++;
p->i = i + n;
}else{
p->i = i + n + sz;
}
while( p->nParent>0 && p->i >= p->aParent[p->nParent-1].iEnd ){
p->nParent--;
+ p->path.nUsed = p->aParent[p->nParent].nPath;
levelChange = 1;
}
if( levelChange ){
break;
}
case JEACH_FULLKEY: {
-#if 0
- u32 i;
- JsonString x;
- jsonStringInit(&x, ctx);
- for(i=0; i<p->nParent; i++){
- jsonPrintf(200,&x,"(%u,%u,%u,%lld)",
- p->aParent[i].iHead,
- p->aParent[i].iValue,
- p->aParent[i].iEnd,
- p->aParent[i].iKey);
- }
- jsonReturnString(&x);
-#endif
-#if 0
- 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);
-#endif
+ 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: {
-#if 0
- 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
-#endif
+ sqlite3_result_text64(ctx, p->path.zBuf, p->path.nUsed,
+ SQLITE_TRANSIENT, SQLITE_UTF8);
break;
}
default: {
if( idxNum==3 ){
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]!='$' ){
sqlite3_free(cur->pVtab->zErrMsg);
cur->pVtab->zErrMsg = jsonPathSyntaxError(zRoot, 0);
i = p->i = 0;
p->eType = 0;
}else{
- i = jsonLookupBlobStep(&p->sParse, 0, p->zRoot+1, 0);
+ i = jsonLookupBlobStep(&p->sParse, 0, zRoot+1, 0);
if( JSON_BLOB_ISERROR(i) ){
p->i = 0;
p->eType = 0;
p->eType = JSONB_ARRAY;
}
}
+ 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;