aboutsummaryrefslogtreecommitdiff
path: root/src/json.c
diff options
context:
space:
mode:
authordrh <>2023-11-09 17:36:37 +0000
committerdrh <>2023-11-09 17:36:37 +0000
commit3839dcf97324b76af86f21a08ba27dcc4a3f6986 (patch)
tree15944daf40f2ddcf513542a0430824b2171ef280 /src/json.c
parent2009a5acba967eab68304cdb8feeb340f5a45782 (diff)
parentbeb06e6b0a17b732ca0ab7e416891175eb87d3af (diff)
downloadsqlite-3839dcf97324b76af86f21a08ba27dcc4a3f6986.tar.gz
sqlite-3839dcf97324b76af86f21a08ba27dcc4a3f6986.zip
Add the SQLITE_RESULT_SUBTYPE flag for application-defined functions. Add
the -DSQLITE_STRICT_SUBTYPE=1 compile-time option that raises an error if any function invokes sqlite3_result_subtype() without the SQLITE_RESULT_SUBTYPE flag. SQLITE_RESULT_SUBTYPE prevents an indexed value of that function from being used to replace an equivalent expression, since the indexed expression does not carry the subtype. Fix for the problem described at [forum:/forumpost/68d284c86b082c3e|forum post 68d284c86b082c3e]. FossilOrigin-Name: ba789a7804ab96d81b15d6ef6fed1f802fa69db47cf91d368933e55289fa1d6e
Diffstat (limited to 'src/json.c')
-rw-r--r--src/json.c89
1 files changed, 48 insertions, 41 deletions
diff --git a/src/json.c b/src/json.c
index 91b96df37..0f11ace02 100644
--- a/src/json.c
+++ b/src/json.c
@@ -839,7 +839,8 @@ static void jsonReturnJson(
JsonParse *pParse, /* The complete JSON */
JsonNode *pNode, /* Node to return */
sqlite3_context *pCtx, /* Return value for this function */
- int bGenerateAlt /* Also store the rendered text in zAlt */
+ int bGenerateAlt, /* Also store the rendered text in zAlt */
+ int omitSubtype /* Do not call sqlite3_result_subtype() */
){
JsonString s;
if( pParse->oom ){
@@ -854,7 +855,7 @@ static void jsonReturnJson(
pParse->nAlt = s.nUsed;
}
jsonResult(&s);
- sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
+ if( !omitSubtype ) sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
}
}
@@ -895,7 +896,8 @@ static u32 jsonHexToInt4(const char *z){
static void jsonReturn(
JsonParse *pParse, /* Complete JSON parse tree */
JsonNode *pNode, /* Node to return */
- sqlite3_context *pCtx /* Return value for this function */
+ sqlite3_context *pCtx, /* Return value for this function */
+ int omitSubtype /* Do not call sqlite3_result_subtype() */
){
switch( pNode->eType ){
default: {
@@ -1041,7 +1043,7 @@ static void jsonReturn(
}
case JSON_ARRAY:
case JSON_OBJECT: {
- jsonReturnJson(pParse, pNode, pCtx, 0);
+ jsonReturnJson(pParse, pNode, pCtx, 0, omitSubtype);
break;
}
}
@@ -2393,7 +2395,7 @@ static void jsonParseFunc(
printf("iSubst = %u\n", p->iSubst);
printf("iHold = %u\n", p->iHold);
jsonDebugPrintNodeEntries(p->aNode, p->nNode);
- jsonReturnJson(p, p->aNode, ctx, 1);
+ jsonReturnJson(p, p->aNode, ctx, 1, 0);
}
/*
@@ -2579,15 +2581,14 @@ static void jsonExtractFunc(
}
if( pNode ){
if( flags & JSON_JSON ){
- jsonReturnJson(p, pNode, ctx, 0);
+ jsonReturnJson(p, pNode, ctx, 0, 0);
}else{
- jsonReturn(p, pNode, ctx);
- sqlite3_result_subtype(ctx, 0);
+ jsonReturn(p, pNode, ctx, 1);
}
}
}else{
pNode = jsonLookup(p, zPath, 0, ctx);
- if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx);
+ if( p->nErr==0 && pNode ) jsonReturn(p, pNode, ctx, 0);
}
}else{
/* Two or more PATH arguments results in a JSON array with each
@@ -2713,7 +2714,7 @@ static void jsonPatchFunc(
if( pResult && pX->oom==0 ){
jsonDebugPrintParse(pX);
jsonDebugPrintNode(pResult);
- jsonReturnJson(pX, pResult, ctx, 0);
+ jsonReturnJson(pX, pResult, ctx, 0, 0);
}else{
sqlite3_result_error_nomem(ctx);
}
@@ -2792,7 +2793,7 @@ static void jsonRemoveFunc(
}
}
if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){
- jsonReturnJson(pParse, pParse->aNode, ctx, 1);
+ jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0);
}
remove_done:
jsonDebugPrintParse(p);
@@ -2921,7 +2922,7 @@ static void jsonReplaceFunc(
jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]);
}
}
- jsonReturnJson(pParse, pParse->aNode, ctx, 1);
+ jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0);
replace_err:
jsonDebugPrintParse(pParse);
jsonParseFree(pParse);
@@ -2975,7 +2976,7 @@ static void jsonSetFunc(
}
}
jsonDebugPrintParse(pParse);
- jsonReturnJson(pParse, pParse->aNode, ctx, 1);
+ jsonReturnJson(pParse, pParse->aNode, ctx, 1, 0);
jsonSetDone:
jsonParseFree(pParse);
}
@@ -3490,7 +3491,7 @@ static int jsonEachColumn(
case JEACH_KEY: {
if( p->i==0 ) break;
if( p->eType==JSON_OBJECT ){
- jsonReturn(&p->sParse, pThis, ctx);
+ jsonReturn(&p->sParse, pThis, ctx, 0);
}else if( p->eType==JSON_ARRAY ){
u32 iKey;
if( p->bRecursive ){
@@ -3506,7 +3507,7 @@ static int jsonEachColumn(
}
case JEACH_VALUE: {
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- jsonReturn(&p->sParse, pThis, ctx);
+ jsonReturn(&p->sParse, pThis, ctx, 0);
break;
}
case JEACH_TYPE: {
@@ -3517,7 +3518,7 @@ static int jsonEachColumn(
case JEACH_ATOM: {
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
if( pThis->eType>=JSON_ARRAY ) break;
- jsonReturn(&p->sParse, pThis, ctx);
+ jsonReturn(&p->sParse, pThis, ctx, 0);
break;
}
case JEACH_ID: {
@@ -3810,37 +3811,43 @@ static sqlite3_module jsonTreeModule = {
void sqlite3RegisterJsonFunctions(void){
#ifndef SQLITE_OMIT_JSON
static FuncDef aJsonFunc[] = {
- /* Uses cache ------, ,---- Might return JSON (subtype J) */
- /* Num args ________ | | ___ Flags */
- /* \ | | / */
- JFUNCTION(json, 1, 1, 1, 0, jsonRemoveFunc),
- JFUNCTION(json_array, -1, 0, 1, 0, jsonArrayFunc),
- JFUNCTION(json_array_length, 1, 1, 0, 0, jsonArrayLengthFunc),
- JFUNCTION(json_array_length, 2, 1, 0, 0, jsonArrayLengthFunc),
- JFUNCTION(json_error_position,1, 1, 0, 0, jsonErrorFunc),
- JFUNCTION(json_extract, -1, 1, 1, 0, jsonExtractFunc),
- JFUNCTION(->, 2, 1, 1, JSON_JSON, jsonExtractFunc),
- JFUNCTION(->>, 2, 1, 0, JSON_SQL, jsonExtractFunc),
- JFUNCTION(json_insert, -1, 1, 1, 0, jsonSetFunc),
- JFUNCTION(json_object, -1, 0, 1, 0, jsonObjectFunc),
- JFUNCTION(json_patch, 2, 1, 1, 0, jsonPatchFunc),
- JFUNCTION(json_quote, 1, 0, 1, 0, jsonQuoteFunc),
- JFUNCTION(json_remove, -1, 1, 1, 0, jsonRemoveFunc),
- JFUNCTION(json_replace, -1, 1, 1, 0, jsonReplaceFunc),
- JFUNCTION(json_set, -1, 1, 1, JSON_ISSET, jsonSetFunc),
- JFUNCTION(json_type, 1, 1, 0, 0, jsonTypeFunc),
- JFUNCTION(json_type, 2, 1, 0, 0, jsonTypeFunc),
- JFUNCTION(json_valid, 1, 1, 0, 0, jsonValidFunc),
+ /* calls sqlite3_result_subtype() */
+ /* | */
+ /* Uses cache ______ | __ calls sqlite3_value_subtype() */
+ /* | | | */
+ /* Num args _________ | | | ___ Flags */
+ /* | | | | | */
+ /* | | | | | */
+ JFUNCTION(json, 1, 1, 1, 0, 0, jsonRemoveFunc),
+ JFUNCTION(json_array, -1, 0, 1, 1, 0, jsonArrayFunc),
+ JFUNCTION(json_array_length, 1, 1, 0, 0, 0, jsonArrayLengthFunc),
+ JFUNCTION(json_array_length, 2, 1, 0, 0, 0, jsonArrayLengthFunc),
+ JFUNCTION(json_error_position,1, 1, 0, 0, 0, jsonErrorFunc),
+ JFUNCTION(json_extract, -1, 1, 1, 0, 0, jsonExtractFunc),
+ JFUNCTION(->, 2, 1, 1, 0, JSON_JSON, jsonExtractFunc),
+ JFUNCTION(->>, 2, 1, 0, 0, JSON_SQL, jsonExtractFunc),
+ JFUNCTION(json_insert, -1, 1, 1, 1, 0, jsonSetFunc),
+ JFUNCTION(json_object, -1, 0, 1, 1, 0, jsonObjectFunc),
+ JFUNCTION(json_patch, 2, 1, 1, 0, 0, jsonPatchFunc),
+ JFUNCTION(json_quote, 1, 0, 1, 1, 0, jsonQuoteFunc),
+ JFUNCTION(json_remove, -1, 1, 1, 0, 0, jsonRemoveFunc),
+ JFUNCTION(json_replace, -1, 1, 1, 1, 0, jsonReplaceFunc),
+ JFUNCTION(json_set, -1, 1, 1, 1, JSON_ISSET, jsonSetFunc),
+ JFUNCTION(json_type, 1, 1, 0, 0, 0, jsonTypeFunc),
+ JFUNCTION(json_type, 2, 1, 0, 0, 0, jsonTypeFunc),
+ JFUNCTION(json_valid, 1, 1, 0, 0, 0, jsonValidFunc),
#if SQLITE_DEBUG
- JFUNCTION(json_parse, 1, 1, 0, 0, jsonParseFunc),
- JFUNCTION(json_test1, 1, 1, 0, 0, jsonTest1Func),
+ JFUNCTION(json_parse, 1, 1, 1, 0, 0, jsonParseFunc),
+ JFUNCTION(json_test1, 1, 1, 0, 1, 0, jsonTest1Func),
#endif
WAGGREGATE(json_group_array, 1, 0, 0,
jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
- SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC),
+ SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|
+ SQLITE_DETERMINISTIC),
WAGGREGATE(json_group_object, 2, 0, 0,
jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
- SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC)
+ SQLITE_SUBTYPE|SQLITE_RESULT_SUBTYPE|SQLITE_UTF8|
+ SQLITE_DETERMINISTIC)
};
sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
#endif