| 909 | } |
| 910 | |
| 911 | static Node * |
| 912 | convert_testexpr_mutator(Node *node, |
| 913 | convert_testexpr_context *context) |
| 914 | { |
| 915 | if (node == NULL) |
| 916 | return NULL; |
| 917 | if (IsA(node, Param)) |
| 918 | { |
| 919 | Param *param = (Param *) node; |
| 920 | |
| 921 | if (param->paramkind == PARAM_SUBLINK) |
| 922 | { |
| 923 | if (param->paramid <= 0 || |
| 924 | param->paramid > list_length(context->subst_nodes)) |
| 925 | elog(ERROR, "unexpected PARAM_SUBLINK ID: %d", param->paramid); |
| 926 | |
| 927 | /* |
| 928 | * We copy the list item to avoid having doubly-linked |
| 929 | * substructure in the modified parse tree. This is probably |
| 930 | * unnecessary when it's a Param, but be safe. |
| 931 | */ |
| 932 | return (Node *) copyObject(list_nth(context->subst_nodes, |
| 933 | param->paramid - 1)); |
| 934 | } |
| 935 | } |
| 936 | if (IsA(node, SubLink)) |
| 937 | { |
| 938 | /* |
| 939 | * If we come across a nested SubLink, it is neither necessary nor |
| 940 | * correct to recurse into it: any PARAM_SUBLINKs we might find inside |
| 941 | * belong to the inner SubLink not the outer. So just return it as-is. |
| 942 | * |
| 943 | * This reasoning depends on the assumption that nothing will pull |
| 944 | * subexpressions into or out of the testexpr field of a SubLink, at |
| 945 | * least not without replacing PARAM_SUBLINKs first. If we did want |
| 946 | * to do that we'd need to rethink the parser-output representation |
| 947 | * altogether, since currently PARAM_SUBLINKs are only unique per |
| 948 | * SubLink not globally across the query. The whole point of |
| 949 | * replacing them with Vars or PARAM_EXEC nodes is to make them |
| 950 | * globally unique before they escape from the SubLink's testexpr. |
| 951 | * |
| 952 | * Note: this can't happen when called during SS_process_sublinks, |
| 953 | * because that recursively processes inner SubLinks first. It can |
| 954 | * happen when called from convert_ANY_sublink_to_join, though. |
| 955 | */ |
| 956 | return node; |
| 957 | } |
| 958 | return expression_tree_mutator(node, |
| 959 | convert_testexpr_mutator, |
| 960 | (void *) context); |
| 961 | } |
| 962 | |
| 963 | /* |
| 964 | * subplan_is_hashable: can we implement an ANY subplan by hashing? |
no test coverage detected