|
11 | 11 | * See the License for the specific language governing permissions and |
12 | 12 | * limitations under the License. |
13 | 13 | */ |
14 | | -package com.facebook.presto.plugin.clp; |
| 14 | +package com.facebook.presto.plugin.clp.optimization; |
15 | 15 |
|
16 | 16 | import com.facebook.airlift.log.Logger; |
| 17 | +import com.facebook.presto.plugin.clp.ClpExpression; |
| 18 | +import com.facebook.presto.plugin.clp.ClpTableHandle; |
| 19 | +import com.facebook.presto.plugin.clp.ClpTableLayoutHandle; |
17 | 20 | import com.facebook.presto.plugin.clp.split.filter.ClpSplitFilterProvider; |
18 | 21 | import com.facebook.presto.spi.ColumnHandle; |
19 | 22 | import com.facebook.presto.spi.ConnectorPlanOptimizer; |
|
31 | 34 | import com.facebook.presto.spi.relation.VariableReferenceExpression; |
32 | 35 | import com.google.common.collect.ImmutableSet; |
33 | 36 |
|
34 | | -import java.util.HashMap; |
35 | 37 | import java.util.HashSet; |
36 | 38 | import java.util.Map; |
37 | 39 | import java.util.Optional; |
|
42 | 44 | import static java.lang.String.format; |
43 | 45 | import static java.util.Objects.requireNonNull; |
44 | 46 |
|
45 | | -public class ClpPlanOptimizer |
| 47 | +public class ClpComputePushDown |
46 | 48 | implements ConnectorPlanOptimizer |
47 | 49 | { |
48 | | - private static final Logger log = Logger.get(ClpPlanOptimizer.class); |
| 50 | + private static final Logger log = Logger.get(ClpComputePushDown.class); |
49 | 51 | private final FunctionMetadataManager functionManager; |
50 | 52 | private final StandardFunctionResolution functionResolution; |
51 | 53 | private final ClpSplitFilterProvider splitFilterProvider; |
52 | 54 |
|
53 | | - public ClpPlanOptimizer(FunctionMetadataManager functionManager, StandardFunctionResolution functionResolution, ClpSplitFilterProvider splitFilterProvider) |
| 55 | + public ClpComputePushDown(FunctionMetadataManager functionManager, StandardFunctionResolution functionResolution, ClpSplitFilterProvider splitFilterProvider) |
54 | 56 | { |
55 | 57 | this.functionManager = requireNonNull(functionManager, "functionManager is null"); |
56 | 58 | this.functionResolution = requireNonNull(functionResolution, "functionResolution is null"); |
@@ -99,59 +101,75 @@ public PlanNode visitFilter(FilterNode node, RewriteContext<Void> context) |
99 | 101 | if (!(node.getSource() instanceof TableScanNode)) { |
100 | 102 | return node; |
101 | 103 | } |
| 104 | + |
| 105 | + return processFilter(node, (TableScanNode) node.getSource()); |
| 106 | + } |
| 107 | + |
| 108 | + private PlanNode processFilter(FilterNode filterNode, TableScanNode tableScanNode) |
| 109 | + { |
102 | 110 | hasVisitedFilter = true; |
103 | 111 |
|
104 | | - TableScanNode tableScanNode = (TableScanNode) node.getSource(); |
105 | | - Map<VariableReferenceExpression, ColumnHandle> assignments = new HashMap<>(tableScanNode.getAssignments()); |
106 | 112 | TableHandle tableHandle = tableScanNode.getTable(); |
107 | 113 | ClpTableHandle clpTableHandle = (ClpTableHandle) tableHandle.getConnectorHandle(); |
| 114 | + |
108 | 115 | String tableScope = CONNECTOR_NAME + "." + clpTableHandle.getSchemaTableName().toString(); |
109 | | - ClpExpression clpExpression = node.getPredicate().accept( |
| 116 | + Map<VariableReferenceExpression, ColumnHandle> assignments = tableScanNode.getAssignments(); |
| 117 | + |
| 118 | + ClpExpression clpExpression = filterNode.getPredicate().accept( |
110 | 119 | new ClpFilterToKqlConverter( |
111 | 120 | functionResolution, |
112 | 121 | functionManager, |
| 122 | + assignments, |
113 | 123 | splitFilterProvider.getColumnNames(tableScope)), |
114 | | - assignments); |
| 124 | + null); |
115 | 125 | Optional<String> kqlQuery = clpExpression.getPushDownExpression(); |
116 | 126 | Optional<String> metadataSqlQuery = clpExpression.getMetadataSqlQuery(); |
117 | 127 | Optional<RowExpression> remainingPredicate = clpExpression.getRemainingExpression(); |
118 | 128 |
|
119 | 129 | // Perform required metadata filter checks before handling the KQL query (if kqlQuery |
120 | 130 | // isn't present, we'll return early, skipping subsequent checks). |
121 | 131 | splitFilterProvider.checkContainsRequiredFilters(ImmutableSet.of(tableScope), metadataSqlQuery.orElse("")); |
122 | | - if (metadataSqlQuery.isPresent()) { |
| 132 | + boolean hasMetadataFilter = metadataSqlQuery.isPresent() && !metadataSqlQuery.get().isEmpty(); |
| 133 | + if (hasMetadataFilter) { |
123 | 134 | metadataSqlQuery = Optional.of(splitFilterProvider.remapSplitFilterPushDownExpression(tableScope, metadataSqlQuery.get())); |
124 | | - log.debug("Metadata SQL query: %s", metadataSqlQuery); |
| 135 | + log.debug("Metadata SQL query: %s", metadataSqlQuery.get()); |
125 | 136 | } |
126 | 137 |
|
127 | | - if (!kqlQuery.isPresent()) { |
128 | | - return node; |
129 | | - } |
130 | | - log.debug("KQL query: %s", kqlQuery); |
131 | | - |
132 | | - ClpTableLayoutHandle clpTableLayoutHandle = new ClpTableLayoutHandle(clpTableHandle, kqlQuery, metadataSqlQuery); |
133 | | - TableScanNode newTableScanNode = new TableScanNode( |
134 | | - tableScanNode.getSourceLocation(), |
135 | | - idAllocator.getNextId(), |
136 | | - new TableHandle( |
137 | | - tableHandle.getConnectorId(), |
138 | | - clpTableHandle, |
139 | | - tableHandle.getTransaction(), |
140 | | - Optional.of(clpTableLayoutHandle)), |
141 | | - tableScanNode.getOutputVariables(), |
142 | | - tableScanNode.getAssignments(), |
143 | | - tableScanNode.getTableConstraints(), |
144 | | - tableScanNode.getCurrentConstraint(), |
145 | | - tableScanNode.getEnforcedConstraint(), |
146 | | - tableScanNode.getCteMaterializationInfo()); |
147 | | - if (!remainingPredicate.isPresent()) { |
148 | | - return newTableScanNode; |
| 138 | + if (kqlQuery.isPresent() || hasMetadataFilter) { |
| 139 | + if (kqlQuery.isPresent()) { |
| 140 | + log.debug("KQL query: %s", kqlQuery.get()); |
| 141 | + } |
| 142 | + |
| 143 | + ClpTableLayoutHandle layoutHandle = new ClpTableLayoutHandle(clpTableHandle, kqlQuery, metadataSqlQuery); |
| 144 | + TableHandle newTableHandle = new TableHandle( |
| 145 | + tableHandle.getConnectorId(), |
| 146 | + clpTableHandle, |
| 147 | + tableHandle.getTransaction(), |
| 148 | + Optional.of(layoutHandle)); |
| 149 | + |
| 150 | + tableScanNode = new TableScanNode( |
| 151 | + tableScanNode.getSourceLocation(), |
| 152 | + idAllocator.getNextId(), |
| 153 | + newTableHandle, |
| 154 | + tableScanNode.getOutputVariables(), |
| 155 | + tableScanNode.getAssignments(), |
| 156 | + tableScanNode.getTableConstraints(), |
| 157 | + tableScanNode.getCurrentConstraint(), |
| 158 | + tableScanNode.getEnforcedConstraint(), |
| 159 | + tableScanNode.getCteMaterializationInfo()); |
149 | 160 | } |
150 | 161 |
|
151 | | - return new FilterNode(node.getSourceLocation(), |
152 | | - idAllocator.getNextId(), |
153 | | - newTableScanNode, |
154 | | - remainingPredicate.get()); |
| 162 | + if (remainingPredicate.isPresent()) { |
| 163 | + // Not all predicate pushed down, need new FilterNode |
| 164 | + return new FilterNode( |
| 165 | + filterNode.getSourceLocation(), |
| 166 | + idAllocator.getNextId(), |
| 167 | + tableScanNode, |
| 168 | + remainingPredicate.get()); |
| 169 | + } |
| 170 | + else { |
| 171 | + return tableScanNode; |
| 172 | + } |
155 | 173 | } |
156 | 174 | } |
157 | 175 | } |
0 commit comments