| 163 | } |
| 164 | |
| 165 | static std::unique_ptr<PhysicalOperator> tryMapPackedFilteredCount(PlanMapper& mapper, |
| 166 | main::ClientContext* clientContext, const LogicalAggregate& agg) { |
| 167 | if (!clientContext->getClientConfig()->enablePackedPathExtend || agg.getKeys().size() != 1 || |
| 168 | agg.getAggregates().size() != 1 || agg.getDependentKeys().size() != 0) { |
| 169 | return nullptr; |
| 170 | } |
| 171 | const auto aggregates = agg.getAggregates(); |
| 172 | const auto& aggregate = aggregates[0]; |
| 173 | if (aggregate->getNumChildren() != 0) { |
| 174 | return nullptr; |
| 175 | } |
| 176 | auto aggregateExpr = aggregate->constPtrCast<AggregateFunctionExpression>(); |
| 177 | if (aggregateExpr->getFunction().name != function::CountStarFunction::name) { |
| 178 | return nullptr; |
| 179 | } |
| 180 | const auto* projection = agg.getChild(0).get(); |
| 181 | if (projection->getOperatorType() != LogicalOperatorType::PROJECTION) { |
| 182 | return nullptr; |
| 183 | } |
| 184 | const auto& logicalProjection = projection->constCast<LogicalProjection>(); |
| 185 | if (logicalProjection.getExpressionsToProject().size() != 1) { |
| 186 | return nullptr; |
| 187 | } |
| 188 | const auto* filter = projection->getChild(0).get(); |
| 189 | if (filter->getOperatorType() != LogicalOperatorType::FILTER) { |
| 190 | return nullptr; |
| 191 | } |
| 192 | const auto& logicalFilter = filter->constCast<LogicalFilter>(); |
| 193 | auto predicateInputs = tryGetModuloSumPredicateInputs(logicalFilter.getPredicate()); |
| 194 | if (!predicateInputs.has_value()) { |
| 195 | return nullptr; |
| 196 | } |
| 197 | const auto* packedChild = unwrapFlattens(filter->getChild(0).get()); |
| 198 | auto* packedChildSchema = packedChild->getSchema(); |
| 199 | auto analyzer = GroupDependencyAnalyzer(true, *packedChildSchema); |
| 200 | analyzer.visit(logicalFilter.getPredicate()); |
| 201 | const auto dependentGroups = analyzer.getDependentGroups(); |
| 202 | if (dependentGroups.size() != 2) { |
| 203 | return nullptr; |
| 204 | } |
| 205 | for (auto groupPos : dependentGroups) { |
| 206 | if (packedChildSchema->getGroup(groupPos)->isFlat()) { |
| 207 | return nullptr; |
| 208 | } |
| 209 | } |
| 210 | const auto keys = agg.getKeys(); |
| 211 | const auto& key = keys[0]; |
| 212 | if (key->getDataType().getLogicalTypeID() != LogicalTypeID::INT64 || |
| 213 | aggregate->getDataType().getLogicalTypeID() != LogicalTypeID::INT64) { |
| 214 | return nullptr; |
| 215 | } |
| 216 | const auto keyGroupPos = packedChildSchema->getGroupPos(*key); |
| 217 | std::vector<data_chunk_pos_t> multiplicityChunks; |
| 218 | for (auto groupPos : packedChildSchema->getGroupsPosInScope()) { |
| 219 | if (groupPos == keyGroupPos || dependentGroups.contains(groupPos) || |
| 220 | packedChildSchema->getGroup(groupPos)->isFlat()) { |
| 221 | continue; |
| 222 | } |
no test coverage detected