From: drh Date: Fri, 21 Aug 2015 20:02:48 +0000 (+0000) Subject: Add the fullkey column to both json_each() and json_tree(). X-Git-Tag: version-3.9.0~204^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4af352d47edaa53f860805157b00fc6cfcdaa155;p=thirdparty%2Fsqlite.git Add the fullkey column to both json_each() and json_tree(). FossilOrigin-Name: 15dd99431e9ddd0fbdbb8dcc921687b0c6d26a29 --- diff --git a/ext/misc/json.c b/ext/misc/json.c index 26cde61056..9d9bf63896 100644 --- a/ext/misc/json.c +++ b/ext/misc/json.c @@ -27,6 +27,7 @@ SQLITE_EXTENSION_INIT1 #include #include #include +#include /* Unsigned integer types */ typedef sqlite3_uint64 u64; @@ -181,6 +182,17 @@ static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){ p->nUsed += N; } +/* Append formatted text (not to exceed N bytes) to the JsonString. +*/ +static void jsonPrintf(int N, JsonString *p, const char *zFormat, ...){ + va_list ap; + if( (p->nUsed + N >= p->nAlloc) && jsonGrow(p, N) ) return; + va_start(ap, zFormat); + sqlite3_vsnprintf(N, p->zBuf+p->nUsed, zFormat, ap); + va_end(ap); + p->nUsed += (int)strlen(p->zBuf+p->nUsed); +} + #ifdef SQLITE_DEBUG /* Append the zero-terminated string zIn */ @@ -1256,17 +1268,19 @@ static int jsonEachConnect( int rc; /* Column numbers */ -#define JEACH_KEY 0 -#define JEACH_VALUE 1 -#define JEACH_TYPE 2 -#define JEACH_ATOM 3 -#define JEACH_ID 4 -#define JEACH_PARENT 5 -#define JEACH_JSON 6 -#define JEACH_PATH 7 +#define JEACH_KEY 0 +#define JEACH_VALUE 1 +#define JEACH_TYPE 2 +#define JEACH_ATOM 3 +#define JEACH_ID 4 +#define JEACH_PARENT 5 +#define JEACH_FULLKEY 6 +#define JEACH_JSON 7 +#define JEACH_PATH 8 rc = sqlite3_declare_vtab(db, - "CREATE TABLE x(key,value,type,atom,id,parent,json hidden,path hidden)"); + "CREATE TABLE x(key,value,type,atom,id,parent,fullkey," + "json HIDDEN,path HIDDEN)"); if( rc==SQLITE_OK ){ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); if( pNew==0 ) return SQLITE_NOMEM; @@ -1331,47 +1345,71 @@ static int jsonEachEof(sqlite3_vtab_cursor *cur){ } /* Advance the cursor to the next element for json_tree() */ -static int jsonEachNextTree(sqlite3_vtab_cursor *cur){ +static int jsonEachNext(sqlite3_vtab_cursor *cur){ JsonEachCursor *p = (JsonEachCursor*)cur; - if( p->i==0 ){ - p->i = 1; - }else if( p->sParse.aNode[p->sParse.aUp[p->i]].eType==JSON_OBJECT ){ - p->i += 2; + if( p->bRecursive ){ + if( p->i==0 ){ + p->i = 1; + }else if( p->sParse.aNode[p->sParse.aUp[p->i]].eType==JSON_OBJECT ){ + p->i += 2; + }else{ + p->i++; + } + p->iRowid++; + if( p->isParse.nNode ){ + JsonNode *pUp = &p->sParse.aNode[p->sParse.aUp[p->i]]; + p->eType = pUp->eType; + if( pUp->eType==JSON_ARRAY ) pUp->u.iKey++; + if( p->sParse.aNode[p->i].eType==JSON_ARRAY ){ + p->sParse.aNode[p->i].u.iKey = 0; + } + } }else{ - p->i++; - } - p->iRowid++; - if( p->isParse.nNode ){ - JsonNode *pUp = &p->sParse.aNode[p->sParse.aUp[p->i]]; - p->eType = pUp->eType; - if( pUp->eType==JSON_ARRAY ) pUp->u.iKey++; - if( p->sParse.aNode[p->i].eType==JSON_ARRAY ){ - p->sParse.aNode[p->i].u.iKey = 0; + 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; } -/* Advance the cursor to the next element for json_each() */ -static int jsonEachNextEach(sqlite3_vtab_cursor *cur){ - JsonEachCursor *p = (JsonEachCursor*)cur; - 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; - } +/* 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; + } + iUp = p->sParse.aUp[i]; + jsonEachComputePath(p, pStr, iUp); + pNode = &p->sParse.aNode[i]; + pUp = &p->sParse.aNode[iUp]; + if( pUp->eType==JSON_ARRAY ){ + jsonPrintf(30, pStr, "[%d]", pUp->u.iKey); + }else{ + assert( pUp->eType==JSON_OBJECT ); + if( pNode->eType>=JSON_ARRAY ) pNode--; + assert( pNode->eType==JSON_STRING ); + jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); } - return SQLITE_OK; } /* Return the value of a column */ @@ -1424,9 +1462,38 @@ static int jsonEachColumn( } break; } + case JEACH_FULLKEY: { + JsonString x; + jsonInit(&x, ctx); + if( p->bRecursive ){ + jsonEachComputePath(p, &x, p->i); + }else{ + if( p->zPath ){ + jsonAppendRaw(&x, p->zPath, (int)strlen(p->zPath)); + }else{ + jsonAppendChar(&x, '$'); + } + if( p->eType==JSON_ARRAY ){ + jsonPrintf(30, &x, "[%d]", p->iRowid); + }else{ + jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); + } + } + jsonResult(&x); + break; + } case JEACH_PATH: { const char *zPath = p->zPath; - if( zPath==0 ) zPath = "$"; + if( zPath==0 ){ + if( p->bRecursive ){ + JsonString x; + jsonInit(&x, ctx); + jsonEachComputePath(p, &x, p->sParse.aUp[p->i]); + jsonResult(&x); + break; + } + zPath = "$"; + } sqlite3_result_text(ctx, zPath, -1, SQLITE_STATIC); break; } @@ -1517,6 +1584,7 @@ static int jsonEachFilter( }else{ JsonNode *pNode; if( idxNum==3 ){ + p->bRecursive = 0; n = sqlite3_value_bytes(argv[1]); p->zPath = sqlite3_malloc( n+1 ); if( p->zPath==0 ) return SQLITE_NOMEM; @@ -1552,7 +1620,7 @@ static sqlite3_module jsonEachModule = { jsonEachOpenEach, /* xOpen - open a cursor */ jsonEachClose, /* xClose - close a cursor */ jsonEachFilter, /* xFilter - configure scan constraints */ - jsonEachNextEach, /* xNext - advance a cursor */ + jsonEachNext, /* xNext - advance a cursor */ jsonEachEof, /* xEof - check for end of scan */ jsonEachColumn, /* xColumn - read data */ jsonEachRowid, /* xRowid - read data */ @@ -1576,7 +1644,7 @@ static sqlite3_module jsonTreeModule = { jsonEachOpenTree, /* xOpen - open a cursor */ jsonEachClose, /* xClose - close a cursor */ jsonEachFilter, /* xFilter - configure scan constraints */ - jsonEachNextTree, /* xNext - advance a cursor */ + jsonEachNext, /* xNext - advance a cursor */ jsonEachEof, /* xEof - check for end of scan */ jsonEachColumn, /* xColumn - read data */ jsonEachRowid, /* xRowid - read data */ diff --git a/manifest b/manifest index 6e096c9ed7..a20995d28b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sheader\sfile\sfixes\sfrom\strunk. -D 2015-08-21T19:56:45.243 +C Add\sthe\sfullkey\scolumn\sto\sboth\sjson_each()\sand\sjson_tree(). +D 2015-08-21T20:02:48.424 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 90f3097efb9a53f5fc59a4f8a08be07cf9f52c02 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -192,7 +192,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2 F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767 F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e -F ext/misc/json.c 522d833e6c4ae55b345cf25776aab335323d2f59 +F ext/misc/json.c 92bb4e5fe2956564d23f933e2140ce8e086d988b F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc @@ -1378,7 +1378,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 08c36e45f0d3a7b89caf823652d7543b76ac802a da3c9df09c46564353218d0163e378b880a3ce62 -R 7de9031da9783d58b8a952bc530228c5 +P 7c2713e98ffb5f0d96eb7de9514eab43f0712011 +R a1c5d56719dd38b21713ad204a82abd5 U drh -Z 5f4a9a3778df860327f346518d686e5d +Z 8567373ad141fc34581702b17b3fb646 diff --git a/manifest.uuid b/manifest.uuid index ded172cdf0..7f4f0b9760 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7c2713e98ffb5f0d96eb7de9514eab43f0712011 \ No newline at end of file +15dd99431e9ddd0fbdbb8dcc921687b0c6d26a29 \ No newline at end of file