Search in sources :

Example 51 with DimensionSpec

use of org.apache.druid.query.dimension.DimensionSpec in project druid by druid-io.

the class HashJoinEngine method makeJoinCursor.

/**
 * Creates a cursor that represents the join of {@param leftCursor} with {@param joinableClause}. The resulting
 * cursor may generate nulls on the left-hand side (for righty joins; see {@link JoinType#isRighty()}) or on
 * the right-hand side (for lefty joins; see {@link JoinType#isLefty()}). Columns that start with the
 * joinable clause's prefix (see {@link JoinableClause#getPrefix()}) will come from the Joinable's column selector
 * factory, and all other columns will come from the leftCursor's column selector factory.
 *
 * Ensuring that the joinable clause's prefix does not conflict with any columns from "leftCursor" is the
 * responsibility of the caller. If there is such a conflict (for example, if the joinable clause's prefix is "j.",
 * and the leftCursor has a field named "j.j.abrams"), then the field from the leftCursor will be shadowed and will
 * not be queryable through the returned Cursor. This happens even if the right-hand joinable doesn't actually have a
 * column with this name.
 */
public static Cursor makeJoinCursor(final Cursor leftCursor, final JoinableClause joinableClause, final boolean descending, final Closer closer) {
    final ColumnSelectorFactory leftColumnSelectorFactory = leftCursor.getColumnSelectorFactory();
    final JoinMatcher joinMatcher = joinableClause.getJoinable().makeJoinMatcher(leftColumnSelectorFactory, joinableClause.getCondition(), joinableClause.getJoinType().isRighty(), descending, closer);
    class JoinColumnSelectorFactory implements ColumnSelectorFactory {

        @Override
        public DimensionSelector makeDimensionSelector(DimensionSpec dimensionSpec) {
            if (joinableClause.includesColumn(dimensionSpec.getDimension())) {
                return joinMatcher.getColumnSelectorFactory().makeDimensionSelector(dimensionSpec.withDimension(joinableClause.unprefix(dimensionSpec.getDimension())));
            } else {
                final DimensionSelector leftSelector = leftColumnSelectorFactory.makeDimensionSelector(dimensionSpec);
                if (!joinableClause.getJoinType().isRighty()) {
                    return leftSelector;
                } else {
                    return new PossiblyNullDimensionSelector(leftSelector, joinMatcher::matchingRemainder);
                }
            }
        }

        @Override
        public ColumnValueSelector makeColumnValueSelector(String column) {
            if (joinableClause.includesColumn(column)) {
                return joinMatcher.getColumnSelectorFactory().makeColumnValueSelector(joinableClause.unprefix(column));
            } else {
                final ColumnValueSelector<?> leftSelector = leftColumnSelectorFactory.makeColumnValueSelector(column);
                if (!joinableClause.getJoinType().isRighty()) {
                    return leftSelector;
                } else {
                    return new PossiblyNullColumnValueSelector<>(leftSelector, joinMatcher::matchingRemainder);
                }
            }
        }

        @Nullable
        @Override
        public ColumnCapabilities getColumnCapabilities(String column) {
            if (joinableClause.includesColumn(column)) {
                return joinMatcher.getColumnSelectorFactory().getColumnCapabilities(joinableClause.unprefix(column));
            } else {
                return leftColumnSelectorFactory.getColumnCapabilities(column);
            }
        }
    }
    final JoinColumnSelectorFactory joinColumnSelectorFactory = new JoinColumnSelectorFactory();
    class JoinCursor implements Cursor {

        public void initialize() {
            matchCurrentPosition();
            if (!joinableClause.getJoinType().isLefty()) {
                while (!joinMatcher.hasMatch() && !isDone()) {
                    advance();
                    matchCurrentPosition();
                }
            }
        }

        @Override
        @Nonnull
        public ColumnSelectorFactory getColumnSelectorFactory() {
            return joinColumnSelectorFactory;
        }

        @Override
        @Nonnull
        public DateTime getTime() {
            return leftCursor.getTime();
        }

        @Override
        public void advance() {
            advanceUninterruptibly();
            BaseQuery.checkInterrupted();
        }

        private void matchCurrentPosition() {
            if (leftCursor.isDone()) {
                if (joinableClause.getJoinType().isRighty() && !joinMatcher.matchingRemainder()) {
                    // Warning! The way this engine handles "righty" joins is flawed: it generates the 'remainder' rows
                    // per-segment, but this should really be done globally. This should be improved in the future.
                    joinMatcher.matchRemainder();
                }
            } else {
                joinMatcher.matchCondition();
            }
        }

        @Override
        public void advanceUninterruptibly() {
            if (joinMatcher.hasMatch()) {
                joinMatcher.nextMatch();
                if (joinMatcher.hasMatch()) {
                    return;
                }
            }
            assert !joinMatcher.hasMatch();
            if (leftCursor.isDone()) {
                // No right-hand matches and nothing on the left cursor. We're done; return.
                assert isDone();
                return;
            }
            do {
                // No more right-hand side matches; advance the left-hand side.
                leftCursor.advanceUninterruptibly();
                // Update joinMatcher state to match new cursor position.
                matchCurrentPosition();
            // If this is not a left/full join, and joinMatcher didn't match anything, then keep advancing until we find
            // left rows that have matching right rows.
            } while (!joinableClause.getJoinType().isLefty() && !joinMatcher.hasMatch() && !leftCursor.isDone());
        }

        @Override
        public boolean isDone() {
            return leftCursor.isDone() && !joinMatcher.hasMatch();
        }

        @Override
        public boolean isDoneOrInterrupted() {
            return isDone() || Thread.currentThread().isInterrupted();
        }

        @Override
        public void reset() {
            leftCursor.reset();
            joinMatcher.reset();
        }
    }
    final JoinCursor joinCursor = new JoinCursor();
    joinCursor.initialize();
    return joinCursor;
}
Also used : DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) DimensionSelector(org.apache.druid.segment.DimensionSelector) ColumnSelectorFactory(org.apache.druid.segment.ColumnSelectorFactory) Cursor(org.apache.druid.segment.Cursor)

Example 52 with DimensionSpec

use of org.apache.druid.query.dimension.DimensionSpec in project druid by druid-io.

the class ExpressionVirtualColumnTest method testMultiObjectSelector.

@Test
public void testMultiObjectSelector() {
    DimensionSpec spec = new DefaultDimensionSpec("expr", "expr");
    final BaseObjectColumnValueSelector selectorImplicit = SCALE_LIST_IMPLICIT.makeDimensionSelector(spec, COLUMN_SELECTOR_FACTORY);
    CURRENT_ROW.set(ROWMULTI);
    Assert.assertEquals(ImmutableList.of("2.0", "4.0", "6.0"), selectorImplicit.getObject());
    CURRENT_ROW.set(ROWMULTI2);
    Assert.assertEquals(ImmutableList.of("6.0", "8.0", "10.0"), selectorImplicit.getObject());
    CURRENT_ROW.set(ROWMULTI3);
    Assert.assertEquals(Arrays.asList("6.0", NullHandling.replaceWithDefault() ? "0.0" : null, "10.0"), selectorImplicit.getObject());
    final BaseObjectColumnValueSelector selectorExplicit = SCALE_LIST_EXPLICIT.makeDimensionSelector(spec, COLUMN_SELECTOR_FACTORY);
    CURRENT_ROW.set(ROWMULTI);
    Assert.assertEquals(ImmutableList.of("2.0", "4.0", "6.0"), selectorExplicit.getObject());
    CURRENT_ROW.set(ROWMULTI2);
    Assert.assertEquals(ImmutableList.of("6.0", "8.0", "10.0"), selectorExplicit.getObject());
    CURRENT_ROW.set(ROWMULTI3);
    Assert.assertEquals(Arrays.asList("6.0", NullHandling.replaceWithDefault() ? "0.0" : null, "10.0"), selectorExplicit.getObject());
}
Also used : DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) ExtractionDimensionSpec(org.apache.druid.query.dimension.ExtractionDimensionSpec) DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) BaseObjectColumnValueSelector(org.apache.druid.segment.BaseObjectColumnValueSelector) DefaultDimensionSpec(org.apache.druid.query.dimension.DefaultDimensionSpec) InitializedNullHandlingTest(org.apache.druid.testing.InitializedNullHandlingTest) Test(org.junit.Test)

Example 53 with DimensionSpec

use of org.apache.druid.query.dimension.DimensionSpec in project druid by druid-io.

the class LookupSerdeModuleTest method testExtractionDimensionSerde.

@Test
public void testExtractionDimensionSerde() throws Exception {
    final ExtractionDimensionSpec dimensionSpec = new ExtractionDimensionSpec("xxx", "d", new RegisteredLookupExtractionFn(null, "beep", false, null, null, null));
    Assert.assertEquals(dimensionSpec, objectMapper.readValue(objectMapper.writeValueAsBytes(dimensionSpec), DimensionSpec.class));
}
Also used : DimensionSpec(org.apache.druid.query.dimension.DimensionSpec) ExtractionDimensionSpec(org.apache.druid.query.dimension.ExtractionDimensionSpec) ExtractionDimensionSpec(org.apache.druid.query.dimension.ExtractionDimensionSpec) Test(org.junit.Test)

Aggregations

DimensionSpec (org.apache.druid.query.dimension.DimensionSpec)53 DefaultDimensionSpec (org.apache.druid.query.dimension.DefaultDimensionSpec)27 AggregatorFactory (org.apache.druid.query.aggregation.AggregatorFactory)20 ArrayList (java.util.ArrayList)19 HashMap (java.util.HashMap)16 Nullable (javax.annotation.Nullable)15 Test (org.junit.Test)15 InitializedNullHandlingTest (org.apache.druid.testing.InitializedNullHandlingTest)14 MapBasedRow (org.apache.druid.data.input.MapBasedRow)12 Row (org.apache.druid.data.input.Row)12 ISE (org.apache.druid.java.util.common.ISE)12 PostAggregator (org.apache.druid.query.aggregation.PostAggregator)11 Map (java.util.Map)10 ColumnType (org.apache.druid.segment.column.ColumnType)10 List (java.util.List)9 LongSumAggregatorFactory (org.apache.druid.query.aggregation.LongSumAggregatorFactory)9 LongMeanAveragerFactory (org.apache.druid.query.movingaverage.averagers.LongMeanAveragerFactory)9 HashSet (java.util.HashSet)8 Function (com.google.common.base.Function)7 ImmutableList (com.google.common.collect.ImmutableList)7