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

Commitf80872b

Browse files
committed
Remove unnecessary restrictions about RowExprs in transformAExprIn().
When the existing code here was written, it made sense to special-caseRowExprs because that was the only way that we could handle row comparisonsat all. Now that we have record_eq() and arrays of composites, the genericlogic for "scalar" types will in fact work on RowExprs too, so there's noreason to throw error for combinations of RowExprs and other ways offorming composite values, nor to ignore the possibility of using aScalarArrayOpExpr. But keep using the old logic when comparing twoRowExprs, for consistency with the main transformAExprOp() logic. (Thisallows some cases with not-quite-identical rowtypes to succeed, so we mightget push-back if we removed it.) Per bug #8198 from Rafal Rzepecki.Back-patch to all supported branches, since this works fine as far back as8.4.Rafal Rzepecki and Tom Lane
1 parent1476a94 commitf80872b

File tree

3 files changed

+78
-24
lines changed

3 files changed

+78
-24
lines changed

‎src/backend/parser/parse_expr.c‎

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
873873
elseif (lexpr&&IsA(lexpr,RowExpr)&&
874874
rexpr&&IsA(rexpr,RowExpr))
875875
{
876-
/*"row oprow" */
876+
/*ROW() opROW() is handled specially */
877877
lexpr=transformExpr(pstate,lexpr);
878878
rexpr=transformExpr(pstate,rexpr);
879879
Assert(IsA(lexpr,RowExpr));
@@ -978,7 +978,7 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
978978
if (lexpr&&IsA(lexpr,RowExpr)&&
979979
rexpr&&IsA(rexpr,RowExpr))
980980
{
981-
/*"row oprow" */
981+
/*ROW() opROW() is handled specially */
982982
returnmake_row_distinct_op(pstate,a->name,
983983
(RowExpr*)lexpr,
984984
(RowExpr*)rexpr,
@@ -1068,7 +1068,6 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
10681068
List*rvars;
10691069
List*rnonvars;
10701070
booluseOr;
1071-
boolhaveRowExpr;
10721071
ListCell*l;
10731072

10741073
/*
@@ -1081,24 +1080,21 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
10811080

10821081
/*
10831082
* We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
1084-
* possible if the inputs are all scalars (no RowExprs) and there is a
1085-
* suitable array type available. If not, we fall back to a boolean
1086-
* condition tree with multiple copies of the lefthand expression. Also,
1087-
* any IN-list items that contain Vars are handled as separate boolean
1088-
* conditions, because that gives the planner more scope for optimization
1089-
* on such clauses.
1083+
* possible if there is a suitable array type available. If not, we fall
1084+
* back to a boolean condition tree with multiple copies of the lefthand
1085+
* expression.Also, any IN-list items that contain Vars are handled as
1086+
* separate boolean conditions, because that gives the planner more scope
1087+
* for optimization on such clauses.
10901088
*
1091-
* First step: transform all the inputs, and detect whether anyare
1092-
*RowExprs or containVars.
1089+
* First step: transform all the inputs, and detect whether anycontain
1090+
* Vars.
10931091
*/
10941092
lexpr=transformExpr(pstate,a->lexpr);
1095-
haveRowExpr= (lexpr&&IsA(lexpr,RowExpr));
10961093
rexprs=rvars=rnonvars=NIL;
10971094
foreach(l, (List*)a->rexpr)
10981095
{
10991096
Node*rexpr=transformExpr(pstate,lfirst(l));
11001097

1101-
haveRowExpr |= (rexpr&&IsA(rexpr,RowExpr));
11021098
rexprs=lappend(rexprs,rexpr);
11031099
if (contain_vars_of_level(rexpr,0))
11041100
rvars=lappend(rvars,rexpr);
@@ -1108,9 +1104,9 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
11081104

11091105
/*
11101106
* ScalarArrayOpExpr is only going to be useful if there's more than one
1111-
* non-Var righthand item.Also, it won't work for RowExprs.
1107+
* non-Var righthand item.
11121108
*/
1113-
if (!haveRowExpr&&list_length(rnonvars)>1)
1109+
if (list_length(rnonvars)>1)
11141110
{
11151111
List*allexprs;
11161112
Oidscalar_type;
@@ -1126,8 +1122,13 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
11261122
allexprs=list_concat(list_make1(lexpr),rnonvars);
11271123
scalar_type=select_common_type(pstate,allexprs,NULL,NULL);
11281124

1129-
/* Do we have an array type to use? */
1130-
if (OidIsValid(scalar_type))
1125+
/*
1126+
* Do we have an array type to use? Aside from the case where there
1127+
* isn't one, we don't risk using ScalarArrayOpExpr when the common
1128+
* type is RECORD, because the RowExpr comparison logic below can cope
1129+
* with some cases of non-identical row types.
1130+
*/
1131+
if (OidIsValid(scalar_type)&&scalar_type!=RECORDOID)
11311132
array_type=get_array_type(scalar_type);
11321133
else
11331134
array_type=InvalidOid;
@@ -1177,26 +1178,25 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
11771178
Node*rexpr= (Node*)lfirst(l);
11781179
Node*cmp;
11791180

1180-
if (haveRowExpr)
1181+
if (IsA(lexpr,RowExpr)&&
1182+
IsA(rexpr,RowExpr))
11811183
{
1182-
if (!IsA(lexpr,RowExpr)||
1183-
!IsA(rexpr,RowExpr))
1184-
ereport(ERROR,
1185-
(errcode(ERRCODE_SYNTAX_ERROR),
1186-
errmsg("arguments of row IN must all be row expressions"),
1187-
parser_errposition(pstate,a->location)));
1184+
/* ROW() op ROW() is handled specially */
11881185
cmp=make_row_comparison_op(pstate,
11891186
a->name,
11901187
(List*)copyObject(((RowExpr*)lexpr)->args),
11911188
((RowExpr*)rexpr)->args,
11921189
a->location);
11931190
}
11941191
else
1192+
{
1193+
/* Ordinary scalar operator */
11951194
cmp= (Node*)make_op(pstate,
11961195
a->name,
11971196
copyObject(lexpr),
11981197
rexpr,
11991198
a->location);
1199+
}
12001200

12011201
cmp=coerce_to_boolean(pstate,cmp,"IN");
12021202
if (result==NULL)

‎src/test/regress/expected/rowtypes.out‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,25 @@ ERROR: could not determine interpretation of row comparison operator ~~
205205
LINE 1: select ROW('ABC','DEF') ~~ ROW('DEF','ABC') as fail;
206206
^
207207
HINT: Row comparison operators must be associated with btree operator families.
208+
-- Comparisons of ROW() expressions can cope with some type mismatches
209+
select ROW(1,2) = ROW(1,2::int8);
210+
?column?
211+
----------
212+
t
213+
(1 row)
214+
215+
select ROW(1,2) in (ROW(3,4), ROW(1,2));
216+
?column?
217+
----------
218+
t
219+
(1 row)
220+
221+
select ROW(1,2) in (ROW(3,4), ROW(1,2::int8));
222+
?column?
223+
----------
224+
t
225+
(1 row)
226+
208227
-- Check row comparison with a subselect
209228
select unique1, unique2 from tenk1
210229
where (unique1, unique2) < any (select ten, ten from tenk1 where hundred < 3)
@@ -249,6 +268,26 @@ order by thousand, tenthous;
249268
999 | 9999
250269
(25 rows)
251270

271+
-- Check row comparisons with IN
272+
select * from int8_tbl i8 where i8 in (row(123,456)); -- fail, type mismatch
273+
ERROR: cannot compare dissimilar column types bigint and integer at record column 1
274+
explain (costs off)
275+
select * from int8_tbl i8
276+
where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
277+
QUERY PLAN
278+
-------------------------------------------------------------------------------------------------------------
279+
Seq Scan on int8_tbl i8
280+
Filter: (i8.* = ANY (ARRAY[ROW(123::bigint, 456::bigint)::int8_tbl, '(4567890123456789,123)'::int8_tbl]))
281+
(2 rows)
282+
283+
select * from int8_tbl i8
284+
where i8 in (row(123,456)::int8_tbl, '(4567890123456789,123)');
285+
q1 | q2
286+
------------------+-----
287+
123 | 456
288+
4567890123456789 | 123
289+
(2 rows)
290+
252291
-- Check some corner cases involving empty rowtypes
253292
select ROW();
254293
row

‎src/test/regress/sql/rowtypes.sql‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ select ROW('ABC','DEF') ~<=~ ROW('DEF','ABC') as true;
9595
select ROW('ABC','DEF') ~>=~ ROW('DEF','ABC')as false;
9696
select ROW('ABC','DEF') ~~ ROW('DEF','ABC')as fail;
9797

98+
-- Comparisons of ROW() expressions can cope with some type mismatches
99+
select ROW(1,2)= ROW(1,2::int8);
100+
select ROW(1,2)in (ROW(3,4), ROW(1,2));
101+
select ROW(1,2)in (ROW(3,4), ROW(1,2::int8));
102+
98103
-- Check row comparison with a subselect
99104
select unique1, unique2from tenk1
100105
where (unique1, unique2)< any (select ten, tenfrom tenk1where hundred<3)
@@ -106,6 +111,16 @@ select thousand, tenthous from tenk1
106111
where (thousand, tenthous)>= (997,5000)
107112
order by thousand, tenthous;
108113

114+
-- Check row comparisons with IN
115+
select*from int8_tbl i8where i8in (row(123,456));-- fail, type mismatch
116+
117+
explain (costs off)
118+
select*from int8_tbl i8
119+
where i8in (row(123,456)::int8_tbl,'(4567890123456789,123)');
120+
121+
select*from int8_tbl i8
122+
where i8in (row(123,456)::int8_tbl,'(4567890123456789,123)');
123+
109124
-- Check some corner cases involving empty rowtypes
110125
select ROW();
111126
select ROW() ISNULL;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp