Skip to content

Commit b2248ec

Browse files
author
Nikita Glukhov
committed
Add optimization flags to debug functions
1 parent 85c7e1c commit b2248ec

File tree

4 files changed

+120
-69
lines changed

4 files changed

+120
-69
lines changed

jsonb_gin_ops.c

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -765,37 +765,76 @@ gin_extract_jsonb_value_path(PG_FUNCTION_ARGS)
765765
PG_RETURN_POINTER(gin_extract_jsonb_value_path_internal(jb, nentries, NULL));
766766
}
767767

768-
Datum
769-
gin_debug_query_value_path(PG_FUNCTION_ARGS)
768+
static text *
769+
gin_debug_query_internal(FunctionCallInfo fcinfo,
770+
MakeEntryHandler makeHandler,
771+
CheckEntryHandler checkHandler, Pointer extra)
770772
{
771-
JsQuery *jq;
772-
Entries e = {0};
773+
JsQuery *jq = PG_GETARG_JSQUERY(0);
773774
ExtractedNode *root;
774775
char *s;
776+
int optimize = 0;
777+
778+
if (PG_GETARG_BOOL(1))
779+
optimize |= optFlatten;
780+
if (PG_GETARG_BOOL(2))
781+
optimize |= optSimplify;
782+
if (PG_GETARG_BOOL(3))
783+
optimize |= optSelectivity;
775784

776-
jq = PG_GETARG_JSQUERY(0);
777-
root = extractJsQuery(jq, make_value_path_entry_handler,
778-
check_value_path_entry_handler, (Pointer)&e);
785+
root = extractJsQuery(jq, optimize, makeHandler, checkHandler, extra);
779786
s = debugExtractedQuery(root);
780787

781-
PG_RETURN_TEXT_P(cstring_to_text(s));
788+
return cstring_to_text(s);
782789
}
783790

784-
#ifndef NO_JSONPATH
785791
Datum
786-
gin_debug_jsonpath_value_path(PG_FUNCTION_ARGS)
792+
gin_debug_query_value_path(PG_FUNCTION_ARGS)
787793
{
788-
JsonPath *jp;
789794
Entries e = {0};
795+
796+
PG_RETURN_TEXT_P(gin_debug_query_internal(fcinfo,
797+
make_value_path_entry_handler,
798+
check_value_path_entry_handler,
799+
(Pointer) &e));
800+
}
801+
802+
#ifndef NO_JSONPATH
803+
static text *
804+
gin_debug_jsonpath_internal(FunctionCallInfo fcinfo,
805+
bool arrayPathItems,
806+
MakeEntryHandler makeHandler,
807+
CheckEntryHandler checkHandler, Pointer extra)
808+
{
809+
JsonPath *jp = PG_GETARG_JSONPATH_P(0);
790810
ExtractedNode *root;
791811
char *s;
792-
793-
jp = PG_GETARG_JSONPATH_P(0);
794-
root = extractJsonPath(jp, false, false, make_value_path_entry_handler,
795-
check_value_path_entry_handler, (Pointer)&e);
812+
int optimize = 0;
813+
bool exists = PG_GETARG_BOOL(1);
814+
815+
if (PG_GETARG_BOOL(2))
816+
optimize |= optFlatten;
817+
if (PG_GETARG_BOOL(3))
818+
optimize |= optSimplify;
819+
if (PG_GETARG_BOOL(4))
820+
optimize |= optSelectivity;
821+
822+
root = extractJsonPath(jp, exists, arrayPathItems, optimize,
823+
makeHandler, checkHandler, extra);
796824
s = debugExtractedQuery(root);
797825

798-
PG_RETURN_TEXT_P(cstring_to_text(s));
826+
return cstring_to_text(s);
827+
}
828+
829+
Datum
830+
gin_debug_jsonpath_value_path(PG_FUNCTION_ARGS)
831+
{
832+
Entries e = {0};
833+
834+
PG_RETURN_TEXT_P(gin_debug_jsonpath_internal(fcinfo, false,
835+
make_value_path_entry_handler,
836+
check_value_path_entry_handler,
837+
(Pointer) &e));
799838
}
800839
#endif
801840

@@ -843,12 +882,14 @@ gin_extract_jsonb_query_value_path(PG_FUNCTION_ARGS)
843882
root = extractJsonPath(PG_GETARG_JSONPATH_P(0),
844883
strategy == JsonpathExistsStrategyNumber,
845884
false,
885+
optAll,
846886
make_value_path_entry_handler,
847887
check_value_path_entry_handler,
848888
(Pointer)&e);
849889
else
850890
#endif
851891
root = extractJsQuery(PG_GETARG_JSQUERY(0),
892+
optAll,
852893
make_value_path_entry_handler,
853894
check_value_path_entry_handler,
854895
(Pointer)&e);
@@ -1257,21 +1298,16 @@ gin_extract_jsonb_laxpath_value(PG_FUNCTION_ARGS)
12571298
static Datum
12581299
gin_debug_query_path_value_internal(FunctionCallInfo fcinfo, bool lax)
12591300
{
1260-
JsQuery *jq;
12611301
Entries e = {0};
12621302
PathValueExtra extra;
1263-
ExtractedNode *root;
1264-
char *s;
12651303

12661304
extra.entries = &e;
12671305
extra.lax = lax;
12681306

1269-
jq = PG_GETARG_JSQUERY(0);
1270-
root = extractJsQuery(jq, make_path_value_entry_handler,
1271-
check_path_value_entry_handler, (Pointer) &extra);
1272-
s = debugExtractedQuery(root);
1273-
1274-
PG_RETURN_TEXT_P(cstring_to_text(s));
1307+
PG_RETURN_TEXT_P(gin_debug_query_internal(fcinfo,
1308+
make_path_value_entry_handler,
1309+
check_path_value_entry_handler,
1310+
(Pointer) &extra));
12751311
}
12761312

12771313
Datum
@@ -1287,38 +1323,31 @@ gin_debug_query_laxpath_value(PG_FUNCTION_ARGS)
12871323
}
12881324

12891325
#ifndef NO_JSONPATH
1290-
static Datum
1326+
static text *
12911327
gin_debug_jsonpath_path_value_internal(FunctionCallInfo fcinfo, bool lax)
12921328
{
1293-
JsonPath *jp;
12941329
Entries e = {0};
12951330
PathValueExtra extra;
1296-
ExtractedNode *root;
1297-
char *s;
12981331

12991332
extra.entries = &e;
13001333
extra.lax = lax;
13011334

1302-
jp = PG_GETARG_JSONPATH_P(0);
1303-
root = extractJsonPath(jp, false, !lax,
1304-
make_path_value_entry_handler,
1305-
check_path_value_entry_handler,
1306-
(Pointer) &extra);
1307-
s = debugExtractedQuery(root);
1308-
1309-
PG_RETURN_TEXT_P(cstring_to_text(s));
1335+
return gin_debug_jsonpath_internal(fcinfo, !lax,
1336+
make_path_value_entry_handler,
1337+
check_path_value_entry_handler,
1338+
(Pointer) &extra);
13101339
}
13111340

13121341
Datum
13131342
gin_debug_jsonpath_path_value(PG_FUNCTION_ARGS)
13141343
{
1315-
PG_RETURN_DATUM(gin_debug_jsonpath_path_value_internal(fcinfo, false));
1344+
PG_RETURN_TEXT_P(gin_debug_jsonpath_path_value_internal(fcinfo, false));
13161345
}
13171346

13181347
Datum
13191348
gin_debug_jsonpath_laxpath_value(PG_FUNCTION_ARGS)
13201349
{
1321-
PG_RETURN_DATUM(gin_debug_jsonpath_path_value_internal(fcinfo, true));
1350+
PG_RETURN_TEXT_P(gin_debug_jsonpath_path_value_internal(fcinfo, true));
13221351
}
13231352
#endif
13241353

@@ -1355,12 +1384,14 @@ gin_extract_jsonb_query_path_value_internal(FunctionCallInfo fcinfo, bool lax)
13551384
root = extractJsonPath(PG_GETARG_JSONPATH_P(0),
13561385
strategy == JsonpathExistsStrategyNumber,
13571386
!lax,
1387+
optAll,
13581388
make_path_value_entry_handler,
13591389
check_path_value_entry_handler,
13601390
(Pointer) &extra);
13611391
else
13621392
#endif
13631393
root = extractJsQuery(PG_GETARG_JSQUERY(0),
1394+
optAll,
13641395
make_path_value_entry_handler,
13651396
check_path_value_entry_handler,
13661397
(Pointer) &extra);

jsquery--1.1.sql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -315,17 +315,17 @@ CREATE OPERATOR CLASS jsonb_laxpath_value_ops
315315
FUNCTION 6 gin_triconsistent_jsonb_path_value(internal, smallint, anyarray, integer, internal, internal, internal),
316316
STORAGE bytea;
317317

318-
CREATE OR REPLACE FUNCTION gin_debug_query_value_path(jsquery)
318+
CREATE OR REPLACE FUNCTION gin_debug_query_value_path(jsquery, flatten bool = true, simplify bool = true, selectivity bool = true)
319319
RETURNS text
320320
AS 'MODULE_PATHNAME'
321321
LANGUAGE C STRICT IMMUTABLE;
322322

323-
CREATE OR REPLACE FUNCTION gin_debug_query_path_value(jsquery)
323+
CREATE OR REPLACE FUNCTION gin_debug_query_path_value(jsquery, flatten bool = true, simplify bool = true, selectivity bool = true)
324324
RETURNS text
325325
AS 'MODULE_PATHNAME'
326326
LANGUAGE C STRICT IMMUTABLE;
327327

328-
CREATE OR REPLACE FUNCTION gin_debug_query_laxpath_value(jsquery)
328+
CREATE OR REPLACE FUNCTION gin_debug_query_laxpath_value(jsquery, flatten bool = true, simplify bool = true, selectivity bool = true)
329329
RETURNS text
330330
AS 'MODULE_PATHNAME'
331331
LANGUAGE C STRICT IMMUTABLE;
@@ -357,17 +357,17 @@ BEGIN
357357
ALTER OPERATOR FAMILY jsonb_value_path_ops USING gin
358358
ADD OPERATOR 16 @@ (jsonb, jsonpath);
359359

360-
CREATE OR REPLACE FUNCTION gin_debug_jsonpath_value_path(jsonpath)
360+
CREATE OR REPLACE FUNCTION gin_debug_jsonpath_value_path(jsonpath, is_exists bool = false, flatten bool = true, simplify bool = true, selectivity bool = true)
361361
RETURNS text
362362
AS 'MODULE_PATHNAME'
363363
LANGUAGE C STRICT IMMUTABLE;
364364

365-
CREATE OR REPLACE FUNCTION gin_debug_jsonpath_path_value(jsonpath)
365+
CREATE OR REPLACE FUNCTION gin_debug_jsonpath_path_value(jsonpath, is_exists bool = false, flatten bool = true, simplify bool = true, selectivity bool = true)
366366
RETURNS text
367367
AS 'MODULE_PATHNAME'
368368
LANGUAGE C STRICT IMMUTABLE;
369369

370-
CREATE OR REPLACE FUNCTION gin_debug_jsonpath_laxpath_value(jsonpath)
370+
CREATE OR REPLACE FUNCTION gin_debug_jsonpath_laxpath_value(jsonpath, is_exists bool = false, flatten bool = true, simplify bool = true, selectivity bool = true)
371371
RETURNS text
372372
AS 'MODULE_PATHNAME'
373373
LANGUAGE C STRICT IMMUTABLE;

jsquery.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,20 @@ typedef int (*MakeEntryHandler)(ExtractedNode *node, Pointer extra);
242242
typedef bool (*CheckEntryHandler)(ExtractedNode *node, Pointer extra);
243243
bool isLogicalNodeType(ExtractedNodeType type);
244244

245-
ExtractedNode *extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler,
245+
typedef enum
246+
{
247+
optFlatten = 0x01,
248+
optSimplify = 0x02,
249+
optSelectivity = 0x04,
250+
optAll = 0x07
251+
} JsQueryOptFlags;
252+
253+
ExtractedNode *extractJsQuery(JsQuery *jq, int optimize,
254+
MakeEntryHandler makeHandler,
246255
CheckEntryHandler checkHandler, Pointer extra);
247256
#ifndef NO_JSONPATH
248257
ExtractedNode *extractJsonPath(JsonPath *jp, bool exists, bool arrayPathItems,
258+
int optimize,
249259
MakeEntryHandler makeHandler,
250260
CheckEntryHandler checkHandler, Pointer extra);
251261
#endif

jsquery_extract.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static int compareJsQueryItem(JsQueryItem *v1, JsQueryItem *v2);
3333
static void processGroup(ExtractedNode *node, int start, int end);
3434
static void simplifyRecursive(ExtractedNode *node);
3535
static SelectivityClass getScalarSelectivityClass(ExtractedNode *node);
36-
static ExtractedNode *makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra);
36+
static ExtractedNode *makeEntries(ExtractedNode *node, bool skipNonSelective, MakeEntryHandler handler, Pointer extra);
3737
static void setSelectivityClass(ExtractedNode *node, CheckEntryHandler checkHandler, Pointer extra);
3838
static void debugPath(StringInfo buf, PathItem *path);
3939
static void debugValue(StringInfo buf, JsQueryItem *v);
@@ -1204,7 +1204,8 @@ getScalarSelectivityClass(ExtractedNode *node)
12041204
* Make entries for all leaf tree nodes using user-provided handler.
12051205
*/
12061206
static ExtractedNode *
1207-
makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra)
1207+
makeEntries(ExtractedNode *node, bool skipNonSelective,
1208+
MakeEntryHandler handler, Pointer extra)
12081209
{
12091210
if (node->type == eAnd || node->type == eOr)
12101211
{
@@ -1216,11 +1217,12 @@ makeEntries(ExtractedNode *node, MakeEntryHandler handler, Pointer extra)
12161217
if (!child)
12171218
continue;
12181219
/* Skip non-selective AND children */
1219-
if (child->sClass > node->sClass &&
1220+
if (skipNonSelective &&
1221+
child->sClass > node->sClass &&
12201222
node->type == eAnd &&
12211223
!child->forceIndex)
12221224
continue;
1223-
child = makeEntries(child, handler, extra);
1225+
child = makeEntries(child, skipNonSelective, handler, extra);
12241226
if (child)
12251227
{
12261228
node->args.items[j] = child;
@@ -1319,34 +1321,48 @@ setSelectivityClass(ExtractedNode *node, CheckEntryHandler checkHandler,
13191321
}
13201322
}
13211323

1324+
static ExtractedNode *
1325+
emitExtractedQuery(ExtractedNode *root, int optimize,
1326+
MakeEntryHandler makeHandler,
1327+
CheckEntryHandler checkHandler,
1328+
Pointer extra)
1329+
{
1330+
if (!root)
1331+
return NULL;
1332+
1333+
if (optimize & optFlatten)
1334+
flatternTree(root);
1335+
1336+
if (optimize & optSimplify)
1337+
simplifyRecursive(root);
1338+
1339+
setSelectivityClass(root, checkHandler, extra);
1340+
1341+
return makeEntries(root, (optimize & optSelectivity) != 0, makeHandler, extra);
1342+
}
1343+
13221344
/*
13231345
* Turn jsquery into tree of entries using user-provided handler.
13241346
*/
13251347
ExtractedNode *
1326-
extractJsQuery(JsQuery *jq, MakeEntryHandler makeHandler,
1327-
CheckEntryHandler checkHandler, Pointer extra)
1348+
extractJsQuery(JsQuery *jq, int optimize, MakeEntryHandler makeHandler,
1349+
CheckEntryHandler checkHandler, Pointer extra)
13281350
{
13291351
ExtractedNode *root;
13301352
JsQueryItem jsq;
13311353

13321354
jsqInit(&jsq, jq);
13331355
root = recursiveExtract(&jsq, false, false, NULL);
1334-
if (root)
1335-
{
1336-
flatternTree(root);
1337-
simplifyRecursive(root);
1338-
setSelectivityClass(root, checkHandler, extra);
1339-
root = makeEntries(root, makeHandler, extra);
1340-
}
1341-
return root;
1356+
1357+
return emitExtractedQuery(root, optimize, makeHandler, checkHandler, extra);
13421358
}
13431359

13441360
#ifndef NO_JSONPATH
13451361
/*
13461362
* Turn jsonpath into tree of entries using user-provided handler.
13471363
*/
13481364
ExtractedNode *
1349-
extractJsonPath(JsonPath *jp, bool exists, bool arrayPathItems,
1365+
extractJsonPath(JsonPath *jp, bool exists, bool arrayPathItems, int optimize,
13501366
MakeEntryHandler makeHandler,
13511367
CheckEntryHandler checkHandler, Pointer extra)
13521368
{
@@ -1358,14 +1374,8 @@ extractJsonPath(JsonPath *jp, bool exists, bool arrayPathItems,
13581374
root = exists
13591375
? extractJsonPathExists(&jsp, lax, NULL)
13601376
: recursiveExtractJsonPathExpr(&jsp, lax, false, NULL);
1361-
if (root)
1362-
{
1363-
flatternTree(root);
1364-
simplifyRecursive(root);
1365-
setSelectivityClass(root, checkHandler, extra);
1366-
root = makeEntries(root, makeHandler, extra);
1367-
}
1368-
return root;
1377+
1378+
return emitExtractedQuery(root, optimize, makeHandler, checkHandler, extra);
13691379
}
13701380
#endif
13711381

0 commit comments

Comments
 (0)