@@ -873,7 +873,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
873
873
else if (lexpr && IsA (lexpr , RowExpr ) &&
874
874
rexpr && IsA (rexpr , RowExpr ))
875
875
{
876
- /* "row op row" */
876
+ /* ROW() op ROW() is handled specially */
877
877
lexpr = transformExpr (pstate , lexpr );
878
878
rexpr = transformExpr (pstate , rexpr );
879
879
Assert (IsA (lexpr , RowExpr ));
@@ -978,7 +978,7 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a)
978
978
if (lexpr && IsA (lexpr , RowExpr ) &&
979
979
rexpr && IsA (rexpr , RowExpr ))
980
980
{
981
- /* "row op row" */
981
+ /* ROW() op ROW() is handled specially */
982
982
return make_row_distinct_op (pstate , a -> name ,
983
983
(RowExpr * ) lexpr ,
984
984
(RowExpr * ) rexpr ,
@@ -1068,7 +1068,6 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1068
1068
List * rvars ;
1069
1069
List * rnonvars ;
1070
1070
bool useOr ;
1071
- bool haveRowExpr ;
1072
1071
ListCell * l ;
1073
1072
1074
1073
/*
@@ -1081,24 +1080,21 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1081
1080
1082
1081
/*
1083
1082
* 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.
1090
1088
*
1091
- * First step: transform all the inputs, and detect whether any are
1092
- * RowExprs or contain Vars.
1089
+ * First step: transform all the inputs, and detect whether any contain
1090
+ * Vars.
1093
1091
*/
1094
1092
lexpr = transformExpr (pstate , a -> lexpr );
1095
- haveRowExpr = (lexpr && IsA (lexpr , RowExpr ));
1096
1093
rexprs = rvars = rnonvars = NIL ;
1097
1094
foreach (l , (List * ) a -> rexpr )
1098
1095
{
1099
1096
Node * rexpr = transformExpr (pstate , lfirst (l ));
1100
1097
1101
- haveRowExpr |= (rexpr && IsA (rexpr , RowExpr ));
1102
1098
rexprs = lappend (rexprs , rexpr );
1103
1099
if (contain_vars_of_level (rexpr , 0 ))
1104
1100
rvars = lappend (rvars , rexpr );
@@ -1108,9 +1104,9 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1108
1104
1109
1105
/*
1110
1106
* 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.
1112
1108
*/
1113
- if (! haveRowExpr && list_length (rnonvars ) > 1 )
1109
+ if (list_length (rnonvars ) > 1 )
1114
1110
{
1115
1111
List * allexprs ;
1116
1112
Oid scalar_type ;
@@ -1126,8 +1122,13 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1126
1122
allexprs = list_concat (list_make1 (lexpr ), rnonvars );
1127
1123
scalar_type = select_common_type (pstate , allexprs , NULL , NULL );
1128
1124
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 )
1131
1132
array_type = get_array_type (scalar_type );
1132
1133
else
1133
1134
array_type = InvalidOid ;
@@ -1177,26 +1178,25 @@ transformAExprIn(ParseState *pstate, A_Expr *a)
1177
1178
Node * rexpr = (Node * ) lfirst (l );
1178
1179
Node * cmp ;
1179
1180
1180
- if (haveRowExpr )
1181
+ if (IsA (lexpr , RowExpr ) &&
1182
+ IsA (rexpr , RowExpr ))
1181
1183
{
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 */
1188
1185
cmp = make_row_comparison_op (pstate ,
1189
1186
a -> name ,
1190
1187
(List * ) copyObject (((RowExpr * ) lexpr )-> args ),
1191
1188
((RowExpr * ) rexpr )-> args ,
1192
1189
a -> location );
1193
1190
}
1194
1191
else
1192
+ {
1193
+ /* Ordinary scalar operator */
1195
1194
cmp = (Node * ) make_op (pstate ,
1196
1195
a -> name ,
1197
1196
copyObject (lexpr ),
1198
1197
rexpr ,
1199
1198
a -> location );
1199
+ }
1200
1200
1201
1201
cmp = coerce_to_boolean (pstate , cmp , "IN" );
1202
1202
if (result == NULL )
0 commit comments