/** * Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com) * * Licensed 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 com.linkedin.pinot.queries; import com.linkedin.pinot.common.data.FieldSpec; import com.linkedin.pinot.common.data.Schema; import com.linkedin.pinot.common.segment.ReadMode; import com.linkedin.pinot.core.data.manager.offline.OfflineSegmentDataManager; import com.linkedin.pinot.core.data.manager.offline.SegmentDataManager; import com.linkedin.pinot.core.indexsegment.IndexSegment; import com.linkedin.pinot.core.indexsegment.columnar.ColumnarSegmentLoader; import com.linkedin.pinot.core.indexsegment.generator.SegmentGeneratorConfig; import com.linkedin.pinot.core.segment.creator.SegmentIndexCreationDriver; import com.linkedin.pinot.core.segment.creator.impl.SegmentIndexCreationDriverImpl; import java.io.File; import java.net.URL; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.commons.io.FileUtils; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeTest; /** * The <code>BaseMultiValueQueriesTest</code> class sets up the index segment for the multi-value queries test. * <p>There are totally 14 columns, 100000 records inside the original Avro file where 10 columns are selected to build * the index segment. Selected columns information are as following: * <ul> * ColumnName, FieldType, DataType, Cardinality, IsSorted, HasInvertedIndex, IsMultiValue * <li>column1, METRIC, INT, 51594, F, F, F</li> * <li>column2, METRIC, INT, 42242, F, F, F</li> * <li>column3, DIMENSION, STRING, 5, F, T, F</li> * <li>column5, DIMENSION, STRING, 9, F, F, F</li> * <li>column6, DIMENSION, INT, 18499, F, F, T</li> * <li>column7, DIMENSION, INT, 359, F, T, T</li> * <li>column8, DIMENSION, INT, 850, F, T, F</li> * <li>column9, METRIC, INT, 146, F, T, F</li> * <li>column10, METRIC, INT, 3960, F, F, F</li> * <li>daysSinceEpoch, TIME, INT, 1, T, F, F</li> * </ul> */ public abstract class BaseMultiValueQueriesTest extends BaseQueriesTest { private static final String AVRO_DATA = "data/test_data-mv.avro"; private static final String SEGMENT_NAME = "testTable_1756015683_1756015683"; private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(), "MultiValueQueriesTest"); // Hard-coded query filter. private static final String QUERY_FILTER = " WHERE column1 > 100000000" + " AND column2 BETWEEN 20000000 AND 1000000000" + " AND column3 <> 'w'" + " AND (column6 < 500000 OR column7 NOT IN (225, 407))" + " AND daysSinceEpoch = 1756015683"; private IndexSegment _indexSegment; // Contains 2 identical index segments. private List<SegmentDataManager> _segmentDataManagers; @BeforeTest public void buildSegment() throws Exception { FileUtils.deleteQuietly(INDEX_DIR); // Get resource file path. URL resource = getClass().getClassLoader().getResource(AVRO_DATA); Assert.assertNotNull(resource); String filePath = resource.getFile(); // Build the segment schema. Schema schema = new Schema.SchemaBuilder().setSchemaName("testTable") .addMetric("column1", FieldSpec.DataType.INT) .addMetric("column2", FieldSpec.DataType.INT) .addSingleValueDimension("column3", FieldSpec.DataType.STRING) .addSingleValueDimension("column5", FieldSpec.DataType.STRING) .addMultiValueDimension("column6", FieldSpec.DataType.INT) .addMultiValueDimension("column7", FieldSpec.DataType.INT) .addSingleValueDimension("column8", FieldSpec.DataType.INT) .addMetric("column9", FieldSpec.DataType.INT) .addMetric("column10", FieldSpec.DataType.INT) .addTime("daysSinceEpoch", TimeUnit.DAYS, FieldSpec.DataType.INT) .build(); // Create the segment generator config. SegmentGeneratorConfig segmentGeneratorConfig = new SegmentGeneratorConfig(schema); segmentGeneratorConfig.setInputFilePath(filePath); segmentGeneratorConfig.setTableName("testTable"); segmentGeneratorConfig.setOutDir(INDEX_DIR.getAbsolutePath()); segmentGeneratorConfig.setInvertedIndexCreationColumns(Arrays.asList("column3", "column7", "column8", "column9")); // Build the index segment. SegmentIndexCreationDriver driver = new SegmentIndexCreationDriverImpl(); driver.init(segmentGeneratorConfig); driver.build(); } @BeforeClass public void loadSegment() throws Exception { File indexSegmentDir = new File(INDEX_DIR, SEGMENT_NAME); _indexSegment = ColumnarSegmentLoader.load(indexSegmentDir, ReadMode.heap); _segmentDataManagers = Arrays.<SegmentDataManager>asList(new OfflineSegmentDataManager(_indexSegment), new OfflineSegmentDataManager(_indexSegment)); } @AfterClass public void destroySegment() { _indexSegment.destroy(); } @AfterTest public void deleteSegment() { FileUtils.deleteQuietly(INDEX_DIR); } @Override protected String getFilter() { return QUERY_FILTER; } @Override protected IndexSegment getIndexSegment() { return _indexSegment; } @Override protected List<SegmentDataManager> getSegmentDataManagers() { return _segmentDataManagers; } }