Add the fullkey column to both json_each() and json_tree().

FossilOrigin-Name: 15dd99431e9ddd0fbdbb8dcc921687b0c6d26a29
This commit is contained in:
drh 2015-08-21 20:02:48 +00:00
parent b1b124d482
commit 4af352d47e
3 changed files with 120 additions and 52 deletions

View File

@ -27,6 +27,7 @@ SQLITE_EXTENSION_INIT1
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
/* 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->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 */
@ -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 */

View File

@ -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

View File

@ -1 +1 @@
7c2713e98ffb5f0d96eb7de9514eab43f0712011
15dd99431e9ddd0fbdbb8dcc921687b0c6d26a29