diff --git a/extensions-core/datasketches/src/test/java/org/apache/druid/segment/DatasketchesProjectionTest.java b/extensions-core/datasketches/src/test/java/org/apache/druid/segment/DatasketchesProjectionTest.java index 6073b0623032..51075d095f59 100644 --- a/extensions-core/datasketches/src/test/java/org/apache/druid/segment/DatasketchesProjectionTest.java +++ b/extensions-core/datasketches/src/test/java/org/apache/druid/segment/DatasketchesProjectionTest.java @@ -227,7 +227,7 @@ private static IndexBuilder makeBuilder(DimensionsSpec dimensionsSpec, boolean a IncrementalIndexSchema.builder() .withDimensionsSpec(dimensionsSpec) .withRollup(false) - .withMinTimestamp(CursorFactoryProjectionTest.TIMESTAMP.getMillis()) + .withMinTimestamp(CursorFactoryProjectionTest.UTC_MIDNIGHT.getMillis()) .withProjections(autoSchema ? AUTO_PROJECTIONS : PROJECTIONS) .build() ) diff --git a/processing/src/main/java/org/apache/druid/data/input/impl/AggregateProjectionSpec.java b/processing/src/main/java/org/apache/druid/data/input/impl/AggregateProjectionSpec.java index d9e09cc6fba7..42fc58eb15fe 100644 --- a/processing/src/main/java/org/apache/druid/data/input/impl/AggregateProjectionSpec.java +++ b/processing/src/main/java/org/apache/druid/data/input/impl/AggregateProjectionSpec.java @@ -29,6 +29,7 @@ import org.apache.druid.error.InvalidInput; import org.apache.druid.java.util.common.granularity.Granularities; import org.apache.druid.java.util.common.granularity.Granularity; +import org.apache.druid.java.util.common.granularity.PeriodGranularity; import org.apache.druid.query.OrderBy; import org.apache.druid.query.aggregation.AggregatorFactory; import org.apache.druid.query.filter.DimFilter; @@ -37,6 +38,7 @@ import org.apache.druid.segment.VirtualColumns; import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.utils.CollectionUtils; +import org.joda.time.DateTimeZone; import javax.annotation.Nullable; import java.util.Arrays; @@ -47,7 +49,7 @@ /** * API type to specify an aggregating projection on {@link org.apache.druid.segment.incremental.IncrementalIndexSchema} - * + *

* Decorated with {@link JsonTypeInfo} annotations as a future-proofing mechanism in the event we add other types of * projections and need to extract out a base interface from this class. */ @@ -208,7 +210,10 @@ public String toString() '}'; } - private static ProjectionOrdering computeOrdering(VirtualColumns virtualColumns, List groupingColumns) + private static ProjectionOrdering computeOrdering( + VirtualColumns virtualColumns, + List groupingColumns + ) { if (groupingColumns.isEmpty()) { // no ordering since there is only 1 row for this projection @@ -218,24 +223,30 @@ private static ProjectionOrdering computeOrdering(VirtualColumns virtualColumns, String timeColumnName = null; Granularity granularity = null; - // try to find the __time column equivalent, which might be a time_floor expression to model granularity - // bucketing. The time column is decided as the finest granularity on __time detected. If the projection does - // not have a time-like column, the granularity will be handled as ALL for the projection and all projection - // rows will use a synthetic timestamp of the minimum timestamp of the incremental index + + // determine the granularity and time column name for the projection, based on the finest time-like grouping column. for (final DimensionSchema dimension : groupingColumns) { ordering.add(OrderBy.ascending(dimension.getName())); if (ColumnHolder.TIME_COLUMN_NAME.equals(dimension.getName())) { timeColumnName = dimension.getName(); - granularity = Granularities.NONE; + // already found exact __time grouping, skip assigning, granularity = Granularities.NONE; + break; } else { final VirtualColumn vc = virtualColumns.getVirtualColumn(dimension.getName()); final Granularity maybeGranularity = Granularities.fromVirtualColumn(vc); - if (granularity == null && maybeGranularity != null) { - granularity = maybeGranularity; + if (maybeGranularity == null || maybeGranularity.equals(Granularities.ALL)) { + // no __time in inputs or not supported, skip + } else if (Granularities.NONE.equals(maybeGranularity)) { timeColumnName = dimension.getName(); - } else if (granularity != null && maybeGranularity != null && maybeGranularity.isFinerThan(granularity)) { - granularity = maybeGranularity; + // already found exact __time grouping, skip assigning, granularity = Granularities.NONE; + break; + } else if (maybeGranularity.getClass().equals(PeriodGranularity.class) + && maybeGranularity.getTimeZone().equals(DateTimeZone.UTC) + && ((PeriodGranularity) maybeGranularity).getOrigin() == null + && (granularity == null || maybeGranularity.isFinerThan(granularity))) { + // found a finer period granularity than the existing granularity, or it's the first one timeColumnName = dimension.getName(); + granularity = maybeGranularity; } } } diff --git a/processing/src/main/java/org/apache/druid/java/util/common/granularity/Granularities.java b/processing/src/main/java/org/apache/druid/java/util/common/granularity/Granularities.java index b3fa3e8ede72..2283aea23e1a 100644 --- a/processing/src/main/java/org/apache/druid/java/util/common/granularity/Granularities.java +++ b/processing/src/main/java/org/apache/druid/java/util/common/granularity/Granularities.java @@ -37,7 +37,6 @@ import org.apache.druid.segment.column.ColumnHolder; import org.apache.druid.segment.column.ColumnType; import org.apache.druid.segment.virtual.ExpressionVirtualColumn; -import org.joda.time.chrono.ISOChronology; import javax.annotation.Nullable; import java.util.Arrays; @@ -145,10 +144,11 @@ public static CursorBuildSpec decorateCursorBuildSpec(Query query, CursorBuil /** * Translates a {@link Granularity} to a {@link ExpressionVirtualColumn} on {@link ColumnHolder#TIME_COLUMN_NAME} of - * the equivalent grouping column. If granularity is {@link #ALL}, this method returns null since we are not grouping - * on time. If granularity is a {@link PeriodGranularity} with UTC timezone and no origin, this method returns a - * virtual column with {@link TimestampFloorExprMacro.TimestampFloorExpr} of the specified period. If granularity is - * {@link #NONE}, or any other kind of granularity (duration, period with non-utc timezone or origin) this method + * the equivalent grouping column. + *