Skip to content

Commit 6703dff

Browse files
committed
Add more commentaries in core
Move up `jsonb_set_element` close to `jsonb_get_element`
1 parent 3950944 commit 6703dff

File tree

12 files changed

+135
-70
lines changed

12 files changed

+135
-70
lines changed

src/backend/catalog/heap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ AddNewRelationType(const char *typeName,
978978
0, /* array dimensions for typBaseType */
979979
false, /* Type NOT NULL */
980980
InvalidOid, /* rowtypes never have a collation */
981-
InvalidOid);
981+
InvalidOid); /* typsubscription - none */
982982
}
983983

984984
/* --------------------------------
@@ -1246,7 +1246,7 @@ heap_create_with_catalog(const char *relname,
12461246
0, /* array dimensions for typBaseType */
12471247
false, /* Type NOT NULL */
12481248
InvalidOid, /* rowtypes never have a collation */
1249-
F_ARRAY_SUBSCRIPTION);
1249+
F_ARRAY_SUBSCRIPTION); /* array implementation */
12501250

12511251
pfree(relarrayname);
12521252
}

src/backend/commands/typecmds.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ DefineType(List *names, List *parameters)
642642
0, /* Array Dimensions of typbasetype */
643643
false, /* Type NOT NULL */
644644
collation, /* type's collation */
645-
subscriptionOid);
645+
subscriptionOid); /* subscription procedure */
646646
Assert(typoid == address.objectId);
647647

648648
/*
@@ -1075,7 +1075,7 @@ DefineDomain(CreateDomainStmt *stmt)
10751075
typNDims, /* Array dimensions for base type */
10761076
typNotNull, /* Type NOT NULL */
10771077
domaincoll, /* type's collation */
1078-
subscriptionProcedure);
1078+
subscriptionProcedure); /* subscription procedure */
10791079

10801080
/*
10811081
* Process constraints which refer to the domain ID returned by TypeCreate
@@ -1188,7 +1188,7 @@ DefineEnum(CreateEnumStmt *stmt)
11881188
0, /* Array dimensions of typbasetype */
11891189
false, /* Type NOT NULL */
11901190
InvalidOid, /* type's collation */
1191-
InvalidOid);
1191+
InvalidOid); /* typsubscription - none */
11921192

11931193
/* Enter the enum's values into pg_enum */
11941194
EnumValuesCreate(enumTypeAddr.objectId, stmt->vals);
@@ -1229,7 +1229,7 @@ DefineEnum(CreateEnumStmt *stmt)
12291229
0, /* Array dimensions of typbasetype */
12301230
false, /* Type NOT NULL */
12311231
InvalidOid, /* type's collation */
1232-
F_ARRAY_SUBSCRIPTION);
1232+
F_ARRAY_SUBSCRIPTION); /* array subscription implementation */
12331233

12341234
pfree(enumArrayName);
12351235

@@ -1529,7 +1529,7 @@ DefineRange(CreateRangeStmt *stmt)
15291529
0, /* Array dimensions of typbasetype */
15301530
false, /* Type NOT NULL */
15311531
InvalidOid, /* type's collation (ranges never have one) */
1532-
InvalidOid);
1532+
InvalidOid); /* typsubscription - none */
15331533
Assert(typoid == address.objectId);
15341534

15351535
/* Create the entry in pg_range */
@@ -1572,7 +1572,7 @@ DefineRange(CreateRangeStmt *stmt)
15721572
0, /* Array dimensions of typbasetype */
15731573
false, /* Type NOT NULL */
15741574
InvalidOid, /* typcollation */
1575-
F_ARRAY_SUBSCRIPTION);
1575+
F_ARRAY_SUBSCRIPTION); /* array subscription implementation */
15761576

15771577
pfree(rangeArrayName);
15781578

src/backend/executor/execQual.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,12 @@ static Datum ExecEvalGroupingFuncExpr(GroupingFuncExprState *gstate,
253253
/*----------
254254
* ExecEvalSubscriptionRef
255255
*
256-
* This function takes an SubscriptionRef and returns the extracted Datum
257-
* if it's a simple reference, or the modified containers value if it's
258-
* an containers assignment (i.e., containers element or slice insertion).
256+
* This function takes a SubscriptionRef, extracts all information required
257+
* for subscription and pass it to a particular subscription procedure,
258+
* specified for this data type. As a result the extracted Datum will be
259+
* returned if it's a simple reference, or the modified containers value if
260+
* it's an containers assignment (i.e., containers element or slice
261+
* insertion).
259262
*
260263
* NOTE: if we get a NULL result from a subscript expression, we return NULL
261264
* when it's an containers reference, or raise an error when it's an assignment.

src/backend/parser/parse_node.c

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,18 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location)
201201

202202
/* NOTE: extra code for array type with isn't affect on other types
203203
* transformArrayType()
204-
* Identify the types involved in a subscripting operation
204+
* Identify the types involved in a subscripting operation for array
205205
*
206206
* On entry, arrayType/arrayTypmod identify the type of the input value
207207
* to be subscripted (which could be a domain type). These are modified
208208
* if necessary to identify the actual array type and typmod, and the
209209
* array's element type is returned. An error is thrown if the input isn't
210210
* an array type.
211+
*
212+
* NOTE: This part of type-specific code is not separated into type-specific
213+
* subscription procedure for now, but it does not affect on the whole logic,
214+
* since InvalidOid will be return in case of other types not an error.
215+
* An error will appears only if a subscription procedure is not defined.
211216
*/
212217
Oid
213218
transformArrayType(Oid *containerType, int32 *containerTypmod)
@@ -257,29 +262,36 @@ transformArrayType(Oid *containerType, int32 *containerTypmod)
257262
* Transform container subscripting. This is used for both
258263
* container fetch and container assignment.
259264
*
260-
* In a container fetch, we are given a source container value and we produce an
261-
* expression that represents the result of extracting a single container element
262-
* or a container slice.
265+
* In a container fetch, we are given a source container value and we produce
266+
* an expression that represents the result of extracting a single container
267+
* element or a container slice.
263268
*
264269
* In a container assignment, we are given a destination container value plus a
265-
* source value that is to be assigned to a single element or a slice of
266-
* that container. We produce an expression that represents the new container value
270+
* source value that is to be assigned to a single element or a slice of that
271+
* container. We produce an expression that represents the new container value
267272
* with the source data inserted into the right part of the container.
268273
*
269-
* For both cases, if the source container is of a domain-over-container type,
270-
* the result is of the base container type or its element type; essentially,
271-
* we must fold a domain to its base type before applying subscripting.
272-
* (Note that int2vector and oidvector are treated as domains here.)
274+
* For both cases, this function contains only general subscription logic while
275+
* type-specific logic (e.g. type verifications and coersion) is placend in
276+
* separate procedure indicated by typsubscription. There is only one exception
277+
* for now about domain-over-container, if the source container is of a
278+
* domain-over-container type, the result is of the base container type or its
279+
* element type; essentially, we must fold a domain to its base type before
280+
* applying subscripting. (Note that int2vector and oidvector are treated as
281+
* domains here.) If domain verification failed we assume, that element type
282+
* must be the same as container type (e.g. in case of jsonb).
283+
* An error will appear in case if current container type doesn't have a
284+
* subscription procedure.
273285
*
274-
* pstate Parse state
286+
* pstate Parse state
275287
* containerBase Already-transformed expression for the container as a whole
276288
* containerType OID of container's datatype (should match type of containerBase,
277-
* or be the base type of containerBase's domain type)
278-
* elementType OID of container's element type (fetch with transformcontainerType,
279-
* or pass InvalidOid to do it here)
289+
* or be the base type of containerBase's domain type)
290+
* elementType OID of container's element type (fetch with transformArrayType,
291+
* or pass InvalidOid to do it here)
280292
* containerTypMod typmod for the container (which is also typmod for the elements)
281-
* indirection Untransformed list of subscripts (must not be NIL)
282-
* assignFrom NULL for container fetch, else transformed expression for source.
293+
* indirection Untransformed list of subscripts (must not be NIL)
294+
* assignFrom NULL for container fetch, else transformed expression for source.
283295
*/
284296

285297
SubscriptionRef *

src/backend/parser/parse_target.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ transformAssignmentIndirection(ParseState *pstate,
776776
}
777777

778778
/*
779-
* helper for transformAssignmentIndirection: process array assignment
779+
* helper for transformAssignmentIndirection: process container assignment
780780
*/
781781
static Node *
782782
transformAssignmentSubscripts(ParseState *pstate,

src/backend/utils/adt/arrayfuncs.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6561,6 +6561,11 @@ isAssignmentIndirectionExpr(ExprState *exprstate)
65616561
return false;
65626562
}
65636563

6564+
/*
6565+
* Perform an actual data extraction or modification for the array
6566+
* subscription. As a result the extracted Datum or the modified containers
6567+
* value will be returned.
6568+
*/
65646569
Datum
65656570
array_subscription_evaluate(PG_FUNCTION_ARGS)
65666571
{
@@ -6722,6 +6727,13 @@ array_subscription_evaluate(PG_FUNCTION_ARGS)
67226727
sbstate->refelemalign);
67236728
}
67246729

6730+
/*
6731+
* Perform preparation for the array subscription, mostly type verification
6732+
* and coersion. This function produces an expression that represents the
6733+
* result of extracting a single container element/container slice or the new
6734+
* container value with the source data inserted into the right part of the
6735+
* container.
6736+
*/
67256737
Datum
67266738
array_subscription_prepare(PG_FUNCTION_ARGS)
67276739
{
@@ -6860,6 +6872,9 @@ array_subscription_prepare(PG_FUNCTION_ARGS)
68606872
PG_RETURN_POINTER(sbsref);
68616873
}
68626874

6875+
/*
6876+
* Handle array-type subscription logic.
6877+
*/
68636878
Datum
68646879
array_subscription(PG_FUNCTION_ARGS)
68656880
{

src/backend/utils/adt/jsonb.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,11 @@ to_jsonb(PG_FUNCTION_ARGS)
11491149
PG_RETURN_POINTER(JsonbValueToJsonb(res));
11501150
}
11511151

1152+
/*
1153+
* Do the actual conversion to jsonb for to_jsonb function. This logic is
1154+
* separated because it can be useful not only in here (e.g. we use it in
1155+
* jsonb subscription)
1156+
*/
11521157
JsonbValue *
11531158
to_jsonb_worker(Datum source, Oid source_type)
11541159
{

src/backend/utils/adt/jsonfuncs.c

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,32 @@ jsonb_get_element(Jsonb *jb, Datum *path, int npath, bool *isnull, bool as_text)
13651365
}
13661366
}
13671367

1368+
Datum
1369+
jsonb_set_element(Datum jsonbdatum, Datum *path, int path_len,
1370+
Datum sourceData, Oid source_type)
1371+
{
1372+
Jsonb *jb = DatumGetJsonb(jsonbdatum);
1373+
JsonbValue *newval,
1374+
*res;
1375+
JsonbParseState *state = NULL;
1376+
JsonbIterator *it;
1377+
bool *path_nulls = palloc0(path_len * sizeof(bool));
1378+
1379+
newval = to_jsonb_worker(sourceData, source_type);
1380+
1381+
if (newval->type == jbvArray && newval->val.array.rawScalar)
1382+
*newval = newval->val.array.elems[0];
1383+
1384+
it = JsonbIteratorInit(&jb->root);
1385+
1386+
res = setPath(&it, path, path_nulls, path_len, &state, 0,
1387+
newval, JB_PATH_CREATE);
1388+
1389+
pfree(path_nulls);
1390+
1391+
PG_RETURN_JSONB(JsonbValueToJsonb(res));
1392+
}
1393+
13681394
/*
13691395
* SQL function json_array_length(json) -> int
13701396
*/
@@ -4033,12 +4059,17 @@ setPathArray(JsonbIterator **it, Datum *path_elems, bool *path_nulls,
40334059
if (op_type & JB_PATH_CREATE_OR_INSERT && !done &&
40344060
level == path_len - 1 && i == nelems - 1)
40354061
{
4036-
(void) pushJsonbValue(st, WJB_ELEM, newval);
4062+
(void) pushJsonbValue(st, WJB_ELEM, new);
40374063
}
40384064
}
40394065
}
40404066
}
40414067

4068+
/*
4069+
* Perform an actual data extraction or modification for the jsonb
4070+
* subscription. As a result the extracted Datum or the modified containers
4071+
* value will be returned.
4072+
*/
40424073
Datum
40434074
jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
40444075
{
@@ -4120,6 +4151,14 @@ jsonb_subscription_evaluate(PG_FUNCTION_ARGS)
41204151
false);
41214152
}
41224153

4154+
/*
4155+
* Perform preparation for the jsonb subscription. Since there are not any
4156+
* particular restrictions for this kind of subscription, we will verify that
4157+
* it is not a slice operation. This function produces an expression that
4158+
* represents the result of extracting a single container element or the new
4159+
* container value with the source data inserted into the right part of the
4160+
* container.
4161+
*/
41234162
Datum
41244163
jsonb_subscription_prepare(PG_FUNCTION_ARGS)
41254164
{
@@ -4168,6 +4207,9 @@ jsonb_subscription_prepare(PG_FUNCTION_ARGS)
41684207
PG_RETURN_POINTER(sbsref);
41694208
}
41704209

4210+
/*
4211+
* Handle jsonb-type subscription logic.
4212+
*/
41714213
Datum
41724214
jsonb_subscription(PG_FUNCTION_ARGS)
41734215
{
@@ -4183,29 +4225,3 @@ jsonb_subscription(PG_FUNCTION_ARGS)
41834225

41844226
elog(ERROR, "incorrect op_type for subscription function: %d", op_type);
41854227
}
4186-
4187-
Datum
4188-
jsonb_set_element(Datum jsonbdatum, Datum *path, int path_len,
4189-
Datum sourceData, Oid source_type)
4190-
{
4191-
Jsonb *jb = DatumGetJsonb(jsonbdatum);
4192-
JsonbValue *newval,
4193-
*res;
4194-
JsonbParseState *state = NULL;
4195-
JsonbIterator *it;
4196-
bool *path_nulls = palloc0(path_len * sizeof(bool));
4197-
4198-
newval = to_jsonb_worker(sourceData, source_type);
4199-
4200-
if (newval->type == jbvArray && newval->val.array.rawScalar)
4201-
*newval = newval->val.array.elems[0];
4202-
4203-
it = JsonbIteratorInit(&jb->root);
4204-
4205-
res = setPath(&it, path, path_nulls, path_len, &state, 0,
4206-
newval, JB_PATH_CREATE);
4207-
4208-
pfree(path_nulls);
4209-
4210-
PG_RETURN_JSONB(JsonbValueToJsonb(res));
4211-
}

src/include/catalog/pg_type.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
198198
* collatable base types, possibly other OID for domains
199199
*/
200200
Oid typcollation;
201+
202+
/*
203+
* Type specific subscription logic. If typsubscription is none, it means
204+
* that this type doesn't support subscription.
205+
*/
201206
regproc typsubscription;
202207

203208
#ifdef CATALOG_VARLEN /* variable-length fields start here */
@@ -224,7 +229,6 @@ CATALOG(pg_type,1247) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71) BKI_SCHEMA_MACRO
224229
*/
225230
aclitem typacl[1];
226231
#endif
227-
228232
} FormData_pg_type;
229233

230234
/* ----------------

src/include/nodes/execnodes.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,12 +657,21 @@ typedef struct SubscriptionRefExprState
657657
List *reflowerindexpr;
658658
ExprState *refexpr;
659659
ExprState *refassgnexpr;
660-
int16 refattrlength; /* typlen of array type */
661-
int16 refelemlength; /* typlen of the array element type */
660+
int16 refattrlength; /* typlen of container type */
661+
int16 refelemlength; /* typlen of the container element type */
662662
bool refelembyval; /* is the element type pass-by-value? */
663663
char refelemalign; /* typalign of the element type */
664664
} SubscriptionRefExprState;
665665

666+
/* ---------------------------------
667+
* Subscription exec information
668+
*
669+
* It contains all information which is required to perform type-specific data
670+
* extraction or modification. This information will be gathered in
671+
* `ExecEvalSubscriptionRef` function and passed to `typsubscription`
672+
* procedure.
673+
* ---------------------------------
674+
*/
666675
typedef struct SubscriptionExecData
667676
{
668677
ExprContext *xprcontext; /* econtext for subscription */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy