1
0
mirror of https://github.com/postgres/postgres.git synced 2026-01-27 21:43:08 +03:00

Revise APIs for pushJsonbValue() and associated routines.

Instead of passing "JsonbParseState **" to pushJsonbValue(),
pass a pointer to a JsonbInState, which will contain the
parseState stack pointer as well as other useful fields.
Also, instead of returning a JsonbValue pointer that is often
meaningless/ignored, return the top-level JsonbValue pointer
in the "result" field of the JsonbInState.

This involves a lot of (mostly mechanical) edits, but I think
the results are notationally cleaner and easier to understand.
Certainly the business with sometimes capturing the result of
pushJsonbValue() and sometimes not was bug-prone and incapable of
mechanical verification.  In the new arrangement, JsonbInState.result
remains null until we've completed a valid sequence of pushes, so
that an incorrect sequence will result in a null-pointer dereference,
not mistaken use of a partial result.

However, this isn't simply an exercise in prettier notation.
The real reason for doing it is to provide a mechanism whereby
pushJsonbValue() can be told to construct the JsonbValue tree
in a context that is not CurrentMemoryContext.  That happens
when a non-null "outcontext" is specified in the JsonbInState.
No callers exercise that option in this patch, but the next
patch in the series will make use of it.

I tried to improve the comments in this area too.

Author: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: jian he <jian.universality@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/1060917.1753202222@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2025-12-07 11:46:49 -05:00
parent 3628af4210
commit 0986e95161
8 changed files with 528 additions and 422 deletions

View File

@@ -67,8 +67,10 @@ typedef enum
#define JGINFLAG_HASHED 0x10 /* OR'd into flag if value was hashed */
#define JGIN_MAXLENGTH 125 /* max length of text part before hashing */
/* Forward struct references */
typedef struct JsonbPair JsonbPair;
typedef struct JsonbValue JsonbValue;
typedef struct JsonbParseState JsonbParseState;
/*
* Jsonbs are varlena objects, so must meet the varlena convention that the
@@ -315,15 +317,40 @@ struct JsonbPair
uint32 order; /* Pair's index in original sequence */
};
/* Conversion state used when parsing Jsonb from text, or for type coercion */
typedef struct JsonbParseState
/*
* State used while constructing or manipulating a JsonbValue.
* For example, when parsing Jsonb from text, we construct a JsonbValue
* data structure and then flatten that into the Jsonb on-disk format.
* JsonbValues are also useful in aggregation and type coercion.
*
* Callers providing a JsonbInState must initialize it to zeroes/nulls,
* except for optionally setting outcontext (if that's left NULL,
* CurrentMemoryContext is used) and escontext (if that's left NULL,
* parsing errors are thrown via ereport).
*/
typedef struct JsonbInState
{
JsonbValue contVal;
Size size;
struct JsonbParseState *next;
JsonbValue *result; /* The completed value; NULL until complete */
MemoryContext outcontext; /* The context to build it in, or NULL */
struct Node *escontext; /* Optional soft-error-reporting context */
/* Remaining fields should be treated as private to jsonb.c/jsonb_util.c */
JsonbParseState *parseState; /* Stack of parsing contexts */
bool unique_keys; /* Check object key uniqueness */
} JsonbInState;
/*
* Parsing context for one level of Jsonb array or object nesting.
* The contVal will be part of the constructed JsonbValue tree,
* but the other fields are just transient state.
*/
struct JsonbParseState
{
JsonbValue contVal; /* An array or object JsonbValue */
Size size; /* Allocated length of array or object */
JsonbParseState *next; /* Link to next outer level, if any */
bool unique_keys; /* Check object key uniqueness */
bool skip_nulls; /* Skip null object fields */
} JsonbParseState;
};
/*
* JsonbIterator holds details of the type for each iteration. It also stores a
@@ -404,8 +431,8 @@ extern JsonbValue *getKeyJsonValueFromContainer(JsonbContainer *container,
JsonbValue *res);
extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *container,
uint32 i);
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
JsonbIteratorToken seq, JsonbValue *jbval);
extern void pushJsonbValue(JsonbInState *pstate,
JsonbIteratorToken seq, JsonbValue *jbval);
extern JsonbIterator *JsonbIteratorInit(JsonbContainer *container);
extern JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val,
bool skipNested);