tree_walker_callback that recursively checks if all field paths in the tree are covered by the index. * Returns true to exit early if any uncovered path is found. */
| 2132 | /* tree_walker_callback that recursively checks if all field paths in the tree are covered by the index. |
| 2133 | * Returns true to exit early if any uncovered path is found. */ |
| 2134 | static bool |
| 2135 | CheckFieldCoverage(Node *node, void *context) |
| 2136 | { |
| 2137 | check_stack_depth(); |
| 2138 | CHECK_FOR_INTERRUPTS(); |
| 2139 | |
| 2140 | FieldCoverageState *state = (FieldCoverageState *) context; |
| 2141 | |
| 2142 | if (node == NULL) |
| 2143 | { |
| 2144 | return false; |
| 2145 | } |
| 2146 | |
| 2147 | /* We need to check Aggrefs in addition to functions because they may have a field path directly under the Aggref, not inside a FuncExpr. */ |
| 2148 | if (IsA(node, Aggref)) |
| 2149 | { |
| 2150 | /* There are two shapes of aggregates: |
| 2151 | * 1. The child node is a FuncExpr |
| 2152 | * 2. The field path is directly on the Aggref args |
| 2153 | * |
| 2154 | * We try to find a direct Var(document) and a BSON const. |
| 2155 | * If we can't find it, we are probably in case one, so we recurse to the FuncExpr. |
| 2156 | * If we find it, we check if the field path is covered by the index. If not, we can mark the field coverage as uncovered and abort. |
| 2157 | */ |
| 2158 | |
| 2159 | const char *fieldPath = NULL; |
| 2160 | bool sawDocumentVar = false; |
| 2161 | |
| 2162 | Aggref *aggref = (Aggref *) node; |
| 2163 | ListCell *aggArgCell; |
| 2164 | |
| 2165 | foreach(aggArgCell, aggref->args) |
| 2166 | { |
| 2167 | Expr *argExpr = StripRelabels(((TargetEntry *) lfirst(aggArgCell))->expr); |
| 2168 | if (IsA(argExpr, Var) && |
| 2169 | IsCurrentScanDocumentVar((Var *) argExpr, state->root, |
| 2170 | state->expectedRti)) |
| 2171 | { |
| 2172 | sawDocumentVar = true; |
| 2173 | continue; |
| 2174 | } |
| 2175 | |
| 2176 | /* Currently, we only handle aggregate functions with two arguments, and one field path. */ |
| 2177 | if (fieldPath == NULL) |
| 2178 | { |
| 2179 | fieldPath = TryExtractFieldPathFromConst(argExpr); |
| 2180 | } |
| 2181 | } |
| 2182 | |
| 2183 | if (sawDocumentVar && fieldPath != NULL) |
| 2184 | { |
| 2185 | if (!IsFieldPathCoveredByIndex(fieldPath, state->indexPath)) |
| 2186 | { |
| 2187 | /* Field path is not in this index so we can't do index-only. */ |
| 2188 | state->hasUncoveredField = true; |
| 2189 | return true; /* abort the walk early */ |
| 2190 | } |
| 2191 |
no test coverage detected