Search in sources :

Example 1 with IndexValidator

use of com.apple.foundationdb.record.metadata.IndexValidator in project fdb-record-layer by FoundationDB.

the class PermutedMinMaxIndexMaintainerFactory method getIndexValidator.

@Override
@Nonnull
public IndexValidator getIndexValidator(Index index) {
    return new IndexValidator(index) {

        @Override
        public void validate(@Nonnull MetaDataValidator metaDataValidator) {
            super.validate(metaDataValidator);
            validateGrouping(1);
            int groupingCount = ((GroupingKeyExpression) index.getRootExpression()).getGroupingCount();
            validateNotVersion();
            int permutedSize = PermutedMinMaxIndexMaintainer.getPermutedSize(index);
            if (permutedSize < 0) {
                throw new MetaDataException("permuted size cannot be negative", LogMessageKeys.INDEX_NAME, index.getName());
            } else if (permutedSize == 0) {
                throw new MetaDataException("no permutation does not need a special index type for MIN and MAX", LogMessageKeys.INDEX_NAME, index.getName());
            } else if (permutedSize > groupingCount) {
                throw new MetaDataException("permuted size cannot be larger than grouping size", LogMessageKeys.INDEX_NAME, index.getName());
            }
        }

        @Override
        public void validateChangedOptions(@Nonnull Index oldIndex, @Nonnull Set<String> changedOptions) {
            if (changedOptions.contains(IndexOptions.PERMUTED_SIZE_OPTION)) {
                throw new MetaDataException("permuted size changed", LogMessageKeys.INDEX_NAME, index.getName());
            }
            super.validateChangedOptions(oldIndex, changedOptions);
        }
    };
}
Also used : IndexValidator(com.apple.foundationdb.record.metadata.IndexValidator) Set(java.util.Set) Nonnull(javax.annotation.Nonnull) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) Index(com.apple.foundationdb.record.metadata.Index) MetaDataValidator(com.apple.foundationdb.record.metadata.MetaDataValidator) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) Nonnull(javax.annotation.Nonnull)

Example 2 with IndexValidator

use of com.apple.foundationdb.record.metadata.IndexValidator in project fdb-record-layer by FoundationDB.

the class BitmapValueIndexMaintainerFactory method getIndexValidator.

@Override
@Nonnull
public IndexValidator getIndexValidator(Index index) {
    return new IndexValidator(index) {

        @Override
        public void validate(@Nonnull MetaDataValidator metaDataValidator) {
            super.validate(metaDataValidator);
            validateGrouping(1);
            final GroupingKeyExpression group = (GroupingKeyExpression) index.getRootExpression();
            if (group.getGroupedCount() != 1) {
                throw new KeyExpression.InvalidExpressionException(String.format("%s index needs grouped position", index.getType()), LogMessageKeys.INDEX_NAME, index.getName(), LogMessageKeys.INDEX_KEY, index.getRootExpression());
            }
            validateNotVersion();
        }

        @Override
        @SuppressWarnings("fallthrough")
        public void validateIndexForRecordType(@Nonnull RecordType recordType, @Nonnull MetaDataValidator metaDataValidator) {
            final List<Descriptors.FieldDescriptor> fields = metaDataValidator.validateIndexForRecordType(index, recordType);
            switch(fields.get(fields.size() - 1).getType()) {
                case INT64:
                case UINT64:
                case INT32:
                case UINT32:
                case SINT32:
                case SINT64:
                case FIXED32:
                case FIXED64:
                case SFIXED32:
                case SFIXED64:
                    break;
                default:
                    throw new KeyExpression.InvalidExpressionException(String.format("%s index only supports integer position key", index.getType()), LogMessageKeys.INDEX_NAME, index.getName(), LogMessageKeys.INDEX_KEY, index.getRootExpression(), "record_type", recordType.getName());
            }
        }
    };
}
Also used : IndexValidator(com.apple.foundationdb.record.metadata.IndexValidator) RecordType(com.apple.foundationdb.record.metadata.RecordType) Nonnull(javax.annotation.Nonnull) GroupingKeyExpression(com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression) MetaDataValidator(com.apple.foundationdb.record.metadata.MetaDataValidator) Nonnull(javax.annotation.Nonnull)

Example 3 with IndexValidator

use of com.apple.foundationdb.record.metadata.IndexValidator in project fdb-record-layer by FoundationDB.

the class TextIndexMaintainerFactory method getIndexValidator.

/**
 * Validates that the index provided is valid for text indexes. This means that
 * the index must:
 *
 * <ul>
 *     <li>Not be a unique index.</li>
 *     <li>Not include a {@link com.apple.foundationdb.record.metadata.expressions.VersionKeyExpression#VERSION} expression in its root expression.</li>
 *     <li>Have a key expression whose first column is of type <code>string</code> (possibly with grouping columns
 *         before the tokenized text column) and is not repeated.</li> <!--Maybe we should support FanType.Concatenate?-->
 *     <li>Specify a valid tokenizer and tokenizer version through the index options (possibly using the defaults).</li>
 *     <li>Not define a value expression.</li>
 * </ul>
 *
 * @param index the index to validate
 * @return a validator to run against the index
 * @throws KeyExpression.InvalidExpressionException if the expression does not contain a string as its first ungrouped column
 * @throws com.apple.foundationdb.record.metadata.MetaDataException if the tokenizer is not defined, if the tokenizer version
 *                                                    is out of range, or if the index is marked as unique
 */
@Nonnull
@Override
public IndexValidator getIndexValidator(Index index) {
    return new IndexValidator(index) {

        @Override
        public void validate(@Nonnull MetaDataValidator metaDataValidator) {
            super.validate(metaDataValidator);
            validateNotVersion();
            validateNotUnique();
            // TODO: allow value expressions for covering text indexes
            validateNoValue();
            // Validate that the tokenizer exists and that the version is in a valid range.
            TextTokenizer tokenizer = TextIndexMaintainer.getTokenizer(index);
            int tokenizerVersion = TextIndexMaintainer.getIndexTokenizerVersion(index);
            tokenizer.validateVersion(tokenizerVersion);
        }

        @Override
        public void validateIndexForRecordType(@Nonnull RecordType recordType, @Nonnull MetaDataValidator metaDataValidator) {
            final List<Descriptors.FieldDescriptor> fields = metaDataValidator.validateIndexForRecordType(index, recordType);
            int textFieldPosition = TextIndexMaintainer.textFieldPosition(index.getRootExpression());
            if (textFieldPosition > fields.size()) {
                throw new KeyExpression.InvalidExpressionException("text index does not have text field after grouped fields");
            } else {
                Descriptors.FieldDescriptor textFieldDescriptor = fields.get(textFieldPosition);
                if (!textFieldDescriptor.getType().equals(Descriptors.FieldDescriptor.Type.STRING)) {
                    throw new KeyExpression.InvalidExpressionException(String.format("text index has non-string type %s as text field", textFieldDescriptor.getLiteJavaType()));
                }
                if (textFieldDescriptor.isRepeated()) {
                    throw new KeyExpression.InvalidExpressionException("text index does not allow a repeated field for text body");
                }
            }
        }

        /**
         * Validate any options that have changed. There are several options unique to text indexes which
         * may change without requiring the index be rebuilt. They are:
         *
         * <ul>
         *     <li>{@link IndexOptions#TEXT_TOKENIZER_VERSION_OPTION} which can be increased (but not decreased)</li>
         *     <li>{@link IndexOptions#TEXT_ADD_AGGRESSIVE_CONFLICT_RANGES_OPTION} which only affects what conflict ranges
         *          are added at index update time and thus has no impact on the on-disk representation</li>
         *     <li>{@link IndexOptions#TEXT_OMIT_POSITIONS_OPTION} which changes whether the position lists are included
         *          in index entries</li>
         * </ul>
         *
         * <p>
         * Note that the {@link IndexOptions#TEXT_TOKENIZER_NAME_OPTION} is <em>not</em> allowed to change
         * (without rebuilding the index).
         * </p>
         *
         * @param oldIndex an older version of this index
         * @param changedOptions the set of changed options
         */
        @Override
        protected void validateChangedOptions(@Nonnull Index oldIndex, @Nonnull Set<String> changedOptions) {
            for (String changedOption : changedOptions) {
                switch(changedOption) {
                    case IndexOptions.TEXT_ADD_AGGRESSIVE_CONFLICT_RANGES_OPTION:
                    case IndexOptions.TEXT_OMIT_POSITIONS_OPTION:
                        // without breaking compatibility.
                        break;
                    case IndexOptions.TEXT_TOKENIZER_NAME_OPTION:
                        String oldTokenizerName = TextIndexMaintainer.getTokenizer(oldIndex).getName();
                        String newTokenizerName = TextIndexMaintainer.getTokenizer(index).getName();
                        if (!oldTokenizerName.equals(newTokenizerName)) {
                            throw new MetaDataException("text tokenizer changed", LogMessageKeys.INDEX_NAME, index.getName());
                        }
                        break;
                    case IndexOptions.TEXT_TOKENIZER_VERSION_OPTION:
                        // The tokenizer version should always go up.
                        int oldTokenizerVersion = TextIndexMaintainer.getIndexTokenizerVersion(oldIndex);
                        int newTokenizerVersion = TextIndexMaintainer.getIndexTokenizerVersion(index);
                        if (oldTokenizerVersion > newTokenizerVersion) {
                            throw new MetaDataException("text tokenizer version downgraded", LogMessageKeys.INDEX_NAME, index.getName(), LogMessageKeys.OLD_VERSION, oldTokenizerVersion, LogMessageKeys.NEW_VERSION, newTokenizerVersion);
                        }
                        break;
                    default:
                        // Changed options that are not text options will be handled by super class
                        if (TEXT_OPTIONS.contains(changedOption)) {
                            throw new MetaDataException("index option changed", LogMessageKeys.INDEX_NAME, index.getName(), LogMessageKeys.INDEX_OPTION, changedOption, LogMessageKeys.OLD_OPTION, oldIndex.getOption(changedOption), LogMessageKeys.NEW_OPTION, index.getOption(changedOption));
                        }
                }
            }
            changedOptions.removeAll(TEXT_OPTIONS);
            super.validateChangedOptions(oldIndex, changedOptions);
        }
    };
}
Also used : IndexValidator(com.apple.foundationdb.record.metadata.IndexValidator) ImmutableSet(com.google.common.collect.ImmutableSet) Set(java.util.Set) Nonnull(javax.annotation.Nonnull) Index(com.apple.foundationdb.record.metadata.Index) MetaDataException(com.apple.foundationdb.record.metadata.MetaDataException) TextTokenizer(com.apple.foundationdb.record.provider.common.text.TextTokenizer) RecordType(com.apple.foundationdb.record.metadata.RecordType) MetaDataValidator(com.apple.foundationdb.record.metadata.MetaDataValidator) Descriptors(com.google.protobuf.Descriptors) Nonnull(javax.annotation.Nonnull)

Aggregations

IndexValidator (com.apple.foundationdb.record.metadata.IndexValidator)3 MetaDataValidator (com.apple.foundationdb.record.metadata.MetaDataValidator)3 Nonnull (javax.annotation.Nonnull)3 Index (com.apple.foundationdb.record.metadata.Index)2 MetaDataException (com.apple.foundationdb.record.metadata.MetaDataException)2 RecordType (com.apple.foundationdb.record.metadata.RecordType)2 GroupingKeyExpression (com.apple.foundationdb.record.metadata.expressions.GroupingKeyExpression)2 Set (java.util.Set)2 TextTokenizer (com.apple.foundationdb.record.provider.common.text.TextTokenizer)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Descriptors (com.google.protobuf.Descriptors)1