|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.207 2006/01/3121: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 | * AUTHORDATEMAJOR EVENT
|
@@ -70,6 +70,7 @@ static bool contain_mutable_functions_walker(Node *node, void *context);
|
70 | 70 | staticboolcontain_volatile_functions_walker(Node*node,void*context);
|
71 | 71 | staticboolcontain_nonstrict_functions_walker(Node*node,void*context);
|
72 | 72 | staticRelidsfind_nonnullable_rels_walker(Node*node,booltop_level);
|
| 73 | +staticboolis_strict_saop(ScalarArrayOpExpr*expr,boolfalseOK); |
73 | 74 | staticboolset_coercionform_dontcare_walker(Node*node,void*context);
|
74 | 75 | staticNode*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 | elseif (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 | elseif (IsA(node,BoolExpr))
|
@@ -991,6 +994,57 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
|
991 | 994 | returnresult;
|
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 | +staticbool |
| 1011 | +is_strict_saop(ScalarArrayOpExpr*expr,boolfalseOK) |
| 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 | +Datumarraydatum= ((Const*)rightop)->constvalue; |
| 1027 | +boolarrayisnull= ((Const*)rightop)->constisnull; |
| 1028 | +ArrayType*arrayval; |
| 1029 | +intnitems; |
| 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 | +elseif (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
|
|