KYLIN-976 Some measures only aggregates in BaseCuboid
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/f9de5a62 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/f9de5a62 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/f9de5a62 Branch: refs/heads/1.x-HBase1.1.3 Commit: f9de5a6247666750a154039cf3f2e88514ab1ad2 Parents: 97c2eac Author: lidongsjtu <don...@ebay.com> Authored: Mon Dec 28 10:36:13 2015 +0800 Committer: lidongsjtu <don...@ebay.com> Committed: Mon Dec 28 10:36:13 2015 +0800 ---------------------------------------------------------------------- .../org/apache/kylin/cube/cuboid/Cuboid.java | 4 + .../kylin/job/constant/BatchConstants.java | 1 + .../apache/kylin/job/hadoop/cube/CuboidJob.java | 2 + .../kylin/job/hadoop/cube/CuboidReducer.java | 17 ++- .../kylin/job/hadoop/cube/CubeReducerTest.java | 107 ++++++++++++-- .../kylin/measure/MeasureAggregators.java | 10 ++ .../org/apache/kylin/measure/MeasureType.java | 13 +- .../kylin/storage/hbase/CubeStorageEngine.java | 11 +- .../storage/hbase/CubeStorageEngineTest.java | 142 +++++++++++++++++++ 9 files changed, 287 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/cube/src/main/java/org/apache/kylin/cube/cuboid/Cuboid.java ---------------------------------------------------------------------- diff --git a/cube/src/main/java/org/apache/kylin/cube/cuboid/Cuboid.java b/cube/src/main/java/org/apache/kylin/cube/cuboid/Cuboid.java index 5ef0c37..7f2b7ab 100644 --- a/cube/src/main/java/org/apache/kylin/cube/cuboid/Cuboid.java +++ b/cube/src/main/java/org/apache/kylin/cube/cuboid/Cuboid.java @@ -88,6 +88,10 @@ public class Cuboid implements Comparable<Cuboid> { return cube.getRowkey().getFullMask(); } + public static Cuboid getBaseCuboid(CubeDesc cube) { + return findById(cube, getBaseCuboidId(cube)); + } + private static long translateToValidCuboid(CubeDesc cubeDesc, long cuboidID) { // add mandantory RowKeyDesc rowkey = cubeDesc.getRowkey(); http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/job/src/main/java/org/apache/kylin/job/constant/BatchConstants.java ---------------------------------------------------------------------- diff --git a/job/src/main/java/org/apache/kylin/job/constant/BatchConstants.java b/job/src/main/java/org/apache/kylin/job/constant/BatchConstants.java index ca8b2c9..38f4a87 100644 --- a/job/src/main/java/org/apache/kylin/job/constant/BatchConstants.java +++ b/job/src/main/java/org/apache/kylin/job/constant/BatchConstants.java @@ -28,6 +28,7 @@ public interface BatchConstants { String CFG_CUBE_NAME = "cube.name"; String CFG_CUBE_SEGMENT_NAME = "cube.segment.name"; + String CFG_CUBE_CUBOID_LEVEL = "cube.cuboid.level"; String CFG_II_NAME = "ii.name"; String CFG_II_SEGMENT_NAME = "ii.segment.name"; http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidJob.java ---------------------------------------------------------------------- diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidJob.java b/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidJob.java index bff9e3a..e4875e9 100644 --- a/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidJob.java +++ b/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidJob.java @@ -115,6 +115,8 @@ public class CuboidJob extends AbstractHadoopJob { // set job configuration job.getConfiguration().set(BatchConstants.CFG_CUBE_NAME, cubeName); job.getConfiguration().set(BatchConstants.CFG_CUBE_SEGMENT_NAME, segmentName); + job.getConfiguration().setInt(BatchConstants.CFG_CUBE_CUBOID_LEVEL, nCuboidLevel); + // add metadata to distributed cache attachKylinPropsAndMetadata(cube, job.getConfiguration()); http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidReducer.java ---------------------------------------------------------------------- diff --git a/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidReducer.java b/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidReducer.java index 4527f30..3859d0e 100644 --- a/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidReducer.java +++ b/job/src/main/java/org/apache/kylin/job/hadoop/cube/CuboidReducer.java @@ -52,6 +52,8 @@ public class CuboidReducer extends KylinReducer<Text, Text, Text, Text> { private MeasureAggregators aggs; private int counter; + private int cuboidLevel; + private boolean[] needAggr; private Object[] input; private Object[] result; @@ -62,6 +64,8 @@ public class CuboidReducer extends KylinReducer<Text, Text, Text, Text> { protected void setup(Context context) throws IOException { super.publishConfiguration(context.getConfiguration()); cubeName = context.getConfiguration().get(BatchConstants.CFG_CUBE_NAME).toUpperCase(); + // only used in Build job, not in Merge job + cuboidLevel = context.getConfiguration().getInt(BatchConstants.CFG_CUBE_CUBOID_LEVEL, 0); KylinConfig config = AbstractHadoopJob.loadKylinPropsAndMetadata(context.getConfiguration()); @@ -73,6 +77,13 @@ public class CuboidReducer extends KylinReducer<Text, Text, Text, Text> { input = new Object[measuresDescs.size()]; result = new Object[measuresDescs.size()]; + needAggr = new boolean[measuresDescs.size()]; + + if (cuboidLevel > 0) { + for (int i = 0; i < measuresDescs.size(); i++) { + needAggr[i] = !measuresDescs.get(i).getFunction().getMeasureType().onlyAggrInBaseCuboid(); + } + } } @Override @@ -82,7 +93,11 @@ public class CuboidReducer extends KylinReducer<Text, Text, Text, Text> { for (Text value : values) { codec.decode(ByteBuffer.wrap(value.getBytes(), 0, value.getLength()), input); - aggs.aggregate(input); + if (cuboidLevel > 0) { + aggs.aggregate(input, needAggr); + } else { + aggs.aggregate(input); + } } aggs.collectStates(result); http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/job/src/test/java/org/apache/kylin/job/hadoop/cube/CubeReducerTest.java ---------------------------------------------------------------------- diff --git a/job/src/test/java/org/apache/kylin/job/hadoop/cube/CubeReducerTest.java b/job/src/test/java/org/apache/kylin/job/hadoop/cube/CubeReducerTest.java index 16cfa89..51f3990 100644 --- a/job/src/test/java/org/apache/kylin/job/hadoop/cube/CubeReducerTest.java +++ b/job/src/test/java/org/apache/kylin/job/hadoop/cube/CubeReducerTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; +import java.lang.reflect.Field; import java.math.BigDecimal; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -37,7 +38,12 @@ import org.apache.kylin.cube.CubeManager; import org.apache.kylin.cube.kv.RowConstants; import org.apache.kylin.cube.model.CubeDesc; import org.apache.kylin.job.constant.BatchConstants; +import org.apache.kylin.measure.MeasureAggregator; import org.apache.kylin.measure.MeasureCodec; +import org.apache.kylin.measure.MeasureIngester; +import org.apache.kylin.measure.MeasureType; +import org.apache.kylin.metadata.model.FunctionDesc; +import org.apache.kylin.metadata.model.MeasureDesc; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -76,18 +82,18 @@ public class CubeReducerTest extends LocalFileMetadataTestCase { Text key1 = new Text("72010ustech"); List<Text> values1 = new ArrayList<Text>(); - values1.add(newValueText(codec, "15.09", "15.09", "15.09", 1,22)); - values1.add(newValueText(codec, "20.34", "20.34", "20.34", 1,23)); - values1.add(newValueText(codec, "10", "10", "10", 1,24)); + values1.add(newValueText(codec, "15.09", "15.09", "15.09", 1, 22)); + values1.add(newValueText(codec, "20.34", "20.34", "20.34", 1, 23)); + values1.add(newValueText(codec, "10", "10", "10", 1, 24)); Text key2 = new Text("1tech"); List<Text> values2 = new ArrayList<Text>(); - values2.add(newValueText(codec, "15.09", "15.09", "15.09", 1,12)); - values2.add(newValueText(codec, "20.34", "20.34", "20.34", 1,13)); + values2.add(newValueText(codec, "15.09", "15.09", "15.09", 1, 12)); + values2.add(newValueText(codec, "20.34", "20.34", "20.34", 1, 13)); Text key3 = new Text("0"); List<Text> values3 = new ArrayList<Text>(); - values3.add(newValueText(codec, "146.52", "146.52", "146.52", 4,11)); + values3.add(newValueText(codec, "146.52", "146.52", "146.52", 4, 11)); reduceDriver.withInput(key1, values1); reduceDriver.withInput(key2, values2); @@ -95,9 +101,9 @@ public class CubeReducerTest extends LocalFileMetadataTestCase { List<Pair<Text, Text>> result = reduceDriver.run(); - Pair<Text, Text> p1 = new Pair<Text, Text>(new Text("72010ustech"), newValueText(codec, "45.43", "10", "20.34", 3,69)); - Pair<Text, Text> p2 = new Pair<Text, Text>(new Text("1tech"), newValueText(codec, "35.43", "15.09", "20.34", 2,25)); - Pair<Text, Text> p3 = new Pair<Text, Text>(new Text("0"), newValueText(codec, "146.52", "146.52", "146.52", 4,11)); + Pair<Text, Text> p1 = new Pair<Text, Text>(new Text("72010ustech"), newValueText(codec, "45.43", "10", "20.34", 3, 69)); + Pair<Text, Text> p2 = new Pair<Text, Text>(new Text("1tech"), newValueText(codec, "35.43", "15.09", "20.34", 2, 25)); + Pair<Text, Text> p3 = new Pair<Text, Text>(new Text("0"), newValueText(codec, "146.52", "146.52", "146.52", 4, 11)); assertEquals(3, result.size()); @@ -106,8 +112,55 @@ public class CubeReducerTest extends LocalFileMetadataTestCase { assertTrue(result.contains(p3)); } - private Text newValueText(MeasureCodec codec, String sum, String min, String max, int count,int itemcount) { - Object[] values = new Object[] { new BigDecimal(sum), new BigDecimal(min), new BigDecimal(max), new LongWritable(count),new LongWritable(itemcount) }; + @Test + public void testReducerOnlyAggrInBaseCuboid() throws Exception { + reduceDriver.getConfiguration().set(BatchConstants.CFG_CUBE_NAME, "test_kylin_cube_with_slr_ready"); + reduceDriver.getConfiguration().setInt(BatchConstants.CFG_CUBE_CUBOID_LEVEL, 1); + + CubeDesc cubeDesc = CubeManager.getInstance(getTestConfig()).getCube("test_kylin_cube_with_slr_ready").getDescriptor(); + MeasureDesc measureDesc = cubeDesc.getMeasures().get(0); + FunctionDesc functionDesc = measureDesc.getFunction(); + Field field = FunctionDesc.class.getDeclaredField("measureType"); + field.setAccessible(true); + MeasureType origMeasureType = functionDesc.getMeasureType(); + field.set(functionDesc, new MockUpMeasureType(origMeasureType)); + + MeasureCodec codec = new MeasureCodec(cubeDesc.getMeasures()); + + Text key1 = new Text("72010ustech"); + List<Text> values1 = new ArrayList<Text>(); + values1.add(newValueText(codec, "15.09", "15.09", "15.09", 1, 100)); + values1.add(newValueText(codec, "20.34", "20.34", "20.34", 1, 200)); + values1.add(newValueText(codec, "10", "10", "10", 1, 300)); + + Text key2 = new Text("1tech"); + List<Text> values2 = new ArrayList<Text>(); + values2.add(newValueText(codec, "15.09", "15.09", "15.09", 1, 500)); + values2.add(newValueText(codec, "20.34", "20.34", "20.34", 1, 1000)); + + Text key3 = new Text("0"); + List<Text> values3 = new ArrayList<Text>(); + values3.add(newValueText(codec, "146.52", "146.52", "146.52", 0, 0)); + + reduceDriver.withInput(key1, values1); + reduceDriver.withInput(key2, values2); + reduceDriver.withInput(key3, values3); + + List<Pair<Text, Text>> result = reduceDriver.run(); + + Pair<Text, Text> p1 = new Pair<Text, Text>(new Text("72010ustech"), newValueText(codec, "0", "10", "20.34", 3, 600)); + Pair<Text, Text> p2 = new Pair<Text, Text>(new Text("1tech"), newValueText(codec, "0", "15.09", "20.34", 2, 1500)); + Pair<Text, Text> p3 = new Pair<Text, Text>(new Text("0"), newValueText(codec, "0", "146.52", "146.52", 0, 0)); + + assertEquals(3, result.size()); + + assertTrue(result.contains(p1)); + assertTrue(result.contains(p2)); + assertTrue(result.contains(p3)); + } + + private Text newValueText(MeasureCodec codec, String sum, String min, String max, int count, int itemcount) { + Object[] values = new Object[] { new BigDecimal(sum), new BigDecimal(min), new BigDecimal(max), new LongWritable(count), new LongWritable(itemcount) }; buf.clear(); codec.encode(values, buf); @@ -117,4 +170,36 @@ public class CubeReducerTest extends LocalFileMetadataTestCase { return t; } + class MockUpMeasureType extends MeasureType { + MeasureType origMeasureType; + + public MockUpMeasureType(MeasureType origMeasureType) { + this.origMeasureType = origMeasureType; + } + + @Override + public boolean onlyAggrInBaseCuboid() { + return true; + } + + @Override + public MeasureIngester newIngester() { + return origMeasureType.newIngester(); + } + + @Override + public MeasureAggregator newAggregator() { + return origMeasureType.newAggregator(); + } + + @Override + public boolean needRewrite() { + return origMeasureType.needRewrite(); + } + + @Override + public Class<?> getRewriteCalciteAggrFunctionClass() { + return origMeasureType.getRewriteCalciteAggrFunctionClass(); + } + } } http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/metadata/src/main/java/org/apache/kylin/measure/MeasureAggregators.java ---------------------------------------------------------------------- diff --git a/metadata/src/main/java/org/apache/kylin/measure/MeasureAggregators.java b/metadata/src/main/java/org/apache/kylin/measure/MeasureAggregators.java index 12832ff..a2cb457 100644 --- a/metadata/src/main/java/org/apache/kylin/measure/MeasureAggregators.java +++ b/metadata/src/main/java/org/apache/kylin/measure/MeasureAggregators.java @@ -72,6 +72,16 @@ public class MeasureAggregators implements Serializable { } } + public void aggregate(Object[] values, boolean[] aggrMask) { + assert values.length == descLength; + assert aggrMask.length == descLength; + + for (int i = 0; i < descLength; i++) { + if (aggrMask[i]) + aggs[i].aggregate(values[i]); + } + } + public void collectStates(Object[] states) { for (int i = 0; i < descLength; i++) { states[i] = aggs[i].getState(); http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/metadata/src/main/java/org/apache/kylin/measure/MeasureType.java ---------------------------------------------------------------------- diff --git a/metadata/src/main/java/org/apache/kylin/measure/MeasureType.java b/metadata/src/main/java/org/apache/kylin/measure/MeasureType.java index 66ca209..661b335 100644 --- a/metadata/src/main/java/org/apache/kylin/measure/MeasureType.java +++ b/metadata/src/main/java/org/apache/kylin/measure/MeasureType.java @@ -39,7 +39,7 @@ import org.apache.kylin.metadata.tuple.TupleInfo; * @param <T> the Java type of aggregation data object, e.g. HyperLogLogPlusCounter */ abstract public class MeasureType<T> { - + /* ============================================================================ * Define * ---------------------------------------------------------------------------- */ @@ -55,7 +55,12 @@ abstract public class MeasureType<T> { public boolean isMemoryHungry() { return false; } - + + /** Return true if this MeasureType only aggregate values in base cuboid, and output initial value in child cuboid. */ + public boolean onlyAggrInBaseCuboid() { + return false; + } + /* ============================================================================ * Build * ---------------------------------------------------------------------------- */ @@ -92,7 +97,7 @@ abstract public class MeasureType<T> { public CapabilityInfluence influenceCapabilityCheck(Collection<TblColRef> unmatchedDimensions, Collection<FunctionDesc> unmatchedAggregations, SQLDigest digest, MeasureDesc measureDesc) { return null; } - + /* ============================================================================ * Query Rewrite * ---------------------------------------------------------------------------- */ @@ -104,7 +109,7 @@ abstract public class MeasureType<T> { /** Returns a Calcite aggregation function implementation class */ abstract public Class<?> getRewriteCalciteAggrFunctionClass(); - + /* ============================================================================ * Storage * ---------------------------------------------------------------------------- */ http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java ---------------------------------------------------------------------- diff --git a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java index e612eb1..626b784 100644 --- a/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java +++ b/storage/src/main/java/org/apache/kylin/storage/hbase/CubeStorageEngine.java @@ -114,7 +114,7 @@ public class CubeStorageEngine implements IStorageEngine { Set<TblColRef> dimensionsD = Sets.newHashSet(); dimensionsD.addAll(groupsD); dimensionsD.addAll(othersD); - Cuboid cuboid = identifyCuboid(dimensionsD); + Cuboid cuboid = identifyCuboid(dimensionsD, metrics); context.setCuboid(cuboid); // isExactAggregation? meaning: tuples returned from storage requires no further aggregation in query engine @@ -163,7 +163,12 @@ public class CubeStorageEngine implements IStorageEngine { } } - private Cuboid identifyCuboid(Set<TblColRef> dimensions) { + private Cuboid identifyCuboid(Set<TblColRef> dimensions, Collection<FunctionDesc> metrics) { + for (FunctionDesc metric : metrics) { + if (metric.getMeasureType().onlyAggrInBaseCuboid()) + return Cuboid.getBaseCuboid(cubeDesc); + } + long cuboidID = 0; for (TblColRef column : dimensions) { int index = cubeDesc.getRowkey().getColumnBitIndex(column); @@ -662,7 +667,6 @@ public class CubeStorageEngine implements IStorageEngine { ObserverEnabler.enableCoprocessorIfBeneficial(cubeInstance, groupsCopD, valueDecoders, context); } - private void notifyBeforeStorageQuery(SQLDigest sqlDigest) { for (MeasureDesc measure : cubeDesc.getMeasures()) { MeasureType<?> measureType = measure.getFunction().getMeasureType(); @@ -670,5 +674,4 @@ public class CubeStorageEngine implements IStorageEngine { } } - } http://git-wip-us.apache.org/repos/asf/kylin/blob/f9de5a62/storage/src/test/java/org/apache/kylin/storage/hbase/CubeStorageEngineTest.java ---------------------------------------------------------------------- diff --git a/storage/src/test/java/org/apache/kylin/storage/hbase/CubeStorageEngineTest.java b/storage/src/test/java/org/apache/kylin/storage/hbase/CubeStorageEngineTest.java new file mode 100644 index 0000000..d41a836 --- /dev/null +++ b/storage/src/test/java/org/apache/kylin/storage/hbase/CubeStorageEngineTest.java @@ -0,0 +1,142 @@ +/* + * 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.hbase; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import org.apache.kylin.common.util.LocalFileMetadataTestCase; +import org.apache.kylin.cube.CubeInstance; +import org.apache.kylin.cube.CubeManager; +import org.apache.kylin.cube.cuboid.Cuboid; +import org.apache.kylin.cube.model.CubeDesc; +import org.apache.kylin.measure.MeasureAggregator; +import org.apache.kylin.measure.MeasureIngester; +import org.apache.kylin.measure.MeasureType; +import org.apache.kylin.metadata.MetadataManager; +import org.apache.kylin.metadata.model.FunctionDesc; +import org.apache.kylin.metadata.model.MeasureDesc; +import org.apache.kylin.metadata.model.TblColRef; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +/** + * Created by dongli on 12/28/15. + */ +public class CubeStorageEngineTest extends LocalFileMetadataTestCase { + + private CubeInstance cube; + + public CubeManager getCubeManager() { + return CubeManager.getInstance(getTestConfig()); + } + + private CubeInstance getTestKylinCubeWithSeller() { + return getCubeManager().getCube("test_kylin_cube_with_slr_empty"); + } + + @Before + public void setUp() throws Exception { + this.createTestMetadata(); + MetadataManager.clearCache(); + + cube = getTestKylinCubeWithSeller(); + } + + @After + public void after() throws Exception { + this.cleanupTestMetadata(); + } + + @Test + public void testIdentifyCuboid() { + CubeDesc cubeDesc = cube.getDescriptor(); + CubeStorageEngine engine = new CubeStorageEngine(cube); + long baseCuboidId = cubeDesc.getRowkey().getFullMask(); + + try { + Method method = engine.getClass().getDeclaredMethod("identifyCuboid", Set.class, Collection.class); + method.setAccessible(true); + + Set<TblColRef> dimensions = Sets.newHashSet(); + List<FunctionDesc> metrics = Lists.newArrayList(); + + Object ret = method.invoke(engine, dimensions, metrics); + + assertTrue(ret instanceof Cuboid); + assertNotEquals(baseCuboidId, ((Cuboid) ret).getId()); + + for (MeasureDesc measureDesc : cubeDesc.getMeasures()) { + Collections.addAll(metrics, measureDesc.getFunction()); + } + + FunctionDesc mockUpFuncDesc = new FunctionDesc(); + Field field = FunctionDesc.class.getDeclaredField("measureType"); + field.setAccessible(true); + field.set(mockUpFuncDesc, new MockUpMeasureType()); + metrics.add(mockUpFuncDesc); + + ret = method.invoke(engine, dimensions, metrics); + assertEquals(baseCuboidId, ((Cuboid) ret).getId()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + class MockUpMeasureType extends MeasureType<String> { + + @Override + public MeasureIngester<String> newIngester() { + return null; + } + + @Override + public MeasureAggregator<String> newAggregator() { + return null; + } + + @Override + public boolean needRewrite() { + return false; + } + + @Override + public Class<?> getRewriteCalciteAggrFunctionClass() { + return null; + } + + @Override + public boolean onlyAggrInBaseCuboid() { + return true; + } + } +}