blob: d13082b8bc74e68091a0e613d75a5325ee4b4463 [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.kylin.storage.gtrecord;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
//import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.BitSet;
import java.util.List;
import org.apache.kylin.common.util.ByteArray;
import org.apache.kylin.common.util.BytesSerializer;
//import org.apache.kylin.common.util.Dictionary;
import org.apache.kylin.common.util.ImmutableBitSet;
import org.apache.kylin.common.util.LocalFileMetadataTestCase;
//import org.apache.kylin.cube.gridtable.CubeCodeSystem;
//import org.apache.kylin.dict.NumberDictionaryForestBuilder;
//import org.apache.kylin.dict.StringBytesConverter;
////import org.apache.kylin.dict.TrieDictionaryBuilder;
//import org.apache.kylin.dimension.DictionaryDimEnc;
//import org.apache.kylin.dimension.DimensionEncoding;
//import org.apache.kylin.gridtable.GTBuilder;
import org.apache.kylin.gridtable.GTFilterScanner.FilterResultCache;
import org.apache.kylin.gridtable.GTInfo;
//import org.apache.kylin.gridtable.GTInfo.Builder;
import org.apache.kylin.gridtable.GTRecord;
import org.apache.kylin.gridtable.GTScanRange;
import org.apache.kylin.gridtable.GTScanRequest;
import org.apache.kylin.gridtable.GTScanRequestBuilder;
import org.apache.kylin.gridtable.GTUtil;
import org.apache.kylin.gridtable.GridTable;
import org.apache.kylin.gridtable.IGTScanner;
//import org.apache.kylin.gridtable.memstore.GTSimpleMemStore;
//import org.apache.kylin.metadata.datatype.DataType;
import org.apache.kylin.metadata.filter.ColumnTupleFilter;
import org.apache.kylin.metadata.filter.CompareTupleFilter;
import org.apache.kylin.metadata.filter.ConstantTupleFilter;
import org.apache.kylin.metadata.filter.ExtractTupleFilter;
import org.apache.kylin.metadata.filter.LogicalTupleFilter;
import org.apache.kylin.metadata.filter.TupleFilter;
import org.apache.kylin.metadata.filter.TupleFilter.FilterOperatorEnum;
import org.apache.kylin.metadata.model.TableDesc;
import org.apache.kylin.metadata.model.TblColRef;
import org.apache.kylin.metadata.model.TblColRef.InnerDataTypeEnum;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.Ignore;
import org.apache.kylin.shaded.com.google.common.collect.Lists;
@Ignore
public class DictGridTableTest extends LocalFileMetadataTestCase {
private GridTable table;
private GTInfo info;
private CompareTupleFilter timeComp0;
private CompareTupleFilter timeComp1;
private CompareTupleFilter timeComp2;
private CompareTupleFilter timeComp3;
private CompareTupleFilter timeComp4;
private CompareTupleFilter timeComp5;
private CompareTupleFilter timeComp6;
private CompareTupleFilter timeComp7;
private CompareTupleFilter ageComp1;
private CompareTupleFilter ageComp2;
private CompareTupleFilter ageComp3;
private CompareTupleFilter ageComp4;
@After
public void after() throws Exception {
this.cleanupTestMetadata();
}
@Before
public void setup() throws IOException {
this.createTestMetadata();
table = null;
info = table.getInfo();
timeComp0 = compare(info.colRef(0), FilterOperatorEnum.LT, enc(info, 0, "2015-01-14"));
timeComp1 = compare(info.colRef(0), FilterOperatorEnum.GT, enc(info, 0, "2015-01-14"));
timeComp2 = compare(info.colRef(0), FilterOperatorEnum.LT, enc(info, 0, "2015-01-13"));
timeComp3 = compare(info.colRef(0), FilterOperatorEnum.LT, enc(info, 0, "2015-01-15"));
timeComp4 = compare(info.colRef(0), FilterOperatorEnum.EQ, enc(info, 0, "2015-01-15"));
timeComp5 = compare(info.colRef(0), FilterOperatorEnum.GT, enc(info, 0, "2015-01-15"));
timeComp6 = compare(info.colRef(0), FilterOperatorEnum.EQ, enc(info, 0, "2015-01-14"));
timeComp7 = compare(info.colRef(0), FilterOperatorEnum.EQ, enc(info, 0, "1970-01-01"));
ageComp1 = compare(info.colRef(1), FilterOperatorEnum.EQ, enc(info, 1, "10"));
ageComp2 = compare(info.colRef(1), FilterOperatorEnum.EQ, enc(info, 1, "20"));
ageComp3 = compare(info.colRef(1), FilterOperatorEnum.EQ, enc(info, 1, "30"));
ageComp4 = compare(info.colRef(1), FilterOperatorEnum.NEQ, enc(info, 1, "30"));
}
@Test
public void verifySegmentSkipping() {
ByteArray segmentStart = enc(info, 0, "2015-01-14");
ByteArray segmentStartX = enc(info, 0, "2015-01-14 00:00:00");//when partition col is dict encoded, time format will be free
assertEquals(segmentStart, segmentStartX);
{
LogicalTupleFilter filter = and(timeComp0, ageComp1);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());//scan range are [close,close]
assertEquals("[null, 10]-[1421193600000, 10]", r.get(0).toString());
assertEquals(1, r.get(0).fuzzyKeys.size());
assertEquals("[[null, 10, null, null, null]]", r.get(0).fuzzyKeys.toString());
}
{
LogicalTupleFilter filter = and(timeComp2, ageComp1);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());
}
{
LogicalTupleFilter filter = and(timeComp4, ageComp1);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());
}
{
LogicalTupleFilter filter = and(timeComp5, ageComp1);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());
}
{
LogicalTupleFilter filter = or(and(timeComp2, ageComp1), and(timeComp1, ageComp1),
and(timeComp6, ageComp1));
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(2, r.size());
assertEquals("[1421193600000, 10]-[null, 10]", r.get(1).toString());
assertEquals("[[null, 10, null, null, null], [1421193600000, 10, null, null, null]]",
r.get(1).fuzzyKeys.toString());
}
{
LogicalTupleFilter filter = or(and(timeComp3, ageComp3), and(timeComp7, ageComp1));
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, null, filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals("[[0, 10]-[1421280000000, 30]]", r.toString());
}
{
LogicalTupleFilter filter = or(timeComp2, timeComp1, timeComp6);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(2, r.size());
assertEquals("[1421193600000, null]-[null, null]", r.get(1).toString());
assertEquals(0, r.get(1).fuzzyKeys.size());
}
{
//skip FALSE filter
LogicalTupleFilter filter = and(ageComp1, ConstantTupleFilter.FALSE);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(0, r.size());
}
{
//TRUE or FALSE filter
LogicalTupleFilter filter = or(ConstantTupleFilter.TRUE, ConstantTupleFilter.FALSE);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());
assertEquals("[null, null]-[null, null]", r.get(0).toString());
}
{
//TRUE or other filter
LogicalTupleFilter filter = or(ageComp1, ConstantTupleFilter.TRUE);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());
assertEquals("[null, null]-[null, null]", r.get(0).toString());
}
}
@Test
public void verifySegmentSkipping2() {
{
LogicalTupleFilter filter = and(timeComp0, ageComp1);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());//scan range are [close,close]
assertEquals("[null, 10]-[1421193600000, 10]", r.get(0).toString());
assertEquals(1, r.get(0).fuzzyKeys.size());
assertEquals("[[null, 10, null, null, null]]", r.get(0).fuzzyKeys.toString());
}
{
LogicalTupleFilter filter = and(timeComp5, ageComp1);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, info.colRef(0), filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());//scan range are [close,close]
}
}
@Test
public void verifyScanRangePlanner() {
// flatten or-and & hbase fuzzy value
{
LogicalTupleFilter filter = and(timeComp1, or(ageComp1, ageComp2));
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, null, filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(1, r.size());
assertEquals("[1421193600000, 10]-[null, 20]", r.get(0).toString());
assertEquals("[[null, 10, null, null, null], [null, 20, null, null, null]]", r.get(0).fuzzyKeys.toString());
}
// pre-evaluate ever false
{
LogicalTupleFilter filter = and(timeComp1, timeComp2);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, null, filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(0, r.size());
}
// pre-evaluate ever true
{
LogicalTupleFilter filter = or(timeComp1, ageComp4);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, null, filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals("[[null, null]-[null, null]]", r.toString());
}
// merge overlap range
{
LogicalTupleFilter filter = or(timeComp1, timeComp3);
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, null, filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals("[[null, null]-[null, null]]", r.toString());
}
// merge too many ranges
{
LogicalTupleFilter filter = or(and(timeComp4, ageComp1), and(timeComp4, ageComp2),
and(timeComp4, ageComp3));
CubeScanRangePlanner planner = new CubeScanRangePlanner(info, null, filter);
List<GTScanRange> r = planner.planScanRanges();
assertEquals(3, r.size());
assertEquals("[1421280000000, 10]-[1421280000000, 10]", r.get(0).toString());
assertEquals("[1421280000000, 20]-[1421280000000, 20]", r.get(1).toString());
assertEquals("[1421280000000, 30]-[1421280000000, 30]", r.get(2).toString());
planner.setMaxScanRanges(2);
List<GTScanRange> r2 = planner.planScanRanges();
assertEquals("[[1421280000000, 10]-[1421280000000, 30]]", r2.toString());
}
}
@Test
public void verifyFirstRow() throws IOException {
doScanAndVerify(table,
new GTScanRequestBuilder().setInfo(table.getInfo()).setRanges(null).setDimensions(null)
.setFilterPushDown(null).createGTScanRequest(),
"[1421193600000, 30, Yang, 10, 10.5]", //
"[1421193600000, 30, Luke, 10, 10.5]", //
"[1421280000000, 20, Dong, 10, 10.5]", //
"[1421280000000, 20, Jason, 10, 10.5]", //
"[1421280000000, 30, Xu, 10, 10.5]", //
"[1421366400000, 20, Mahone, 10, 10.5]", //
"[1421366400000, 20, Qianhao, 10, 10.5]", //
"[1421366400000, 30, George, 10, 10.5]", //
"[1421366400000, 30, Shaofeng, 10, 10.5]", //
"[1421452800000, 10, Kejia, 10, 10.5]");
}
//for testing GTScanRequest serialization and deserialization
public static GTScanRequest useDeserializedGTScanRequest(GTScanRequest origin) {
ByteBuffer buffer = ByteBuffer.allocate(BytesSerializer.SERIALIZE_BUFFER_SIZE);
GTScanRequest.serializer.serialize(origin, buffer);
buffer.flip();
GTScanRequest sGTScanRequest = GTScanRequest.serializer.deserialize(buffer);
Assert.assertArrayEquals(origin.getAggrMetricsFuncs(), sGTScanRequest.getAggrMetricsFuncs());
Assert.assertEquals(origin.getAggCacheMemThreshold(), sGTScanRequest.getAggCacheMemThreshold(), 0.01);
return sGTScanRequest;
}
@Test
public void verifyScanWithUnevaluatableFilter() throws IOException {
GTInfo info = table.getInfo();
CompareTupleFilter fComp = compare(info.colRef(0), FilterOperatorEnum.GT, enc(info, 0, "2015-01-14"));
ExtractTupleFilter fUnevaluatable = unevaluatable(info.colRef(1));
LogicalTupleFilter fNotPlusUnevaluatable = not(unevaluatable(info.colRef(1)));
LogicalTupleFilter filter = and(fComp, fUnevaluatable, fNotPlusUnevaluatable);
GTScanRequest req = new GTScanRequestBuilder().setInfo(info).setRanges(null).setDimensions(null)
.setAggrGroupBy(setOf(0)).setAggrMetrics(setOf(3)).setAggrMetricsFuncs(new String[] { "sum" })
.setFilterPushDown(filter).createGTScanRequest();
// note the unEvaluatable column 1 in filter is added to group by
assertEquals(
"GTScanRequest [range=[[null, null]-[null, null]], columns={0, 1, 3}, filterPushDown=AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], [], []], aggrGroupBy={0, 1}, aggrMetrics={3}, aggrMetricsFuncs=[sum]]",
req.toString());
doScanAndVerify(table, useDeserializedGTScanRequest(req), "[1421280000000, 20, null, 20, null]",
"[1421280000000, 30, null, 10, null]", "[1421366400000, 20, null, 20, null]",
"[1421366400000, 30, null, 20, null]", "[1421452800000, 10, null, 10, null]");
}
@Test
public void verifyScanWithEvaluatableFilter() throws IOException {
GTInfo info = table.getInfo();
CompareTupleFilter fComp1 = compare(info.colRef(0), FilterOperatorEnum.GT, enc(info, 0, "2015-01-14"));
CompareTupleFilter fComp2 = compare(info.colRef(1), FilterOperatorEnum.GT, enc(info, 1, "10"));
LogicalTupleFilter filter = and(fComp1, fComp2);
GTScanRequest req = new GTScanRequestBuilder().setInfo(info).setRanges(null).setDimensions(null)
.setAggrGroupBy(setOf(0)).setAggrMetrics(setOf(3)).setAggrMetricsFuncs(new String[] { "sum" })
.setFilterPushDown(filter).createGTScanRequest();
// note the evaluatable column 1 in filter is added to returned columns but not in group by
assertEquals(
"GTScanRequest [range=[[null, null]-[null, null]], columns={0, 1, 3}, filterPushDown=AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 GT [\\x00]], aggrGroupBy={0}, aggrMetrics={3}, aggrMetricsFuncs=[sum]]",
req.toString());
doScanAndVerify(table, useDeserializedGTScanRequest(req), "[1421280000000, 20, null, 30, null]",
"[1421366400000, 20, null, 40, null]");
}
@Test
public void verifyAggregateAndHavingFilter() throws IOException {
GTInfo info = table.getInfo();
TblColRef havingCol = TblColRef.newInnerColumn("SUM_OF_BIGDECIMAL", InnerDataTypeEnum.LITERAL);
havingCol.getColumnDesc().setId("1"); // point to the first aggregated measure
CompareTupleFilter havingFilter = compare(havingCol, FilterOperatorEnum.GT, "20");
GTScanRequest req = new GTScanRequestBuilder().setInfo(info).setRanges(null).setDimensions(null)
.setAggrGroupBy(setOf(1)).setAggrMetrics(setOf(4)).setAggrMetricsFuncs(new String[] { "sum" })
.setHavingFilterPushDown(havingFilter).createGTScanRequest();
doScanAndVerify(table, useDeserializedGTScanRequest(req), "[null, 20, null, null, 42.0]",
"[null, 30, null, null, 52.5]");
}
@SuppressWarnings("unused")
private void testFilterScannerPerfInner(GridTable table, GTInfo info, LogicalTupleFilter filter)
throws IOException {
long start = System.currentTimeMillis();
GTScanRequest req = new GTScanRequestBuilder().setInfo(info).setRanges(null).setDimensions(null)
.setFilterPushDown(filter).createGTScanRequest();
int i = 0;
try (IGTScanner scanner = table.scan(req)) {
for (GTRecord r : scanner) {
i++;
}
}
long end = System.currentTimeMillis();
System.out.println(
(end - start) + "ms with filter cache enabled=" + FilterResultCache.DEFAULT_OPTION + ", " + i + " rows");
}
@Test
public void verifyConvertFilterConstants1() {
GTInfo info = table.getInfo();
TableDesc extTable = TableDesc.mockup("ext");
TblColRef extColA = TblColRef.mockup(extTable, 1, "A", "timestamp");
TblColRef extColB = TblColRef.mockup(extTable, 2, "B", "integer");
CompareTupleFilter fComp1 = compare(extColA, FilterOperatorEnum.GT, "2015-01-14");
CompareTupleFilter fComp2 = compare(extColB, FilterOperatorEnum.EQ, "10");
LogicalTupleFilter filter = and(fComp1, fComp2);
List<TblColRef> colMapping = Lists.newArrayList();
colMapping.add(extColA);
colMapping.add(extColB);
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 EQ [\\x00]]",
newFilter.toString());
}
@Test
public void verifyConvertFilterConstants2() {
GTInfo info = table.getInfo();
TableDesc extTable = TableDesc.mockup("ext");
TblColRef extColA = TblColRef.mockup(extTable, 1, "A", "timestamp");
TblColRef extColB = TblColRef.mockup(extTable, 2, "B", "integer");
List<TblColRef> colMapping = Lists.newArrayList();
colMapping.add(extColA);
colMapping.add(extColB);
CompareTupleFilter fComp1 = compare(extColA, FilterOperatorEnum.GT, "2015-01-14");
// $1<"9" round down to FALSE
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.LT, "9"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 ISNOTNULL []]",
newFilter.toString());
}
// $1<"10" needs no rounding
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.LT, "10"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 LT [\\x00]]",
newFilter.toString());
}
// $1<"11" round down to <="10"
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.LT, "11"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 LTE [\\x00]]",
newFilter.toString());
}
// $1<="9" round down to FALSE
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.LTE, "9"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(ConstantTupleFilter.FALSE, newFilter);
}
// $1<="10" needs no rounding
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.LTE, "10"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 LTE [\\x00]]",
newFilter.toString());
}
// $1<="11" round down to <="10"
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.LTE, "11"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 LTE [\\x00]]",
newFilter.toString());
}
}
@Test
public void verifyConvertFilterConstants3() {
GTInfo info = table.getInfo();
TableDesc extTable = TableDesc.mockup("ext");
TblColRef extColA = TblColRef.mockup(extTable, 1, "A", "timestamp");
TblColRef extColB = TblColRef.mockup(extTable, 2, "B", "integer");
List<TblColRef> colMapping = Lists.newArrayList();
colMapping.add(extColA);
colMapping.add(extColB);
CompareTupleFilter fComp1 = compare(extColA, FilterOperatorEnum.GT, "2015-01-14");
// $1>"101" round up to FALSE
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.GT, "101"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals("AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 ISNOTNULL []]",
newFilter.toString());
}
// $1>"100" needs no rounding
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.GT, "100"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 GT [\\x09]]",
newFilter.toString());
}
// $1>"99" round up to >="100"
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.GT, "99"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 GTE [\\x09]]",
newFilter.toString());
}
// $1>="101" round up to FALSE
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.GTE, "101"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(ConstantTupleFilter.FALSE, newFilter);
}
// $1>="100" needs no rounding
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.GTE, "100"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 GTE [\\x09]]",
newFilter.toString());
}
// $1>="99" round up to >="100"
{
LogicalTupleFilter filter = and(fComp1, compare(extColB, FilterOperatorEnum.GTE, "99"));
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 GTE [\\x09]]",
newFilter.toString());
}
}
@Test
public void verifyConvertFilterConstants4() {
GTInfo info = table.getInfo();
TableDesc extTable = TableDesc.mockup("ext");
TblColRef extColA = TblColRef.mockup(extTable, 1, "A", "timestamp");
TblColRef extColB = TblColRef.mockup(extTable, 2, "B", "integer");
CompareTupleFilter fComp1 = compare(extColA, FilterOperatorEnum.GT, "2015-01-14");
CompareTupleFilter fComp2 = compare(extColB, FilterOperatorEnum.IN, "9", "10", "15");
LogicalTupleFilter filter = and(fComp1, fComp2);
List<TblColRef> colMapping = Lists.newArrayList();
colMapping.add(extColA);
colMapping.add(extColB);
// $1 in ("9", "10", "15") has only "10" left
TupleFilter newFilter = GTUtil.convertFilterColumnsAndConstants(filter, info, colMapping, null);
assertEquals(
"AND [UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.0 GT [\\x00\\x00\\x01J\\xE5\\xBD\\x5C\\x00], UNKNOWN_MODEL:NULL.GT_MOCKUP_TABLE.1 IN [\\x00]]",
newFilter.toString());
}
private void doScanAndVerify(GridTable table, GTScanRequest req, String... verifyRows) throws IOException {
System.out.println(req);
try (IGTScanner scanner = table.scan(req)) {
int i = 0;
for (GTRecord r : scanner) {
System.out.println(r);
if (verifyRows == null || i >= verifyRows.length) {
Assert.fail();
}
assertEquals(verifyRows[i], r.toString());
i++;
}
}
}
public static ByteArray enc(GTInfo info, int col, String value) {
ByteBuffer buf = ByteBuffer.allocate(info.getMaxColumnLength());
info.getCodeSystem().encodeColumnValue(col, value, buf);
return ByteArray.copyOf(buf.array(), buf.arrayOffset(), buf.position());
}
public static ExtractTupleFilter unevaluatable(TblColRef col) {
ExtractTupleFilter r = new ExtractTupleFilter(FilterOperatorEnum.EXTRACT);
r.addChild(new ColumnTupleFilter(col));
return r;
}
public static CompareTupleFilter compare(TblColRef col, FilterOperatorEnum op, Object... value) {
CompareTupleFilter result = new CompareTupleFilter(op);
result.addChild(new ColumnTupleFilter(col));
result.addChild(new ConstantTupleFilter(Arrays.asList(value)));
return result;
}
public static LogicalTupleFilter and(TupleFilter... children) {
return logic(FilterOperatorEnum.AND, children);
}
public static LogicalTupleFilter or(TupleFilter... children) {
return logic(FilterOperatorEnum.OR, children);
}
public static LogicalTupleFilter not(TupleFilter child) {
return logic(FilterOperatorEnum.NOT, child);
}
public static LogicalTupleFilter logic(FilterOperatorEnum op, TupleFilter... children) {
LogicalTupleFilter result = new LogicalTupleFilter(op);
for (TupleFilter c : children) {
result.addChild(c);
}
return result;
}
// public static GridTable newTestTable() throws IOException {
// GTInfo info = newInfo();
// GTSimpleMemStore store = new GTSimpleMemStore(info);
// GridTable table = new GridTable(info, store);
//
// GTRecord r = new GTRecord(table.getInfo());
// GTBuilder builder = table.rebuild();
//
// builder.write(r.setValues("2015-01-14", "30", "Yang", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-14", "30", "Luke", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-15", "20", "Dong", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-15", "20", "Jason", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-15", "30", "Xu", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-16", "20", "Mahone", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-16", "20", "Qianhao", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-16", "30", "George", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-16", "30", "Shaofeng", new Long(10), new BigDecimal("10.5")));
// builder.write(r.setValues("2015-01-17", "10", "Kejia", new Long(10), new BigDecimal("10.5")));
// builder.close();
//
// return table;
// }
// static GridTable newTestPerfTable() throws IOException {
// GTInfo info = newInfo();
// GTSimpleMemStore store = new GTSimpleMemStore(info);
// GridTable table = new GridTable(info, store);
//
// GTRecord r = new GTRecord(table.getInfo());
// GTBuilder builder = table.rebuild();
//
// for (int i = 0; i < 100000; i++) {
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-14", "30", "Yang", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-14", "30", "Luke", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-15", "20", "Dong", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-15", "20", "Jason", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-15", "30", "Xu", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-16", "20", "Mahone", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-16", "20", "Qianhao", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-16", "30", "George", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-16", "30", "Shaofeng", new Long(10), new BigDecimal("10.5")));
//
// for (int j = 0; j < 10; j++)
// builder.write(r.setValues("2015-01-17", "10", "Kejia", new Long(10), new BigDecimal("10.5")));
// }
// builder.close();
//
// return table;
// }
// static GTInfo newInfo() {
// Builder builder = GTInfo.builder();
// builder.setCodeSystem(newDictCodeSystem());
// builder.setColumns(//
// DataType.getType("timestamp"), //
// DataType.getType("integer"), //
// DataType.getType("varchar(10)"), //
// DataType.getType("bigint"), //
// DataType.getType("decimal") //
// );
// builder.setPrimaryKey(setOf(0, 1));
// builder.setColumnPreferIndex(setOf(0));
// builder.enableColumnBlock(new ImmutableBitSet[] { setOf(0, 1), setOf(2), setOf(3, 4) });
// builder.enableRowBlock(4);
// GTInfo info = builder.build();
// return info;
// }
// private static CubeCodeSystem newDictCodeSystem() {
// DimensionEncoding[] dimEncs = new DimensionEncoding[3];
// dimEncs[1] = new DictionaryDimEnc(newDictionaryOfInteger());
// dimEncs[2] = new DictionaryDimEnc(newDictionaryOfString());
// return new CubeCodeSystem(dimEncs);
// }
// private static Dictionary newDictionaryOfString() {
// TrieDictionaryBuilder<String> builder = new TrieDictionaryBuilder<>(new StringBytesConverter());
// builder.addValue("Dong");
// builder.addValue("George");
// builder.addValue("Jason");
// builder.addValue("Kejia");
// builder.addValue("Luke");
// builder.addValue("Mahone");
// builder.addValue("Qianhao");
// builder.addValue("Shaofeng");
// builder.addValue("Xu");
// builder.addValue("Yang");
// return builder.build(0);
// }
//
// private static Dictionary newDictionaryOfInteger() {
// NumberDictionaryForestBuilder builder = new NumberDictionaryForestBuilder();
// builder.addValue("10");
// builder.addValue("20");
// builder.addValue("30");
// builder.addValue("40");
// builder.addValue("50");
// builder.addValue("60");
// builder.addValue("70");
// builder.addValue("80");
// builder.addValue("90");
// builder.addValue("100");
// return builder.build();
// }
public static ImmutableBitSet setOf(int... values) {
BitSet set = new BitSet();
for (int i : values)
set.set(i);
return new ImmutableBitSet(set);
}
}