Class RecordMetaDataBuilder
- java.lang.Object
-
- com.apple.foundationdb.record.RecordMetaDataBuilder
-
- All Implemented Interfaces:
RecordMetaDataProvider
@API(MAINTAINED) public class RecordMetaDataBuilder extends Object implements RecordMetaDataProvider
A builder forRecordMetaData
. Meta-data can be built in two ways.From compiled .proto
Simple single field indexes and single field primary keys can be specified in the Protobuf source file using option extensions. Additional indexes or more complicated primary keys need to be specified with code using this builder. ThesetRecords(Descriptors.FileDescriptor, boolean)
method loads the meta-data information from the Protobuf source file. Indexes and other properties such as version are not accessible before callingsetRecords
.From a
RecordMetaDataProto.MetaData
Protobuf message
The Protobuf form can store the complete meta-data. ThesetRecords(RecordMetaDataProto.MetaData, boolean)
method loads the Protobuf message. Similar to loading the meta-data directly from a Protobuf file descriptor, indexes and other properties are not accessible before callingsetRecords
. The Protobuf message may contain all of the dependencies required for resolving the record types and indexes. If some of the dependencies are missing (e.g., when a list of excluded dependencies is passed toRecordMetaData.toProto()
), before callingsetRecords
, callers must first add the missing dependencies usingaddDependency(Descriptors.FileDescriptor)
oraddDependencies(Descriptors.FileDescriptor[])
. TheaddDependency
oraddDependencies
methods can also be used to override the embedded dependencies.- See Also:
RecordMetaData.toProto()
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
RecordMetaDataBuilder.MetaDataProtoDeserializationException
Exception thrown when meta-data cannot be loaded from serialized form.
-
Field Summary
Fields Modifier and Type Field Description static String
DEFAULT_UNION_NAME
-
Constructor Summary
Constructors Constructor Description RecordMetaDataBuilder(RecordMetaDataProto.MetaData metaDataProto)
Deprecated.useRecordMetaData.newBuilder()
insteadRecordMetaDataBuilder(RecordMetaDataProto.MetaData metaDataProto, boolean processExtensionOptions)
Deprecated.useRecordMetaData.newBuilder()
insteadRecordMetaDataBuilder(RecordMetaDataProto.MetaData metaDataProto, Descriptors.FileDescriptor[] dependencies)
Deprecated.useRecordMetaData.newBuilder()
insteadRecordMetaDataBuilder(RecordMetaDataProto.MetaData metaDataProto, Descriptors.FileDescriptor[] dependencies, boolean processExtensionOptions)
Deprecated.useRecordMetaData.newBuilder()
insteadRecordMetaDataBuilder(Descriptors.FileDescriptor fileDescriptor)
Deprecated.useRecordMetaData.newBuilder()
insteadRecordMetaDataBuilder(Descriptors.FileDescriptor fileDescriptor, boolean processExtensionOptions)
Deprecated.useRecordMetaData.newBuilder()
instead
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description RecordMetaDataBuilder
addDependencies(Descriptors.FileDescriptor[] fileDescriptors)
Adds dependencies to be used for loading theRecordMetaData
from a meta-data proto.RecordMetaDataBuilder
addDependency(Descriptors.FileDescriptor fileDescriptor)
Adds a dependency to the list of dependencies.void
addFormerIndex(FormerIndex formerIndex)
void
addIndex(RecordTypeIndexesBuilder recordType, Index index)
Adds a new index.void
addIndex(String recordType, Index index)
Adds a new index.void
addIndex(String recordType, String fieldName)
Adds a new index on a single field.void
addIndex(String recordType, String indexName, KeyExpression indexExpression)
Adds a new index.void
addIndex(String recordType, String indexName, String fieldName)
Adds a new index.JoinedRecordTypeBuilder
addJoinedRecordType(String name)
Add a new joined record type.void
addMultiTypeIndex(List<? extends RecordTypeIndexesBuilder> recordTypes, Index index)
Adds a new index that contains multiple record types.void
addUniversalIndex(Index index)
Adds a new index on all record types.RecordMetaData
build()
Build and validate meta-data.RecordMetaData
build(boolean validate)
Build and validate meta-data with specific index registry.static int[]
buildPrimaryKeyComponentPositions(KeyExpression indexKey, KeyExpression primaryKey)
RecordMetaDataBuilder
enableCounterBasedSubspaceKeys()
Enable counter-based subspace keys assignment.MetaDataEvolutionValidator
getEvolutionValidator()
Get the validator used to compare the local file descriptor to the descriptor included in the meta-data proto.Index
getIndex(String indexName)
RecordTypeIndexesBuilder
getIndexableRecordType(String name)
Get a record type or synthetic record type by name for use withaddIndex(com.apple.foundationdb.record.metadata.RecordTypeIndexesBuilder, com.apple.foundationdb.record.metadata.Index)
.IndexMaintainerRegistry
getIndexMaintainerRegistry()
Get the index registry used for validation.RecordTypeBuilder
getOnlyRecordType()
If there is only one record type, get it.KeyExpression
getRecordCountKey()
Deprecated.useCOUNT
type indexes insteadRecordMetaData
getRecordMetaData()
Provide an instance ofRecordMetaData
.RecordTypeBuilder
getRecordType(String name)
long
getSubspaceKeyCounter()
Get the current value of the index subspace key counter.SyntheticRecordTypeBuilder<?>
getSyntheticRecordType(String name)
Descriptors.Descriptor
getUnionDescriptor()
Descriptors.FieldDescriptor
getUnionFieldForRecordType(RecordType recordType)
int
getVersion()
boolean
isSplitLongRecords()
boolean
isStoreRecordVersions()
void
removeIndex(String name)
RecordMetaDataBuilder
setEvolutionValidator(MetaDataEvolutionValidator evolutionValidator)
Set the validator used to compare the local file descriptor to the descriptor included in the meta-data proto.void
setIndexMaintainerRegistry(IndexMaintainerRegistry indexMaintainerRegistry)
Set the index registry used for validation.RecordMetaDataBuilder
setLocalFileDescriptor(Descriptors.FileDescriptor localFileDescriptor)
Sets the local file descriptor.void
setRecordCountKey(KeyExpression recordCountKey)
Deprecated.useCOUNT
type indexes insteadRecordMetaDataBuilder
setRecords(RecordMetaDataProto.MetaData metaDataProto)
Deserializes the meta-data proto into the builder.RecordMetaDataBuilder
setRecords(RecordMetaDataProto.MetaData metaDataProto, boolean processExtensionOptions)
Deserializes the meta-data proto into the builder.RecordMetaDataBuilder
setRecords(Descriptors.FileDescriptor fileDescriptor)
Adds the root file descriptor of theRecordMetaData
and processes the extension options.RecordMetaDataBuilder
setRecords(Descriptors.FileDescriptor fileDescriptor, boolean processExtensionOptions)
Adds the root file descriptor of theRecordMetaData
.void
setSplitLongRecords(boolean splitLongRecords)
void
setStoreRecordVersions(boolean storeRecordVersions)
RecordMetaDataBuilder
setSubspaceKeyCounter(long subspaceKeyCounter)
Set the initial value of the subspace key counter.void
setVersion(int version)
void
updateRecords(Descriptors.FileDescriptor recordsDescriptor)
Update the records descriptor of the record meta-data.void
updateRecords(Descriptors.FileDescriptor newRecordsDescriptor, boolean processExtensionOptions)
Update the records descriptor of the record meta-data.boolean
usesSubspaceKeyCounter()
Checks if counter-based subspace key assignment is used.
-
-
-
Field Detail
-
DEFAULT_UNION_NAME
public static final String DEFAULT_UNION_NAME
- See Also:
- Constant Field Values
-
-
Constructor Detail
-
RecordMetaDataBuilder
@Deprecated public RecordMetaDataBuilder(@Nonnull Descriptors.FileDescriptor fileDescriptor)
Deprecated.useRecordMetaData.newBuilder()
insteadCreates a new builder from the provided record types protobuf.- Parameters:
fileDescriptor
- a file descriptor containing all the record types in the metadata
-
RecordMetaDataBuilder
@Deprecated public RecordMetaDataBuilder(@Nonnull Descriptors.FileDescriptor fileDescriptor, boolean processExtensionOptions)
Deprecated.useRecordMetaData.newBuilder()
insteadCreates a new builder from the provided record types protobuf.- Parameters:
fileDescriptor
- a file descriptor containing all the record types in the metadataprocessExtensionOptions
- whether to add primary keys and indexes based on extensions in the protobuf
-
RecordMetaDataBuilder
@Deprecated public RecordMetaDataBuilder(@Nonnull RecordMetaDataProto.MetaData metaDataProto)
Deprecated.useRecordMetaData.newBuilder()
insteadCreates a new builder from the provided meta-data protobuf. This constructor assumes thatmetaDataProto
is not the result ofRecordMetaData.toProto()
and will not already include all the indexes defined by any original extension options, so that they still need to be processed. IfmetaDataProto
is the result oftoProto
and indexes also appear in extension options, a duplicate index error will result. In that case,RecordMetaDataBuilder(RecordMetaDataProto.MetaData, boolean)
will be needed instead.- Parameters:
metaDataProto
- the protobuf form of the meta-data
-
RecordMetaDataBuilder
@Deprecated public RecordMetaDataBuilder(@Nonnull RecordMetaDataProto.MetaData metaDataProto, boolean processExtensionOptions)
Deprecated.useRecordMetaData.newBuilder()
insteadCreates a new builder from the provided meta-data protobuf. IfmetaDataProto
is the result ofRecordMetaData.toProto()
, it will already include all the indexes defined by any original extension options, soprocessExtensionOptions
should befalse
.- Parameters:
metaDataProto
- the protobuf form of the meta-dataprocessExtensionOptions
- whether to add primary keys and indexes based on extensions in the protobuf
-
RecordMetaDataBuilder
@Deprecated public RecordMetaDataBuilder(@Nonnull RecordMetaDataProto.MetaData metaDataProto, @Nonnull Descriptors.FileDescriptor[] dependencies)
Deprecated.useRecordMetaData.newBuilder()
insteadCreates a new builder from the provided meta-data protobuf. This constructor assumes thatmetaDataProto
is not the result ofRecordMetaData.toProto()
and will not already include all the indexes defined by any original extension options, so that they still need to be processed. IfmetaDataProto
is the result oftoProto
and indexes also appear in extension options, a duplicate index error will result. In that case,RecordMetaDataBuilder(RecordMetaDataProto.MetaData, Descriptors.FileDescriptor[], boolean)
will be needed instead.- Parameters:
metaDataProto
- the protobuf form of the meta-datadependencies
- other files imported by the record types protobuf
-
RecordMetaDataBuilder
@Deprecated public RecordMetaDataBuilder(@Nonnull RecordMetaDataProto.MetaData metaDataProto, @Nonnull Descriptors.FileDescriptor[] dependencies, boolean processExtensionOptions)
Deprecated.useRecordMetaData.newBuilder()
insteadCreates a new builder from the provided meta-data protobuf. IfmetaDataProto
is the result ofRecordMetaData.toProto()
, it will already include all the indexes defined by any original extension options, soprocessExtensionOptions
should befalse
.- Parameters:
metaDataProto
- the protobuf form of the meta-datadependencies
- other files imported by the record types protobufprocessExtensionOptions
- whether to add primary keys and indexes based on extensions in the protobuf
-
-
Method Detail
-
setRecords
@Nonnull public RecordMetaDataBuilder setRecords(@Nonnull RecordMetaDataProto.MetaData metaDataProto)
Deserializes the meta-data proto into the builder. The extension options are not processed.- Parameters:
metaDataProto
- the proto of theRecordMetaData
- Returns:
- this builder
-
setRecords
@Nonnull public RecordMetaDataBuilder setRecords(@Nonnull RecordMetaDataProto.MetaData metaDataProto, boolean processExtensionOptions)
Deserializes the meta-data proto into the builder.- Parameters:
metaDataProto
- the proto of theRecordMetaData
processExtensionOptions
- whether to add primary keys and indexes based on extensions in the protobuf- Returns:
- this builder
-
setRecords
@Nonnull public RecordMetaDataBuilder setRecords(@Nonnull Descriptors.FileDescriptor fileDescriptor)
Adds the root file descriptor of theRecordMetaData
and processes the extension options.- Parameters:
fileDescriptor
- the file descriptor of the record meta-data- Returns:
- this builder
-
setRecords
@Nonnull public RecordMetaDataBuilder setRecords(@Nonnull Descriptors.FileDescriptor fileDescriptor, boolean processExtensionOptions)
Adds the root file descriptor of theRecordMetaData
.- Parameters:
fileDescriptor
- the file descriptor of the record meta-dataprocessExtensionOptions
- whether to add primary keys and indexes based on extensions in the protobuf- Returns:
- this builder
-
updateRecords
public void updateRecords(@Nonnull Descriptors.FileDescriptor recordsDescriptor)
Update the records descriptor of the record meta-data.This involves adding new record types and updating descriptors for the existing record types and union fields. By contract, the extension options will be processed for all of the new record types and will not be processed for any of the old record types. Also, it is not allowed to call this method when the local file descriptor is set.
See
updateRecords(Descriptors.FileDescriptor, boolean)
for more information.- Parameters:
recordsDescriptor
- the new record descriptor
-
updateRecords
public void updateRecords(@Nonnull Descriptors.FileDescriptor newRecordsDescriptor, boolean processExtensionOptions)
Update the records descriptor of the record meta-data.This adds any new record types and updates the descriptors for existing record types. By contract, the extension options will not be processed for the old record types. If
processExtensionOptions
is set, extension options will be processed only for the new record types. Also, this method may not be called whenlocalFileDescriptor
is set. This method bumps the meta-data version and sets the since version for the new record types (and their indexes).To avoid accidental changes, this method only updates the record types (i.e., updates the message descriptors of the old record types and adds new record types with their primary keys and indexes). This method does not process schema options. To update the schema options, use
setSplitLongRecords(boolean)
andsetStoreRecordVersions(boolean)
.- Parameters:
newRecordsDescriptor
- the new record descriptorprocessExtensionOptions
- whether to add primary keys and indexes using the extensions in the protobuf (only for the new record types)
-
setLocalFileDescriptor
@Nonnull public RecordMetaDataBuilder setLocalFileDescriptor(@Nonnull Descriptors.FileDescriptor localFileDescriptor)
Sets the local file descriptor. A local meta-data file descriptor may contain newer versions of record types or indexes.This method is handy when two versions of the record meta-data are compatible (i.e., they follow the Record Layer guidelines on schema evolution), but their descriptors are not equal, e.g., a statically-generated proto and its serialized version stored in a meta-data store (i.e.,
FDBMetaDataStore
). A record store created using the meta-data store may not be able to store a record created by the statically-generated proto file because the meta-data and record have mismatched descriptors. Using this method, the meta-data can use the same version of the descriptor as the record.This should only be used when the records descriptor is set through a meta-data Protobuf message (i.e, it is followed by a call to
setRecords(RecordMetaDataProto.MetaData)
orsetRecords(RecordMetaDataProto.MetaData, boolean)
). This will not work if the records are set using a file descriptor. Note also that once the local file descriptor is set, theRecordMetaData
object that is produced from this builder may differ from the original Protobuf definition in ways that make serializing the meta-data back to Protobuf unsafe. As a result, callingtoProto()
on the producedRecordMetaData
is disallowed.To verify that the file descriptor supplied here and the file descriptor included in the meta-data proto are compatible, the two descriptors are compared using a
MetaDataEvolutionValidator
. The user may provide their own validator by callingsetEvolutionValidator(MetaDataEvolutionValidator)
. By default, this will use that class's default instance.- Parameters:
localFileDescriptor
- a file descriptor that contains updated record types- Returns:
- this builder
-
addDependency
@Nonnull public RecordMetaDataBuilder addDependency(@Nonnull Descriptors.FileDescriptor fileDescriptor)
Adds a dependency to the list of dependencies. It will be used for loading theRecordMetaData
from a meta-data proto.- Parameters:
fileDescriptor
- the file descriptor of the dependency- Returns:
- this builder
-
addDependencies
@Nonnull public RecordMetaDataBuilder addDependencies(@Nonnull Descriptors.FileDescriptor[] fileDescriptors)
Adds dependencies to be used for loading theRecordMetaData
from a meta-data proto.- Parameters:
fileDescriptors
- a list of dependencies- Returns:
- this builder
-
getUnionDescriptor
@Nonnull public Descriptors.Descriptor getUnionDescriptor()
-
getUnionFieldForRecordType
@Nonnull public Descriptors.FieldDescriptor getUnionFieldForRecordType(@Nonnull RecordType recordType)
-
getRecordType
@Nonnull public RecordTypeBuilder getRecordType(@Nonnull String name)
-
getSyntheticRecordType
@Nonnull @API(EXPERIMENTAL) public SyntheticRecordTypeBuilder<?> getSyntheticRecordType(@Nonnull String name)
-
addJoinedRecordType
@Nonnull @API(EXPERIMENTAL) public JoinedRecordTypeBuilder addJoinedRecordType(@Nonnull String name)
Add a new joined record type.- Parameters:
name
- the name of the new record type- Returns:
- a new uninitialized joined record type
-
getIndexableRecordType
public RecordTypeIndexesBuilder getIndexableRecordType(@Nonnull String name)
Get a record type or synthetic record type by name for use withaddIndex(com.apple.foundationdb.record.metadata.RecordTypeIndexesBuilder, com.apple.foundationdb.record.metadata.Index)
.- Parameters:
name
- the name of the record type- Returns:
- the possibly synthetic record type
-
addIndex
public void addIndex(@Nullable RecordTypeIndexesBuilder recordType, @Nonnull Index index)
Adds a new index. This index can either be a universal index or an index for a single record type.- Parameters:
recordType
- if null this index will exist for all record typesindex
- the index to be added
-
addIndex
public void addIndex(@Nonnull String recordType, @Nonnull Index index)
Adds a new index.- Parameters:
recordType
- name of the record typeindex
- the index to be added
-
addIndex
public void addIndex(@Nonnull String recordType, @Nonnull String indexName, @Nonnull KeyExpression indexExpression)
Adds a new index.- Parameters:
recordType
- name of the record typeindexName
- the name of the new indexindexExpression
- the root expression of the new index
-
addIndex
public void addIndex(@Nonnull String recordType, @Nonnull String indexName, @Nonnull String fieldName)
Adds a new index.- Parameters:
recordType
- name of the record typeindexName
- the name of the new indexfieldName
- the record field to be indexed
-
addIndex
public void addIndex(@Nonnull String recordType, @Nonnull String fieldName)
Adds a new index on a single field.- Parameters:
recordType
- name of the record typefieldName
- the record field to be indexed
-
addMultiTypeIndex
public void addMultiTypeIndex(@Nullable List<? extends RecordTypeIndexesBuilder> recordTypes, @Nonnull Index index)
Adds a new index that contains multiple record types. If the list is null or empty, the resulting index will include all record types. If the list has one element it will just be a normal single record type index.- Parameters:
recordTypes
- a list of record types that the index will includeindex
- the index to be added
-
addUniversalIndex
public void addUniversalIndex(@Nonnull Index index)
Adds a new index on all record types.- Parameters:
index
- the index to be added
-
addFormerIndex
public void addFormerIndex(@Nonnull FormerIndex formerIndex)
-
isSplitLongRecords
public boolean isSplitLongRecords()
-
setSplitLongRecords
public void setSplitLongRecords(boolean splitLongRecords)
-
isStoreRecordVersions
public boolean isStoreRecordVersions()
-
setStoreRecordVersions
public void setStoreRecordVersions(boolean storeRecordVersions)
-
getRecordCountKey
@Nullable @Deprecated @API(DEPRECATED) public KeyExpression getRecordCountKey()
Deprecated.useCOUNT
type indexes insteadGet the record count key, if any.- Returns:
- the record count key of
null
-
setRecordCountKey
@Deprecated @API(DEPRECATED) public void setRecordCountKey(KeyExpression recordCountKey)
Deprecated.useCOUNT
type indexes insteadSet the key used for maintaining record counts.- Parameters:
recordCountKey
- grouping key for counting
-
getVersion
public int getVersion()
-
setVersion
public void setVersion(int version)
-
enableCounterBasedSubspaceKeys
@Nonnull public RecordMetaDataBuilder enableCounterBasedSubspaceKeys()
Enable counter-based subspace keys assignment.If enabled, index subspace keys will be set using a counter instead of defaulting to the indexes' names. This must be called prior to setting the records descriptor (for example
setRecords(Descriptors.FileDescriptor)
).Existing clients should be careful about enabling this feature. The name of an index is the default value of its subspace key when counter-based subspace keys are disabled. If a subspace key was not set explicitly before, enabling the counter-based scheme will change the index's subspace key. Note that it is important that the subspace key of an index that has data does not change. See
Index.setSubspaceKey(Object)
for more details.- Returns:
- this builder
-
usesSubspaceKeyCounter
public boolean usesSubspaceKeyCounter()
Checks if counter-based subspace key assignment is used.- Returns:
true
if the subspace key counter is used
-
getSubspaceKeyCounter
public long getSubspaceKeyCounter()
Get the current value of the index subspace key counter. If it is not enabled, the value will be 0.- Returns:
- the current value of the index subspace key counter
- See Also:
enableCounterBasedSubspaceKeys()
-
setSubspaceKeyCounter
@Nonnull public RecordMetaDataBuilder setSubspaceKeyCounter(long subspaceKeyCounter)
Set the initial value of the subspace key counter. This method can be handy when users want to assign subspace keys using a counter, but their indexes already have subspace keys that may conflict with the counter-based assignment.Note that the new counter must be greater than the current value. Also, users must first enable this feature by calling
enableCounterBasedSubspaceKeys()
before updating the counter value.- Parameters:
subspaceKeyCounter
- the new value- Returns:
- this builder
- See Also:
enableCounterBasedSubspaceKeys()
-
getOnlyRecordType
@Nonnull public RecordTypeBuilder getOnlyRecordType()
If there is only one record type, get it.- Returns:
- the only type defined for this store.
-
getIndexMaintainerRegistry
@Nonnull public IndexMaintainerRegistry getIndexMaintainerRegistry()
Get the index registry used for validation.- Returns:
- the index maintainer registry
-
setIndexMaintainerRegistry
public void setIndexMaintainerRegistry(@Nonnull IndexMaintainerRegistry indexMaintainerRegistry)
Set the index registry used for validation. If a record store has a custom index maintainer registry, that same registry may need to be used to properly validate the meta-data.- Parameters:
indexMaintainerRegistry
- the index maintainer registry- See Also:
FDBRecordStoreBase.BaseBuilder.setIndexMaintainerRegistry(com.apple.foundationdb.record.provider.foundationdb.IndexMaintainerRegistry)
-
getEvolutionValidator
@Nonnull public MetaDataEvolutionValidator getEvolutionValidator()
Get the validator used to compare the local file descriptor to the descriptor included in the meta-data proto. By default, this instance is set to theMetaDataEvolutionValidator
's default instance, but the user may provide their own throughsetEvolutionValidator(MetaDataEvolutionValidator)
if they want to tweak certain validator options.- Returns:
- the validator used to check the local file descriptor against the one in the meta-data proto
- See Also:
setLocalFileDescriptor(Descriptors.FileDescriptor)
,MetaDataEvolutionValidator
-
setEvolutionValidator
@Nonnull public RecordMetaDataBuilder setEvolutionValidator(@Nonnull MetaDataEvolutionValidator evolutionValidator)
Set the validator used to compare the local file descriptor to the descriptor included in the meta-data proto. As this validator is used only to check whether the local file descriptor is compatible with the records descriptor set insetRecords()
through the meta-data proto, this method must be called beforesetRecords()
.- Parameters:
evolutionValidator
- the validator used to check the local file descriptor against the one in the meta-data proto- Returns:
- this builder
- See Also:
setLocalFileDescriptor(Descriptors.FileDescriptor)
,MetaDataEvolutionValidator
-
getRecordMetaData
@Nonnull public RecordMetaData getRecordMetaData()
Description copied from interface:RecordMetaDataProvider
Provide an instance ofRecordMetaData
. Implementors should assume that this method will be called frequently, so it may be necessary to cache the result if generating theRecordMetaData
is expensive.- Specified by:
getRecordMetaData
in interfaceRecordMetaDataProvider
- Returns:
- an instance of
RecordMetaData
-
build
@Nonnull public RecordMetaData build()
Build and validate meta-data.- Returns:
- new validated meta-data
-
build
@Nonnull public RecordMetaData build(boolean validate)
Build and validate meta-data with specific index registry.- Parameters:
validate
-true
to validate the new meta-data- Returns:
- new meta-data
-
buildPrimaryKeyComponentPositions
@Nullable public static int[] buildPrimaryKeyComponentPositions(@Nonnull KeyExpression indexKey, @Nonnull KeyExpression primaryKey)
-
-