* Transform a "row compare-op row" construct * * The inputs are lists of already-transformed expressions. * As with coerce_type, pstate may be NULL if no special unknown-Param * processing is wanted. * * The output may be a single OpExpr, an AND or OR combination of OpExprs, * or a RowCompareExpr. In all cases it is guaranteed to return boolean. * The AND, OR, and RowCompareExpr cases fur
| 2866 | * behavior of the operators (ie, they behave as =, <>, or < <= > >=). |
| 2867 | */ |
| 2868 | static Node * |
| 2869 | make_row_comparison_op(ParseState *pstate, List *opname, |
| 2870 | List *largs, List *rargs, int location) |
| 2871 | { |
| 2872 | RowCompareExpr *rcexpr; |
| 2873 | RowCompareType rctype; |
| 2874 | List *opexprs; |
| 2875 | List *opnos; |
| 2876 | List *opfamilies; |
| 2877 | ListCell *l, |
| 2878 | *r; |
| 2879 | List **opinfo_lists; |
| 2880 | Bitmapset *strats; |
| 2881 | int nopers; |
| 2882 | int i; |
| 2883 | |
| 2884 | nopers = list_length(largs); |
| 2885 | if (nopers != list_length(rargs)) |
| 2886 | ereport(ERROR, |
| 2887 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 2888 | errmsg("unequal number of entries in row expressions"), |
| 2889 | parser_errposition(pstate, location))); |
| 2890 | |
| 2891 | /* |
| 2892 | * We can't compare zero-length rows because there is no principled basis |
| 2893 | * for figuring out what the operator is. |
| 2894 | */ |
| 2895 | if (nopers == 0) |
| 2896 | ereport(ERROR, |
| 2897 | (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 2898 | errmsg("cannot compare rows of zero length"), |
| 2899 | parser_errposition(pstate, location))); |
| 2900 | |
| 2901 | /* |
| 2902 | * Identify all the pairwise operators, using make_op so that behavior is |
| 2903 | * the same as in the simple scalar case. |
| 2904 | */ |
| 2905 | opexprs = NIL; |
| 2906 | forboth(l, largs, r, rargs) |
| 2907 | { |
| 2908 | Node *larg = (Node *) lfirst(l); |
| 2909 | Node *rarg = (Node *) lfirst(r); |
| 2910 | OpExpr *cmp; |
| 2911 | |
| 2912 | cmp = castNode(OpExpr, make_op(pstate, opname, larg, rarg, |
| 2913 | pstate->p_last_srf, location)); |
| 2914 | |
| 2915 | /* |
| 2916 | * We don't use coerce_to_boolean here because we insist on the |
| 2917 | * operator yielding boolean directly, not via coercion. If it |
| 2918 | * doesn't yield bool it won't be in any index opfamilies... |
| 2919 | */ |
| 2920 | if (cmp->opresulttype != BOOLOID) |
| 2921 | ereport(ERROR, |
| 2922 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
| 2923 | errmsg("row comparison operator must yield type boolean, " |
| 2924 | "not type %s", |
| 2925 | format_type_be(cmp->opresulttype)), |
no test coverage detected