Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 54c2964

Browse files
feodorNikita Glukhov
authored and
Nikita Glukhov
committed
make beauty
1 parent 60f13d2 commit 54c2964

File tree

2 files changed

+94
-39
lines changed

2 files changed

+94
-39
lines changed

src/backend/utils/adt/jsonpath.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#include "utils/jsonpath.h"
2020

2121
/*****************************INPUT/OUTPUT************************************/
22+
23+
/*
24+
* Convert AST to flat jsonpath type representation
25+
*/
2226
static int
2327
flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
2428
bool forbiddenRoot)
@@ -33,6 +37,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
3337
alignStringInfoInt(buf);
3438

3539
next = (item->next) ? buf->len : 0;
40+
41+
/*
42+
* actual value will be recorded later, after next and
43+
* children processing
44+
*/
3645
appendBinaryStringInfo(buf, (char*)&next /* fake value */, sizeof(next));
3746

3847
switch(item->type)
@@ -84,6 +93,11 @@ flattenJsonPathParseItem(StringInfo buf, JsonPathParseItem *item,
8493

8594
forbiddenRoot = true;
8695
left = buf->len;
96+
97+
/*
98+
* first, reserve place for left/right arg's positions, then
99+
* record both args and sets actual position in reserved places
100+
*/
87101
appendBinaryStringInfo(buf, (char*)&left /* fake value */, sizeof(left));
88102
right = buf->len;
89103
appendBinaryStringInfo(buf, (char*)&right /* fake value */, sizeof(right));
@@ -402,6 +416,10 @@ jsonpath_out(PG_FUNCTION_ARGS)
402416

403417
/********************Support functions for JsonPath****************************/
404418

419+
/*
420+
* Support macroses to read stored values
421+
*/
422+
405423
#define read_byte(v, b, p) do { \
406424
(v) = *(uint8*)((b) + (p)); \
407425
(p) += 1; \
@@ -417,13 +435,19 @@ jsonpath_out(PG_FUNCTION_ARGS)
417435
(p) += sizeof(int32) * (n); \
418436
} while(0) \
419437

438+
/*
439+
* Read root node and fill root node representation
440+
*/
420441
void
421442
jspInit(JsonPathItem *v, JsonPath *js)
422443
{
423444
Assert(js->header == JSONPATH_VERSION);
424445
jspInitByBuffer(v, js->data, 0);
425446
}
426447

448+
/*
449+
* Read node from buffer and fill its representation
450+
*/
427451
void
428452
jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
429453
{

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
#include "postgres.h"
1414
#include "funcapi.h"
1515
#include "miscadmin.h"
16+
#include "catalog/pg_collation.h"
1617
#include "catalog/pg_type.h"
1718
#include "lib/stringinfo.h"
1819
#include "utils/builtins.h"
1920
#include "utils/json.h"
2021
#include "utils/jsonpath.h"
22+
#include "utils/varlena.h"
2123

2224
typedef struct JsonPathExecContext
2325
{
@@ -31,6 +33,9 @@ static JsonPathExecResult recursiveExecute(JsonPathExecContext *cxt,
3133

3234
/********************Execute functions for JsonPath***************************/
3335

36+
/*
37+
* Find value of jsonpath variable in a list of passing params
38+
*/
3439
static void
3540
computeJsonPathVariable(JsonPathItem *variable, List *vars, JsonbValue *value)
3641
{
@@ -132,6 +137,9 @@ computeJsonPathVariable(JsonPathItem *variable, List *vars, JsonbValue *value)
132137
}
133138
}
134139

140+
/*
141+
* Convert jsonpath's scalar or variable node to actual jsonb value
142+
*/
135143
static void
136144
computeJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *value)
137145
{
@@ -161,6 +169,12 @@ computeJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item, JsonbValue *va
161169
}
162170

163171

172+
/*
173+
* Returns jbv* type of of JsonbValue. Note, it never returns
174+
* jbvBinary as is - jbvBinary is used as mark of store naked
175+
* scalar value. To improve readability it defines jbvScalar
176+
* as alias to jbvBinary
177+
*/
164178
#define jbvScalar jbvBinary
165179
static int
166180
JsonbType(JsonbValue *jb)
@@ -196,31 +210,10 @@ compareNumeric(Numeric a, Numeric b)
196210
);
197211
}
198212

199-
static bool
200-
checkScalarEquality(JsonbValue *jb1, JsonbValue *jb2)
201-
{
202-
switch (jb1->type)
203-
{
204-
case jbvNull:
205-
return true;
206-
case jbvString:
207-
return (jb1->val.string.len == jb2->val.string.len &&
208-
memcmp(jb2->val.string.val, jb1->val.string.val,
209-
jb1->val.string.len) == 0);
210-
case jbvBool:
211-
return (jb2->val.boolean == jb1->val.boolean);
212-
case jbvNumeric:
213-
return (compareNumeric(jb1->val.numeric, jb2->val.numeric) == 0);
214-
default:
215-
elog(ERROR,"1Wrong state");
216-
return false;
217-
}
218-
}
219-
220213
static JsonPathExecResult
221214
checkEquality(JsonbValue *jb1, JsonbValue *jb2, bool not)
222215
{
223-
bool eq;
216+
bool eq = false;
224217

225218
if (jb1->type != jb2->type)
226219
{
@@ -232,14 +225,28 @@ checkEquality(JsonbValue *jb1, JsonbValue *jb2, bool not)
232225

233226
if (jb1->type == jbvBinary)
234227
return jperError;
235-
/*
236-
eq = compareJsonbContainers(jb1->val.binary.data,
237-
jb2->val.binary.data) == 0;
238-
*/
239-
else
240-
eq = checkScalarEquality(jb1, jb2);
241228

242-
return !!not ^ !!eq ? jperOk : jperNotFound;
229+
switch (jb1->type)
230+
{
231+
case jbvNull:
232+
eq = true;
233+
break;
234+
case jbvString:
235+
eq = (jb1->val.string.len == jb2->val.string.len &&
236+
memcmp(jb2->val.string.val, jb1->val.string.val,
237+
jb1->val.string.len) == 0);
238+
break;
239+
case jbvBool:
240+
eq = (jb2->val.boolean == jb1->val.boolean);
241+
break;
242+
case jbvNumeric:
243+
eq = (compareNumeric(jb1->val.numeric, jb2->val.numeric) == 0);
244+
break;
245+
default:
246+
elog(ERROR,"1Wrong state");
247+
}
248+
249+
return (not ^ eq) ? jperOk : jperNotFound;
243250
}
244251

245252
static JsonPathExecResult
@@ -261,13 +268,11 @@ makeCompare(int32 op, JsonbValue *jb1, JsonbValue *jb2)
261268
case jbvNumeric:
262269
cmp = compareNumeric(jb1->val.numeric, jb2->val.numeric);
263270
break;
264-
/*
265271
case jbvString:
266272
cmp = varstr_cmp(jb1->val.string.val, jb1->val.string.len,
267273
jb2->val.string.val, jb2->val.string.len,
268-
collationId);
274+
DEFAULT_COLLATION_OID);
269275
break;
270-
*/
271276
default:
272277
return jperError;
273278
}
@@ -524,6 +529,9 @@ executeUnaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
524529
return jper;
525530
}
526531

532+
/*
533+
* implements jpiAny node (** operator)
534+
*/
527535
static JsonPathExecResult
528536
recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
529537
List **found, uint32 level, uint32 first, uint32 last)
@@ -540,6 +548,9 @@ recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
540548

541549
it = JsonbIteratorInit(jb->val.binary.data);
542550

551+
/*
552+
* Recursivly iterate over jsonb objects/arrays
553+
*/
543554
while((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
544555
{
545556
if (r == WJB_KEY)
@@ -582,12 +593,23 @@ recursiveAny(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
582593
return res;
583594
}
584595

596+
/*
597+
* Main executor function: walks on jsonpath structure and tries to find
598+
* correspoding parts of jsonb. Note, jsonb and jsonpath values should be
599+
* avaliable and untoasted during work because JsonPathItem, JsonbValue
600+
* and found could have pointers into input values. If caller wants just to
601+
* check matching of json by jsonpath then it doesn't provide a found arg.
602+
* In this case executor works till first positive result and does not check
603+
* the rest if it is possible. In other case it tries to find all satisfied
604+
* results
605+
*/
585606
static JsonPathExecResult
586607
recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
587608
List **found)
588609
{
589610
JsonPathItem elem;
590611
JsonPathExecResult res = jperNotFound;
612+
bool hasNext;
591613

592614
check_stack_depth();
593615

@@ -599,10 +621,15 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
599621
{
600622
JsonPathExecResult res2;
601623

624+
/*
625+
* SQL/JSON says that we should check second arg
626+
* in case of jperError
627+
*/
628+
602629
jspGetRightArg(jsp, &elem);
603630
res2 = recursiveExecute(cxt, &elem, jb, NULL);
604631

605-
res = res2 == jperOk ? res : res2;
632+
res = (res2 == jperOk) ? res : res2;
606633
}
607634
break;
608635
case jpiOr:
@@ -615,7 +642,7 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
615642
jspGetRightArg(jsp, &elem);
616643
res2 = recursiveExecute(cxt, &elem, jb, NULL);
617644

618-
res = res2 == jperNotFound ? res : res2;
645+
res = (res2 == jperNotFound) ? res : res2;
619646
}
620647
break;
621648
case jpiNot:
@@ -635,7 +662,7 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
635662
case jpiIsUnknown:
636663
jspGetArg(jsp, &elem);
637664
res = recursiveExecute(cxt, &elem, jb, NULL);
638-
res = res == jperError ? jperOk : jperNotFound;
665+
res = (res == jperError) ? jperOk : jperNotFound;
639666
break;
640667
case jpiKey:
641668
if (JsonbType(jb) == jbvObject)
@@ -668,6 +695,7 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
668695
case jpiCurrent:
669696
if (!jspGetNext(jsp, &elem))
670697
{
698+
/* we are last in chain of node */
671699
res = jperOk;
672700
if (found)
673701
{
@@ -677,7 +705,7 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
677705
v = JsonbExtractScalar(jb->val.binary.data,
678706
palloc(sizeof(*v)));
679707
else
680-
v = copyJsonbValue(jb); /* FIXME */
708+
v = copyJsonbValue(jb);
681709

682710
*found = lappend(*found, v);
683711
}
@@ -701,7 +729,6 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
701729
JsonbIterator *it;
702730
int32 r;
703731
JsonbValue v;
704-
bool hasNext;
705732

706733
hasNext = jspGetNext(jsp, &elem);
707734
it = JsonbIteratorInit(jb->val.binary.data);
@@ -738,7 +765,6 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
738765
if (JsonbType(jb) == jbvArray)
739766
{
740767
JsonbValue *v;
741-
bool hasNext;
742768
int i;
743769

744770
hasNext = jspGetNext(jsp, &elem);
@@ -780,7 +806,6 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
780806
JsonbIterator *it;
781807
int32 r;
782808
JsonbValue v;
783-
bool hasNext;
784809

785810
hasNext = jspGetNext(jsp, &elem);
786811
it = JsonbIteratorInit(jb->val.binary.data);
@@ -907,6 +932,9 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
907932
return res;
908933
}
909934

935+
/*
936+
* Public interface to jsonpath executor
937+
*/
910938
JsonPathExecResult
911939
executeJsonPath(JsonPath *path, List *vars, Jsonb *json, List **foundJson)
912940
{
@@ -942,6 +970,9 @@ returnNULL(void *arg, bool *isNull)
942970
return Int32GetDatum(0);
943971
}
944972

973+
/*
974+
* Convert jsonb object into list of vars for executor
975+
*/
945976
static List*
946977
makePassingVars(Jsonb *jb)
947978
{

0 commit comments

Comments
 (0)