diff options
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r-- | src/backend/parser/parse_expr.c | 48 |
1 files changed, 24 insertions, 24 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 7f0995fae1f..06f6512c4e4 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -889,7 +889,7 @@ transformAExprOp(ParseState *pstate, A_Expr *a) else if (lexpr && IsA(lexpr, RowExpr) && rexpr && IsA(rexpr, RowExpr)) { - /* "row op row" */ + /* ROW() op ROW() is handled specially */ lexpr = transformExprRecurse(pstate, lexpr); rexpr = transformExprRecurse(pstate, rexpr); Assert(IsA(lexpr, RowExpr)); @@ -994,7 +994,7 @@ transformAExprDistinct(ParseState *pstate, A_Expr *a) if (lexpr && IsA(lexpr, RowExpr) && rexpr && IsA(rexpr, RowExpr)) { - /* "row op row" */ + /* ROW() op ROW() is handled specially */ return make_row_distinct_op(pstate, a->name, (RowExpr *) lexpr, (RowExpr *) rexpr, @@ -1093,7 +1093,6 @@ transformAExprIn(ParseState *pstate, A_Expr *a) List *rvars; List *rnonvars; bool useOr; - bool haveRowExpr; ListCell *l; /* @@ -1106,24 +1105,21 @@ transformAExprIn(ParseState *pstate, A_Expr *a) /* * We try to generate a ScalarArrayOpExpr from IN/NOT IN, but this is only - * possible if the inputs are all scalars (no RowExprs) and there is a - * suitable array type available. If not, we fall back to a boolean - * condition tree with multiple copies of the lefthand expression. Also, - * any IN-list items that contain Vars are handled as separate boolean - * conditions, because that gives the planner more scope for optimization - * on such clauses. + * possible if there is a suitable array type available. If not, we fall + * back to a boolean condition tree with multiple copies of the lefthand + * expression. Also, any IN-list items that contain Vars are handled as + * separate boolean conditions, because that gives the planner more scope + * for optimization on such clauses. * - * First step: transform all the inputs, and detect whether any are - * RowExprs or contain Vars. + * First step: transform all the inputs, and detect whether any contain + * Vars. */ lexpr = transformExprRecurse(pstate, a->lexpr); - haveRowExpr = (lexpr && IsA(lexpr, RowExpr)); rexprs = rvars = rnonvars = NIL; foreach(l, (List *) a->rexpr) { Node *rexpr = transformExprRecurse(pstate, lfirst(l)); - haveRowExpr |= (rexpr && IsA(rexpr, RowExpr)); rexprs = lappend(rexprs, rexpr); if (contain_vars_of_level(rexpr, 0)) rvars = lappend(rvars, rexpr); @@ -1133,9 +1129,9 @@ transformAExprIn(ParseState *pstate, A_Expr *a) /* * ScalarArrayOpExpr is only going to be useful if there's more than one - * non-Var righthand item. Also, it won't work for RowExprs. + * non-Var righthand item. */ - if (!haveRowExpr && list_length(rnonvars) > 1) + if (list_length(rnonvars) > 1) { List *allexprs; Oid scalar_type; @@ -1151,8 +1147,13 @@ transformAExprIn(ParseState *pstate, A_Expr *a) allexprs = list_concat(list_make1(lexpr), rnonvars); scalar_type = select_common_type(pstate, allexprs, NULL, NULL); - /* Do we have an array type to use? */ - if (OidIsValid(scalar_type)) + /* + * Do we have an array type to use? Aside from the case where there + * isn't one, we don't risk using ScalarArrayOpExpr when the common + * type is RECORD, because the RowExpr comparison logic below can cope + * with some cases of non-identical row types. + */ + if (OidIsValid(scalar_type) && scalar_type != RECORDOID) array_type = get_array_type(scalar_type); else array_type = InvalidOid; @@ -1203,14 +1204,10 @@ transformAExprIn(ParseState *pstate, A_Expr *a) Node *rexpr = (Node *) lfirst(l); Node *cmp; - if (haveRowExpr) + if (IsA(lexpr, RowExpr) && + IsA(rexpr, RowExpr)) { - if (!IsA(lexpr, RowExpr) || - !IsA(rexpr, RowExpr)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("arguments of row IN must all be row expressions"), - parser_errposition(pstate, a->location))); + /* ROW() op ROW() is handled specially */ cmp = make_row_comparison_op(pstate, a->name, (List *) copyObject(((RowExpr *) lexpr)->args), @@ -1218,11 +1215,14 @@ transformAExprIn(ParseState *pstate, A_Expr *a) a->location); } else + { + /* Ordinary scalar operator */ cmp = (Node *) make_op(pstate, a->name, copyObject(lexpr), rexpr, a->location); + } cmp = coerce_to_boolean(pstate, cmp, "IN"); if (result == NULL) |