@@ -879,7 +879,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
879
879
else if (lexpr && IsA (lexpr , RowExpr ) &&
880
880
rexpr && IsA (rexpr , RowExpr ))
881
881
{
882
- /* "row op row" */
882
+ /* ROW() op ROW() is handled specially */
883
883
lexpr = transformExpr (pstate , lexpr );
884
884
rexpr = transformExpr (pstate , rexpr );
885
885
Assert (IsA (lexpr , RowExpr ));
@@ -984,7 +984,7 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
984
984
if (lexpr && IsA (lexpr , RowExpr ) &&
985
985
rexpr && IsA (rexpr , RowExpr ))
986
986
{
987
- /* "row op row" */
987
+ /* ROW() op ROW() is handled specially */
988
988
return make_row_distinct_op (pstate , a -> name ,
989
989
(RowExpr * ) lexpr ,
990
990
(RowExpr * ) rexpr ,
@@ -1083,7 +1083,6 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1083
1083
List * rvars ;
1084
1084
List * rnonvars ;
1085
1085
bool useOr ;
1086
- bool haveRowExpr ;
1087
1086
ListCell * l ;
1088
1087
1089
1088
/*
@@ -1096,24 +1095,21 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1096
1095
1097
1096
/*
1098
1097
* 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.
1105
1103
*
1106
- * First step: transform all the inputs, and detect whether any are
1107
- * RowExprs or contain Vars.
1104
+ * First step: transform all the inputs, and detect whether any contain
1105
+ * Vars.
1108
1106
*/
1109
1107
lexpr = transformExpr (pstate , a -> lexpr );
1110
- haveRowExpr = (lexpr && IsA (lexpr , RowExpr ));
1111
1108
rexprs = rvars = rnonvars = NIL ;
1112
1109
foreach (l , (List * ) a -> rexpr )
1113
1110
{
1114
1111
Node * rexpr = transformExpr (pstate , lfirst (l ));
1115
1112
1116
- haveRowExpr |= (rexpr && IsA (rexpr , RowExpr ));
1117
1113
rexprs = lappend (rexprs , rexpr );
1118
1114
if (contain_vars_of_level (rexpr , 0 ))
1119
1115
rvars = lappend (rvars , rexpr );
@@ -1123,9 +1119,9 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1123
1119
1124
1120
/*
1125
1121
* 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.
1127
1123
*/
1128
- if (! haveRowExpr && list_length (rnonvars ) > 1 )
1124
+ if (list_length (rnonvars ) > 1 )
1129
1125
{
1130
1126
List * allexprs ;
1131
1127
Oid scalar_type ;
@@ -1141,8 +1137,13 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1141
1137
allexprs = list_concat (list_make1 (lexpr ), rnonvars );
1142
1138
scalar_type = select_common_type (pstate , allexprs , NULL , NULL );
1143
1139
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 )
1146
1147
array_type = get_array_type (scalar_type );
1147
1148
else
1148
1149
array_type = InvalidOid ;
@@ -1193,26 +1194,25 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1193
1194
Node * rexpr = (Node * ) lfirst (l );
1194
1195
Node * cmp ;
1195
1196
1196
- if (haveRowExpr )
1197
+ if (IsA (lexpr , RowExpr ) &&
1198
+ IsA (rexpr , RowExpr ))
1197
1199
{
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 */
1204
1201
cmp = make_row_comparison_op (pstate ,
1205
1202
a -> name ,
1206
1203
(List * ) copyObject (((RowExpr * ) lexpr )-> args ),
1207
1204
((RowExpr * ) rexpr )-> args ,
1208
1205
a -> location );
1209
1206
}
1210
1207
else
1208
+ {
1209
+ /* Ordinary scalar operator */
1211
1210
cmp = (Node * ) make_op (pstate ,
1212
1211
a -> name ,
1213
1212
copyObject (lexpr ),
1214
1213
rexpr ,
1215
1214
a -> location );
1215
+ }
1216
1216
1217
1217
cmp = coerce_to_boolean (pstate , cmp , "IN" );
1218
1218
if (result == NULL )
0 commit comments