github-advanced-security[bot] commented on code in PR #18880:
URL: https://github.com/apache/druid/pull/18880#discussion_r2663606645


##########
processing/src/main/java/org/apache/druid/segment/projections/AggregateProjectionSchema.java:
##########
@@ -0,0 +1,393 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.segment.projections;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.collect.Lists;
+import org.apache.druid.error.DruidException;
+import org.apache.druid.java.util.common.granularity.Granularities;
+import org.apache.druid.java.util.common.granularity.Granularity;
+import org.apache.druid.query.OrderBy;
+import org.apache.druid.query.aggregation.AggregatorFactory;
+import org.apache.druid.query.filter.DimFilter;
+import org.apache.druid.segment.CursorBuildSpec;
+import org.apache.druid.segment.VirtualColumn;
+import org.apache.druid.segment.VirtualColumns;
+import org.apache.druid.segment.column.ColumnHolder;
+import org.apache.druid.utils.CollectionUtils;
+import org.joda.time.Interval;
+
+import javax.annotation.Nullable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class AggregateProjectionSchema implements ProjectionSchema
+{
+  /**
+   * It is not likely the best way to find the best matching projections, but 
it is the one we have for now. This
+   * comparator is used to sort all the projections in a segment "best" first, 
where best is defined as fewest grouping
+   * columns, most virtual columns and aggregators, as an approximation of 
likely to have the fewest number of rows to
+   * scan.
+   */
+  public static final Comparator<AggregateProjectionSchema> COMPARATOR = (o1, 
o2) -> {
+    // coarsest granularity first
+    if 
(o1.getEffectiveGranularity().isFinerThan(o2.getEffectiveGranularity())) {
+      return 1;
+    }
+    if 
(o2.getEffectiveGranularity().isFinerThan(o1.getEffectiveGranularity())) {
+      return -1;
+    }
+    // fewer dimensions first
+    final int dimsCompare = Integer.compare(
+        o1.groupingColumns.size(),
+        o2.groupingColumns.size()
+    );
+    if (dimsCompare != 0) {
+      return dimsCompare;
+    }
+    // more metrics first
+    int metCompare = Integer.compare(o2.aggregators.length, 
o1.aggregators.length);
+    if (metCompare != 0) {
+      return metCompare;
+    }
+    // more virtual columns first
+    final int virtCompare = Integer.compare(
+        o2.virtualColumns.getVirtualColumns().length,
+        o1.virtualColumns.getVirtualColumns().length
+    );
+    if (virtCompare != 0) {
+      return virtCompare;
+    }
+    return o1.name.compareTo(o2.name);
+  };
+
+  private final String name;
+  @Nullable
+  private final String timeColumnName;
+  @Nullable
+  private final DimFilter filter;
+  private final VirtualColumns virtualColumns;
+  private final List<String> groupingColumns;
+  private final AggregatorFactory[] aggregators;
+  private final List<OrderBy> ordering;
+  private final List<OrderBy> orderingWithTimeSubstitution;
+
+  // computed fields
+  private final int timeColumnPosition;
+  private final Granularity effectiveGranularity;
+
+  @JsonCreator
+  public AggregateProjectionSchema(
+      @JsonProperty("name") String name,
+      @JsonProperty("timeColumnName") @Nullable String timeColumnName,
+      @JsonProperty("filter") @Nullable DimFilter filter,
+      @JsonProperty("virtualColumns") @Nullable VirtualColumns virtualColumns,
+      @JsonProperty("groupingColumns") @Nullable List<String> groupingColumns,
+      @JsonProperty("aggregators") @Nullable AggregatorFactory[] aggregators,
+      @JsonProperty("ordering") List<OrderBy> ordering
+  )
+  {
+    if (name == null || name.isEmpty()) {
+      throw DruidException.defensive("projection schema name cannot be null or 
empty");
+    }
+    this.name = name;
+    if (CollectionUtils.isNullOrEmpty(groupingColumns) && (aggregators == null 
|| aggregators.length == 0)) {
+      throw DruidException.defensive(
+          "projection schema[%s] groupingColumns and aggregators must not both 
be null or empty",
+          name
+      );
+    }
+    if (ordering == null) {
+      throw DruidException.defensive("projection schema[%s] ordering must not 
be null", name);
+    }
+    this.filter = filter;
+    this.virtualColumns = virtualColumns == null ? VirtualColumns.EMPTY : 
virtualColumns;
+    this.groupingColumns = groupingColumns == null ? Collections.emptyList() : 
groupingColumns;
+    this.aggregators = aggregators == null ? new AggregatorFactory[0] : 
aggregators;
+    this.ordering = ordering;
+
+    int foundTimePosition = -1;
+    this.orderingWithTimeSubstitution = 
Lists.newArrayListWithCapacity(ordering.size());
+    Granularity granularity = null;
+    for (int i = 0; i < ordering.size(); i++) {
+      OrderBy orderBy = ordering.get(i);
+      if (orderBy.getColumnName().equals(timeColumnName)) {
+        orderingWithTimeSubstitution.add(new 
OrderBy(ColumnHolder.TIME_COLUMN_NAME, orderBy.getOrder()));
+        foundTimePosition = i;
+        timeColumnName = this.groupingColumns.get(foundTimePosition);
+        final VirtualColumn vc = 
this.virtualColumns.getVirtualColumn(groupingColumns.get(foundTimePosition));

Review Comment:
   ## Dereferenced variable may be null
   
   Variable [groupingColumns](1) may be null at this access as suggested by 
[this](2) null guard.
   
   [Show more 
details](https://github.com/apache/druid/security/code-scanning/10630)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to