diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaData.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaData.java index 7844e42ccc..69ef00735e 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaData.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaData.java @@ -31,7 +31,9 @@ import com.apple.foundationdb.record.metadata.UnnestedRecordType; import com.apple.foundationdb.record.metadata.expressions.KeyExpression; import com.apple.foundationdb.record.metadata.expressions.LiteralKeyExpression; +import com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; +import com.apple.foundationdb.record.query.plan.serialization.DefaultPlanSerializationRegistry; import com.apple.foundationdb.record.query.plan.synthetic.SyntheticRecordPlanner; import com.apple.foundationdb.record.util.MapUtils; import com.google.common.base.Verify; @@ -48,6 +50,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -83,6 +86,8 @@ public class RecordMetaData implements RecordMetaDataProvider { @Nonnull private final Map> recordTypeKeyToSyntheticTypeMap; @Nonnull + private final Set userDefinedFunctions; + @Nonnull private final Map indexes; @Nonnull private final Map universalIndexes; @@ -112,6 +117,7 @@ protected RecordMetaData(@Nonnull RecordMetaData orig) { Collections.unmodifiableMap(orig.indexes), Collections.unmodifiableMap(orig.universalIndexes), Collections.unmodifiableList(orig.formerIndexes), + Collections.unmodifiableSet(orig.userDefinedFunctions), orig.splitLongRecords, orig.storeRecordVersions, orig.version, @@ -131,6 +137,7 @@ protected RecordMetaData(@Nonnull Descriptors.FileDescriptor recordsDescriptor, @Nonnull Map indexes, @Nonnull Map universalIndexes, @Nonnull List formerIndexes, + @Nonnull Set userDefinedFunctions, boolean splitLongRecords, boolean storeRecordVersions, int version, @@ -147,6 +154,7 @@ protected RecordMetaData(@Nonnull Descriptors.FileDescriptor recordsDescriptor, this.indexes = indexes; this.universalIndexes = universalIndexes; this.formerIndexes = formerIndexes; + this.userDefinedFunctions = userDefinedFunctions; this.splitLongRecords = splitLongRecords; this.storeRecordVersions = storeRecordVersions; this.version = version; @@ -692,7 +700,9 @@ public RecordMetaDataProto.MetaData toProto(@Nullable Descriptors.FileDescriptor builder.addFormerIndexes(formerIndex.toProto()); } - // Add in the final options. + PlanSerializationContext serializationContext = new PlanSerializationContext(DefaultPlanSerializationRegistry.INSTANCE, + PlanHashable.CURRENT_FOR_CONTINUATION); + builder.addAllUserDefinedFunctions(userDefinedFunctions.stream().map(func -> func.toProto(serializationContext)).collect(Collectors.toList())); builder.setSplitLongRecords(splitLongRecords); builder.setStoreRecordVersions(storeRecordVersions); builder.setVersion(version); diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaDataBuilder.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaDataBuilder.java index 3e425dc135..0c16cf3a74 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaDataBuilder.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/RecordMetaDataBuilder.java @@ -42,6 +42,8 @@ import com.apple.foundationdb.record.provider.foundationdb.IndexMaintainerRegistry; import com.apple.foundationdb.record.provider.foundationdb.IndexMaintainerRegistryImpl; import com.apple.foundationdb.record.provider.foundationdb.MetaDataProtoEditor; +import com.apple.foundationdb.record.query.plan.cascades.UserDefinedFunction; +import com.apple.foundationdb.record.query.plan.serialization.DefaultPlanSerializationRegistry; import com.google.common.base.Verify; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; @@ -110,6 +112,8 @@ public class RecordMetaDataBuilder implements RecordMetaDataProvider { @Nonnull private final Map> syntheticRecordTypes; @Nonnull + private final Set userDefinedFunctions; + @Nonnull private final Map indexes; @Nonnull private final Map universalIndexes; @@ -144,6 +148,7 @@ public class RecordMetaDataBuilder implements RecordMetaDataProvider { indexMaintainerRegistry = IndexMaintainerRegistryImpl.instance(); evolutionValidator = MetaDataEvolutionValidator.getDefaultInstance(); syntheticRecordTypes = new HashMap<>(); + userDefinedFunctions = new HashSet<>(); } private void processSchemaOptions(boolean processExtensionOptions) { @@ -222,6 +227,14 @@ private void loadProtoExceptRecords(@Nonnull RecordMetaDataProto.MetaData metaDa typeBuilder.setRecordTypeKey(LiteralKeyExpression.fromProtoValue(typeProto.getExplicitKey())); } } + PlanSerializationContext serializationContext = new PlanSerializationContext(DefaultPlanSerializationRegistry.INSTANCE, + PlanHashable.CURRENT_FOR_CONTINUATION); + for (RecordMetaDataProto.UserDefinedFunction function: metaDataProto.getUserDefinedFunctionsList()) { + UserDefinedFunction func = UserDefinedFunction.fromProto(serializationContext, function); + if (func != null) { + userDefinedFunctions.add(func); + } + } if (metaDataProto.hasSplitLongRecords()) { splitLongRecords = metaDataProto.getSplitLongRecords(); } @@ -1179,6 +1192,14 @@ public void addFormerIndex(@Nonnull FormerIndex formerIndex) { formerIndexes.add(formerIndex); } + public void addUserDefinedFunction(@Nonnull UserDefinedFunction userDefinedFunction) { + userDefinedFunctions.add(userDefinedFunction); + } + + public void addUserDefinedFunctions(@Nonnull Iterable functions) { + functions.forEach(this.userDefinedFunctions::add); + } + public boolean isSplitLongRecords() { return splitLongRecords; } @@ -1420,7 +1441,7 @@ public RecordMetaData build(boolean validate) { Map> recordTypeKeyToSyntheticRecordTypeMap = Maps.newHashMapWithExpectedSize(syntheticRecordTypes.size()); RecordMetaData metaData = new RecordMetaData(recordsDescriptor, getUnionDescriptor(), unionFields, builtRecordTypes, builtSyntheticRecordTypes, recordTypeKeyToSyntheticRecordTypeMap, - indexes, universalIndexes, formerIndexes, + indexes, universalIndexes, formerIndexes, userDefinedFunctions, splitLongRecords, storeRecordVersions, version, subspaceKeyCounter, usesSubspaceKeyCounter, recordCountKey, localFileDescriptor != null); for (RecordTypeBuilder recordTypeBuilder : recordTypes.values()) { KeyExpression primaryKey = recordTypeBuilder.getPrimaryKey(); diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/Key.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/Key.java index 326ec42d26..4e4bcde4c9 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/Key.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/Key.java @@ -22,7 +22,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.annotation.SpotBugsSuppressWarnings; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.logging.LogMessageKeys; import com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression; import com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression; @@ -392,21 +392,21 @@ public static class Evaluated { * Values used in index keys in place of missing fields. */ public enum NullStandin { - NULL(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE), // Missing field here skips uniqueness checks. - NULL_UNIQUE(RecordMetaDataProto.Field.NullInterpretation.UNIQUE), // Missing field here like ordinary value, but null, for uniqueness. - NOT_NULL(RecordMetaDataProto.Field.NullInterpretation.NOT_NULL); // Missing field has type's ordinary default value. + NULL(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE), // Missing field here skips uniqueness checks. + NULL_UNIQUE(RecordKeyExpressionProto.Field.NullInterpretation.UNIQUE), // Missing field here like ordinary value, but null, for uniqueness. + NOT_NULL(RecordKeyExpressionProto.Field.NullInterpretation.NOT_NULL); // Missing field has type's ordinary default value. - private RecordMetaDataProto.Field.NullInterpretation proto; + private RecordKeyExpressionProto.Field.NullInterpretation proto; - NullStandin(RecordMetaDataProto.Field.NullInterpretation nullInterpretation) { + NullStandin(RecordKeyExpressionProto.Field.NullInterpretation nullInterpretation) { proto = nullInterpretation; } - public RecordMetaDataProto.Field.NullInterpretation toProto() { + public RecordKeyExpressionProto.Field.NullInterpretation toProto() { return proto; } - public static NullStandin valueOf(RecordMetaDataProto.Field.NullInterpretation nullInterpretation) throws KeyExpression.DeserializationException { + public static NullStandin valueOf(RecordKeyExpressionProto.Field.NullInterpretation nullInterpretation) throws KeyExpression.DeserializationException { switch (nullInterpretation) { case NOT_UNIQUE: return NULL; diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/DimensionsKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/DimensionsKeyExpression.java index a4aeed8d32..6fe8b5628f 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/DimensionsKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/DimensionsKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -63,7 +63,7 @@ private DimensionsKeyExpression(@Nonnull final KeyExpression wholeKey, this.dimensionsSize = dimensionsSize; } - DimensionsKeyExpression(@Nonnull final RecordMetaDataProto.Dimensions dimensions) throws DeserializationException { + DimensionsKeyExpression(@Nonnull final RecordKeyExpressionProto.Dimensions dimensions) throws DeserializationException { this(KeyExpression.fromProto(dimensions.getWholeKey()), dimensions.getPrefixSize(), dimensions.getDimensionsSize()); } @@ -114,8 +114,8 @@ public boolean needsCopyingToPartialRecord() { @Nonnull @Override - public RecordMetaDataProto.Dimensions toProto() throws SerializationException { - final RecordMetaDataProto.Dimensions.Builder builder = RecordMetaDataProto.Dimensions.newBuilder(); + public RecordKeyExpressionProto.Dimensions toProto() throws SerializationException { + final RecordKeyExpressionProto.Dimensions.Builder builder = RecordKeyExpressionProto.Dimensions.newBuilder(); builder.setWholeKey(getWholeKey().toKeyExpression()); builder.setPrefixSize(prefixSize); builder.setDimensionsSize(dimensionsSize); @@ -124,8 +124,8 @@ public RecordMetaDataProto.Dimensions toProto() throws SerializationException { @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setDimensions(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setDimensions(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/EmptyKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/EmptyKeyExpression.java index 1442fac22f..c3a3cef2ec 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/EmptyKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/EmptyKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -45,8 +45,8 @@ public class EmptyKeyExpression extends BaseKeyExpression implements KeyExpressi private static final ObjectPlanHash BASE_HASH = new ObjectPlanHash("Empty-Key-Expression"); public static final EmptyKeyExpression EMPTY = new EmptyKeyExpression(); - public static final RecordMetaDataProto.KeyExpression EMPTY_PROTO = - RecordMetaDataProto.KeyExpression.newBuilder().setEmpty(EMPTY.toProto()).build(); + public static final RecordKeyExpressionProto.KeyExpression EMPTY_PROTO = + RecordKeyExpressionProto.KeyExpression.newBuilder().setEmpty(EMPTY.toProto()).build(); private EmptyKeyExpression() { // nothing to initialize @@ -75,8 +75,8 @@ public int getColumnSize() { @Nonnull @Override - public RecordMetaDataProto.Empty toProto() throws SerializationException { - return RecordMetaDataProto.Empty.getDefaultInstance(); + public RecordKeyExpressionProto.Empty toProto() throws SerializationException { + return RecordKeyExpressionProto.Empty.getDefaultInstance(); } @Nonnull @@ -87,7 +87,7 @@ public R expand(@Nonnull final KeyExpr @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { return EMPTY_PROTO; } diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FieldKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FieldKeyExpression.java index dd0069b5da..907030c730 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FieldKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FieldKeyExpression.java @@ -24,7 +24,7 @@ import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.logging.LogMessageKeys; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; @@ -71,7 +71,7 @@ public FieldKeyExpression(@Nonnull String fieldName, @Nonnull FanType fanType, @ this.nullStandin = nullStandin; } - public FieldKeyExpression(@Nonnull RecordMetaDataProto.Field field) throws DeserializationException { + public FieldKeyExpression(@Nonnull RecordKeyExpressionProto.Field field) throws DeserializationException { if (!field.hasFieldName()) { throw new DeserializationException("Serialized Field is missing field name"); } @@ -193,8 +193,8 @@ public int getColumnSize() { @Nonnull @Override - public RecordMetaDataProto.Field toProto() throws SerializationException { - return RecordMetaDataProto.Field.newBuilder() + public RecordKeyExpressionProto.Field toProto() throws SerializationException { + return RecordKeyExpressionProto.Field.newBuilder() .setFieldName(fieldName) .setFanType(fanType.toProto()) .setNullInterpretation(nullStandin.toProto()) @@ -203,8 +203,8 @@ public RecordMetaDataProto.Field toProto() throws SerializationException { @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setField(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setField(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FunctionKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FunctionKeyExpression.java index 4ab23d4fae..0d2884e628 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FunctionKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/FunctionKeyExpression.java @@ -25,7 +25,7 @@ import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.RecordCoreArgumentException; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.logging.LogMessageKeys; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; @@ -232,7 +232,7 @@ public boolean equalsAtomic(AtomKeyExpression other) { * implementation, or the arguments provided are not suitable for the function. */ @Nonnull - public static FunctionKeyExpression fromProto(RecordMetaDataProto.Function function) throws DeserializationException { + public static FunctionKeyExpression fromProto(RecordKeyExpressionProto.Function function) throws DeserializationException { try { return create(function.getName(), KeyExpression.fromProto(function.getArguments())); } catch (RecordCoreException e) { @@ -242,8 +242,8 @@ public static FunctionKeyExpression fromProto(RecordMetaDataProto.Function funct @Nonnull @Override - public final RecordMetaDataProto.Function toProto() throws SerializationException { - RecordMetaDataProto.Function.Builder builder = RecordMetaDataProto.Function.newBuilder() + public final RecordKeyExpressionProto.Function toProto() throws SerializationException { + RecordKeyExpressionProto.Function.Builder builder = RecordKeyExpressionProto.Function.newBuilder() .setName(getName()); builder.setArguments(getArguments().toKeyExpression()); return builder.build(); @@ -251,8 +251,8 @@ public final RecordMetaDataProto.Function toProto() throws SerializationExceptio @Nonnull @Override - public final RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setFunction(toProto()).build(); + public final RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setFunction(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/GroupingKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/GroupingKeyExpression.java index 1183bd4c69..412cacce9c 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/GroupingKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/GroupingKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -53,7 +53,7 @@ public GroupingKeyExpression(@Nonnull KeyExpression wholeKey, int groupedCount) this.groupedCount = groupedCount; } - public GroupingKeyExpression(@Nonnull RecordMetaDataProto.Grouping grouping) throws DeserializationException { + public GroupingKeyExpression(@Nonnull RecordKeyExpressionProto.Grouping grouping) throws DeserializationException { this(KeyExpression.fromProto(grouping.getWholeKey()), grouping.getGroupedCount()); } @@ -100,8 +100,8 @@ public boolean needsCopyingToPartialRecord() { @Nonnull @Override - public RecordMetaDataProto.Grouping toProto() throws SerializationException { - final RecordMetaDataProto.Grouping.Builder builder = RecordMetaDataProto.Grouping.newBuilder(); + public RecordKeyExpressionProto.Grouping toProto() throws SerializationException { + final RecordKeyExpressionProto.Grouping.Builder builder = RecordKeyExpressionProto.Grouping.newBuilder(); builder.setWholeKey(getWholeKey().toKeyExpression()); builder.setGroupedCount(groupedCount); return builder.build(); @@ -109,8 +109,8 @@ public RecordMetaDataProto.Grouping toProto() throws SerializationException { @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setGrouping(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setGrouping(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyExpression.java index fcaa2cf581..4e738fff06 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyExpression.java @@ -24,7 +24,7 @@ import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.QueryHashable; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.ExpansionVisitor; @@ -165,28 +165,28 @@ enum FanType { * Convert a repeated field into a single list. * This does not cause the number of index values to increase. */ - Concatenate(RecordMetaDataProto.Field.FanType.CONCATENATE), + Concatenate(RecordKeyExpressionProto.Field.FanType.CONCATENATE), /** * Create an index value for each value of the field. */ - FanOut(RecordMetaDataProto.Field.FanType.FAN_OUT), + FanOut(RecordKeyExpressionProto.Field.FanType.FAN_OUT), /** * Nothing, only allowed with scalar fields. */ - None(RecordMetaDataProto.Field.FanType.SCALAR); + None(RecordKeyExpressionProto.Field.FanType.SCALAR); - private RecordMetaDataProto.Field.FanType proto; + private RecordKeyExpressionProto.Field.FanType proto; - FanType(RecordMetaDataProto.Field.FanType fanType) { + FanType(RecordKeyExpressionProto.Field.FanType fanType) { proto = fanType; } - RecordMetaDataProto.Field.FanType toProto() { + RecordKeyExpressionProto.Field.FanType toProto() { return proto; } - public static FanType valueOf(RecordMetaDataProto.Field.FanType fanType) throws DeserializationException { + public static FanType valueOf(RecordKeyExpressionProto.Field.FanType fanType) throws DeserializationException { switch (fanType) { case SCALAR: return None; @@ -204,7 +204,7 @@ public static FanType valueOf(RecordMetaDataProto.Field.FanType fanType) throws Message toProto() throws SerializationException; @Nonnull - RecordMetaDataProto.KeyExpression toKeyExpression(); + RecordKeyExpressionProto.KeyExpression toKeyExpression(); /** * Get key in normalized form for comparing field-by-field. @@ -339,7 +339,7 @@ default boolean hasProperInterfaces() { } @Nonnull - static KeyExpression fromProto(RecordMetaDataProto.KeyExpression expression) + static KeyExpression fromProto(RecordKeyExpressionProto.KeyExpression expression) throws DeserializationException { KeyExpression root = null; int found = 0; diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyWithValueExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyWithValueExpression.java index eaa93c9725..db134d000f 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyWithValueExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/KeyWithValueExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -61,7 +61,7 @@ public KeyWithValueExpression(@Nonnull KeyExpression innerKey, int splitPoint) { this.splitPoint = splitPoint; } - public KeyWithValueExpression(@Nonnull RecordMetaDataProto.KeyWithValue proto) throws DeserializationException { + public KeyWithValueExpression(@Nonnull RecordKeyExpressionProto.KeyWithValue proto) throws DeserializationException { this(KeyExpression.fromProto(proto.getInnerKey()), proto.getSplitPoint()); } @@ -133,8 +133,8 @@ public boolean needsCopyingToPartialRecord() { @Nonnull @Override - public RecordMetaDataProto.KeyWithValue toProto() throws SerializationException { - return RecordMetaDataProto.KeyWithValue.newBuilder() + public RecordKeyExpressionProto.KeyWithValue toProto() throws SerializationException { + return RecordKeyExpressionProto.KeyWithValue.newBuilder() .setInnerKey(getInnerKey().toKeyExpression()) .setSplitPoint(splitPoint) .build(); @@ -142,8 +142,8 @@ public RecordMetaDataProto.KeyWithValue toProto() throws SerializationException @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setKeyWithValue(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setKeyWithValue(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ListKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ListKeyExpression.java index 90165aef6d..98c75ac620 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ListKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ListKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -79,7 +79,7 @@ private ListKeyExpression(@Nonnull ListKeyExpression orig, int start, int end) { children = orig.children.subList(start, end); } - public ListKeyExpression(@Nonnull RecordMetaDataProto.List list) throws DeserializationException { + public ListKeyExpression(@Nonnull RecordKeyExpressionProto.List list) throws DeserializationException { children = list.getChildList().stream().map(KeyExpression::fromProto).collect(Collectors.toList()); } @@ -140,8 +140,8 @@ public int getColumnSize() { @Nonnull @Override - public RecordMetaDataProto.List toProto() throws SerializationException { - final RecordMetaDataProto.List.Builder builder = RecordMetaDataProto.List.newBuilder(); + public RecordKeyExpressionProto.List toProto() throws SerializationException { + final RecordKeyExpressionProto.List.Builder builder = RecordKeyExpressionProto.List.newBuilder(); for (KeyExpression child : children) { builder.addChild(child.toKeyExpression()); } @@ -150,8 +150,8 @@ public RecordMetaDataProto.List toProto() throws SerializationException { @Override @Nonnull - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setList(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setList(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpression.java index d660d86688..057f804f4d 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpression.java @@ -24,7 +24,7 @@ import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier; @@ -57,14 +57,14 @@ public class LiteralKeyExpression extends BaseKeyExpression implements AtomKe @Nonnull private final List evaluated; @Nonnull - private final RecordMetaDataProto.Value proto; + private final RecordKeyExpressionProto.Value proto; public LiteralKeyExpression(@Nullable T value) { // getProto() performs validation that it is a type we can serialize this(value, toProtoValue(value)); } - private LiteralKeyExpression(@Nullable T value, @Nonnull RecordMetaDataProto.Value proto) { + private LiteralKeyExpression(@Nullable T value, @Nonnull RecordKeyExpressionProto.Value proto) { this.value = value; this.evaluated = ImmutableList.of(value == null ? Key.Evaluated.NULL : Key.Evaluated.scalar(value)); this.proto = proto; @@ -98,7 +98,7 @@ public int getColumnSize() { @Nonnull @Override - public RecordMetaDataProto.Value toProto() throws SerializationException { + public RecordKeyExpressionProto.Value toProto() throws SerializationException { return proto; } @@ -117,8 +117,8 @@ public Value toValue(@Nonnull final CorrelationIdentifier baseAlias, @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setValue(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setValue(toProto()).build(); } @Override @@ -127,12 +127,12 @@ public boolean needsCopyingToPartialRecord() { } @Nonnull - public static LiteralKeyExpression fromProto(RecordMetaDataProto.Value proto) { + public static LiteralKeyExpression fromProto(RecordKeyExpressionProto.Value proto) { return new LiteralKeyExpression<>(fromProtoValue(proto), proto); } @Nullable - public static Object fromProtoValue(RecordMetaDataProto.Value proto) { + public static Object fromProtoValue(RecordKeyExpressionProto.Value proto) { int found = 0; Object value = null; if (proto.hasDoubleValue()) { @@ -174,8 +174,8 @@ public static Object fromProtoValue(RecordMetaDataProto.Value proto) { } @Nonnull - public static RecordMetaDataProto.Value toProtoValue(@Nullable Object value) { - RecordMetaDataProto.Value.Builder builder = RecordMetaDataProto.Value.newBuilder(); + public static RecordKeyExpressionProto.Value toProtoValue(@Nullable Object value) { + RecordKeyExpressionProto.Value.Builder builder = RecordKeyExpressionProto.Value.newBuilder(); if (value instanceof Double) { builder.setDoubleValue((Double) value); } else if (value instanceof Float) { diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/NestingKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/NestingKeyExpression.java index fe63dc68db..1a967a83bf 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/NestingKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/NestingKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -60,7 +60,7 @@ public NestingKeyExpression(@Nonnull FieldKeyExpression parent, @Nonnull KeyExpr this.child = child; } - public NestingKeyExpression(@Nonnull RecordMetaDataProto.Nesting nesting) throws DeserializationException { + public NestingKeyExpression(@Nonnull RecordKeyExpressionProto.Nesting nesting) throws DeserializationException { if (!nesting.hasParent()) { throw new DeserializationException("Serialized Nesting is missing parent"); } @@ -100,8 +100,8 @@ public int getColumnSize() { @Nonnull @Override - public RecordMetaDataProto.Nesting toProto() throws SerializationException { - final RecordMetaDataProto.Nesting.Builder builder = RecordMetaDataProto.Nesting.newBuilder(); + public RecordKeyExpressionProto.Nesting toProto() throws SerializationException { + final RecordKeyExpressionProto.Nesting.Builder builder = RecordKeyExpressionProto.Nesting.newBuilder(); builder.setParent(parent.toProto()); builder.setChild(getChild().toKeyExpression()); return builder.build(); @@ -109,8 +109,8 @@ public RecordMetaDataProto.Nesting toProto() throws SerializationException { @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setNesting(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setNesting(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/RecordTypeKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/RecordTypeKeyExpression.java index 5284d9d703..add3e51b0b 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/RecordTypeKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/RecordTypeKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.CorrelationIdentifier; @@ -60,8 +60,8 @@ public class RecordTypeKeyExpression extends BaseKeyExpression implements AtomKeyExpression, KeyExpressionWithoutChildren, KeyExpressionWithValue { private static final ObjectPlanHash BASE_HASH = new ObjectPlanHash("Record-Type-Key-Expression"); public static final RecordTypeKeyExpression RECORD_TYPE_KEY = new RecordTypeKeyExpression(); - public static final RecordMetaDataProto.KeyExpression RECORD_TYPE_KEY_PROTO = - RecordMetaDataProto.KeyExpression.newBuilder().setRecordTypeKey(RECORD_TYPE_KEY.toProto()).build(); + public static final RecordKeyExpressionProto.KeyExpression RECORD_TYPE_KEY_PROTO = + RecordKeyExpressionProto.KeyExpression.newBuilder().setRecordTypeKey(RECORD_TYPE_KEY.toProto()).build(); private static final GroupingKeyExpression UNGROUPED = new GroupingKeyExpression(new RecordTypeKeyExpression(), 0); @@ -107,13 +107,13 @@ public GroupingKeyExpression ungrouped() { @Nonnull @Override - public RecordMetaDataProto.RecordTypeKey toProto() throws SerializationException { - return RecordMetaDataProto.RecordTypeKey.getDefaultInstance(); + public RecordKeyExpressionProto.RecordTypeKey toProto() throws SerializationException { + return RecordKeyExpressionProto.RecordTypeKey.getDefaultInstance(); } @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { return RECORD_TYPE_KEY_PROTO; } diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/SplitKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/SplitKeyExpression.java index 2f4ad1a60b..f31e8b115f 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/SplitKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/SplitKeyExpression.java @@ -24,7 +24,7 @@ import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -56,7 +56,7 @@ public SplitKeyExpression(KeyExpression joined, int splitSize) { this.splitSize = splitSize; } - public SplitKeyExpression(@Nonnull RecordMetaDataProto.Split split) throws DeserializationException { + public SplitKeyExpression(@Nonnull RecordKeyExpressionProto.Split split) throws DeserializationException { this(KeyExpression.fromProto(split.getJoined()), split.getSplitSize()); } @@ -110,8 +110,8 @@ public boolean needsCopyingToPartialRecord() { @Nonnull @Override - public RecordMetaDataProto.Split toProto() throws SerializationException { - final RecordMetaDataProto.Split.Builder builder = RecordMetaDataProto.Split.newBuilder(); + public RecordKeyExpressionProto.Split toProto() throws SerializationException { + final RecordKeyExpressionProto.Split.Builder builder = RecordKeyExpressionProto.Split.newBuilder(); builder.setJoined(getJoined().toKeyExpression()); builder.setSplitSize(splitSize); return builder.build(); @@ -119,8 +119,8 @@ public RecordMetaDataProto.Split toProto() throws SerializationException { @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setSplit(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setSplit(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ThenKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ThenKeyExpression.java index 7833a8a22a..0a77a067a1 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ThenKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/ThenKeyExpression.java @@ -24,7 +24,7 @@ import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.query.plan.cascades.KeyExpressionVisitor; @@ -75,9 +75,9 @@ public ThenKeyExpression(@Nonnull KeyExpression first, @Nonnull KeyExpression se } } - public ThenKeyExpression(@Nonnull RecordMetaDataProto.Then then) throws DeserializationException { + public ThenKeyExpression(@Nonnull RecordKeyExpressionProto.Then then) throws DeserializationException { children = new ArrayList<>(then.getChildCount()); - for (RecordMetaDataProto.KeyExpression child : then.getChildList()) { + for (RecordKeyExpressionProto.KeyExpression child : then.getChildList()) { final KeyExpression expression = KeyExpression.fromProto(child); add(children, expression); } @@ -171,8 +171,8 @@ public GroupingKeyExpression group(int count) { @Nonnull @Override - public RecordMetaDataProto.Then toProto() throws SerializationException { - final RecordMetaDataProto.Then.Builder builder = RecordMetaDataProto.Then.newBuilder(); + public RecordKeyExpressionProto.Then toProto() throws SerializationException { + final RecordKeyExpressionProto.Then.Builder builder = RecordKeyExpressionProto.Then.newBuilder(); for (KeyExpression child : children) { builder.addChild(child.toKeyExpression()); } @@ -181,8 +181,8 @@ public RecordMetaDataProto.Then toProto() throws SerializationException { @Override @Nonnull - public RecordMetaDataProto.KeyExpression toKeyExpression() { - return RecordMetaDataProto.KeyExpression.newBuilder().setThen(toProto()).build(); + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { + return RecordKeyExpressionProto.KeyExpression.newBuilder().setThen(toProto()).build(); } @Nonnull diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/VersionKeyExpression.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/VersionKeyExpression.java index f8e0824525..cf8b7149a4 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/VersionKeyExpression.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/metadata/expressions/VersionKeyExpression.java @@ -23,7 +23,7 @@ import com.apple.foundationdb.annotation.API; import com.apple.foundationdb.record.ObjectPlanHash; import com.apple.foundationdb.record.PlanHashable; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; import com.apple.foundationdb.record.provider.foundationdb.FDBRecordVersion; @@ -50,8 +50,8 @@ @API(API.Status.UNSTABLE) public class VersionKeyExpression extends BaseKeyExpression implements AtomKeyExpression, KeyExpressionWithoutChildren, KeyExpressionWithValue { public static final VersionKeyExpression VERSION = new VersionKeyExpression(); - public static final RecordMetaDataProto.KeyExpression VERSION_PROTO = - RecordMetaDataProto.KeyExpression.newBuilder().setVersion(VERSION.toProto()).build(); + public static final RecordKeyExpressionProto.KeyExpression VERSION_PROTO = + RecordKeyExpressionProto.KeyExpression.newBuilder().setVersion(VERSION.toProto()).build(); private static final ObjectPlanHash BASE_HASH = new ObjectPlanHash("Version-Key-Expression"); private static final GroupingKeyExpression UNGROUPED = new GroupingKeyExpression(new VersionKeyExpression(), 1); @@ -98,13 +98,13 @@ public GroupingKeyExpression groupBy(@Nonnull KeyExpression groupByFirst, @Nonnu @Nonnull @Override - public RecordMetaDataProto.Version toProto() throws SerializationException { - return RecordMetaDataProto.Version.getDefaultInstance(); + public RecordKeyExpressionProto.Version toProto() throws SerializationException { + return RecordKeyExpressionProto.Version.getDefaultInstance(); } @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { return VERSION_PROTO; } diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/BuiltInFunction.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/BuiltInFunction.java index 29b7d51817..950fc6b187 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/BuiltInFunction.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/BuiltInFunction.java @@ -22,15 +22,12 @@ import com.apple.foundationdb.record.query.plan.cascades.typing.Type; import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; -import com.google.common.base.Verify; -import com.google.common.collect.ImmutableList; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; /** * Main interface for defining a built-in function that can be evaluated against a number of arguments. @@ -41,19 +38,7 @@ * @param The resulting type of the function. */ @SuppressWarnings("PMD.AbstractClassWithoutAbstractMethod") -public abstract class BuiltInFunction { - @Nonnull - final String functionName; - - @Nonnull - final List parameterTypes; - - /** - * The type of the function's variadic parameters (if any). - */ - @Nullable - final Type variadicSuffixType; - +public abstract class BuiltInFunction extends CatalogedFunction { @Nonnull final EncapsulationFunction encapsulationFunction; @@ -75,54 +60,10 @@ protected BuiltInFunction(@Nonnull final String functionName, @Nonnull final Lis * @param encapsulationFunction An encapsulation of the function's runtime computation. */ protected BuiltInFunction(@Nonnull final String functionName, @Nonnull final List parameterTypes, @Nullable final Type variadicSuffixType, @Nonnull final EncapsulationFunction encapsulationFunction) { - this.functionName = functionName; - this.parameterTypes = ImmutableList.copyOf(parameterTypes); - this.variadicSuffixType = variadicSuffixType; + super(functionName, parameterTypes, variadicSuffixType); this.encapsulationFunction = encapsulationFunction; } - @Nonnull - public String getFunctionName() { - return functionName; - } - - @Nonnull - public List getParameterTypes() { - return parameterTypes; - } - - @Nonnull - public Type resolveParameterType(int index) { - Verify.verify(index >= 0, "unexpected negative parameter index"); - if (index < parameterTypes.size()) { - return parameterTypes.get(index); - } else { - if (hasVariadicSuffix()) { - return variadicSuffixType; - } - throw new IllegalArgumentException("cannot resolve declared parameter at index " + index); - } - } - - @Nonnull - public List resolveParameterTypes(int numberOfArguments) { - Verify.verify(numberOfArguments > 0, "unexpected number of arguments"); - final ImmutableList.Builder resultBuilder = ImmutableList.builder(); - for (int i = 0; i < numberOfArguments; i ++) { - resultBuilder.add(resolveParameterType(i)); - } - return resultBuilder.build(); - } - - @Nullable - public Type getVariadicSuffixType() { - return variadicSuffixType; - } - - public boolean hasVariadicSuffix() { - return variadicSuffixType != null; - } - /** * Checks whether the provided list of argument types matches the list of function's parameter types. * @@ -169,21 +110,8 @@ public EncapsulationFunction getEncapsulationFunction() { } @Nonnull + @Override public Typed encapsulate(@Nonnull final List arguments) { return encapsulationFunction.encapsulate(this, arguments); } - - @Nonnull - @Override - public String toString() { - String variadicSuffixString = ""; - if (variadicSuffixType != null) { - variadicSuffixString = variadicSuffixType + "..."; - if (!parameterTypes.isEmpty()) { - variadicSuffixString = ", " + variadicSuffixString; - } - } - - return functionName + "(" + parameterTypes.stream().map(Object::toString).collect(Collectors.joining(",")) + variadicSuffixString + ")"; - } } diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/CatalogedFunction.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/CatalogedFunction.java new file mode 100644 index 0000000000..c2d731c387 --- /dev/null +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/CatalogedFunction.java @@ -0,0 +1,110 @@ +/* + * CatalogedFunction.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2015-2025 Apple Inc. and the FoundationDB project authors + * + * 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.apple.foundationdb.record.query.plan.cascades; + +import com.apple.foundationdb.record.query.plan.cascades.typing.Type; +import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; +import com.google.common.base.Verify; +import com.google.common.collect.ImmutableList; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class CatalogedFunction { + @Nonnull + final String functionName; + + @Nonnull + final List parameterTypes; + + /** + * The type of the function's variadic parameters (if any). + */ + @Nullable + final Type variadicSuffixType; + + public CatalogedFunction(@Nonnull final String functionName, @Nonnull final List parameterTypes, @Nullable final Type variadicSuffixType) { + this.functionName = functionName; + this.parameterTypes = ImmutableList.copyOf(parameterTypes); + this.variadicSuffixType = variadicSuffixType; + } + + @Nonnull + public String getFunctionName() { + return functionName; + } + + @Nonnull + public List getParameterTypes() { + return parameterTypes; + } + + @Nullable + public Type getVariadicSuffixType() { + return variadicSuffixType; + } + + public boolean hasVariadicSuffix() { + return variadicSuffixType != null; + } + + @Nonnull + public Type resolveParameterType(int index) { + Verify.verify(index >= 0, "unexpected negative parameter index"); + if (index < parameterTypes.size()) { + return parameterTypes.get(index); + } else { + if (hasVariadicSuffix()) { + return variadicSuffixType; + } + throw new IllegalArgumentException("cannot resolve declared parameter at index " + index); + } + } + + @Nonnull + public List resolveParameterTypes(int numberOfArguments) { + Verify.verify(numberOfArguments > 0, "unexpected number of arguments"); + final ImmutableList.Builder resultBuilder = ImmutableList.builder(); + for (int i = 0; i < numberOfArguments; i ++) { + resultBuilder.add(resolveParameterType(i)); + } + return resultBuilder.build(); + } + + @Nonnull + @Override + public String toString() { + String variadicSuffixString = ""; + if (variadicSuffixType != null) { + variadicSuffixString = variadicSuffixType + "..."; + if (!parameterTypes.isEmpty()) { + variadicSuffixString = ", " + variadicSuffixString; + } + } + + return functionName + "(" + parameterTypes.stream().map(Object::toString).collect(Collectors.joining(",")) + variadicSuffixString + ")"; + } + + @Nonnull + public abstract Typed encapsulate(@Nonnull List arguments); +} diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/KeyExpressionExpansionVisitor.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/KeyExpressionExpansionVisitor.java index 1e856877ab..aa7a24caa6 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/KeyExpressionExpansionVisitor.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/KeyExpressionExpansionVisitor.java @@ -21,7 +21,7 @@ package com.apple.foundationdb.record.query.plan.cascades; import com.apple.foundationdb.record.RecordCoreException; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.expressions.EmptyKeyExpression; import com.apple.foundationdb.record.metadata.expressions.FieldKeyExpression; import com.apple.foundationdb.record.metadata.expressions.FunctionKeyExpression; @@ -238,14 +238,14 @@ public GraphExpansion visitExpression(@Nonnull final NestingKeyExpression nestin .add(parent.getFieldName()) .build(); if (NullableArrayTypeUtils.isArrayWrapper(nestingKeyExpression)) { - final RecordMetaDataProto.KeyExpression childProto = nestingKeyExpression.getChild().toKeyExpression(); + final RecordKeyExpressionProto.KeyExpression childProto = nestingKeyExpression.getChild().toKeyExpression(); if (childProto.hasNesting()) { - RecordMetaDataProto.Nesting.Builder newNestingBuilder = RecordMetaDataProto.Nesting.newBuilder() - .setParent(parent.toProto().toBuilder().setFanType(RecordMetaDataProto.Field.FanType.FAN_OUT)) + RecordKeyExpressionProto.Nesting.Builder newNestingBuilder = RecordKeyExpressionProto.Nesting.newBuilder() + .setParent(parent.toProto().toBuilder().setFanType(RecordKeyExpressionProto.Field.FanType.FAN_OUT)) .setChild(childProto.getNesting().getChild()); return visitExpression(new NestingKeyExpression(newNestingBuilder.build())); } else { - return visitExpression(new FieldKeyExpression(parent.toProto().toBuilder().setFanType(RecordMetaDataProto.Field.FanType.FAN_OUT).build())); + return visitExpression(new FieldKeyExpression(parent.toProto().toBuilder().setFanType(RecordKeyExpressionProto.Field.FanType.FAN_OUT).build())); } } return pop(child.expand(push(state.withFieldNamePrefix(newPrefix)))); diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/MacroFunction.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/MacroFunction.java new file mode 100644 index 0000000000..1d6a406863 --- /dev/null +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/MacroFunction.java @@ -0,0 +1,109 @@ +/* + * MacroFunction.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2015-2025 Apple Inc. and the FoundationDB project authors + * + * 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.apple.foundationdb.record.query.plan.cascades; + +import com.apple.foundationdb.record.PlanDeserializer; +import com.apple.foundationdb.record.PlanSerializationContext; +import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.planprotos.PMacroFunctionValue; +import com.apple.foundationdb.record.query.plan.cascades.typing.Typed; +import com.apple.foundationdb.record.query.plan.cascades.values.QuantifiedObjectValue; +import com.apple.foundationdb.record.query.plan.cascades.values.Value; +import com.apple.foundationdb.record.query.plan.cascades.values.translation.TranslationMap; +import com.google.auto.service.AutoService; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +/** + * MacroFunction that expands a body (referring to parameters) into a {@link Value} (through encapsulation) call site. + */ +public class MacroFunction extends UserDefinedFunction { + private static final long serialVersionUID = 1L; + + @Nonnull + private final Value bodyValue; + private final List parameterIdentifiers; + + public MacroFunction(@Nonnull final String functionName, @Nonnull final List parameters, @Nonnull final Value bodyValue) { + super(functionName, parameters.stream().map(QuantifiedObjectValue::getResultType).collect(Collectors.toUnmodifiableList())); + this.parameterIdentifiers = parameters.stream().map(QuantifiedObjectValue::getAlias).collect(Collectors.toList()); + this.bodyValue = bodyValue; + } + + @Nonnull + @Override + public Value encapsulate(@Nonnull List arguments) { + // replace the QuantifiedObjectValue in body with arguments + SemanticException.check(arguments.size() == parameterTypes.size(), SemanticException.ErrorCode.FUNCTION_UNDEFINED_FOR_GIVEN_ARGUMENT_TYPES, "argument length doesn't match with function definition"); + TranslationMap.Builder translationMapBuilder = new TranslationMap.Builder(); + for (int i = 0; i < arguments.size(); i++) { + // check that arguments[i] type matches with parameterTypes[i] + final int finalI = i; + SemanticException.check(arguments.get(finalI).getResultType().equals(parameterTypes.get(i)), SemanticException.ErrorCode.FUNCTION_UNDEFINED_FOR_GIVEN_ARGUMENT_TYPES, "argument type doesn't match with function definition"); + translationMapBuilder.when(parameterIdentifiers.get(finalI)).then((sourceAlias, leafValue) -> (Value)arguments.get(finalI)); + } + return bodyValue.translateCorrelations(translationMapBuilder.build()); + } + + @Nonnull + @Override + public RecordMetaDataProto.UserDefinedFunction toProto(@Nonnull PlanSerializationContext serializationContext) { + PMacroFunctionValue.Builder builder = PMacroFunctionValue.newBuilder(); + for (int i = 0; i < parameterTypes.size(); i++) { + builder.addArguments(QuantifiedObjectValue.of(parameterIdentifiers.get(i), parameterTypes.get(i)).toValueProto(serializationContext)); + } + return RecordMetaDataProto.UserDefinedFunction.newBuilder() + .setMacroFunction(builder + .setFunctionName(functionName) + .setBody(bodyValue.toValueProto(serializationContext))) + .build(); + + } + + @Nonnull + public static MacroFunction fromProto(@Nonnull final PlanSerializationContext serializationContext, @Nonnull final PMacroFunctionValue functionValue) { + return new MacroFunction( + functionValue.getFunctionName(), + functionValue.getArgumentsList().stream().map(pvalue -> ((QuantifiedObjectValue)Value.fromValueProto(serializationContext, pvalue))).collect(Collectors.toList()), + Value.fromValueProto(serializationContext, functionValue.getBody())); + } + + /** + * Deserializer. + */ + @AutoService(PlanDeserializer.class) + public static class Deserializer implements PlanDeserializer { + @Nonnull + @Override + public Class getProtoMessageClass() { + return PMacroFunctionValue.class; + } + + @Nonnull + @Override + public MacroFunction fromProto(@Nonnull final PlanSerializationContext serializationContext, + @Nonnull final PMacroFunctionValue macroFunctionValue) { + return MacroFunction.fromProto(serializationContext, macroFunctionValue); + } + } +} diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/NullableArrayTypeUtils.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/NullableArrayTypeUtils.java index 14637de059..4686a68d06 100644 --- a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/NullableArrayTypeUtils.java +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/NullableArrayTypeUtils.java @@ -20,7 +20,7 @@ package com.apple.foundationdb.record.query.plan.cascades; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.expressions.NestingKeyExpression; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; import com.apple.foundationdb.record.query.plan.cascades.values.MessageHelpers; @@ -79,10 +79,10 @@ public static boolean describesWrappedArray(@Nonnull Descriptors.Descriptor desc * @return true if it describes a wrapped array, otherwise false. */ public static boolean isArrayWrapper(@Nonnull NestingKeyExpression nestingKeyExpression) { - RecordMetaDataProto.KeyExpression child = nestingKeyExpression.getChild().toKeyExpression(); + RecordKeyExpressionProto.KeyExpression child = nestingKeyExpression.getChild().toKeyExpression(); if (child.hasNesting()) { // if child is Nesting, check child.parent - RecordMetaDataProto.Field firstChild = child.getNesting().getParent(); + RecordKeyExpressionProto.Field firstChild = child.getNesting().getParent(); return isWrappedField(firstChild); } else if (child.hasField()) { // if child is Field, check itself @@ -118,7 +118,7 @@ public static Object unwrapIfArray(@Nullable Object wrappedValue, @Nonnull Type * * @return true if it is a wrapped array, otherwise false. */ - private static boolean isWrappedField(@Nonnull RecordMetaDataProto.Field field) { - return REPEATED_FIELD_NAME.equals(field.getFieldName()) && RecordMetaDataProto.Field.FanType.FAN_OUT.equals(field.getFanType()); + private static boolean isWrappedField(@Nonnull RecordKeyExpressionProto.Field field) { + return REPEATED_FIELD_NAME.equals(field.getFieldName()) && RecordKeyExpressionProto.Field.FanType.FAN_OUT.equals(field.getFanType()); } } diff --git a/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/UserDefinedFunction.java b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/UserDefinedFunction.java new file mode 100644 index 0000000000..804dc6194d --- /dev/null +++ b/fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/UserDefinedFunction.java @@ -0,0 +1,51 @@ +/* + * UserDefinedFunction.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2015-2025 Apple Inc. and the FoundationDB project authors + * + * 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.apple.foundationdb.record.query.plan.cascades; + +import com.apple.foundationdb.record.PlanSerializationContext; +import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.query.plan.cascades.typing.Type; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * User defined functions that are serialized in MetaData. + */ +public abstract class UserDefinedFunction extends CatalogedFunction { + + public UserDefinedFunction(@Nonnull final String functionName, @Nonnull final List parameterTypes) { + super(functionName, parameterTypes, null); + } + + @Nullable + public static UserDefinedFunction fromProto(@Nonnull PlanSerializationContext serializationContext, @Nonnull RecordMetaDataProto.UserDefinedFunction proto) { + if (proto.hasMacroFunction()) { + return MacroFunction.fromProto(serializationContext, proto); + } else { + return null; + } + } + + @Nonnull + public abstract RecordMetaDataProto.UserDefinedFunction toProto(@Nonnull PlanSerializationContext serializationContext); +} diff --git a/fdb-record-layer-core/src/main/proto/planner_debugger.proto b/fdb-record-layer-core/src/main/proto/planner_debugger.proto index f163678e0e..dbb4310aa8 100644 --- a/fdb-record-layer-core/src/main/proto/planner_debugger.proto +++ b/fdb-record-layer-core/src/main/proto/planner_debugger.proto @@ -21,9 +21,6 @@ syntax = "proto2"; package com.apple.foundationdb.record.query.plan.cascades.debug.eventprotos; import "google/protobuf/descriptor.proto"; -import "google/protobuf/any.proto"; -import "record_metadata.proto"; -import "record_query_plan.proto"; option java_outer_classname = "PlannerDebuggerProto"; option java_multiple_files = true; diff --git a/fdb-record-layer-core/src/main/proto/record_key_expression.proto b/fdb-record-layer-core/src/main/proto/record_key_expression.proto new file mode 100644 index 0000000000..b351ea9367 --- /dev/null +++ b/fdb-record-layer-core/src/main/proto/record_key_expression.proto @@ -0,0 +1,118 @@ +/* + * record_key_expression.proto + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2015-2018 Apple Inc. and the FoundationDB project authors + * + * 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. + */ +syntax = "proto2"; + +package com.apple.foundationdb.record.expressions; +import "google/protobuf/descriptor.proto"; + +option java_outer_classname = "RecordKeyExpressionProto"; + +message Then { + repeated KeyExpression child = 1; +} + +message List { + repeated KeyExpression child = 1; +} + +message Field { + required string field_name = 1; + required FanType fan_type = 2; + enum FanType { + SCALAR = 1; + FAN_OUT = 2; + CONCATENATE = 3; + } + optional NullInterpretation nullInterpretation = 3 [default = NOT_UNIQUE]; + enum NullInterpretation { + NOT_UNIQUE = 1; // Missing values allowed multiple times in unique index + UNIQUE = 2; // Missing values treated like null value in unique index + NOT_NULL = 3; // Missing values are the default for the type, not null + } +} + +message Nesting { + optional Field parent = 1; + optional KeyExpression child = 2; +} + +message Grouping { + required KeyExpression whole_key = 1; + optional int32 grouped_count = 3 [default = 1]; +} + +message Dimensions { + required KeyExpression whole_key = 1; + optional int32 prefix_size = 2; + optional int32 dimensions_size = 3; +} + +message KeyWithValue { + required KeyExpression inner_key = 1; + optional int32 split_point = 2 [default = 1]; +} + +message Split { + required KeyExpression joined = 1; + optional int32 split_size = 2; +} + +message Empty { +} + +message Version { +} + +message RecordTypeKey { +} + +message Value { + // TODO: This should be a oneof {} + optional double double_value = 1; + optional float float_value = 2; + optional int64 long_value = 3; + optional bool bool_value = 4; + optional string string_value = 5; + optional bytes bytes_value = 6; + optional int32 int_value = 7; +} + + +message Function { + required string name = 1; + required KeyExpression arguments = 2; +} + +message KeyExpression { + // Exactly one of the following: + optional Then then = 1; + optional Nesting nesting = 2; + optional Field field = 3; + optional Grouping grouping = 4; + optional Empty empty = 5; + optional Split split = 6; + optional Version version = 7; + optional Value value = 8; + optional Function function = 9; + optional KeyWithValue key_with_value = 10; + optional RecordTypeKey record_type_key = 11; + optional List list = 12; + optional Dimensions dimensions = 13; +} diff --git a/fdb-record-layer-core/src/main/proto/record_metadata.proto b/fdb-record-layer-core/src/main/proto/record_metadata.proto index 29fbb26cc1..11181b4ec8 100644 --- a/fdb-record-layer-core/src/main/proto/record_metadata.proto +++ b/fdb-record-layer-core/src/main/proto/record_metadata.proto @@ -21,6 +21,8 @@ syntax = "proto2"; package com.apple.foundationdb.record; import "google/protobuf/descriptor.proto"; +import "record_key_expression.proto"; +import "record_query_plan.proto"; option java_outer_classname = "RecordMetaDataProto"; @@ -28,7 +30,7 @@ message DataStoreInfo { optional int32 formatVersion = 1; optional int32 metaDataversion = 2; optional int32 userVersion = 3; - optional KeyExpression record_count_key = 4; + optional com.apple.foundationdb.record.expressions.KeyExpression record_count_key = 4; optional uint64 lastUpdateTime = 5; optional bool omit_unsplit_record_suffix = 6; optional bool cacheable = 7; @@ -51,11 +53,11 @@ message Index { repeated string record_type = 1; optional Type index_type = 2 [deprecated = true]; // Use type. optional string name = 3; - optional KeyExpression root_expression = 4; + optional com.apple.foundationdb.record.expressions.KeyExpression root_expression = 4; optional bytes subspace_key = 5; optional int32 last_modified_version = 6; // value_expression should now be expressed as a KeyWithValue() root expression - optional KeyExpression value_expression = 7 [deprecated = true]; + optional com.apple.foundationdb.record.expressions.KeyExpression value_expression = 7 [deprecated = true]; optional string type = 8; repeated Option options = 9; message Option { @@ -69,9 +71,9 @@ message Index { message RecordType { required string name = 1; - optional KeyExpression primary_key = 2; + optional com.apple.foundationdb.record.expressions.KeyExpression primary_key = 2; optional int32 since_version = 3; - optional Value explicit_key = 4; + optional com.apple.foundationdb.record.expressions.Value explicit_key = 4; extensions 1000 to 2000; } @@ -90,111 +92,26 @@ message MetaData { optional bool split_long_records = 4; optional int32 version = 5; repeated FormerIndex former_indexes = 6; - optional KeyExpression record_count_key = 7 [deprecated = true]; + optional com.apple.foundationdb.record.expressions.KeyExpression record_count_key = 7 [deprecated = true]; optional bool store_record_versions = 8; repeated google.protobuf.FileDescriptorProto dependencies = 9; optional int64 subspace_key_counter = 10; optional bool uses_subspace_key_counter = 11; repeated JoinedRecordType joined_record_types = 12; repeated UnnestedRecordType unnested_record_types = 13; + repeated UserDefinedFunction user_defined_functions = 14; extensions 1000 to 2000; } -message Then { - repeated KeyExpression child = 1; -} - -message List { - repeated KeyExpression child = 1; -} - -message Field { - required string field_name = 1; - required FanType fan_type = 2; - enum FanType { - SCALAR = 1; - FAN_OUT = 2; - CONCATENATE = 3; +message UserDefinedFunction { + oneof specific_function { + com.apple.foundationdb.record.planprotos.PMacroFunctionValue macro_function = 1; } - optional NullInterpretation nullInterpretation = 3 [default = NOT_UNIQUE]; - enum NullInterpretation { - NOT_UNIQUE = 1; // Missing values allowed multiple times in unique index - UNIQUE = 2; // Missing values treated like null value in unique index - NOT_NULL = 3; // Missing values are the default for the type, not null - } -} - -message Nesting { - optional Field parent = 1; - optional KeyExpression child = 2; -} - -message Grouping { - required KeyExpression whole_key = 1; - optional int32 grouped_count = 3 [default = 1]; -} - -message Dimensions { - required KeyExpression whole_key = 1; - optional int32 prefix_size = 2; - optional int32 dimensions_size = 3; -} - -message KeyWithValue { - required KeyExpression inner_key = 1; - optional int32 split_point = 2 [default = 1]; -} - -message Split { - required KeyExpression joined = 1; - optional int32 split_size = 2; -} - -message Empty { -} - -message Version { -} - -message RecordTypeKey { -} - -message Value { - // TODO: This should be a oneof {} - optional double double_value = 1; - optional float float_value = 2; - optional int64 long_value = 3; - optional bool bool_value = 4; - optional string string_value = 5; - optional bytes bytes_value = 6; - optional int32 int_value = 7; -} - -message Function { - required string name = 1; - required KeyExpression arguments = 2; -} - -message KeyExpression { - // Exactly one of the following: - optional Then then = 1; - optional Nesting nesting = 2; - optional Field field = 3; - optional Grouping grouping = 4; - optional Empty empty = 5; - optional Split split = 6; - optional Version version = 7; - optional Value value = 8; - optional Function function = 9; - optional KeyWithValue key_with_value = 10; - optional RecordTypeKey record_type_key = 11; - optional List list = 12; - optional Dimensions dimensions = 13; } message JoinedRecordType { optional string name = 1; - optional Value record_type_key = 4; + optional com.apple.foundationdb.record.expressions.Value record_type_key = 4; message JoinConstituent { optional string name = 1; @@ -204,9 +121,9 @@ message JoinedRecordType { message Join { optional string left = 1; - optional KeyExpression left_expression = 2; + optional com.apple.foundationdb.record.expressions.KeyExpression left_expression = 2; optional string right = 3; - optional KeyExpression right_expression = 4; + optional com.apple.foundationdb.record.expressions.KeyExpression right_expression = 4; } repeated JoinConstituent join_constituents = 10; @@ -215,13 +132,13 @@ message JoinedRecordType { message UnnestedRecordType { optional string name = 1; - optional Value record_type_key = 2; + optional com.apple.foundationdb.record.expressions.Value record_type_key = 2; message NestedConstituent { optional string name = 1; optional string parent = 2; optional string type_name = 3; - optional KeyExpression nesting_expression = 4; + optional com.apple.foundationdb.record.expressions.KeyExpression nesting_expression = 4; } repeated NestedConstituent nested_constituents = 3; @@ -243,7 +160,7 @@ enum ComparisonType { message SimpleComparison { optional ComparisonType type = 1; - optional Value operand = 2; + optional com.apple.foundationdb.record.expressions.Value operand = 2; } // in Comparisons.Comparison we have a special NullComparison that takes care of comparing diff --git a/fdb-record-layer-core/src/main/proto/record_metadata_options.proto b/fdb-record-layer-core/src/main/proto/record_metadata_options.proto index 000d13efd1..26ecbeb261 100644 --- a/fdb-record-layer-core/src/main/proto/record_metadata_options.proto +++ b/fdb-record-layer-core/src/main/proto/record_metadata_options.proto @@ -23,6 +23,7 @@ package com.apple.foundationdb.record; option java_outer_classname = "RecordMetaDataOptionsProto"; import "google/protobuf/descriptor.proto"; +import "record_key_expression.proto"; import "record_metadata.proto"; message SchemaOptions { @@ -43,7 +44,7 @@ message RecordTypeOptions { } optional Usage usage = 1 [default = UNSET]; optional int32 since_version = 2; // This record_type is introduced on this metadata version - optional Value record_type_key = 3; + optional com.apple.foundationdb.record.expressions.Value record_type_key = 3; } extend google.protobuf.MessageOptions { diff --git a/fdb-record-layer-core/src/main/proto/record_query_plan.proto b/fdb-record-layer-core/src/main/proto/record_query_plan.proto index 4e93153c64..3ee4a28e59 100644 --- a/fdb-record-layer-core/src/main/proto/record_query_plan.proto +++ b/fdb-record-layer-core/src/main/proto/record_query_plan.proto @@ -22,8 +22,7 @@ syntax = "proto2"; package com.apple.foundationdb.record.planprotos; import "google/protobuf/descriptor.proto"; import "google/protobuf/any.proto"; -import "record_query_runtime.proto"; -import "record_metadata.proto"; +import "record_key_expression.proto"; option java_outer_classname = "RecordQueryPlanProto"; option java_multiple_files = true; @@ -244,9 +243,16 @@ message PValue { PCollateValue collate_value = 44; PNumericAggregationValue.PBitmapConstructAgg numeric_aggregation_value_bitmap_construct_agg = 45; PQuantifiedRecordValue quantified_record_value = 46; + PMacroFunctionValue macro_function_value = 47; } } +message PMacroFunctionValue { + optional string function_name = 1; + repeated PValue arguments = 2; + optional PValue body = 3; +} + message PAbstractArrayConstructorValue { repeated PValue children = 1; optional PType element_type = 2; @@ -1010,7 +1016,7 @@ message PSimpleComparison { message PConversionSimpleComparison { optional PComparison.PComparisonType type = 1; optional PComparableObject object = 2; - optional KeyExpression conversion = 3; + optional com.apple.foundationdb.record.expressions.KeyExpression conversion = 3; } message PParameterComparison { @@ -1030,7 +1036,7 @@ message PConversionParameterComparison { optional PComparison.PComparisonType type = 1; optional string parameter = 2; optional PParameterComparison.PBindingKind internal = 3; - optional KeyExpression conversion = 4; + optional com.apple.foundationdb.record.expressions.KeyExpression conversion = 4; } message PValueComparison { @@ -1056,7 +1062,7 @@ message PMultiColumnComparison { } message PInvertedFunctionComparison { - optional Function function = 1; + optional com.apple.foundationdb.record.expressions.Function function = 1; optional PComparison original_comparison = 2; optional PComparison.PComparisonType type = 3; } @@ -1382,7 +1388,7 @@ message PRecordQueryFlatMapPlan { // message PRecordQueryIndexPlan { optional string index_name = 1; - optional KeyExpression common_primary_key = 2; + optional com.apple.foundationdb.record.expressions.KeyExpression common_primary_key = 2; optional PIndexScanParameters scan_parameters = 3; optional PIndexFetchMethod index_fetch_method = 4; optional PFetchIndexRecords fetch_index_records = 5; @@ -1551,7 +1557,7 @@ message PRecordQueryIntersectionPlan { message PComparisonKeyFunction { message POnKeyExpression { - optional KeyExpression comparison_key_expression = 1; + optional com.apple.foundationdb.record.expressions.KeyExpression comparison_key_expression = 1; } message POnValues { optional string base_alias = 1; @@ -1642,7 +1648,7 @@ message PRecordQuerySortPlan { } message PRecordQuerySortKey { - optional KeyExpression key = 1; + optional com.apple.foundationdb.record.expressions.KeyExpression key = 1; optional bool reverse = 2; } @@ -1653,7 +1659,7 @@ message PRecordQueryScanPlan { optional bool has_record_types = 1; repeated string record_types = 2; optional PType flowed_type = 3; - optional KeyExpression common_primary_key = 4; + optional com.apple.foundationdb.record.expressions.KeyExpression common_primary_key = 4; optional PScanComparisons comparisons = 5; optional bool reverse = 6; optional bool strictly_sorted = 7; @@ -1687,7 +1693,7 @@ message PScoreForRank { message PIndexAggregateFunction { optional string name = 1; - optional KeyExpression operand = 2; + optional com.apple.foundationdb.record.expressions.KeyExpression operand = 2; optional string index = 3; } @@ -1741,7 +1747,7 @@ message PRecordQueryUnionPlan { // message PRecordQueryUnorderedDistinctPlan { optional PPhysicalQuantifier inner = 1; - optional KeyExpression comparison_key = 2; + optional com.apple.foundationdb.record.expressions.KeyExpression comparison_key = 2; } // @@ -1773,6 +1779,30 @@ message PRecordQueryUpdatePlan { optional PRecordQueryAbstractDataModificationPlan super = 1; } +message PEnumLightValue { + optional string name = 1; + optional int32 number = 2; +} + +message PUUID { + optional uint64 mostSigBits = 1; + optional uint64 leastSigBits = 2; +} + +message PFDBRecordVersion { + optional bytes raw_bytes = 1; +} + +message PComparableObject { + oneof specific_object { + com.apple.foundationdb.record.expressions.Value primitive_object = 1; + PEnumLightValue enum_object = 2; + PUUID uuid = 3; + PFDBRecordVersion fdb_record_version = 4; + bytes bytes_as_byte_string = 5; + } +} + // // PRecursiveUnionQueryPlan // @@ -1781,4 +1811,4 @@ message PRecursiveUnionQueryPlan { optional PPhysicalQuantifier recursiveStateQuantifier = 2; optional string initialTempTableAlias = 3; optional string recursiveTempTableAlias = 4; -} \ No newline at end of file +} diff --git a/fdb-record-layer-core/src/main/proto/record_query_runtime.proto b/fdb-record-layer-core/src/main/proto/record_query_runtime.proto index e8c41196f8..0a8d67bca8 100644 --- a/fdb-record-layer-core/src/main/proto/record_query_runtime.proto +++ b/fdb-record-layer-core/src/main/proto/record_query_runtime.proto @@ -21,35 +21,11 @@ syntax = "proto2"; package com.apple.foundationdb.record.planprotos; import "google/protobuf/descriptor.proto"; -import "record_metadata.proto"; +import "record_query_plan.proto"; option java_outer_classname = "RecordQueryRuntimeProto"; option java_multiple_files = true; -message PEnumLightValue { - optional string name = 1; - optional int32 number = 2; -} - -message PUUID { - optional uint64 mostSigBits = 1; - optional uint64 leastSigBits = 2; -} - -message PFDBRecordVersion { - optional bytes raw_bytes = 1; -} - -message PComparableObject { - oneof specific_object { - Value primitive_object = 1; - PEnumLightValue enum_object = 2; - PUUID uuid = 3; - PFDBRecordVersion fdb_record_version = 4; - bytes bytes_as_byte_string = 5; - } -} - message PQueryResult { oneof datum { PComparableObject primitive = 1; diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataEvolutionValidatorTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataEvolutionValidatorTest.java index 236079966f..c888cd0027 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataEvolutionValidatorTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataEvolutionValidatorTest.java @@ -22,6 +22,7 @@ import com.apple.foundationdb.async.RankedSet; import com.apple.foundationdb.record.RecordCoreException; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataBuilder; import com.apple.foundationdb.record.RecordMetaDataOptionsProto; @@ -1020,7 +1021,7 @@ public void recordTypeKeyChanged() { RecordMetaDataProto.MetaData.Builder protoBuilder = metaData1.toProto().toBuilder() .setVersion(metaData1.getVersion() + 1); protoBuilder.getRecordTypesBuilder(0) - .setExplicitKey(RecordMetaDataProto.Value.newBuilder() + .setExplicitKey(RecordKeyExpressionProto.Value.newBuilder() .setStringValue("new_key")); RecordMetaData metaData2 = RecordMetaData.build(protoBuilder.build()); assertInvalid("record type key changed", metaData1, metaData2); diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataProtoTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataProtoTest.java index 7eb4d7678c..34c64f23e3 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataProtoTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/MetaDataProtoTest.java @@ -23,6 +23,7 @@ import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataBuilder; import com.apple.foundationdb.record.RecordMetaDataOptionsProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.TestRecords1Proto; import com.apple.foundationdb.record.TestRecords2Proto; @@ -270,10 +271,10 @@ public void indexProtoOptions() throws Exception { } } - public static RecordMetaDataProto.Field.Builder scalarField(String name) { - return RecordMetaDataProto.Field.newBuilder() + public static RecordKeyExpressionProto.Field.Builder scalarField(String name) { + return RecordKeyExpressionProto.Field.newBuilder() .setFieldName(name) - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR); + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR); } @Test @@ -287,23 +288,23 @@ public void versionstampIndexDeserialization() throws Exception { .setType(IndexTypes.VERSION) .addRecordType("MyRecord") .setRootExpression( - RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() + RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() .setParent(scalarField("header")) - .setChild(RecordMetaDataProto.KeyExpression.newBuilder() - .setThen(RecordMetaDataProto.Then.newBuilder() - .addChild(RecordMetaDataProto.KeyExpression.newBuilder() + .setChild(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setThen(RecordKeyExpressionProto.Then.newBuilder() + .addChild(RecordKeyExpressionProto.KeyExpression.newBuilder() .setField(scalarField("num"))) - .addChild(RecordMetaDataProto.KeyExpression.newBuilder() - .setVersion(RecordMetaDataProto.Version.getDefaultInstance())))))); + .addChild(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setVersion(RecordKeyExpressionProto.Version.getDefaultInstance())))))); protoBuilder.addRecordTypes(RecordMetaDataProto.RecordType.newBuilder() .setName("MyRecord") .setPrimaryKey( - RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() + RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() .setParent(scalarField("header")) - .setChild(RecordMetaDataProto.KeyExpression.newBuilder() + .setChild(RecordKeyExpressionProto.KeyExpression.newBuilder() .setField(scalarField("rec_no")))))); RecordMetaData metaData = RecordMetaData.newBuilder().addDependencies(BASE_DEPENDENCIES) @@ -326,25 +327,25 @@ public void indexGroupingCompatibility() throws Exception { .setName("RecordCount") .setType(IndexTypes.COUNT) .addRecordType("MyModernRecord") - .setRootExpression(RecordMetaDataProto.KeyExpression.newBuilder() - .setEmpty(RecordMetaDataProto.Empty.getDefaultInstance())); + .setRootExpression(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setEmpty(RecordKeyExpressionProto.Empty.getDefaultInstance())); protoBuilder.addIndexesBuilder() .setName("MaxRecNo") .setType(IndexTypes.MAX_EVER) .addRecordType("MyModernRecord") - .setRootExpression(RecordMetaDataProto.KeyExpression.newBuilder() + .setRootExpression(RecordKeyExpressionProto.KeyExpression.newBuilder() .setField(scalarField("rec_no"))); protoBuilder.addIndexesBuilder() .setName("MaxRecNoGrouped") .setType(IndexTypes.MAX_EVER) .addRecordType("MyModernRecord") - .setRootExpression(RecordMetaDataProto.KeyExpression.newBuilder() - .setThen(RecordMetaDataProto.Then.newBuilder() - .addChild(RecordMetaDataProto.KeyExpression.newBuilder() + .setRootExpression(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setThen(RecordKeyExpressionProto.Then.newBuilder() + .addChild(RecordKeyExpressionProto.KeyExpression.newBuilder() .setField(scalarField("index"))) - .addChild(RecordMetaDataProto.KeyExpression.newBuilder() + .addChild(RecordKeyExpressionProto.KeyExpression.newBuilder() .setField(scalarField("rec_no"))))); RecordMetaData metaData = RecordMetaData.newBuilder().addDependencies(BASE_DEPENDENCIES).setRecords(protoBuilder.build(), true).getRecordMetaData(); diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/UnknownKeyExpression.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/UnknownKeyExpression.java index 395cbca5b7..0c6b5be7a9 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/UnknownKeyExpression.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/UnknownKeyExpression.java @@ -21,7 +21,7 @@ package com.apple.foundationdb.record.metadata; import com.apple.foundationdb.record.ObjectPlanHash; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.expressions.BaseKeyExpression; import com.apple.foundationdb.record.metadata.expressions.KeyExpression; import com.apple.foundationdb.record.provider.foundationdb.FDBRecord; @@ -87,7 +87,7 @@ public Message toProto() throws SerializationException { @Nonnull @Override - public RecordMetaDataProto.KeyExpression toKeyExpression() { + public RecordKeyExpressionProto.KeyExpression toKeyExpression() { throw new UnsupportedOperationException("UnknownKeyExpressions cannot be converted to Protobuf"); } diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpressionTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpressionTest.java index f9443d8511..98957d74c6 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpressionTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/metadata/expressions/LiteralKeyExpressionTest.java @@ -20,7 +20,7 @@ package com.apple.foundationdb.record.metadata.expressions; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.provider.common.text.TextSamples; import com.google.protobuf.InvalidProtocolBufferException; @@ -69,7 +69,7 @@ public void serializationTest(@Nonnull Object value) throws InvalidProtocolBuffe final LiteralKeyExpression keyExpression = Key.Expressions.value(value); final LiteralKeyExpression parsedViaProto = LiteralKeyExpression.fromProto(keyExpression.toProto()); final LiteralKeyExpression parsedViaBytes = LiteralKeyExpression.fromProto( - RecordMetaDataProto.Value.parseFrom(keyExpression.toProto().toByteArray())); + RecordKeyExpressionProto.Value.parseFrom(keyExpression.toProto().toByteArray())); assertEquals(keyExpression, parsedViaProto); assertEquals(keyExpression, parsedViaBytes); if (value instanceof byte[]) { @@ -90,7 +90,7 @@ public void incorrectUnicodeSurrogatePairSerializationTest() throws InvalidProto final LiteralKeyExpression parsedViaProto = LiteralKeyExpression.fromProto(keyExpression.toProto()); final LiteralKeyExpression parsedViaBytes = LiteralKeyExpression.fromProto( - RecordMetaDataProto.Value.parseFrom(keyExpression.toProto().toByteArray())); + RecordKeyExpressionProto.Value.parseFrom(keyExpression.toProto().toByteArray())); assertEquals(keyExpression, parsedViaProto); // Comparison uses proto objects, so both sides have Longs. // Comparison with proto objects works since we never leave Java. diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBMetaDataStoreTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBMetaDataStoreTest.java index 9c3e7c65af..c0cbe34eca 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBMetaDataStoreTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBMetaDataStoreTest.java @@ -26,6 +26,7 @@ import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataBuilder; import com.apple.foundationdb.record.RecordMetaDataOptionsProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.TestNoUnionEvolvedIllegalProto; import com.apple.foundationdb.record.TestNoUnionEvolvedProto; @@ -191,7 +192,7 @@ public void manyTypes() { metaData.addRecordTypesBuilder() .setName("type_" + ri) .getPrimaryKeyBuilder().getFieldBuilder() - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR) + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) .setFieldName("field_1"); } @@ -218,10 +219,10 @@ public void historyCompat() { metaData.setRecords(TestRecords1Proto.getDescriptor().toProto()); metaData.addRecordTypesBuilder() .setName("MySimpleRecord") - .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordMetaDataProto.Field.FanType.SCALAR); + .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR); metaData.addRecordTypesBuilder() .setName("MyOtherRecord") - .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordMetaDataProto.Field.FanType.SCALAR); + .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR); metaData.setVersion(101); metaDataStore.saveRecordMetaData(metaData.build()); @@ -259,7 +260,7 @@ public void historyCompat() { metaData.setRecords(TestRecords1Proto.getDescriptor().toProto()); metaData.addRecordTypesBuilder() .setName("MySimpleRecord") - .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordMetaDataProto.Field.FanType.SCALAR); + .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR); metaData.addIndexesBuilder() .setName("MyIndex") .addRecordType("MySimpleRecord") @@ -267,10 +268,10 @@ public void historyCompat() { .setLastModifiedVersion(102) .getRootExpressionBuilder().getFieldBuilder() .setFieldName("num_value_2") - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR); + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR); metaData.addRecordTypesBuilder() .setName("MyOtherRecord") - .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordMetaDataProto.Field.FanType.SCALAR); + .getPrimaryKeyBuilder().getFieldBuilder().setFieldName("rec_no").setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR); metaData.setVersion(102); metaDataStore.saveRecordMetaData(metaData.build()); context.commit(); diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreTest.java index 855bf4eb5e..a9f3a15bd6 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/FDBRecordStoreTest.java @@ -35,6 +35,7 @@ import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataBuilder; import com.apple.foundationdb.record.RecordMetaDataOptionsProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.RecordMetaDataProvider; import com.apple.foundationdb.record.ScanProperties; @@ -770,7 +771,7 @@ public void testAccessUserField() throws Exception { assertEquals("µs", recordStore.getHeaderUserField("foo").toStringUtf8()); ByteString bazValue = recordStore.getHeaderUserField("baz"); assertNotNull(bazValue); - KeyExpression expr = KeyExpression.fromProto(RecordMetaDataProto.KeyExpression.parseFrom(bazValue)); + KeyExpression expr = KeyExpression.fromProto(RecordKeyExpressionProto.KeyExpression.parseFrom(bazValue)); assertEquals(field("baz"), expr); // Add in a new field diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/storestate/FDBRecordStoreStateCacheTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/storestate/FDBRecordStoreStateCacheTest.java index 74c1586fe9..5eec68fc94 100644 --- a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/storestate/FDBRecordStoreStateCacheTest.java +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/storestate/FDBRecordStoreStateCacheTest.java @@ -25,7 +25,7 @@ import com.apple.foundationdb.record.RecordCoreException; import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataBuilder; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.TestRecords1Proto; import com.apple.foundationdb.record.metadata.Key; import com.apple.foundationdb.record.metadata.expressions.KeyExpression; @@ -790,7 +790,7 @@ public void cacheUserFields(@Nonnull StateCacheTestContext testContext) throws E try (FDBRecordContext context = testContext.getCachedContext(fdb, storeBuilder, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NOT_EXISTS)) { openSimpleRecordStore(context); assertNotNull(recordStore.getHeaderUserField("expr")); - KeyExpression expr = KeyExpression.fromProto(RecordMetaDataProto.KeyExpression.parseFrom(recordStore.getHeaderUserField("expr"))); + KeyExpression expr = KeyExpression.fromProto(RecordKeyExpressionProto.KeyExpression.parseFrom(recordStore.getHeaderUserField("expr"))); assertEquals(Key.Expressions.field("parent").nest("child"), expr); recordStore.clearHeaderUserField("expr"); commit(context); diff --git a/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/MacroFunctionTest.java b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/MacroFunctionTest.java new file mode 100644 index 0000000000..0ff371ca33 --- /dev/null +++ b/fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/query/plan/cascades/MacroFunctionTest.java @@ -0,0 +1,78 @@ +/* + * MacroFunctionTest.java + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2015-2025 Apple Inc. and the FoundationDB project authors + * + * 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.apple.foundationdb.record.query.plan.cascades; + + +import com.apple.foundationdb.record.query.plan.cascades.typing.Type; +import com.apple.foundationdb.record.query.plan.cascades.values.ArithmeticValue; +import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue; +import com.apple.foundationdb.record.query.plan.cascades.values.LiteralValue; +import com.apple.foundationdb.record.query.plan.cascades.values.QuantifiedObjectValue; +import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue; +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +/** + * Tests of {@link MacroFunction}. + */ +public class MacroFunctionTest { + @Test + void testColumnProjection() { + ImmutableList fields = ImmutableList.of( + Type.Record.Field.of(Type.primitiveType(Type.TypeCode.STRING), Optional.of("name")), + Type.Record.Field.of(Type.primitiveType(Type.TypeCode.LONG), Optional.of("id"))); + Type record = Type.Record.fromFields(false, fields); + QuantifiedObjectValue param = QuantifiedObjectValue.of(CorrelationIdentifier.uniqueID(), record); + FieldValue bodyValue = FieldValue.ofFieldName(param, "name"); + MacroFunction macroFunction = new MacroFunction("getName", ImmutableList.of(param), bodyValue); + + RecordConstructorValue testValue1 = RecordConstructorValue.ofColumns(ImmutableList.of( + Column.of(fields.get(0), new LiteralValue<>(fields.get(0).getFieldType(), "Rose")), + Column.of(fields.get(1), new LiteralValue<>(fields.get(1).getFieldType(), 1L)) + )); + + Assertions.assertEquals(FieldValue.ofFieldName(testValue1, "name"), macroFunction.encapsulate(ImmutableList.of(testValue1))); + } + + @Test + void testAdd() { + ImmutableList fields = ImmutableList.of( + Type.Record.Field.of(Type.primitiveType(Type.TypeCode.LONG), Optional.of("id"))); + Type record = Type.Record.fromFields(false, fields); + QuantifiedObjectValue param1 = QuantifiedObjectValue.of(CorrelationIdentifier.uniqueID(), record); + QuantifiedObjectValue param2 = QuantifiedObjectValue.of(CorrelationIdentifier.uniqueID(), record); + + ArithmeticValue bodyValue = new ArithmeticValue(ArithmeticValue.PhysicalOperator.ADD_LL, param1, param2); + MacroFunction macroFunction = new MacroFunction("add", ImmutableList.of(param1, param2), bodyValue); + + RecordConstructorValue testValue1 = RecordConstructorValue.ofColumns(ImmutableList.of( + Column.of(fields.get(0), new LiteralValue<>(fields.get(0).getFieldType(), 1L)) + )); + RecordConstructorValue testValue2 = RecordConstructorValue.ofColumns(ImmutableList.of( + Column.of(fields.get(0), new LiteralValue<>(fields.get(0).getFieldType(), 2L)) + )); + + Assertions.assertEquals(new ArithmeticValue(ArithmeticValue.PhysicalOperator.ADD_LL, testValue1, testValue2), macroFunction.encapsulate(ImmutableList.of(testValue1, testValue2))); + } +} diff --git a/fdb-record-layer-lucene/src/main/proto/lucene_record_query_plan.proto b/fdb-record-layer-lucene/src/main/proto/lucene_record_query_plan.proto index d3e647b92b..760f2b012e 100644 --- a/fdb-record-layer-lucene/src/main/proto/lucene_record_query_plan.proto +++ b/fdb-record-layer-lucene/src/main/proto/lucene_record_query_plan.proto @@ -21,7 +21,7 @@ syntax = "proto2"; package com.apple.foundationdb.record.planprotos; import "google/protobuf/descriptor.proto"; -import "record_metadata.proto"; +import "record_key_expression.proto"; import "record_query_plan.proto"; option java_outer_classname = "LuceneRecordQueryPlanProto"; @@ -30,7 +30,7 @@ option java_multiple_files = true; message PLuceneIndexQueryPlan { optional PRecordQueryIndexPlan super = 1; optional bool has_stored_fields = 2; - repeated KeyExpression stored_fields = 3; + repeated com.apple.foundationdb.record.expressions.KeyExpression stored_fields = 3; } message PLuceneScanParameters { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java index ead8f3b62a..3e14a5abbc 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/recordlayer/CatalogMetaData.java @@ -24,6 +24,7 @@ import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.Index; import com.apple.foundationdb.record.metadata.MetaDataException; import com.apple.foundationdb.record.metadata.RecordType; @@ -155,7 +156,7 @@ public RelationalResultSet getPrimaryKeys(String database, String schema, String Stream rows = schemaInfo.getRecordTypesList().stream() .filter(type -> type.getName().equals(table)) .map(type -> { - RecordMetaDataProto.KeyExpression ke = type.getPrimaryKey(); + RecordKeyExpressionProto.KeyExpression ke = type.getPrimaryKey(); return new AbstractMap.SimpleEntry<>(type.getName(), keyExpressionToPrimaryKey(ke)); }).flatMap(pks -> IntStream.range(0, pks.getValue().length) .mapToObj(pos -> new ArrayRow(database, @@ -347,12 +348,12 @@ private RecordMetaDataProto.MetaData loadSchemaMetadata(@Nonnull final String da } //the position in the array is the key sequence, the value is the name of the column - private String[] keyExpressionToPrimaryKey(RecordMetaDataProto.KeyExpression ke) throws UncheckedRelationalException { + private String[] keyExpressionToPrimaryKey(RecordKeyExpressionProto.KeyExpression ke) throws UncheckedRelationalException { if (ke.hasThen()) { - final List childList = ke.getThen().getChildList(); + final List childList = ke.getThen().getChildList(); String[] fields = new String[childList.size()]; int pos = 0; - for (RecordMetaDataProto.KeyExpression childKe : childList) { + for (RecordKeyExpressionProto.KeyExpression childKe : childList) { //skip record type keys if (!childKe.hasRecordTypeKey()) { if (childKe.hasField()) { diff --git a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java index 86b85b689f..2dca39405b 100644 --- a/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java +++ b/fdb-relational-core/src/main/java/com/apple/foundationdb/relational/util/NullableArrayUtils.java @@ -21,8 +21,7 @@ package com.apple.foundationdb.relational.util; import com.apple.foundationdb.annotation.API; - -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.query.plan.cascades.typing.Type; import com.apple.foundationdb.record.query.plan.cascades.typing.TypeRepository; @@ -70,9 +69,9 @@ public static boolean isWrappedArrayDescriptor(@Nonnull final Descriptors.Descri * * TODO Add the wrapped array structure for nullable arrays. */ - public static RecordMetaDataProto.KeyExpression wrapArray(RecordMetaDataProto.KeyExpression keyExpression, - final Type.Record record, - boolean containsNullableArray) { + public static RecordKeyExpressionProto.KeyExpression wrapArray(RecordKeyExpressionProto.KeyExpression keyExpression, + final Type.Record record, + boolean containsNullableArray) { if (!containsNullableArray) { return keyExpression; } @@ -87,7 +86,7 @@ public static RecordMetaDataProto.KeyExpression wrapArray(RecordMetaDataProto.Ke For example, reviews.rating -> reviews.values.rating (TODO): Add the wrapped array structure for nullable arrays. */ - public static RecordMetaDataProto.KeyExpression wrapArray(RecordMetaDataProto.KeyExpression keyExpression, + public static RecordKeyExpressionProto.KeyExpression wrapArray(RecordKeyExpressionProto.KeyExpression keyExpression, Descriptors.Descriptor parentDescriptor, boolean containsNullableArray) { if (!containsNullableArray) { @@ -97,15 +96,15 @@ public static RecordMetaDataProto.KeyExpression wrapArray(RecordMetaDataProto.Ke return wrapArrayInternal(keyExpression, parentDescriptor); } - private static RecordMetaDataProto.KeyExpression wrapArrayInternal(RecordMetaDataProto.KeyExpression keyExpression, + private static RecordKeyExpressionProto.KeyExpression wrapArrayInternal(RecordKeyExpressionProto.KeyExpression keyExpression, Descriptors.Descriptor parentDescriptor) { // handle concat (straightforward recursion) if (keyExpression.hasThen()) { - final var newThenBuilder = RecordMetaDataProto.Then.newBuilder(); + final var newThenBuilder = RecordKeyExpressionProto.Then.newBuilder(); for (final var child : keyExpression.getThen().getChildList()) { newThenBuilder.addChild(wrapArrayInternal(child, parentDescriptor)); } - return RecordMetaDataProto.KeyExpression.newBuilder().setThen(newThenBuilder).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setThen(newThenBuilder).build(); } // handle nested field @@ -120,20 +119,20 @@ private static RecordMetaDataProto.KeyExpression wrapArrayInternal(RecordMetaDat final var wrappedChild = wrapArrayInternal(child, parentDescriptor.findFieldByName(parentFieldName).getMessageType().findFieldByName(REPEATED_FIELD_NAME).getMessageType()); // the child is actually a grand child (since parent->child is actually parent->values->child), fix that. - final var newChild = RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() + final var newChild = RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() .setParent(wrappedParent.getChild().getField()) .setChild(wrappedChild)) .build(); - return RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() + return RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() .setParent(wrappedParent.getParent()) .setChild(newChild)) .build(); } else { final var wrappedChild = wrapArrayInternal(child, parentDescriptor.findFieldByName(parentFieldName).getMessageType()); - return RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() + return RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() .setParent(parent) .setChild(wrappedChild)) .build(); @@ -143,7 +142,7 @@ private static RecordMetaDataProto.KeyExpression wrapArrayInternal(RecordMetaDat // check key expression's field if (keyExpression.hasField()) { if (NullableArrayUtils.isWrappedArrayDescriptor(keyExpression.getField().getFieldName(), parentDescriptor)) { - return RecordMetaDataProto.KeyExpression.newBuilder().setNesting(splitFieldIntoNestedWithValues(keyExpression.getField())).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setNesting(splitFieldIntoNestedWithValues(keyExpression.getField())).build(); } else { return keyExpression; } @@ -152,50 +151,50 @@ private static RecordMetaDataProto.KeyExpression wrapArrayInternal(RecordMetaDat // grouping key expression if (keyExpression.hasGrouping()) { final var newWholeKey = wrapArrayInternal(keyExpression.getGrouping().getWholeKey(), parentDescriptor); - return RecordMetaDataProto.KeyExpression.newBuilder().setGrouping(keyExpression.getGrouping().toBuilder().setWholeKey(newWholeKey)).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setGrouping(keyExpression.getGrouping().toBuilder().setWholeKey(newWholeKey)).build(); } // split key expression if (keyExpression.hasSplit()) { final var newJoined = wrapArrayInternal(keyExpression.getSplit().getJoined(), parentDescriptor); - return RecordMetaDataProto.KeyExpression.newBuilder().setSplit(keyExpression.getSplit().toBuilder().setJoined(newJoined)).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setSplit(keyExpression.getSplit().toBuilder().setJoined(newJoined)).build(); } // function key expression. if (keyExpression.hasFunction()) { final var newArguments = wrapArrayInternal(keyExpression.getFunction().getArguments(), parentDescriptor); - return RecordMetaDataProto.KeyExpression.newBuilder().setFunction(keyExpression.getFunction().toBuilder().setArguments(newArguments)).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setFunction(keyExpression.getFunction().toBuilder().setArguments(newArguments)).build(); } // covering key expression. if (keyExpression.hasKeyWithValue()) { final var newInnerKey = wrapArrayInternal(keyExpression.getKeyWithValue().getInnerKey(), parentDescriptor); - return RecordMetaDataProto.KeyExpression.newBuilder().setKeyWithValue(keyExpression.getKeyWithValue().toBuilder().setInnerKey(newInnerKey)).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setKeyWithValue(keyExpression.getKeyWithValue().toBuilder().setInnerKey(newInnerKey)).build(); } // key expression containing list. if (keyExpression.hasList()) { - final var newListBuilder = RecordMetaDataProto.List.newBuilder(); + final var newListBuilder = RecordKeyExpressionProto.List.newBuilder(); for (final var listItem : keyExpression.getList().getChildList()) { newListBuilder.addChild(wrapArrayInternal(listItem, parentDescriptor)); } - return RecordMetaDataProto.KeyExpression.newBuilder().setList(newListBuilder).build(); + return RecordKeyExpressionProto.KeyExpression.newBuilder().setList(newListBuilder).build(); } return keyExpression; } // wrap repeated fields in a Field type keyExpression - private static RecordMetaDataProto.Nesting splitFieldIntoNestedWithValues(@Nonnull final RecordMetaDataProto.Field original) { - final var nestedArrayBuilder = RecordMetaDataProto.Field.newBuilder() + private static RecordKeyExpressionProto.Nesting splitFieldIntoNestedWithValues(@Nonnull final RecordKeyExpressionProto.Field original) { + final var nestedArrayBuilder = RecordKeyExpressionProto.Field.newBuilder() .setFieldName(original.getFieldName()) - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR) + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) .setNullInterpretation(original.getNullInterpretation()); - final var arrayValueBuilder = RecordMetaDataProto.KeyExpression.newBuilder() - .setField(RecordMetaDataProto.Field.newBuilder() + final var arrayValueBuilder = RecordKeyExpressionProto.KeyExpression.newBuilder() + .setField(RecordKeyExpressionProto.Field.newBuilder() .setFieldName(REPEATED_FIELD_NAME) .setFanType(original.getFanType()) .setNullInterpretation(original.getNullInterpretation())); - return RecordMetaDataProto.Nesting.newBuilder().setParent(nestedArrayBuilder).setChild(arrayValueBuilder).build(); + return RecordKeyExpressionProto.Nesting.newBuilder().setParent(nestedArrayBuilder).setChild(arrayValueBuilder).build(); } } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java index 8164078a21..ddb1b4da93 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/api/ddl/DdlStatementParsingTest.java @@ -23,6 +23,7 @@ import com.apple.foundationdb.record.RecordMetaData; import com.apple.foundationdb.record.RecordMetaDataProto; import com.apple.foundationdb.record.RecordStoreState; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.record.metadata.expressions.KeyExpression; import com.apple.foundationdb.record.metadata.expressions.ThenKeyExpression; import com.apple.foundationdb.record.provider.foundationdb.FDBRecordStoreBase; @@ -478,7 +479,7 @@ public ConstantAction getCreateSchemaTemplateConstantAction(@Nonnull SchemaTempl Assertions.assertEquals("V_IDX", index.getName(), "Incorrect index name!"); final var actualKe = ((RecordLayerIndex) index).getKeyExpression().toKeyExpression(); - List keys = null; + List keys = null; if (actualKe.hasThen()) { keys = new ArrayList<>(actualKe.getThen().getChildList()); } else if (actualKe.hasField()) { @@ -523,14 +524,14 @@ public ConstantAction getCreateSchemaTemplateConstantAction(@Nonnull SchemaTempl final Index index = info.getIndexes().stream().findFirst().get(); Assertions.assertEquals("V_IDX", index.getName(), "Incorrect index name!"); - RecordMetaDataProto.KeyExpression actualKe = ((RecordLayerIndex) index).getKeyExpression().toKeyExpression(); + RecordKeyExpressionProto.KeyExpression actualKe = ((RecordLayerIndex) index).getKeyExpression().toKeyExpression(); Assertions.assertNotNull(actualKe.getKeyWithValue(), "Null KeyExpression for included columns!"); - final RecordMetaDataProto.KeyWithValue keyWithValue = actualKe.getKeyWithValue(); + final RecordKeyExpressionProto.KeyWithValue keyWithValue = actualKe.getKeyWithValue(); //This is a weird workaround for the problem fixed in https://github.com/FoundationDB/fdb-record-layer/pull/1585, // once that's been merged and we get a release that contains it, we can replace this with a more //natural api - final RecordMetaDataProto.KeyExpression innerKey = keyWithValue.getInnerKey(); + final RecordKeyExpressionProto.KeyExpression innerKey = keyWithValue.getInnerKey(); int splitPoint = keyWithValue.getSplitPoint(); final ThenKeyExpression then = new ThenKeyExpression(innerKey.getThen()); KeyExpression keyExpr = then.getSubKey(0, splitPoint); @@ -538,13 +539,13 @@ public ConstantAction getCreateSchemaTemplateConstantAction(@Nonnull SchemaTempl Assertions.assertEquals(indexedColumns.size(), keyExpr.getColumnSize(), "Incorrect number of parsed columns!"); for (int i = 0; i < indexedColumns.size(); i++) { - final RecordMetaDataProto.KeyExpression ke = keyExpr.getSubKey(i, i + 1).toKeyExpression(); + final RecordKeyExpressionProto.KeyExpression ke = keyExpr.getSubKey(i, i + 1).toKeyExpression(); Assertions.assertEquals(indexedColumns.get(i), ke.getField().getFieldName(), "Incorrect column at position " + i); } Assertions.assertEquals(unindexedColumns.size(), valueExpr.getColumnSize(), "Incorrect number of parsed columns!"); for (int i = 0; i < unindexedColumns.size(); i++) { - final RecordMetaDataProto.KeyExpression ve = valueExpr.getSubKey(i, i + 1).toKeyExpression(); + final RecordKeyExpressionProto.KeyExpression ve = valueExpr.getSubKey(i, i + 1).toKeyExpression(); Assertions.assertEquals(unindexedColumns.get(i), ve.getField().getFieldName(), "Incorrect column at position " + i); } diff --git a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/NullableArrayUtilsTest.java b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/NullableArrayUtilsTest.java index 07db2a9a9e..1c9c36f0d7 100644 --- a/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/NullableArrayUtilsTest.java +++ b/fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/NullableArrayUtilsTest.java @@ -20,7 +20,7 @@ package com.apple.foundationdb.relational.recordlayer.query; -import com.apple.foundationdb.record.RecordMetaDataProto; +import com.apple.foundationdb.record.expressions.RecordKeyExpressionProto; import com.apple.foundationdb.relational.util.NullableArrayUtils; import com.google.protobuf.DescriptorProtos; @@ -55,56 +55,56 @@ void testWrapArray() throws Descriptors.DescriptorValidationException { Descriptors.FileDescriptor file = generateFileDescriptor(); Descriptors.Descriptor parentDescriptor = file.findMessageTypeByName("Parent"); // original field("stringListField", FAN_OUT), expected to become stringListField.values - RecordMetaDataProto.KeyExpression original1 = RecordMetaDataProto.KeyExpression.newBuilder() - .setField(RecordMetaDataProto.Field.newBuilder() + RecordKeyExpressionProto.KeyExpression original1 = RecordKeyExpressionProto.KeyExpression.newBuilder() + .setField(RecordKeyExpressionProto.Field.newBuilder() .setFieldName("stringListField") - .setFanType(RecordMetaDataProto.Field.FanType.FAN_OUT) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)) + .setFanType(RecordKeyExpressionProto.Field.FanType.FAN_OUT) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)) .build(); - RecordMetaDataProto.KeyExpression expected1 = RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() - .setParent(RecordMetaDataProto.Field.newBuilder() + RecordKeyExpressionProto.KeyExpression expected1 = RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() + .setParent(RecordKeyExpressionProto.Field.newBuilder() .setFieldName("stringListField") - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)) - .setChild(RecordMetaDataProto.KeyExpression.newBuilder() - .setField(RecordMetaDataProto.Field.newBuilder() + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)) + .setChild(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setField(RecordKeyExpressionProto.Field.newBuilder() .setFieldName(NullableArrayUtils.getRepeatedFieldName()) - .setFanType(RecordMetaDataProto.Field.FanType.FAN_OUT) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)))) + .setFanType(RecordKeyExpressionProto.Field.FanType.FAN_OUT) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)))) .build(); Assertions.assertEquals(expected1, NullableArrayUtils.wrapArray(original1, parentDescriptor, true)); // userListField.name, expected to become userListField.values.name - RecordMetaDataProto.KeyExpression original2 = RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() - .setParent(RecordMetaDataProto.Field.newBuilder() + RecordKeyExpressionProto.KeyExpression original2 = RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() + .setParent(RecordKeyExpressionProto.Field.newBuilder() .setFieldName("userListField") - .setFanType(RecordMetaDataProto.Field.FanType.FAN_OUT) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)) - .setChild(RecordMetaDataProto.KeyExpression.newBuilder() - .setField(RecordMetaDataProto.Field.newBuilder() + .setFanType(RecordKeyExpressionProto.Field.FanType.FAN_OUT) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)) + .setChild(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setField(RecordKeyExpressionProto.Field.newBuilder() .setFieldName("name") - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)))) + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)))) .build(); - RecordMetaDataProto.KeyExpression expected2 = RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() - .setParent(RecordMetaDataProto.Field.newBuilder() + RecordKeyExpressionProto.KeyExpression expected2 = RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() + .setParent(RecordKeyExpressionProto.Field.newBuilder() .setFieldName("userListField") - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)) - .setChild(RecordMetaDataProto.KeyExpression.newBuilder() - .setNesting(RecordMetaDataProto.Nesting.newBuilder() - .setParent(RecordMetaDataProto.Field.newBuilder() + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)) + .setChild(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setNesting(RecordKeyExpressionProto.Nesting.newBuilder() + .setParent(RecordKeyExpressionProto.Field.newBuilder() .setFieldName(NullableArrayUtils.getRepeatedFieldName()) - .setFanType(RecordMetaDataProto.Field.FanType.FAN_OUT) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)) - .setChild(RecordMetaDataProto.KeyExpression.newBuilder() - .setField(RecordMetaDataProto.Field.newBuilder() + .setFanType(RecordKeyExpressionProto.Field.FanType.FAN_OUT) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)) + .setChild(RecordKeyExpressionProto.KeyExpression.newBuilder() + .setField(RecordKeyExpressionProto.Field.newBuilder() .setFieldName("name") - .setFanType(RecordMetaDataProto.Field.FanType.SCALAR) - .setNullInterpretation(RecordMetaDataProto.Field.NullInterpretation.NOT_UNIQUE)))))) + .setFanType(RecordKeyExpressionProto.Field.FanType.SCALAR) + .setNullInterpretation(RecordKeyExpressionProto.Field.NullInterpretation.NOT_UNIQUE)))))) .build(); Assertions.assertEquals(expected2, NullableArrayUtils.wrapArray(original2, parentDescriptor, true)); }