blob: cc5630b9331726b5fbb7f45cd89007cd8578459c [file] [log] [blame]
/*
* 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.query.lookup;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Lists;
import org.apache.druid.java.util.common.Intervals;
import org.apache.druid.java.util.common.Pair;
import org.apache.druid.java.util.common.granularity.Granularities;
import org.apache.druid.java.util.common.guava.Sequence;
import org.apache.druid.query.extraction.MapLookupExtractor;
import org.apache.druid.segment.ColumnValueSelector;
import org.apache.druid.segment.Cursor;
import org.apache.druid.segment.DimensionDictionarySelector;
import org.apache.druid.segment.RowBasedStorageAdapter;
import org.apache.druid.segment.VirtualColumns;
import org.apache.druid.segment.column.ColumnCapabilities;
import org.apache.druid.segment.column.ValueType;
import org.apache.druid.timeline.SegmentId;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class LookupSegmentTest
{
public static final String LOOKUP_NAME = "mylookup";
public static final Map<String, String> LOOKUP_MAP =
ImmutableSortedMap.of(
"a", "b",
"x", "y"
);
public static final LookupExtractorFactory LOOKUP_EXTRACTOR_FACTORY =
new LookupExtractorFactory()
{
@Override
public boolean start()
{
return true;
}
@Override
public boolean close()
{
return true;
}
@Override
public boolean replaces(@Nullable LookupExtractorFactory other)
{
return true;
}
@Nullable
@Override
public LookupIntrospectHandler getIntrospectHandler()
{
throw new UnsupportedOperationException("not needed for this test");
}
@Override
public LookupExtractor get()
{
return new MapLookupExtractor(LOOKUP_MAP, false);
}
};
private static final LookupSegment LOOKUP_SEGMENT = new LookupSegment(LOOKUP_NAME, LOOKUP_EXTRACTOR_FACTORY);
@Test
public void test_getId()
{
Assert.assertEquals(SegmentId.dummy(LOOKUP_NAME), LOOKUP_SEGMENT.getId());
}
@Test
public void test_getDataInterval()
{
Assert.assertEquals(Intervals.ETERNITY, LOOKUP_SEGMENT.getDataInterval());
}
@Test
public void test_asQueryableIndex()
{
Assert.assertNull(LOOKUP_SEGMENT.asQueryableIndex());
}
@Test
public void test_asStorageAdapter_getAvailableDimensions()
{
Assert.assertEquals(
ImmutableList.of("k", "v"),
Lists.newArrayList(LOOKUP_SEGMENT.asStorageAdapter().getAvailableDimensions().iterator())
);
}
@Test
public void test_asStorageAdapter_getAvailableMetrics()
{
Assert.assertEquals(
ImmutableList.of(),
Lists.newArrayList(LOOKUP_SEGMENT.asStorageAdapter().getAvailableMetrics())
);
}
@Test
public void test_asStorageAdapter_getColumnCapabilitiesK()
{
final ColumnCapabilities capabilities = LOOKUP_SEGMENT.asStorageAdapter().getColumnCapabilities("k");
Assert.assertEquals(ValueType.STRING, capabilities.getType());
// Note: the "k" column does not actually have multiple values, but the RowBasedStorageAdapter doesn't allow
// reporting complete single-valued capabilities. It would be good to change this in the future, so query engines
// running on top of lookups can take advantage of singly-valued optimizations.
Assert.assertTrue(capabilities.hasMultipleValues().isUnknown());
Assert.assertFalse(capabilities.isDictionaryEncoded().isTrue());
}
@Test
public void test_asStorageAdapter_getColumnCapabilitiesV()
{
final ColumnCapabilities capabilities = LOOKUP_SEGMENT.asStorageAdapter().getColumnCapabilities("v");
// Note: the "v" column does not actually have multiple values, but the RowBasedStorageAdapter doesn't allow
// reporting complete single-valued capabilities. It would be good to change this in the future, so query engines
// running on top of lookups can take advantage of singly-valued optimizations.
Assert.assertEquals(ValueType.STRING, capabilities.getType());
Assert.assertTrue(capabilities.hasMultipleValues().isUnknown());
Assert.assertFalse(capabilities.isDictionaryEncoded().isTrue());
}
@Test
public void test_asStorageAdapter_getInterval()
{
Assert.assertEquals(Intervals.ETERNITY, LOOKUP_SEGMENT.asStorageAdapter().getInterval());
}
@Test
public void test_asStorageAdapter_getDimensionCardinalityK()
{
Assert.assertEquals(
DimensionDictionarySelector.CARDINALITY_UNKNOWN,
LOOKUP_SEGMENT.asStorageAdapter().getDimensionCardinality("k")
);
}
@Test
public void test_asStorageAdapter_getDimensionCardinalityV()
{
Assert.assertEquals(
DimensionDictionarySelector.CARDINALITY_UNKNOWN,
LOOKUP_SEGMENT.asStorageAdapter().getDimensionCardinality("v")
);
}
@Test
public void test_asStorageAdapter_makeCursors()
{
final Sequence<Cursor> cursors = LOOKUP_SEGMENT.asStorageAdapter().makeCursors(
null,
Intervals.of("1970/PT1H"),
VirtualColumns.EMPTY,
Granularities.ALL,
false,
null
);
final List<Pair<String, String>> kvs = new ArrayList<>();
cursors.accumulate(
null,
(ignored, cursor) -> {
final ColumnValueSelector keySelector = cursor.getColumnSelectorFactory().makeColumnValueSelector("k");
final ColumnValueSelector valueSelector = cursor.getColumnSelectorFactory().makeColumnValueSelector("v");
while (!cursor.isDone()) {
kvs.add(Pair.of(String.valueOf(keySelector.getObject()), String.valueOf(valueSelector.getObject())));
cursor.advanceUninterruptibly();
}
return null;
}
);
Assert.assertEquals(
ImmutableList.of(
Pair.of("a", "b"),
Pair.of("x", "y")
),
kvs
);
}
@Test
public void test_asStorageAdapter_isRowBasedAdapter()
{
// This allows us to assume that RowBasedStorageAdapterTest is further exercising makeCursors and verifying misc.
// methods like getMinTime, getMaxTime, getMetadata, etc, without checking them explicitly in _this_ test class.
Assert.assertThat(LOOKUP_SEGMENT.asStorageAdapter(), CoreMatchers.instanceOf(RowBasedStorageAdapter.class));
}
}