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

Commita2c2336

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 parentaee8a60 commita2c2336

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
@@ -879,7 +879,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
879879
elseif (lexpr&&IsA(lexpr,RowExpr)&&
880880
rexpr&&IsA(rexpr,RowExpr))
881881
{
882-
/*"row oprow" */
882+
/*ROW() opROW() is handled specially */
883883
lexpr=transformExpr(pstate,lexpr);
884884
rexpr=transformExpr(pstate,rexpr);
885885
Assert(IsA(lexpr,RowExpr));
@@ -984,7 +984,7 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
984984
if (lexpr&&IsA(lexpr,RowExpr)&&
985985
rexpr&&IsA(rexpr,RowExpr))
986986
{
987-
/*"row oprow" */
987+
/*ROW() opROW() is handled specially */
988988
returnmake_row_distinct_op(pstate,a->name,
989989
(RowExpr*)lexpr,
990990
(RowExpr*)rexpr,
@@ -1083,7 +1083,6 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
10831083
List*rvars;
10841084
List*rnonvars;
10851085
booluseOr;
1086-
boolhaveRowExpr;
10871086
ListCell*l;
10881087

10891088
/*
@@ -1096,24 +1095,21 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
10961095

10971096
/*
10981097
* We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only
1099-
* possible if the inputs are all scalars (no RowExprs) and there is a
1100-
* suitable array type available. If not, we fall back to a boolean
1101-
* condition tree with multiple copies of the lefthand expression. Also,
1102-
* any IN-list items that contain Vars are handled as separate boolean
1103-
* conditions, because that gives the planner more scope for optimization
1104-
* on such clauses.
1098+
* possible if there is a suitable array type available. If not, we fall
1099+
* back to a boolean condition tree with multiple copies of the lefthand
1100+
* expression.Also, any IN-list items that contain Vars are handled as
1101+
* separate boolean conditions, because that gives the planner more scope
1102+
* for optimization on such clauses.
11051103
*
1106-
* First step: transform all the inputs, and detect whether anyare
1107-
*RowExprs or containVars.
1104+
* First step: transform all the inputs, and detect whether anycontain
1105+
* Vars.
11081106
*/
11091107
lexpr=transformExpr(pstate,a->lexpr);
1110-
haveRowExpr= (lexpr&&IsA(lexpr,RowExpr));
11111108
rexprs=rvars=rnonvars=NIL;
11121109
foreach(l, (List*)a->rexpr)
11131110
{
11141111
Node*rexpr=transformExpr(pstate,lfirst(l));
11151112

1116-
haveRowExpr |= (rexpr&&IsA(rexpr,RowExpr));
11171113
rexprs=lappend(rexprs,rexpr);
11181114
if (contain_vars_of_level(rexpr,0))
11191115
rvars=lappend(rvars,rexpr);
@@ -1123,9 +1119,9 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
11231119

11241120
/*
11251121
* ScalarArrayOpExpr is only going to be useful if there's more than one
1126-
* non-Var righthand item.Also, it won't work for RowExprs.
1122+
* non-Var righthand item.
11271123
*/
1128-
if (!haveRowExpr&&list_length(rnonvars)>1)
1124+
if (list_length(rnonvars)>1)
11291125
{
11301126
List*allexprs;
11311127
Oidscalar_type;
@@ -1141,8 +1137,13 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
11411137
allexprs=list_concat(list_make1(lexpr),rnonvars);
11421138
scalar_type=select_common_type(pstate,allexprs,NULL,NULL);
11431139

1144-
/* Do we have an array type to use? */
1145-
if (OidIsValid(scalar_type))
1140+
/*
1141+
* Do we have an array type to use? Aside from the case where there
1142+
* isn't one, we don't risk using ScalarArrayOpExpr when the common
1143+
* type is RECORD, because the RowExpr comparison logic below can cope
1144+
* with some cases of non-identical row types.
1145+
*/
1146+
if (OidIsValid(scalar_type)&&scalar_type!=RECORDOID)
11461147
array_type=get_array_type(scalar_type);
11471148
else
11481149
array_type=InvalidOid;
@@ -1193,26 +1194,25 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
11931194
Node*rexpr= (Node*)lfirst(l);
11941195
Node*cmp;
11951196

1196-
if (haveRowExpr)
1197+
if (IsA(lexpr,RowExpr)&&
1198+
IsA(rexpr,RowExpr))
11971199
{
1198-
if (!IsA(lexpr,RowExpr)||
1199-
!IsA(rexpr,RowExpr))
1200-
ereport(ERROR,
1201-
(errcode(ERRCODE_SYNTAX_ERROR),
1202-
errmsg("arguments of row IN must all be row expressions"),
1203-
parser_errposition(pstate,a->location)));
1200+
/* ROW() op ROW() is handled specially */
12041201
cmp=make_row_comparison_op(pstate,
12051202
a->name,
12061203
(List*)copyObject(((RowExpr*)lexpr)->args),
12071204
((RowExpr*)rexpr)->args,
12081205
a->location);
12091206
}
12101207
else
1208+
{
1209+
/* Ordinary scalar operator */
12111210
cmp= (Node*)make_op(pstate,
12121211
a->name,
12131212
copyObject(lexpr),
12141213
rexpr,
12151214
a->location);
1215+
}
12161216

12171217
cmp=coerce_to_boolean(pstate,cmp,"IN");
12181218
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