#include <string.h>
#include <ctype.h>
#include <stdlib.h>
+#include <stdarg.h>
/* Unsigned integer types */
typedef sqlite3_uint64 u64;
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
*/
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;
}
/* 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->i<p->sParse.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->i<p->sParse.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 */
}
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;
}
}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;
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 */
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 */
-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
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
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