|
20 | 20 |
|
21 | 21 | import java.io.File; |
22 | 22 | import java.net.URL; |
23 | | -import java.util.ArrayList; |
24 | | -import java.util.Arrays; |
25 | | -import java.util.Collections; |
26 | | -import java.util.HashSet; |
27 | 23 | import java.util.List; |
28 | 24 | import java.util.Map; |
29 | | -import java.util.concurrent.TimeUnit; |
30 | 25 | import org.apache.commons.io.FileUtils; |
31 | 26 | import org.apache.pinot.common.response.broker.BrokerResponseNative; |
32 | 27 | import org.apache.pinot.common.response.broker.ResultTable; |
|
39 | 34 | import org.apache.pinot.segment.spi.IndexSegment; |
40 | 35 | import org.apache.pinot.segment.spi.creator.SegmentGeneratorConfig; |
41 | 36 | import org.apache.pinot.segment.spi.creator.SegmentIndexCreationDriver; |
42 | | -import org.apache.pinot.segment.spi.index.ForwardIndexConfig; |
43 | | -import org.apache.pinot.segment.spi.index.StandardIndexes; |
44 | 37 | import org.apache.pinot.spi.config.table.FieldConfig; |
45 | | -import org.apache.pinot.spi.config.table.IndexConfig; |
46 | 38 | import org.apache.pinot.spi.config.table.TableConfig; |
47 | 39 | import org.apache.pinot.spi.config.table.TableType; |
48 | | -import org.apache.pinot.spi.data.FieldSpec; |
| 40 | +import org.apache.pinot.spi.data.FieldSpec.DataType; |
49 | 41 | import org.apache.pinot.spi.data.Schema; |
50 | | -import org.apache.pinot.spi.data.TimeGranularitySpec; |
51 | | -import org.apache.pinot.spi.utils.ReadMode; |
52 | 42 | import org.apache.pinot.spi.utils.builder.TableConfigBuilder; |
53 | 43 | import org.testng.Assert; |
54 | | -import org.testng.annotations.AfterMethod; |
55 | | -import org.testng.annotations.BeforeMethod; |
| 44 | +import org.testng.annotations.AfterClass; |
| 45 | +import org.testng.annotations.BeforeClass; |
56 | 46 | import org.testng.annotations.Test; |
57 | 47 |
|
58 | 48 | import static org.testng.Assert.*; |
|
78 | 68 | * </ul> |
79 | 69 | */ |
80 | 70 | public class ForwardIndexDisabledMultiValueQueriesTest extends BaseQueriesTest { |
| 71 | + private static final File INDEX_DIR = |
| 72 | + new File(FileUtils.getTempDirectory(), ForwardIndexDisabledMultiValueQueriesTest.class.getSimpleName()); |
81 | 73 | private static final String AVRO_DATA = "data" + File.separator + "test_data-mv.avro"; |
82 | | - private static final String SEGMENT_NAME_1 = "testTable_1756015688_1756015688"; |
83 | | - private static final String SEGMENT_NAME_2 = "testTable_1756015689_1756015689"; |
84 | | - private static final File INDEX_DIR = new File(FileUtils.getTempDirectory(), |
85 | | - "ForwardIndexDisabledMultiValueQueriesTest"); |
| 74 | + private static final String RAW_TABLE_NAME = "testTable"; |
| 75 | + private static final String SEGMENT_NAME = "testSegment"; |
86 | 76 |
|
87 | 77 | private static final String SELECT_STAR_QUERY = "SELECT * FROM testTable"; |
88 | 78 |
|
89 | | - // Hard-coded query filter. |
| 79 | + //@formatter:off |
| 80 | + // Hard-coded query filter |
90 | 81 | protected static final String FILTER = " WHERE column1 > 100000000" |
91 | 82 | + " AND column2 BETWEEN 20000000 AND 1000000000" |
92 | 83 | + " AND column3 <> 'w'" |
93 | 84 | + " AND (column6 < 500000 OR column7 NOT IN (225, 407))" |
94 | 85 | + " AND daysSinceEpoch = 1756015683"; |
| 86 | + //@formatter:on |
95 | 87 |
|
96 | 88 | private IndexSegment _indexSegment; |
97 | 89 | // Contains 2 identical index segments. |
98 | 90 | private List<IndexSegment> _indexSegments; |
99 | 91 |
|
100 | | - private TableConfig _tableConfig; |
101 | | - private List<String> _invertedIndexColumns; |
102 | | - private List<String> _forwardIndexDisabledColumns; |
103 | | - |
104 | | - @BeforeMethod |
105 | | - public void buildSegment() |
| 92 | + @BeforeClass |
| 93 | + public void setUp() |
106 | 94 | throws Exception { |
107 | 95 | FileUtils.deleteQuietly(INDEX_DIR); |
108 | 96 |
|
109 | | - // Get resource file path. |
| 97 | + //@formatter:off |
| 98 | + Schema schema = new Schema.SchemaBuilder().setSchemaName(RAW_TABLE_NAME) |
| 99 | + .addMetric("column1", DataType.INT) |
| 100 | + .addMetric("column2", DataType.INT) |
| 101 | + .addSingleValueDimension("column3", DataType.STRING) |
| 102 | + .addSingleValueDimension("column5", DataType.STRING) |
| 103 | + .addMultiValueDimension("column6", DataType.INT) |
| 104 | + .addMultiValueDimension("column7", DataType.INT) |
| 105 | + .addSingleValueDimension("column8", DataType.INT) |
| 106 | + .addMetric("column9", DataType.INT) |
| 107 | + .addMetric("column10", DataType.INT) |
| 108 | + .addDateTime("daysSinceEpoch", DataType.INT, "EPOCH|DAYS", "1:DAYS") |
| 109 | + .build(); |
| 110 | + |
| 111 | + List<FieldConfig> fieldConfigs = List.of( |
| 112 | + new FieldConfig("column6", FieldConfig.EncodingType.DICTIONARY, List.of(), null, |
| 113 | + Map.of(FieldConfig.FORWARD_INDEX_DISABLED, "true")), |
| 114 | + new FieldConfig("column7", FieldConfig.EncodingType.DICTIONARY, List.of(), null, |
| 115 | + Map.of(FieldConfig.FORWARD_INDEX_DISABLED, "true"))); |
| 116 | + TableConfig tableConfig = new TableConfigBuilder(TableType.OFFLINE).setTableName(RAW_TABLE_NAME) |
| 117 | + .setTimeColumnName("daysSinceEpoch") |
| 118 | + .setNoDictionaryColumns(List.of("column5")) |
| 119 | + .setInvertedIndexColumns(List.of("column3", "column6", "column7", "column8", "column9")) |
| 120 | + .setCreateInvertedIndexDuringSegmentGeneration(true) |
| 121 | + .setFieldConfigList(fieldConfigs) |
| 122 | + .build(); |
| 123 | + //@formatter:on |
| 124 | + |
110 | 125 | URL resource = getClass().getClassLoader().getResource(AVRO_DATA); |
111 | 126 | assertNotNull(resource); |
112 | | - String filePath = resource.getFile(); |
113 | | - |
114 | | - // Build the segment schema. |
115 | | - Schema schema = new Schema.SchemaBuilder().setSchemaName("testTable").addMetric("column1", FieldSpec.DataType.INT) |
116 | | - .addMetric("column2", FieldSpec.DataType.INT).addSingleValueDimension("column3", FieldSpec.DataType.STRING) |
117 | | - .addSingleValueDimension("column5", FieldSpec.DataType.STRING) |
118 | | - .addMultiValueDimension("column6", FieldSpec.DataType.INT) |
119 | | - .addMultiValueDimension("column7", FieldSpec.DataType.INT) |
120 | | - .addSingleValueDimension("column8", FieldSpec.DataType.INT).addMetric("column9", FieldSpec.DataType.INT) |
121 | | - .addMetric("column10", FieldSpec.DataType.INT) |
122 | | - .addTime(new TimeGranularitySpec(FieldSpec.DataType.INT, TimeUnit.DAYS, "daysSinceEpoch"), null).build(); |
123 | | - |
124 | | - createSegment(filePath, SEGMENT_NAME_1, schema); |
125 | | - createSegment(filePath, SEGMENT_NAME_2, schema); |
126 | | - |
127 | | - ImmutableSegment immutableSegment1 = loadSegmentWithMetadataChecks(SEGMENT_NAME_1); |
128 | | - ImmutableSegment immutableSegment2 = loadSegmentWithMetadataChecks(SEGMENT_NAME_2); |
129 | | - |
130 | | - _indexSegment = immutableSegment1; |
131 | | - _indexSegments = Arrays.asList(immutableSegment1, immutableSegment2); |
132 | | - } |
133 | | - |
134 | | - private void createSegment(String filePath, String segmentName, Schema schema) |
135 | | - throws Exception { |
136 | | - // Create field configs for the no forward index columns |
137 | | - List<FieldConfig> fieldConfigList = new ArrayList<>(); |
138 | | - fieldConfigList.add(new FieldConfig("column6", FieldConfig.EncodingType.DICTIONARY, Collections.emptyList(), null, |
139 | | - Collections.singletonMap(FieldConfig.FORWARD_INDEX_DISABLED, Boolean.TRUE.toString()))); |
140 | | - if (segmentName.equals(SEGMENT_NAME_1)) { |
141 | | - fieldConfigList.add(new FieldConfig("column7", FieldConfig.EncodingType.DICTIONARY, Collections.emptyList(), |
142 | | - null, Collections.singletonMap(FieldConfig.FORWARD_INDEX_DISABLED, Boolean.TRUE.toString()))); |
| 127 | + String avroFile = resource.getFile(); |
143 | 128 |
|
144 | | - // Build table config based on segment 1 as it contains both columns under no forward index |
145 | | - _tableConfig = new TableConfigBuilder(TableType.OFFLINE).setNoDictionaryColumns(Arrays.asList("column5")) |
146 | | - .setTableName("testTable").setTimeColumnName("daysSinceEpoch").setFieldConfigList(fieldConfigList).build(); |
147 | | - } |
148 | | - |
149 | | - // Create the segment generator config. |
150 | | - SegmentGeneratorConfig segmentGeneratorConfig = new SegmentGeneratorConfig(_tableConfig, schema); |
151 | | - segmentGeneratorConfig.setInputFilePath(filePath); |
152 | | - segmentGeneratorConfig.setTableName("testTable"); |
153 | | - segmentGeneratorConfig.setOutDir(INDEX_DIR.getAbsolutePath()); |
154 | | - segmentGeneratorConfig.setSegmentName(segmentName); |
155 | | - _invertedIndexColumns = Arrays.asList("column3", "column6", "column7", "column8", "column9"); |
156 | | - segmentGeneratorConfig.setIndexOn(StandardIndexes.inverted(), IndexConfig.ENABLED, _invertedIndexColumns); |
157 | | - _forwardIndexDisabledColumns = new ArrayList<>(Arrays.asList("column6", "column7")); |
158 | | - segmentGeneratorConfig.setIndexOn(StandardIndexes.forward(), ForwardIndexConfig.DISABLED, |
159 | | - _forwardIndexDisabledColumns); |
160 | | - // The segment generation code in SegmentColumnarIndexCreator will throw |
161 | | - // exception if start and end time in time column are not in acceptable |
162 | | - // range. For this test, we first need to fix the input avro data |
163 | | - // to have the time column values in allowed range. Until then, the check |
164 | | - // is explicitly disabled |
165 | | - segmentGeneratorConfig.setSkipTimeValueCheck(true); |
166 | | - |
167 | | - // Build the index segment. |
| 129 | + SegmentGeneratorConfig generatorConfig = new SegmentGeneratorConfig(tableConfig, schema); |
| 130 | + generatorConfig.setInputFilePath(avroFile); |
| 131 | + generatorConfig.setOutDir(INDEX_DIR.getAbsolutePath()); |
| 132 | + generatorConfig.setSegmentName(SEGMENT_NAME); |
| 133 | + generatorConfig.setSkipTimeValueCheck(true); |
168 | 134 | SegmentIndexCreationDriver driver = new SegmentIndexCreationDriverImpl(); |
169 | | - driver.init(segmentGeneratorConfig); |
| 135 | + driver.init(generatorConfig); |
170 | 136 | driver.build(); |
171 | | - } |
172 | 137 |
|
173 | | - private ImmutableSegment loadSegmentWithMetadataChecks(String segmentName) |
174 | | - throws Exception { |
175 | | - IndexLoadingConfig indexLoadingConfig = new IndexLoadingConfig(); |
176 | | - indexLoadingConfig.setTableConfig(_tableConfig); |
177 | | - indexLoadingConfig.setInvertedIndexColumns(new HashSet<>(_invertedIndexColumns)); |
178 | | - indexLoadingConfig.setForwardIndexDisabledColumns(new HashSet<>(_forwardIndexDisabledColumns)); |
179 | | - indexLoadingConfig.setReadMode(ReadMode.heap); |
180 | | - |
181 | | - ImmutableSegment immutableSegment = ImmutableSegmentLoader.load(new File(INDEX_DIR, segmentName), |
182 | | - indexLoadingConfig); |
183 | | - |
184 | | - Map<String, ColumnMetadata> columnMetadataMap1 = immutableSegment.getSegmentMetadata().getColumnMetadataMap(); |
185 | | - columnMetadataMap1.forEach((column, metadata) -> { |
| 138 | + ImmutableSegment segment = ImmutableSegmentLoader.load(new File(INDEX_DIR, SEGMENT_NAME), |
| 139 | + new IndexLoadingConfig(tableConfig, schema)); |
| 140 | + Map<String, ColumnMetadata> columnMetadataMap = segment.getSegmentMetadata().getColumnMetadataMap(); |
| 141 | + for (Map.Entry<String, ColumnMetadata> entry : columnMetadataMap.entrySet()) { |
| 142 | + String column = entry.getKey(); |
| 143 | + ColumnMetadata metadata = entry.getValue(); |
186 | 144 | if (column.equals("column6") || column.equals("column7")) { |
187 | 145 | assertTrue(metadata.hasDictionary()); |
188 | 146 | assertFalse(metadata.isSingleValue()); |
189 | | - assertNull(immutableSegment.getForwardIndex(column)); |
| 147 | + assertNull(segment.getForwardIndex(column)); |
190 | 148 | } else { |
191 | | - assertNotNull(immutableSegment.getForwardIndex(column)); |
| 149 | + assertNotNull(segment.getForwardIndex(column)); |
192 | 150 | } |
193 | | - }); |
| 151 | + } |
194 | 152 |
|
195 | | - return immutableSegment; |
| 153 | + _indexSegment = segment; |
| 154 | + _indexSegments = List.of(segment, segment); |
196 | 155 | } |
197 | 156 |
|
198 | | - @AfterMethod |
199 | | - public void deleteAndDestroySegment() { |
| 157 | + @AfterClass |
| 158 | + public void tearDown() { |
| 159 | + _indexSegment.destroy(); |
200 | 160 | FileUtils.deleteQuietly(INDEX_DIR); |
201 | | - _indexSegments.forEach((IndexSegment::destroy)); |
202 | 161 | } |
203 | 162 |
|
204 | 163 | @Override |
|
0 commit comments