aboutsummaryrefslogtreecommitdiff
path: root/src/json.c
diff options
context:
space:
mode:
authordrh <>2023-11-10 18:59:23 +0000
committerdrh <>2023-11-10 18:59:23 +0000
commite8d4fd59e458d774373c011dd3f88ce0804813a0 (patch)
treef78533eb236350502e4a162eaa53fda6650cdcbd /src/json.c
parenta4cf38ca9b9f2217b163888b3d4811e316e538c4 (diff)
parent5a81e6e5cedb29be1ce8d41053c27e5b4a4f82fd (diff)
downloadsqlite-e8d4fd59e458d774373c011dd3f88ce0804813a0.tar.gz
sqlite-e8d4fd59e458d774373c011dd3f88ce0804813a0.zip
Merge recent trunk enhancements and fixes into the jsonb branch.
FossilOrigin-Name: 091a5f058dfe2115fb9213655b34f00bcec80aebb299b571975cfe4ecd5ec206
Diffstat (limited to 'src/json.c')
-rw-r--r--src/json.c123
1 files changed, 66 insertions, 57 deletions
diff --git a/src/json.c b/src/json.c
index 04349899c..3787167e9 100644
--- a/src/json.c
+++ b/src/json.c
@@ -593,7 +593,7 @@ static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){
u32 i;
jsonAppendChar(p, '"');
while( N>0 ){
- for(i=0; i<N && zIn[i]!='\\'; i++){}
+ for(i=0; i<N && zIn[i]!='\\' && zIn[i]!='"'; i++){}
if( i>0 ){
jsonAppendRawNZ(p, zIn, i);
if( i>=N ) break;
@@ -604,6 +604,12 @@ static void jsonAppendNormalizedString(JsonString *p, const char *zIn, u32 N){
p->eErr |= JSTRING_MALFORMED;
break;
}
+ if( zIn[0]=='"' ){
+ jsonAppendRawNZ(p, "\\\"", 2);
+ zIn++;
+ N--;
+ continue;
+ }
assert( zIn[0]=='\\' );
switch( (u8)zIn[1] ){
case '\'':
@@ -1031,7 +1037,8 @@ static void jsonReturnNodeAsJson(
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() */
){
int flags;
JsonString s;
@@ -1061,7 +1068,7 @@ static void jsonReturnNodeAsJson(
pParse->nAlt = s.nUsed;
}
jsonReturnString(&s);
- sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
+ if( !omitSubtype ) sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
}
}
@@ -1105,7 +1112,8 @@ static u32 jsonHexToInt4(const char *z){
static void jsonReturnFromNode(
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: {
@@ -1259,7 +1267,7 @@ static void jsonReturnFromNode(
}
case JSON_ARRAY:
case JSON_OBJECT: {
- jsonReturnNodeAsJson(pParse, pNode, pCtx, 0);
+ jsonReturnNodeAsJson(pParse, pNode, pCtx, 0, omitSubtype);
break;
}
}
@@ -4318,7 +4326,7 @@ static void jsonParseFunc(
printf("iSubst = %u\n", p->iSubst);
printf("iHold = %u\n", p->iHold);
jsonDebugPrintNodeEntries(p->aNode, p->nNode);
- jsonReturnNodeAsJson(p, p->aNode, ctx, 1);
+ jsonReturnNodeAsJson(p, p->aNode, ctx, 1, 0);
}
/*
@@ -4570,15 +4578,14 @@ static void jsonExtractFunc(
}
if( pNode ){
if( flags & JSON_JSON ){
- jsonReturnNodeAsJson(p, pNode, ctx, 0);
+ jsonReturnNodeAsJson(p, pNode, ctx, 0, 0);
}else{
- jsonReturnFromNode(p, pNode, ctx);
- sqlite3_result_subtype(ctx, 0);
+ jsonReturnFromNode(p, pNode, ctx, 1);
}
}
}else{
pNode = jsonLookup(p, zPath, 0, ctx);
- if( p->nErr==0 && pNode ) jsonReturnFromNode(p, pNode, ctx);
+ if( p->nErr==0 && pNode ) jsonReturnFromNode(p, pNode, ctx, 0);
}
}else{
/* Two or more PATH arguments results in a JSON array with each
@@ -4710,7 +4717,7 @@ static void jsonPatchFunc(
}else if( pResult ){
jsonDebugPrintParse(pX);
jsonDebugPrintNode(pResult);
- jsonReturnNodeAsJson(pX, pResult, ctx, 0);
+ jsonReturnNodeAsJson(pX, pResult, ctx, 0, 0);
}
}
@@ -4787,7 +4794,7 @@ static void jsonRemoveFunc(
}
}
if( (pParse->aNode[0].jnFlags & JNODE_REMOVE)==0 ){
- jsonReturnNodeAsJson(pParse, pParse->aNode, ctx, 1);
+ jsonReturnNodeAsJson(pParse, pParse->aNode, ctx, 1, 0);
}
remove_done:
jsonDebugPrintParse(p);
@@ -4923,7 +4930,7 @@ static void jsonReplaceFunc(
jsonReplaceNode(ctx, pParse, (u32)(pNode - pParse->aNode), argv[i+1]);
}
}
- jsonReturnNodeAsJson(pParse, pParse->aNode, ctx, 1);
+ jsonReturnNodeAsJson(pParse, pParse->aNode, ctx, 1, 0);
replace_err:
jsonDebugPrintParse(pParse);
jsonParseFree(pParse);
@@ -4978,7 +4985,7 @@ static void jsonSetFunc(
}
}
jsonDebugPrintParse(pParse);
- jsonReturnNodeAsJson(pParse, pParse->aNode, ctx, 1);
+ jsonReturnNodeAsJson(pParse, pParse->aNode, ctx, 1, 0);
jsonSetDone:
jsonParseFree(pParse);
}
@@ -5526,7 +5533,7 @@ static int jsonEachColumn(
case JEACH_KEY: {
if( p->i==0 ) break;
if( p->eType==JSON_OBJECT ){
- jsonReturnFromNode(&p->sParse, pThis, ctx);
+ jsonReturnFromNode(&p->sParse, pThis, ctx, 0);
}else if( p->eType==JSON_ARRAY ){
u32 iKey;
if( p->bRecursive ){
@@ -5542,7 +5549,7 @@ static int jsonEachColumn(
}
case JEACH_VALUE: {
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
- jsonReturnFromNode(&p->sParse, pThis, ctx);
+ jsonReturnFromNode(&p->sParse, pThis, ctx, 0);
break;
}
case JEACH_TYPE: {
@@ -5553,7 +5560,7 @@ static int jsonEachColumn(
case JEACH_ATOM: {
if( pThis->jnFlags & JNODE_LABEL ) pThis++;
if( pThis->eType>=JSON_ARRAY ) break;
- jsonReturnFromNode(&p->sParse, pThis, ctx);
+ jsonReturnFromNode(&p->sParse, pThis, ctx, 0);
break;
}
case JEACH_ID: {
@@ -5859,56 +5866,58 @@ static sqlite3_module jsonTreeModule = {
void sqlite3RegisterJsonFunctions(void){
#ifndef SQLITE_OMIT_JSON
static FuncDef aJsonFunc[] = {
- /* Might return JSON text (subtype J) */
- /* | */
- /* Uses cache ------, | ,---- Returns JSONB */
- /* | | | */
- /* Number of arguments ---, | | | ,--- Flags */
- /* | | | | | */
- JFUNCTION(json, 1, 1, 1, 0, 0, jsonRemoveFunc),
- JFUNCTION(jsonb, 1, 1, 0, 1, 0, jsonbFunc),
- JFUNCTION(json_array, -1, 0, 1, 0, 0, jsonArrayFunc),
- JFUNCTION(jsonb_array, -1, 0, 0, 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(jsonb_extract, -1, 1, 0, 1, 0, jsonExtractFunc),
- JFUNCTION(->, 2, 1, 1, 0, JSON_JSON, jsonExtractFunc),
- JFUNCTION(->>, 2, 1, 0, 0, JSON_SQL, jsonExtractFunc),
- JFUNCTION(json_insert, -1, 1, 1, 0, 0, jsonSetFunc),
- JFUNCTION(jsonb_insert, -1, 1, 0, 1, 0, jsonSetFunc),
- JFUNCTION(json_object, -1, 0, 1, 0, 0, jsonObjectFunc),
- JFUNCTION(jsonb_object, -1, 0, 0, 1, 0, jsonObjectFunc),
- JFUNCTION(json_patch, 2, 1, 1, 0, 0, jsonPatchFunc),
- JFUNCTION(jsonb_patch, 2, 1, 0, 1, 0, jsonPatchFunc),
- JFUNCTION(json_quote, 1, 0, 1, 0, 0, jsonQuoteFunc),
- JFUNCTION(json_remove, -1, 1, 1, 0, 0, jsonRemoveFunc),
- JFUNCTION(jsonb_remove, -1, 1, 0, 1, 0, jsonRemoveFunc),
- JFUNCTION(json_replace, -1, 1, 1, 0, 0, jsonReplaceFunc),
- JFUNCTION(jsonb_replace, -1, 1, 0, 1, 0, jsonReplaceFunc),
- JFUNCTION(json_set, -1, 1, 1, 0, JSON_ISSET, jsonSetFunc),
- JFUNCTION(jsonb_set, -1, 1, 0, 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),
+ /* sqlite3_result_subtype() ----, ,--- sqlite3_value_subtype() */
+ /* | | */
+ /* Uses cache ------, | | ,---- Returns JSONB */
+ /* | | | | */
+ /* Number of arguments ---, | | | | ,--- Flags */
+ /* | | | | | | */
+ JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc),
+ JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonbFunc),
+ JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc),
+ JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc),
+ JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),
+ JFUNCTION(json_array_length, 2,1,0, 0,0,0, jsonArrayLengthFunc),
+ JFUNCTION(json_error_position,1,1,0, 0,0,0, jsonErrorFunc),
+ JFUNCTION(json_extract, -1,1,1, 0,0,0, jsonExtractFunc),
+ JFUNCTION(jsonb_extract, -1,1,0, 0,1,0, jsonExtractFunc),
+ JFUNCTION(->, 2,1,1, 0,0,JSON_JSON, jsonExtractFunc),
+ JFUNCTION(->>, 2,1,0, 0,0,JSON_SQL, jsonExtractFunc),
+ JFUNCTION(json_insert, -1,1,1, 1,0,0, jsonSetFunc),
+ JFUNCTION(jsonb_insert, -1,1,0, 1,1,0, jsonSetFunc),
+ JFUNCTION(json_object, -1,0,1, 1,0,0, jsonObjectFunc),
+ JFUNCTION(jsonb_object, -1,0,1, 1,1,0, jsonObjectFunc),
+ JFUNCTION(json_patch, 2,1,1, 0,0,0, jsonPatchFunc),
+ JFUNCTION(jsonb_patch, 2,1,0, 0,1,0, jsonPatchFunc),
+ JFUNCTION(json_quote, 1,0,1, 1,0,0, jsonQuoteFunc),
+ JFUNCTION(json_remove, -1,1,1, 0,0,0, jsonRemoveFunc),
+ JFUNCTION(jsonb_remove, -1,1,0, 0,1,0, jsonRemoveFunc),
+ JFUNCTION(json_replace, -1,1,1, 1,0,0, jsonReplaceFunc),
+ JFUNCTION(jsonb_replace, -1,1,0, 1,1,0, jsonReplaceFunc),
+ JFUNCTION(json_set, -1,1,1, 1,0,JSON_ISSET, jsonSetFunc),
+ JFUNCTION(jsonb_set, -1,1,0, 1,1,JSON_ISSET, jsonSetFunc),
+ JFUNCTION(json_type, 1,1,0, 0,0,0, jsonTypeFunc),
+ JFUNCTION(json_type, 2,1,0, 0,0,0, jsonTypeFunc),
+ JFUNCTION(json_valid, 1,1,0, 0,0,0, jsonValidFunc),
#if SQLITE_DEBUG
- JFUNCTION(json_parse, 1, 1, 0, 0, 0, jsonParseFunc),
- JFUNCTION(json_test1, 1, 1, 0, 0, 0, jsonTest1Func),
- JFUNCTION(jsonb_test2, 1, 1, 0, 1, 0, jsonbTest2),
+ JFUNCTION(json_parse, 1,1,0, 0,0,0, jsonParseFunc),
+ JFUNCTION(json_test1, 1,1,0, 1,0,0, jsonTest1Func),
+ JFUNCTION(jsonb_test2, 1,1,0, 0,1,0, jsonbTest2),
#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(jsonb_group_array, 1, JSON_BLOB, 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),
WAGGREGATE(jsonb_group_object,2, JSON_BLOB, 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