|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.207 2006/01/31 21:39:24 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.208 2006/02/06 22:21:12 tgl Exp $ |
12 | 12 | *
|
13 | 13 | * HISTORY
|
14 | 14 | * AUTHOR DATE MAJOR EVENT
|
@@ -70,6 +70,7 @@ static bool contain_mutable_functions_walker(Node *node, void *context);
|
70 | 70 | static bool contain_volatile_functions_walker(Node *node, void *context);
|
71 | 71 | static bool contain_nonstrict_functions_walker(Node *node, void *context);
|
72 | 72 | static Relids find_nonnullable_rels_walker(Node *node, bool top_level);
|
| 73 | +static bool is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK); |
73 | 74 | static bool set_coercionform_dontcare_walker(Node *node, void *context);
|
74 | 75 | static Node *eval_const_expressions_mutator(Node *node,
|
75 | 76 | eval_const_expressions_context *context);
|
@@ -816,8 +817,11 @@ contain_nonstrict_functions_walker(Node *node, void *context)
|
816 | 817 | }
|
817 | 818 | if (IsA(node, ScalarArrayOpExpr))
|
818 | 819 | {
|
819 |
| - /* inherently non-strict, consider null scalar and empty array */ |
820 |
| - return true; |
| 820 | + ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; |
| 821 | + |
| 822 | + if (!is_strict_saop(expr, false)) |
| 823 | + return true; |
| 824 | + /* else fall through to check args */ |
821 | 825 | }
|
822 | 826 | if (IsA(node, BoolExpr))
|
823 | 827 | {
|
@@ -937,10 +941,9 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
|
937 | 941 | }
|
938 | 942 | else if (IsA(node, ScalarArrayOpExpr))
|
939 | 943 | {
|
940 |
| - /* Strict if it's "foo op ANY array" and op is strict */ |
941 | 944 | ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node;
|
942 | 945 |
|
943 |
| - if (expr->useOr && op_strict(expr->opno)) |
| 946 | + if (is_strict_saop(expr, true)) |
944 | 947 | result = find_nonnullable_rels_walker((Node *) expr->args, false);
|
945 | 948 | }
|
946 | 949 | else if (IsA(node, BoolExpr))
|
@@ -991,6 +994,57 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
|
991 | 994 | return result;
|
992 | 995 | }
|
993 | 996 |
|
| 997 | +/* |
| 998 | + * Can we treat a ScalarArrayOpExpr as strict? |
| 999 | + * |
| 1000 | + * If "falseOK" is true, then a "false" result can be considered strict, |
| 1001 | + * else we need to guarantee an actual NULL result for NULL input. |
| 1002 | + * |
| 1003 | + * "foo op ALL array" is strict if the op is strict *and* we can prove |
| 1004 | + * that the array input isn't an empty array. We can check that |
| 1005 | + * for the cases of an array constant and an ARRAY[] construct. |
| 1006 | + * |
| 1007 | + * "foo op ANY array" is strict in the falseOK sense if the op is strict. |
| 1008 | + * If not falseOK, the test is the same as for "foo op ALL array". |
| 1009 | + */ |
| 1010 | +static bool |
| 1011 | +is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK) |
| 1012 | +{ |
| 1013 | + Node *rightop; |
| 1014 | + |
| 1015 | + /* The contained operator must be strict. */ |
| 1016 | + if (!op_strict(expr->opno)) |
| 1017 | + return false; |
| 1018 | + /* If ANY and falseOK, that's all we need to check. */ |
| 1019 | + if (expr->useOr && falseOK) |
| 1020 | + return true; |
| 1021 | + /* Else, we have to see if the array is provably non-empty. */ |
| 1022 | + Assert(list_length(expr->args) == 2); |
| 1023 | + rightop = (Node *) lsecond(expr->args); |
| 1024 | + if (rightop && IsA(rightop, Const)) |
| 1025 | + { |
| 1026 | + Datum arraydatum = ((Const *) rightop)->constvalue; |
| 1027 | + bool arrayisnull = ((Const *) rightop)->constisnull; |
| 1028 | + ArrayType *arrayval; |
| 1029 | + int nitems; |
| 1030 | + |
| 1031 | + if (arrayisnull) |
| 1032 | + return false; |
| 1033 | + arrayval = DatumGetArrayTypeP(arraydatum); |
| 1034 | + nitems = ArrayGetNItems(ARR_NDIM(arrayval), ARR_DIMS(arrayval)); |
| 1035 | + if (nitems > 0) |
| 1036 | + return true; |
| 1037 | + } |
| 1038 | + else if (rightop && IsA(rightop, ArrayExpr)) |
| 1039 | + { |
| 1040 | + ArrayExpr *arrayexpr = (ArrayExpr *) rightop; |
| 1041 | + |
| 1042 | + if (arrayexpr->elements != NIL && !arrayexpr->multidims) |
| 1043 | + return true; |
| 1044 | + } |
| 1045 | + return false; |
| 1046 | +} |
| 1047 | + |
994 | 1048 |
|
995 | 1049 | /*****************************************************************************
|
996 | 1050 | * Check for "pseudo-constant" clauses
|
|
0 commit comments