Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitef5e60a

Browse files
committed
Fix internal error from CollateExpr in SQL/JSON DEFAULT expressions
SQL/JSON functions such as JSON_VALUE could fail with "unrecognizednode type" errors when a DEFAULT clause contained an explicit COLLATEexpression. That happened because assign_collations_walker() couldinvoke exprSetCollation() on a JsonBehavior expression whose DEFAULTstill contained a CollateExpr, which exprSetCollation() does nothandle.For example: SELECT JSON_VALUE('{"a":1}', '$.c' RETURNING text DEFAULT 'A' COLLATE "C" ON EMPTY);Fix by validating in transformJsonBehavior() that the DEFAULTexpression's collation matches the enclosing JSON expression’scollation. In exprSetCollation(), replace the recursive call on theJsonBehavior expression with an assertion that its collation alreadymatches the target, since the parser now enforces that condition.Reported-by: Jian He <jian.universality@gmail.com>Author: Jian He <jian.universality@gmail.com>Reviewed-by: Amit Langote <amitlangote09@gmail.com>Discussion:https://postgr.es/m/CACJufxHVwYYSyiVQ6o+PsRX6zQ7rAFinh_fv1kCfTsT1xG4Zeg@mail.gmail.comBackpatch-through: 17
1 parenta5a68dd commitef5e60a

File tree

4 files changed

+113
-14
lines changed

4 files changed

+113
-14
lines changed

‎src/backend/nodes/nodeFuncs.c‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,12 +1274,8 @@ exprSetCollation(Node *expr, Oid collation)
12741274
}
12751275
break;
12761276
caseT_JsonBehavior:
1277-
{
1278-
JsonBehavior*behavior= (JsonBehavior*)expr;
1279-
1280-
if (behavior->expr)
1281-
exprSetCollation(behavior->expr,collation);
1282-
}
1277+
Assert(((JsonBehavior*)expr)->expr==NULL||
1278+
exprCollation(((JsonBehavior*)expr)->expr)==collation);
12831279
break;
12841280
caseT_NullTest:
12851281
/* NullTest's result is boolean ... */

‎src/backend/parser/parse_expr.c‎

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ static Node *transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func);
9494
staticvoidtransformJsonPassingArgs(ParseState*pstate,constchar*constructName,
9595
JsonFormatTypeformat,List*args,
9696
List**passing_values,List**passing_names);
97-
staticJsonBehavior*transformJsonBehavior(ParseState*pstate,JsonBehavior*behavior,
97+
staticJsonBehavior*transformJsonBehavior(ParseState*pstate,JsonExpr*jsexpr,
98+
JsonBehavior*behavior,
9899
JsonBehaviorTypedefault_behavior,
99100
JsonReturning*returning);
100101
staticNode*GetJsonBehaviorConst(JsonBehaviorTypebtype,intlocation);
@@ -4529,13 +4530,16 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
45294530
{
45304531
jsexpr->returning->typid=BOOLOID;
45314532
jsexpr->returning->typmod=-1;
4533+
jsexpr->collation=InvalidOid;
45324534
}
45334535

45344536
/* JSON_TABLE() COLUMNS can specify a non-boolean type. */
45354537
if (jsexpr->returning->typid!=BOOLOID)
45364538
jsexpr->use_json_coercion= true;
45374539

4538-
jsexpr->on_error=transformJsonBehavior(pstate,func->on_error,
4540+
jsexpr->on_error=transformJsonBehavior(pstate,
4541+
jsexpr,
4542+
func->on_error,
45394543
JSON_BEHAVIOR_FALSE,
45404544
jsexpr->returning);
45414545
break;
@@ -4550,6 +4554,8 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
45504554
ret->typmod=-1;
45514555
}
45524556

4557+
jsexpr->collation=get_typcollation(jsexpr->returning->typid);
4558+
45534559
/*
45544560
* Keep quotes on scalar strings by default, omitting them only if
45554561
* OMIT QUOTES is specified.
@@ -4566,11 +4572,15 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
45664572
jsexpr->use_json_coercion= true;
45674573

45684574
/* Assume NULL ON EMPTY when ON EMPTY is not specified. */
4569-
jsexpr->on_empty=transformJsonBehavior(pstate,func->on_empty,
4575+
jsexpr->on_empty=transformJsonBehavior(pstate,
4576+
jsexpr,
4577+
func->on_empty,
45704578
JSON_BEHAVIOR_NULL,
45714579
jsexpr->returning);
45724580
/* Assume NULL ON ERROR when ON ERROR is not specified. */
4573-
jsexpr->on_error=transformJsonBehavior(pstate,func->on_error,
4581+
jsexpr->on_error=transformJsonBehavior(pstate,
4582+
jsexpr,
4583+
func->on_error,
45744584
JSON_BEHAVIOR_NULL,
45754585
jsexpr->returning);
45764586
break;
@@ -4582,6 +4592,7 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
45824592
jsexpr->returning->typid=TEXTOID;
45834593
jsexpr->returning->typmod=-1;
45844594
}
4595+
jsexpr->collation=get_typcollation(jsexpr->returning->typid);
45854596

45864597
/*
45874598
* Override whatever transformJsonOutput() set these to, which
@@ -4607,11 +4618,15 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
46074618
}
46084619

46094620
/* Assume NULL ON EMPTY when ON EMPTY is not specified. */
4610-
jsexpr->on_empty=transformJsonBehavior(pstate,func->on_empty,
4621+
jsexpr->on_empty=transformJsonBehavior(pstate,
4622+
jsexpr,
4623+
func->on_empty,
46114624
JSON_BEHAVIOR_NULL,
46124625
jsexpr->returning);
46134626
/* Assume NULL ON ERROR when ON ERROR is not specified. */
4614-
jsexpr->on_error=transformJsonBehavior(pstate,func->on_error,
4627+
jsexpr->on_error=transformJsonBehavior(pstate,
4628+
jsexpr,
4629+
func->on_error,
46154630
JSON_BEHAVIOR_NULL,
46164631
jsexpr->returning);
46174632
break;
@@ -4622,14 +4637,17 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
46224637
jsexpr->returning->typid=exprType(jsexpr->formatted_expr);
46234638
jsexpr->returning->typmod=-1;
46244639
}
4640+
jsexpr->collation=get_typcollation(jsexpr->returning->typid);
46254641

46264642
/*
46274643
* Assume EMPTY ARRAY ON ERROR when ON ERROR is not specified.
46284644
*
46294645
* ON EMPTY cannot be specified at the top level but it can be for
46304646
* the individual columns.
46314647
*/
4632-
jsexpr->on_error=transformJsonBehavior(pstate,func->on_error,
4648+
jsexpr->on_error=transformJsonBehavior(pstate,
4649+
jsexpr,
4650+
func->on_error,
46334651
JSON_BEHAVIOR_EMPTY_ARRAY,
46344652
jsexpr->returning);
46354653
break;
@@ -4705,7 +4723,8 @@ ValidJsonBehaviorDefaultExpr(Node *expr, void *context)
47054723
* Transform a JSON BEHAVIOR clause.
47064724
*/
47074725
staticJsonBehavior*
4708-
transformJsonBehavior(ParseState*pstate,JsonBehavior*behavior,
4726+
transformJsonBehavior(ParseState*pstate,JsonExpr*jsexpr,
4727+
JsonBehavior*behavior,
47094728
JsonBehaviorTypedefault_behavior,
47104729
JsonReturning*returning)
47114730
{
@@ -4720,7 +4739,11 @@ transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior,
47204739
location=behavior->location;
47214740
if (btype==JSON_BEHAVIOR_DEFAULT)
47224741
{
4742+
Oidtargetcoll=jsexpr->collation;
4743+
Oidexprcoll;
4744+
47234745
expr=transformExprRecurse(pstate,behavior->expr);
4746+
47244747
if (!ValidJsonBehaviorDefaultExpr(expr,NULL))
47254748
ereport(ERROR,
47264749
(errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -4736,6 +4759,24 @@ transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior,
47364759
(errcode(ERRCODE_DATATYPE_MISMATCH),
47374760
errmsg("DEFAULT expression must not return a set"),
47384761
parser_errposition(pstate,exprLocation(expr))));
4762+
4763+
/*
4764+
* Reject a DEFAULT expression whose collation differs from the
4765+
* enclosing JSON expression's result collation
4766+
* (jsexpr->collation), as chosen by the RETURNING clause.
4767+
*/
4768+
exprcoll=exprCollation(expr);
4769+
if (!OidIsValid(exprcoll))
4770+
exprcoll=get_typcollation(exprType(expr));
4771+
if (OidIsValid(targetcoll)&&OidIsValid(exprcoll)&&
4772+
targetcoll!=exprcoll)
4773+
ereport(ERROR,
4774+
errcode(ERRCODE_COLLATION_MISMATCH),
4775+
errmsg("the collation of DEFAULT expression conflicts with RETURNING clause"),
4776+
errdetail("\"%s\" versus \"%s\"",
4777+
get_collation_name(exprcoll),
4778+
get_collation_name(targetcoll)),
4779+
parser_errposition(pstate,exprLocation(expr)));
47394780
}
47404781
}
47414782

‎src/test/regress/expected/collate.icu.utf8.out‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2694,6 +2694,55 @@ SELECT * FROM t5 ORDER BY c ASC, a ASC;
26942694
3 | d1 | d1
26952695
(3 rows)
26962696

2697+
-- Check that DEFAULT expressions in SQL/JSON functions use the same collation
2698+
-- as the RETURNING type. Mismatched collations should raise an error.
2699+
CREATE DOMAIN d1 AS text COLLATE case_insensitive;
2700+
CREATE DOMAIN d2 AS text COLLATE "C";
2701+
SELECT JSON_VALUE('{"a": "A"}', '$.a' RETURNING d1 DEFAULT ('C' COLLATE "C") COLLATE case_insensitive ON EMPTY) = 'a'; -- true
2702+
?column?
2703+
----------
2704+
t
2705+
(1 row)
2706+
2707+
SELECT JSON_VALUE('{"a": "A"}', '$.a' RETURNING d1 DEFAULT 'C' ON EMPTY) = 'a'; -- true
2708+
?column?
2709+
----------
2710+
t
2711+
(1 row)
2712+
2713+
SELECT JSON_VALUE('{"a": "A"}', '$.a' RETURNING d1 DEFAULT 'C'::d2 ON EMPTY) = 'a'; -- error
2714+
ERROR: the collation of DEFAULT expression conflicts with RETURNING clause
2715+
LINE 1: ...ON_VALUE('{"a": "A"}', '$.a' RETURNING d1 DEFAULT 'C'::d2 ON...
2716+
^
2717+
DETAIL: "C" versus "case_insensitive"
2718+
SELECT JSON_VALUE('{"a": "A"}', '$.a' RETURNING d1 DEFAULT 'C' COLLATE "C" ON EMPTY) = 'a'; -- error
2719+
ERROR: the collation of DEFAULT expression conflicts with RETURNING clause
2720+
LINE 1: ...ON_VALUE('{"a": "A"}', '$.a' RETURNING d1 DEFAULT 'C' COLLAT...
2721+
^
2722+
DETAIL: "C" versus "case_insensitive"
2723+
SELECT JSON_VALUE('{"a": "A"}', '$.c' RETURNING d1 DEFAULT 'A' ON EMPTY) = 'a'; -- true
2724+
?column?
2725+
----------
2726+
t
2727+
(1 row)
2728+
2729+
SELECT JSON_VALUE('{"a": "A"}', '$.c' RETURNING d1 DEFAULT 'A' COLLATE case_insensitive ON EMPTY) = 'a'; -- true
2730+
?column?
2731+
----------
2732+
t
2733+
(1 row)
2734+
2735+
SELECT JSON_VALUE('{"a": "A"}', '$.c' RETURNING d1 DEFAULT 'A'::d2 ON EMPTY) = 'a'; -- error
2736+
ERROR: the collation of DEFAULT expression conflicts with RETURNING clause
2737+
LINE 1: ...ON_VALUE('{"a": "A"}', '$.c' RETURNING d1 DEFAULT 'A'::d2 ON...
2738+
^
2739+
DETAIL: "C" versus "case_insensitive"
2740+
SELECT JSON_VALUE('{"a": "A"}', '$.c' RETURNING d1 DEFAULT 'A' COLLATE "C" ON EMPTY) = 'a'; -- error
2741+
ERROR: the collation of DEFAULT expression conflicts with RETURNING clause
2742+
LINE 1: ...ON_VALUE('{"a": "A"}', '$.c' RETURNING d1 DEFAULT 'A' COLLAT...
2743+
^
2744+
DETAIL: "C" versus "case_insensitive"
2745+
DROP DOMAIN d1, d2;
26972746
-- cleanup
26982747
RESET search_path;
26992748
SET client_min_messages TO warning;

‎src/test/regress/sql/collate.icu.utf8.sql‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,19 @@ INSERT INTO t5 (a, b) values (1, 'D1'), (2, 'D2'), (3, 'd1');
997997
-- rewriting.)
998998
SELECT*FROM t5ORDER BY cASC, aASC;
999999

1000+
-- Check that DEFAULT expressions in SQL/JSON functions use the same collation
1001+
-- as the RETURNING type. Mismatched collations should raise an error.
1002+
CREATEDOMAINd1AStext COLLATE case_insensitive;
1003+
CREATEDOMAINd2AStext COLLATE"C";
1004+
SELECT JSON_VALUE('{"a": "A"}','$.a' RETURNING d1 DEFAULT ('C' COLLATE"C") COLLATE case_insensitiveON EMPTY)='a';-- true
1005+
SELECT JSON_VALUE('{"a": "A"}','$.a' RETURNING d1 DEFAULT'C'ON EMPTY)='a';-- true
1006+
SELECT JSON_VALUE('{"a": "A"}','$.a' RETURNING d1 DEFAULT'C'::d2ON EMPTY)='a';-- error
1007+
SELECT JSON_VALUE('{"a": "A"}','$.a' RETURNING d1 DEFAULT'C' COLLATE"C"ON EMPTY)='a';-- error
1008+
SELECT JSON_VALUE('{"a": "A"}','$.c' RETURNING d1 DEFAULT'A'ON EMPTY)='a';-- true
1009+
SELECT JSON_VALUE('{"a": "A"}','$.c' RETURNING d1 DEFAULT'A' COLLATE case_insensitiveON EMPTY)='a';-- true
1010+
SELECT JSON_VALUE('{"a": "A"}','$.c' RETURNING d1 DEFAULT'A'::d2ON EMPTY)='a';-- error
1011+
SELECT JSON_VALUE('{"a": "A"}','$.c' RETURNING d1 DEFAULT'A' COLLATE"C"ON EMPTY)='a';-- error
1012+
DROPDOMAIN d1, d2;
10001013

10011014
-- cleanup
10021015
RESET search_path;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp