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

Commit 4e00dd5

Browse files
author
Nikita Glukhov
committed
Improve immutability check for JsonCtorExpr
1 parent 39d0a43 commit 4e00dd5

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
#include "utils/builtins.h"
4949
#include "utils/datum.h"
5050
#include "utils/fmgroids.h"
51+
#include "utils/json.h"
52+
#include "utils/jsonb.h"
5153
#include "utils/lsyscache.h"
5254
#include "utils/memutils.h"
5355
#include "utils/syscache.h"
@@ -665,6 +667,27 @@ contain_mutable_functions_walker(Node *node, void *context)
665667
context))
666668
return true;
667669

670+
if (IsA(node, JsonCtorExpr))
671+
{
672+
JsonCtorExpr *ctor = (JsonCtorExpr *) node;
673+
ListCell *lc;
674+
bool is_jsonb =
675+
ctor->returning->format->format == JS_FORMAT_JSONB;
676+
677+
/* Check argument_type => json[b] conversions */
678+
foreach(lc, ctor->args)
679+
{
680+
Oid typid = exprType(lfirst(lc));
681+
682+
if (is_jsonb ?
683+
!to_jsonb_is_immutable(typid) :
684+
!to_json_is_immutable(typid))
685+
return true;
686+
}
687+
688+
/* Check all subnodes */
689+
}
690+
668691
if (IsA(node, SQLValueFunction))
669692
{
670693
/* all variants of SQLValueFunction are stable */
@@ -677,12 +700,6 @@ contain_mutable_functions_walker(Node *node, void *context)
677700
return true;
678701
}
679702

680-
if (IsA(node, JsonCtorExpr))
681-
{
682-
/* JsonCtorExpr is stable */
683-
return true;
684-
}
685-
686703
/*
687704
* It should be safe to treat MinMaxExpr as immutable, because it will
688705
* depend on a non-cross-type btree comparison function, and those should

src/backend/utils/adt/json.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
*/
1414
#include "postgres.h"
1515

16+
#include "catalog/pg_proc.h"
1617
#include "catalog/pg_type.h"
1718
#include "common/hashfn.h"
1819
#include "funcapi.h"
@@ -760,6 +761,38 @@ row_to_json_pretty(PG_FUNCTION_ARGS)
760761
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
761762
}
762763

764+
bool
765+
to_json_is_immutable(Oid typoid)
766+
{
767+
JsonTypeCategory tcategory;
768+
Oid outfuncoid;
769+
770+
json_categorize_type(typoid, &tcategory, &outfuncoid);
771+
772+
switch (tcategory)
773+
{
774+
case JSONTYPE_BOOL:
775+
case JSONTYPE_JSON:
776+
return true;
777+
778+
case JSONTYPE_DATE:
779+
case JSONTYPE_TIMESTAMP:
780+
case JSONTYPE_TIMESTAMPTZ:
781+
return false;
782+
783+
case JSONTYPE_ARRAY:
784+
return false; /* TODO recurse into elements */
785+
786+
case JSONTYPE_COMPOSITE:
787+
return false; /* TODO recurse into fields */
788+
789+
case JSONTYPE_NUMERIC:
790+
case JSONTYPE_CAST:
791+
default:
792+
return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
793+
}
794+
}
795+
763796
/*
764797
* SQL function to_json(anyvalue)
765798
*/

src/backend/utils/adt/jsonb.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "access/htup_details.h"
1616
#include "access/transam.h"
17+
#include "catalog/pg_proc.h"
1718
#include "catalog/pg_type.h"
1819
#include "funcapi.h"
1920
#include "libpq/pqformat.h"
@@ -1126,6 +1127,39 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
11261127
datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
11271128
}
11281129

1130+
bool
1131+
to_jsonb_is_immutable(Oid typoid)
1132+
{
1133+
JsonbTypeCategory tcategory;
1134+
Oid outfuncoid;
1135+
1136+
jsonb_categorize_type(typoid, &tcategory, &outfuncoid);
1137+
1138+
switch (tcategory)
1139+
{
1140+
case JSONBTYPE_BOOL:
1141+
case JSONBTYPE_JSON:
1142+
case JSONBTYPE_JSONB:
1143+
return true;
1144+
1145+
case JSONBTYPE_DATE:
1146+
case JSONBTYPE_TIMESTAMP:
1147+
case JSONBTYPE_TIMESTAMPTZ:
1148+
return false;
1149+
1150+
case JSONBTYPE_ARRAY:
1151+
return false; /* TODO recurse into elements */
1152+
1153+
case JSONBTYPE_COMPOSITE:
1154+
return false; /* TODO recurse into fields */
1155+
1156+
case JSONBTYPE_NUMERIC:
1157+
case JSONBTYPE_JSONCAST:
1158+
default:
1159+
return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
1160+
}
1161+
}
1162+
11291163
/*
11301164
* SQL function to_jsonb(anyvalue)
11311165
*/

src/include/utils/json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
extern void escape_json(StringInfo buf, const char *str);
2121
extern char *JsonEncodeDateTime(char *buf, Datum value, Oid typid,
2222
const int *tzp);
23+
extern bool to_json_is_immutable(Oid typoid);
2324
extern Datum json_build_object_worker(int nargs, Datum *args, bool *nulls,
2425
Oid *types, bool absent_on_null,
2526
bool unique_keys);

src/include/utils/jsonb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
408408
int estimated_len);
409409
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
410410
extern const char *JsonbTypeName(JsonbValue *jb);
411-
411+
extern bool to_jsonb_is_immutable(Oid typoid);
412412
extern Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls,
413413
Oid *types, bool absent_on_null,
414414
bool unique_keys);

0 commit comments

Comments
 (0)