diff --git a/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java b/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java index 84767c99201f..1a5100f797ce 100644 --- a/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java +++ b/pinot-common/src/test/java/org/apache/pinot/common/utils/config/TableConfigSerDeUtilsTest.java @@ -242,6 +242,10 @@ public void testSerDe() new FieldConfig("column3", FieldConfig.EncodingType.RAW, Collections.emptyList(), FieldConfig.CompressionCodec.SNAPPY, null)); TableConfig tableConfig = tableConfigBuilder.setFieldConfigList(fieldConfigList).build(); + String tableConfigJson = tableConfig.toJsonString(); + assertTrue(tableConfigJson.contains("\"indexes\"")); + assertFalse(tableConfigJson.contains("\"indexTypes\"")); + assertFalse(tableConfigJson.contains("\"indexType\"")); checkFieldConfig(tableConfig); diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexType.java index b67c7c77f2de..81da8309caa7 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexType.java @@ -31,10 +31,8 @@ import org.apache.pinot.segment.spi.V1Constants; import org.apache.pinot.segment.spi.creator.IndexCreationContext; import org.apache.pinot.segment.spi.index.AbstractIndexType; -import org.apache.pinot.segment.spi.index.ColumnConfigDeserializer; import org.apache.pinot.segment.spi.index.FieldIndexConfigs; import org.apache.pinot.segment.spi.index.FstIndexConfig; -import org.apache.pinot.segment.spi.index.IndexConfigDeserializer; import org.apache.pinot.segment.spi.index.IndexHandler; import org.apache.pinot.segment.spi.index.IndexReaderConstraintException; import org.apache.pinot.segment.spi.index.IndexReaderFactory; @@ -44,7 +42,6 @@ import org.apache.pinot.segment.spi.index.reader.TextIndexReader; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; import org.apache.pinot.spi.data.Schema; @@ -91,12 +88,6 @@ public String getPrettyName() { return INDEX_DISPLAY_NAME; } - @Override - protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { - return IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.FST, - (tableConfig, fieldConfig) -> new FstIndexConfig(false)); - } - @Override public FSTIndexCreator createIndexCreator(IndexCreationContext context, FstIndexConfig indexConfig) throws IOException { diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/IFSTIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/IFSTIndexType.java index 790f576d8c87..9d9f66d2b6d8 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/IFSTIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/fst/IFSTIndexType.java @@ -30,10 +30,8 @@ import org.apache.pinot.segment.spi.V1Constants; import org.apache.pinot.segment.spi.creator.IndexCreationContext; import org.apache.pinot.segment.spi.index.AbstractIndexType; -import org.apache.pinot.segment.spi.index.ColumnConfigDeserializer; import org.apache.pinot.segment.spi.index.FieldIndexConfigs; import org.apache.pinot.segment.spi.index.FstIndexConfig; -import org.apache.pinot.segment.spi.index.IndexConfigDeserializer; import org.apache.pinot.segment.spi.index.IndexHandler; import org.apache.pinot.segment.spi.index.IndexReaderConstraintException; import org.apache.pinot.segment.spi.index.IndexReaderFactory; @@ -43,7 +41,6 @@ import org.apache.pinot.segment.spi.index.reader.TextIndexReader; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; import org.apache.pinot.spi.data.Schema; @@ -87,12 +84,6 @@ public String getPrettyName() { return INDEX_DISPLAY_NAME; } - @Override - protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { - return IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.IFST, - (tableConfig, fieldConfig) -> new FstIndexConfig(false)); - } - @Override public FSTIndexCreator createIndexCreator(IndexCreationContext context, FstIndexConfig indexConfig) throws IOException { diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/h3/H3IndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/h3/H3IndexType.java index 194ae655f588..17bb624b67f7 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/h3/H3IndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/h3/H3IndexType.java @@ -19,6 +19,7 @@ package org.apache.pinot.segment.local.segment.index.h3; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Preconditions; import java.io.IOException; import java.io.UncheckedIOException; @@ -51,11 +52,11 @@ import org.apache.pinot.segment.spi.index.reader.H3IndexResolution; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; import org.apache.pinot.spi.data.FieldSpec.DataType; import org.apache.pinot.spi.data.Schema; +import org.apache.pinot.spi.utils.JsonUtils; public class H3IndexType extends AbstractIndexType { @@ -94,9 +95,18 @@ public String getPrettyName() { } @Override - protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { - return IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.H3, - (tableConfig, fieldConfig) -> new H3IndexConfig(fieldConfig.getProperties())); + protected ColumnConfigDeserializer createDeserializer() { + return IndexConfigDeserializer.fromIndexes(getPrettyName(), (tableConfig, fieldConfig) -> { + JsonNode indexNode = fieldConfig.getIndexes().get(getPrettyName()); + if (IndexConfigDeserializer.isEnabledOnlyConfig(indexNode)) { + return new H3IndexConfig(fieldConfig.getProperties()); + } + try { + return JsonUtils.jsonNodeToObject(indexNode, H3IndexConfig.class); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); } @Override diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexType.java index 8988ef818eb6..6ceea4a60d3e 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexType.java @@ -51,7 +51,6 @@ import org.apache.pinot.segment.spi.index.reader.SortedIndexReader; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.IndexConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; @@ -96,13 +95,9 @@ public String getPrettyName() { @Override protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { - ColumnConfigDeserializer fromInvertedIndexColumns = - IndexConfigDeserializer.fromCollection(tableConfig -> tableConfig.getIndexingConfig().getInvertedIndexColumns(), - (acum, column) -> acum.put(column, IndexConfig.ENABLED)); - ColumnConfigDeserializer fromFieldConfigs = - IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.INVERTED, - (tableConfig, fieldConfig) -> IndexConfig.ENABLED); - return fromInvertedIndexColumns.withFallbackAlternative(fromFieldConfigs); + return IndexConfigDeserializer.fromCollection( + tableConfig -> tableConfig.getIndexingConfig().getInvertedIndexColumns(), + (acum, column) -> acum.put(column, IndexConfig.ENABLED)); } public DictionaryBasedInvertedIndexCreator createIndexCreator(IndexCreationContext context) diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/json/JsonIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/json/JsonIndexType.java index 17ded67a0e01..409babd2fe45 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/json/JsonIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/json/JsonIndexType.java @@ -48,7 +48,6 @@ import org.apache.pinot.segment.spi.index.reader.JsonIndexReader; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.JsonIndexConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; @@ -100,10 +99,7 @@ protected ColumnConfigDeserializer createDeserializerForLegacyC ColumnConfigDeserializer fromJsonIndexColumns = IndexConfigDeserializer.fromCollection(tableConfig -> tableConfig.getIndexingConfig().getJsonIndexColumns(), (accum, column) -> accum.put(column, JsonIndexConfig.DEFAULT)); - ColumnConfigDeserializer fromFieldConfigs = - IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.JSON, - (tableConfig, fieldConfig) -> JsonIndexConfig.DEFAULT); - return fromJsonIndexConfigs.withFallbackAlternative(fromJsonIndexColumns).withFallbackAlternative(fromFieldConfigs); + return fromJsonIndexConfigs.withFallbackAlternative(fromJsonIndexColumns); } @Override diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/range/RangeIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/range/RangeIndexType.java index 0e34761c6066..f4a29c8c7a9f 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/range/RangeIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/range/RangeIndexType.java @@ -19,6 +19,7 @@ package org.apache.pinot.segment.local.segment.index.range; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Preconditions; import java.io.IOException; import java.util.Collections; @@ -48,7 +49,6 @@ import org.apache.pinot.segment.spi.index.reader.RangeIndexReader; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; import org.apache.pinot.spi.data.FieldSpec.DataType; @@ -93,6 +93,16 @@ public String getPrettyName() { return INDEX_DISPLAY_NAME; } + @Override + protected ColumnConfigDeserializer createDeserializer() { + return IndexConfigDeserializer.fromIndexes(getPrettyName(), (tableConfig, fieldConfig) -> { + JsonNode indexNode = fieldConfig.getIndexes().get(getPrettyName()); + Boolean disabled = indexNode.has("disabled") ? indexNode.get("disabled").asBoolean() : null; + Integer version = indexNode.has("version") ? indexNode.get("version").asInt() : getRangeIndexVersion(tableConfig); + return new RangeIndexConfig(disabled, version); + }).withExclusiveAlternative(createDeserializerForLegacyConfigs()); + } + @Override protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { ColumnConfigDeserializer fromRangeIndexColumns = (tableConfig, schema) -> { @@ -110,10 +120,7 @@ protected ColumnConfigDeserializer createDeserializerForLegacy } return result; }; - ColumnConfigDeserializer fromIndexTypes = - IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.RANGE, - (tableConfig, fieldConfig) -> new RangeIndexConfig(getRangeIndexVersion(tableConfig))); - return fromRangeIndexColumns.withFallbackAlternative(fromIndexTypes); + return fromRangeIndexColumns; } private static int getRangeIndexVersion(TableConfig tableConfig) { diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/text/TextIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/text/TextIndexType.java index fe634b0602f8..11ad5e8c5694 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/text/TextIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/text/TextIndexType.java @@ -19,10 +19,12 @@ package org.apache.pinot.segment.local.segment.index.text; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -48,10 +50,10 @@ import org.apache.pinot.segment.spi.index.reader.TextIndexReader; import org.apache.pinot.segment.spi.memory.PinotDataBuffer; import org.apache.pinot.segment.spi.store.SegmentDirectory; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; import org.apache.pinot.spi.data.Schema; +import org.apache.pinot.spi.utils.JsonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,9 +97,19 @@ public String getPrettyName() { } @Override - protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { - return IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.TEXT, - (tableConfig, fieldConfig) -> new TextIndexConfigBuilder().withProperties(fieldConfig.getProperties()).build()); + protected ColumnConfigDeserializer createDeserializer() { + return IndexConfigDeserializer.fromIndexes(getPrettyName(), (tableConfig, fieldConfig) -> { + JsonNode indexNode = fieldConfig.getIndexes().get(getPrettyName()); + TextIndexConfig indexConfig; + try { + indexConfig = JsonUtils.jsonNodeToObject(indexNode, TextIndexConfig.class); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return IndexConfigDeserializer.isEnabledOnlyConfig(indexNode) + ? new TextIndexConfigBuilder(indexConfig).withProperties(fieldConfig.getProperties()).build() + : indexConfig; + }); } @Override diff --git a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/vector/VectorIndexType.java b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/vector/VectorIndexType.java index 0cfab63d1266..8abbf5cba1c4 100644 --- a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/vector/VectorIndexType.java +++ b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/vector/VectorIndexType.java @@ -18,9 +18,11 @@ */ package org.apache.pinot.segment.local.segment.index.vector; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.base.Preconditions; import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.List; import java.util.Map; import javax.annotation.Nullable; @@ -51,10 +53,10 @@ import org.apache.pinot.segment.spi.index.reader.VectorIndexReader; import org.apache.pinot.segment.spi.store.SegmentDirectory; import org.apache.pinot.segment.spi.store.SegmentDirectoryPaths; -import org.apache.pinot.spi.config.table.FieldConfig; import org.apache.pinot.spi.config.table.TableConfig; import org.apache.pinot.spi.data.FieldSpec; import org.apache.pinot.spi.data.Schema; +import org.apache.pinot.spi.utils.JsonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -120,9 +122,18 @@ public String getPrettyName() { } @Override - protected ColumnConfigDeserializer createDeserializerForLegacyConfigs() { - return IndexConfigDeserializer.fromIndexTypes(FieldConfig.IndexType.VECTOR, - (tableConfig, fieldConfig) -> new VectorIndexConfig(fieldConfig.getProperties())); + protected ColumnConfigDeserializer createDeserializer() { + return IndexConfigDeserializer.fromIndexes(getPrettyName(), (tableConfig, fieldConfig) -> { + JsonNode indexNode = fieldConfig.getIndexes().get(getPrettyName()); + if (IndexConfigDeserializer.isEnabledOnlyConfig(indexNode)) { + return new VectorIndexConfig(fieldConfig.getProperties()); + } + try { + return JsonUtils.jsonNodeToObject(indexNode, VectorIndexConfig.class); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); } @Override diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/H3IndexTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/H3IndexTest.java index 2ea6ae55e643..42243b744f26 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/H3IndexTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/H3IndexTest.java @@ -60,7 +60,6 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; public class H3IndexTest implements PinotBuffersAfterMethodCheckRule { @@ -431,7 +430,7 @@ public void oldToNewConfConversion() .filter(fc -> fc.getName().equals("dimStr")) .collect(Collectors.toList()).get(0); assertNotNull(fieldConfig.getIndexes().get(H3IndexType.INDEX_DISPLAY_NAME)); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + Assert.assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.H3); } @Test @@ -454,7 +453,7 @@ public void testConvertToUpdatedFormat() .filter(fc -> fc.getName().equals("location_st_point")) .collect(Collectors.toList()).get(0); Assert.assertEquals(fieldConfig.getEncodingType(), RAW); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + Assert.assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.H3); assertNull(fieldConfig.getProperties()); JsonNode node = fieldConfig.getIndexes().get(H3IndexType.INDEX_DISPLAY_NAME); Assert.assertEquals(node.toString(), "{\"disabled\":false,\"resolution\":[5,6,13]}"); diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java index b576a4439426..32b4298c329d 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/JsonIndexTest.java @@ -1054,7 +1054,7 @@ public void oldToNewConfConversion() { assertNull(_tableConfig.getIndexingConfig().getJsonIndexColumns()); assertNull(_tableConfig.getIndexingConfig().getJsonIndexConfigs()); assertNotNull(fieldConfig.getIndexes().get(JsonIndexType.INDEX_DISPLAY_NAME)); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.JSON); assertNull(fieldConfig.getProperties()); } } diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/RangeIndexTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/RangeIndexTest.java index ca3ab4259e15..10d4e639082e 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/RangeIndexTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/RangeIndexTest.java @@ -32,7 +32,6 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; public class RangeIndexTest { public static class ConfTest extends AbstractSerdeIndexContract { @@ -48,7 +47,7 @@ public void oldToNewConfConversion() { JsonNode indexConfig = fieldConfig.getIndexes().get(RangeIndexType.INDEX_DISPLAY_NAME); assertNotNull(indexConfig); assertEquals(RangeIndexConfig.DEFAULT.getVersion(), indexConfig.get("version").asInt()); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.RANGE); assertNull(fieldConfig.getProperties()); } } diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/TextIndexTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/TextIndexTest.java index 4d49d51ebff1..e4371b158dbd 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/TextIndexTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/TextIndexTest.java @@ -31,7 +31,6 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; public class TextIndexTest { public static class ConfTest extends AbstractSerdeIndexContract { @@ -51,7 +50,7 @@ public void oldToNewConfConversion() JsonNode indexConfig = fieldConfig.getIndexes().get(TextIndexType.INDEX_DISPLAY_NAME); assertNotNull(indexConfig); assertFalse(indexConfig.get("disabled").asBoolean()); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.TEXT); assertNull(fieldConfig.getProperties()); } } diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/VectorIndexTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/VectorIndexTest.java index 9775e3ca7ac4..0082f6f75ef8 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/VectorIndexTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/VectorIndexTest.java @@ -29,7 +29,6 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; public class VectorIndexTest { public static class ConfTest extends AbstractSerdeIndexContract { @@ -59,7 +58,7 @@ public void testConvertToUpdatedFormat() JsonNode indexConfig = fieldConfig.getIndexes().get(VectorIndexType.INDEX_DISPLAY_NAME); assertNotNull(indexConfig); assertFalse(indexConfig.get("disabled").asBoolean()); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + Assert.assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.VECTOR); assertNull(fieldConfig.getProperties()); Assert.assertEquals(indexConfig.toString(), "{\"disabled\":false,\"vectorIndexType\":\"HNSW\",\"vectorDimension\":1536," diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexTypeTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexTypeTest.java index a98f81b7f35f..c75ea2be1eeb 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexTypeTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/fst/FstIndexTypeTest.java @@ -95,7 +95,7 @@ public void oldToNewConfConversion() .filter(fc -> fc.getName().equals("dimStr")) .collect(Collectors.toList()).get(0); assertNotNull(fieldConfig.getIndexes().get(FstIndexType.INDEX_DISPLAY_NAME)); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + Assert.assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.FST); } } diff --git a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexTypeTest.java b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexTypeTest.java index 67412f1add08..7882a1004911 100644 --- a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexTypeTest.java +++ b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/inverted/InvertedIndexTypeTest.java @@ -116,7 +116,7 @@ public void oldToNewConfConversion() .collect(Collectors.toList()).get(0); assertNotNull(fieldConfig.getIndexes().get(InvertedIndexType.INDEX_DISPLAY_NAME)); assertNull(_tableConfig.getIndexingConfig().getInvertedIndexColumns()); - assertTrue(fieldConfig.getIndexTypes().isEmpty()); + Assert.assertEquals(fieldConfig.getIndexType(), FieldConfig.IndexType.INVERTED); } } diff --git a/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/IndexConfigDeserializer.java b/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/IndexConfigDeserializer.java index 6b6c2a3437cd..4b5cd51cdc9f 100644 --- a/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/IndexConfigDeserializer.java +++ b/pinot-segment-spi/src/main/java/org/apache/pinot/segment/spi/index/IndexConfigDeserializer.java @@ -103,6 +103,33 @@ public static ColumnConfigDeserializer fromIndexes(St }; } + /** + * Returns a {@link ColumnConfigDeserializer} that reads a specific fieldName of the
indexes
attribute on + * each FieldConfig and lets the caller decide how to translate it. + */ + public static ColumnConfigDeserializer fromIndexes(String fieldName, + BiFunction mapFunction) { + return (tableConfig, schema) -> { + Map result = new HashMap<>(); + List fieldConfigList = tableConfig.getFieldConfigList(); + if (fieldConfigList == null) { + return result; + } + for (FieldConfig fieldConfig : fieldConfigList) { + if (!fieldConfig.getIndexes().isObject() || fieldConfig.getIndexes().get(fieldName) == null) { + continue; + } + result.put(fieldConfig.getName(), mapFunction.apply(tableConfig, fieldConfig)); + } + return result; + }; + } + + public static boolean isEnabledOnlyConfig(JsonNode jsonNode) { + return jsonNode != null && jsonNode.isObject() && !jsonNode.path("disabled").asBoolean(false) + && (jsonNode.size() == 0 || (jsonNode.size() == 1 && jsonNode.has("disabled"))); + } + public static ColumnConfigDeserializer fromIndexTypes( FieldConfig.IndexType configIndexType, BiFunction mapFunction) { return (tableConfig, schema) -> { diff --git a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/FieldConfig.java b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/FieldConfig.java index 064526695d45..d15f6c1d9dad 100644 --- a/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/FieldConfig.java +++ b/pinot-spi/src/main/java/org/apache/pinot/spi/config/table/FieldConfig.java @@ -19,13 +19,19 @@ package org.apache.pinot.spi.config.table; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.NullNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import javax.annotation.Nullable; import org.apache.pinot.spi.config.BaseJsonConfig; @@ -70,10 +76,10 @@ public class FieldConfig extends BaseJsonConfig { public static final String TEXT_INDEX_LUCENE_REUSE_MUTABLE_INDEX = "reuseMutableIndex"; public static final String TEXT_INDEX_LUCENE_NRT_CACHING_DIRECTORY_BUFFER_SIZE = "luceneNRTCachingDirectoryMaxBufferSizeMB"; + private static final JsonNodeFactory JSON_NODE_FACTORY = JsonNodeFactory.instance; private final String _name; private final EncodingType _encodingType; - private final List _indexTypes; private final JsonNode _indexes; private final JsonNode _tierOverwrites; private final CompressionCodec _compressionCodec; @@ -111,12 +117,10 @@ public FieldConfig(@JsonProperty(value = "name", required = true) String name, Preconditions.checkArgument(name != null, "'name' must be configured"); _name = name; _encodingType = encodingType == null ? EncodingType.DICTIONARY : encodingType; - _indexTypes = - indexTypes != null ? indexTypes : (indexType == null ? Lists.newArrayList() : Lists.newArrayList(indexType)); _compressionCodec = compressionCodec; _timestampConfig = timestampConfig; _properties = properties; - _indexes = indexes == null ? NullNode.getInstance() : indexes; + _indexes = normalizeIndexes(name, indexType, indexTypes, indexes); _tierOverwrites = tierOverwrites == null ? NullNode.getInstance() : tierOverwrites; } @@ -128,7 +132,26 @@ public enum EncodingType { // If null, there won't be any index // NOTE: TIMESTAMP is ignored. In order to create TIMESTAMP index, configure 'timestampConfig' instead. public enum IndexType { - INVERTED, SORTED, TEXT, FST, IFST, H3, JSON, TIMESTAMP, VECTOR, RANGE + INVERTED("inverted"), + SORTED("sorted"), + TEXT("text"), + FST("fst"), + IFST("ifst"), + H3("h3"), + JSON("json"), + TIMESTAMP("timestamp"), + VECTOR("vector"), + RANGE("range"); + + private final String _prettyName; + + IndexType(String prettyName) { + _prettyName = prettyName; + } + + public String getPrettyName() { + return _prettyName; + } } public enum CompressionCodec { @@ -181,12 +204,28 @@ public EncodingType getEncodingType() { @Nullable @Deprecated + @JsonIgnore public IndexType getIndexType() { - return !_indexTypes.isEmpty() ? _indexTypes.get(0) : null; + List indexTypes = getIndexTypes(); + return indexTypes.isEmpty() ? null : indexTypes.get(0); } + @Deprecated + @JsonIgnore public List getIndexTypes() { - return _indexTypes; + if (!_indexes.isObject()) { + return Collections.emptyList(); + } + + List indexTypes = new ArrayList<>(); + ObjectNode indexes = (ObjectNode) _indexes; + for (IndexType indexType : IndexType.values()) { + JsonNode indexConfig = indexes.get(indexType.getPrettyName()); + if (indexConfig != null && !indexConfig.path("disabled").asBoolean(false)) { + indexTypes.add(indexType); + } + } + return indexTypes; } public JsonNode getIndexes() { @@ -229,7 +268,6 @@ public Builder(String name) { public Builder(FieldConfig other) { _name = other._name; _encodingType = other._encodingType; - _indexTypes = other._indexTypes; _indexes = other._indexes; _compressionCodec = other._compressionCodec; _properties = other._properties; @@ -282,4 +320,44 @@ public FieldConfig build() { _properties, _tierOverwrites); } } + + private static JsonNode normalizeIndexes(String fieldName, @Nullable IndexType indexType, + @Nullable List indexTypes, @Nullable JsonNode indexes) { + Set legacyIndexTypes = collectLegacyIndexTypes(indexType, indexTypes); + if (legacyIndexTypes.isEmpty()) { + return indexes == null ? NullNode.getInstance() : indexes; + } + + Preconditions.checkArgument(indexes == null || indexes.isNull() || indexes.isObject(), + "'indexes' must be an object when used with legacy 'indexType'/'indexTypes' for column: %s", fieldName); + + ObjectNode normalizedIndexes = + indexes != null && indexes.isObject() ? ((ObjectNode) indexes).deepCopy() : JSON_NODE_FACTORY.objectNode(); + for (IndexType legacyIndexType : legacyIndexTypes) { + String indexKey = legacyIndexType.getPrettyName(); + Preconditions.checkArgument(!normalizedIndexes.has(indexKey), + "Index '%s' is declared in both 'indexes' and legacy 'indexType'/'indexTypes' for column: %s", indexKey, + fieldName); + normalizedIndexes.set(indexKey, enabledIndexConfigNode()); + } + return normalizedIndexes.size() == 0 ? NullNode.getInstance() : normalizedIndexes; + } + + private static Set collectLegacyIndexTypes(@Nullable IndexType indexType, + @Nullable List indexTypes) { + Set legacyIndexTypes = new LinkedHashSet<>(); + if (indexType != null) { + legacyIndexTypes.add(indexType); + } + if (indexTypes != null) { + legacyIndexTypes.addAll(indexTypes); + } + return legacyIndexTypes; + } + + private static ObjectNode enabledIndexConfigNode() { + ObjectNode indexConfig = JSON_NODE_FACTORY.objectNode(); + indexConfig.put("disabled", false); + return indexConfig; + } }