Search in sources :

Example 1 with IndexFieldInfo

use of com.torodb.torod.IndexFieldInfo in project torodb by torodb.

the class CreateIndexesReplImpl method apply.

@Override
public Status<CreateIndexesResult> apply(Request req, Command<? super CreateIndexesArgument, ? super CreateIndexesResult> command, CreateIndexesArgument arg, SharedWriteTorodTransaction trans) {
    int indexesBefore = (int) trans.getIndexesInfo(req.getDatabase(), arg.getCollection()).count();
    int indexesAfter = indexesBefore;
    try {
        boolean existsCollection = trans.existsCollection(req.getDatabase(), arg.getCollection());
        final boolean createdCollectionAutomatically = !existsCollection;
        if (!existsCollection) {
            LOGGER.info("Creating collection {} on {}.{}", req.getDatabase(), arg.getCollection());
            trans.createIndex(req.getDatabase(), arg.getCollection(), Constants.ID_INDEX, ImmutableList.<IndexFieldInfo>of(new IndexFieldInfo(new AttributeReference(Arrays.asList(new Key[] { new ObjectKey(Constants.ID) })), FieldIndexOrdering.ASC.isAscending())), true);
        }
        for (IndexOptions indexOptions : arg.getIndexesToCreate()) {
            if (!replicationFilters.getIndexPredicate().test(req.getDatabase(), arg.getCollection(), indexOptions.getName(), indexOptions.isUnique(), indexOptions.getKeys())) {
                LOGGER.info("Skipping filtered index {}.{}.{}.", req.getDatabase(), arg.getCollection(), indexOptions.getName());
                continue;
            }
            if (indexOptions.getKeys().size() < 1) {
                return Status.from(ErrorCode.CANNOT_CREATE_INDEX, "Index keys cannot be empty.");
            }
            if (indexOptions.isBackground()) {
                LOGGER.info("Building index in background is not supported. Ignoring option");
            }
            if (indexOptions.isSparse()) {
                LOGGER.info("Sparse index are not supported. Ignoring option");
            }
            boolean skipIndex = false;
            List<IndexFieldInfo> fields = new ArrayList<>(indexOptions.getKeys().size());
            for (IndexOptions.Key indexKey : indexOptions.getKeys()) {
                AttributeReference.Builder attRefBuilder = new AttributeReference.Builder();
                for (String key : indexKey.getKeys()) {
                    attRefBuilder.addObjectKey(key);
                }
                IndexType indexType = indexKey.getType();
                if (!KnownType.contains(indexType)) {
                    String note = "Bad index key pattern: Unknown index type '" + indexKey.getType().getName() + "'. Skipping index.";
                    LOGGER.info(note);
                    skipIndex = true;
                    break;
                }
                Optional<FieldIndexOrdering> ordering = indexType.accept(filedIndexOrderingConverterVisitor, null);
                if (!ordering.isPresent()) {
                    String note = "Index of type " + indexType.getName() + " is not supported. Skipping index.";
                    LOGGER.info(note);
                    skipIndex = true;
                    break;
                }
                fields.add(new IndexFieldInfo(attRefBuilder.build(), ordering.get().isAscending()));
            }
            if (skipIndex) {
                continue;
            }
            try {
                LOGGER.info("Creating index {} on collection {}.{}", req.getDatabase(), arg.getCollection(), indexOptions.getName());
                if (trans.createIndex(req.getDatabase(), arg.getCollection(), indexOptions.getName(), fields, indexOptions.isUnique())) {
                    indexesAfter++;
                }
            } catch (UnsupportedCompoundIndexException ex) {
                String note = "Compound indexes are not supported. Skipping index.";
                LOGGER.info(note);
                continue;
            } catch (UnsupportedUniqueIndexException ex) {
                String note = "Unique index with keys on distinct subdocuments is not supported. Skipping index.";
                LOGGER.info(note);
                continue;
            }
        }
        String note = null;
        if (indexesAfter == indexesBefore) {
            note = "all indexes already exist";
        }
        return Status.ok(new CreateIndexesResult(indexesBefore, indexesAfter, note, createdCollectionAutomatically));
    } catch (UserException ex) {
        return Status.from(ErrorCode.COMMAND_FAILED, ex.getLocalizedMessage());
    }
}
Also used : IndexOptions(com.torodb.mongodb.commands.pojos.index.IndexOptions) AttributeReference(com.torodb.core.language.AttributeReference) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) ArrayList(java.util.ArrayList) UnsupportedUniqueIndexException(com.torodb.core.exceptions.user.UnsupportedUniqueIndexException) UnsupportedCompoundIndexException(com.torodb.core.exceptions.user.UnsupportedCompoundIndexException) CreateIndexesResult(com.torodb.mongodb.commands.signatures.admin.CreateIndexesCommand.CreateIndexesResult) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) UserException(com.torodb.core.exceptions.user.UserException) AscIndexType(com.torodb.mongodb.commands.pojos.index.type.AscIndexType) DescIndexType(com.torodb.mongodb.commands.pojos.index.type.DescIndexType) IndexType(com.torodb.mongodb.commands.pojos.index.type.IndexType) FieldIndexOrdering(com.torodb.core.transaction.metainf.FieldIndexOrdering)

Example 2 with IndexFieldInfo

use of com.torodb.torod.IndexFieldInfo in project torodb by torodb.

the class CreateCollectionReplImpl method apply.

@Override
public Status<Empty> apply(Request req, Command<? super CreateCollectionArgument, ? super Empty> command, CreateCollectionArgument arg, SharedWriteTorodTransaction trans) {
    try {
        LOGGER.info("Creating collection {}.{}", req.getDatabase(), arg.getCollection());
        if (arg.getOptions().isCapped()) {
            LOGGER.info("Ignoring capped flag for collection {}.{}", req.getDatabase(), arg.getCollection());
        }
        if (!trans.existsCollection(req.getDatabase(), arg.getCollection())) {
            trans.createIndex(req.getDatabase(), arg.getCollection(), Constants.ID_INDEX, ImmutableList.of(new IndexFieldInfo(new AttributeReference(Arrays.asList(new Key[] { new ObjectKey(Constants.ID) })), FieldIndexOrdering.ASC.isAscending())), true);
        }
        trans.createCollection(req.getDatabase(), arg.getCollection());
    } catch (UserException ex) {
        reportErrorIgnored(LOGGER, command, ex);
    }
    return Status.ok();
}
Also used : AttributeReference(com.torodb.core.language.AttributeReference) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) UserException(com.torodb.core.exceptions.user.UserException)

Example 3 with IndexFieldInfo

use of com.torodb.torod.IndexFieldInfo in project torodb by torodb.

the class SqlWriteTorodTransaction method createIndex.

@Override
public boolean createIndex(String dbName, String colName, String indexName, List<IndexFieldInfo> fields, boolean unique) throws UserException {
    if (fields.size() > 1) {
        throw new UnsupportedCompoundIndexException(dbName, colName, indexName);
    }
    MutableMetaDatabase metaDb = getOrCreateMetaDatabase(dbName);
    MutableMetaCollection metaColl = getOrCreateMetaCollection(metaDb, colName);
    List<Tuple3<TableRef, String, FieldIndexOrdering>> indexFieldDefs = new ArrayList<>(fields.size());
    for (IndexFieldInfo field : fields) {
        AttributeReference attRef = field.getAttributeReference();
        FieldIndexOrdering ordering = field.isAscending() ? FieldIndexOrdering.ASC : FieldIndexOrdering.DESC;
        TableRef tableRef = extractTableRef(attRef);
        String lastKey = extractKeyName(attRef.getKeys().get(attRef.getKeys().size() - 1));
        indexFieldDefs.add(new Tuple3<>(tableRef, lastKey, ordering));
    }
    if (unique) {
        TableRef anyIndexTableRef = indexFieldDefs.stream().findAny().get().v1();
        boolean isUniqueIndexWithMutlipleTableRefs = indexFieldDefs.stream().anyMatch(t -> !t.v1().equals(anyIndexTableRef));
        if (isUniqueIndexWithMutlipleTableRefs) {
            throw new UnsupportedUniqueIndexException(dbName, colName, indexName);
        }
    }
    boolean indexExists = metaColl.streamContainedMetaIndexes().anyMatch(index -> index.getName().equals(indexName) || (index.isUnique() == unique && index.size() == indexFieldDefs.size() && Seq.seq(index.iteratorFields()).allMatch(indexField -> {
        Tuple3<TableRef, String, FieldIndexOrdering> indexFieldDef = indexFieldDefs.get(indexField.getPosition());
        return indexFieldDef != null && indexFieldDef.v1().equals(indexField.getTableRef()) && indexFieldDef.v2().equals(indexField.getName()) && indexFieldDef.v3() == indexField.getOrdering();
    })));
    if (!indexExists) {
        MutableMetaIndex metaIndex = metaColl.addMetaIndex(indexName, unique);
        for (Tuple3<TableRef, String, FieldIndexOrdering> indexFieldDef : indexFieldDefs) {
            metaIndex.addMetaIndexField(indexFieldDef.v1(), indexFieldDef.v2(), indexFieldDef.v3());
        }
        getInternalTransaction().getBackendTransaction().createIndex(metaDb, metaColl, metaIndex);
    }
    return !indexExists;
}
Also used : MutableMetaCollection(com.torodb.core.transaction.metainf.MutableMetaCollection) AttributeReference(com.torodb.core.language.AttributeReference) ArrayList(java.util.ArrayList) UnsupportedUniqueIndexException(com.torodb.core.exceptions.user.UnsupportedUniqueIndexException) MutableMetaDatabase(com.torodb.core.transaction.metainf.MutableMetaDatabase) UnsupportedCompoundIndexException(com.torodb.core.exceptions.user.UnsupportedCompoundIndexException) Tuple3(org.jooq.lambda.tuple.Tuple3) MutableMetaIndex(com.torodb.core.transaction.metainf.MutableMetaIndex) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) FieldIndexOrdering(com.torodb.core.transaction.metainf.FieldIndexOrdering) TableRef(com.torodb.core.TableRef)

Example 4 with IndexFieldInfo

use of com.torodb.torod.IndexFieldInfo in project torodb by torodb.

the class InsertImplementation method apply.

@Override
public Status<InsertResult> apply(Request req, Command<? super InsertArgument, ? super InsertResult> command, InsertArgument arg, WriteMongodTransaction context) {
    mongodMetrics.getInserts().mark(arg.getDocuments().size());
    Stream<KvDocument> docsToInsert = arg.getDocuments().stream().map(FromBsonValueTranslator.getInstance()).map((v) -> (KvDocument) v);
    try {
        if (!context.getTorodTransaction().existsCollection(req.getDatabase(), arg.getCollection())) {
            context.getTorodTransaction().createIndex(req.getDatabase(), arg.getCollection(), Constants.ID_INDEX, ImmutableList.<IndexFieldInfo>of(new IndexFieldInfo(new AttributeReference(Arrays.asList(new Key[] { new ObjectKey(Constants.ID) })), FieldIndexOrdering.ASC.isAscending())), true);
        }
        context.getTorodTransaction().insert(req.getDatabase(), arg.getCollection(), docsToInsert);
    } catch (UserException ex) {
        //TODO: Improve error reporting
        return Status.from(ErrorCode.COMMAND_FAILED, ex.getLocalizedMessage());
    }
    return Status.ok(new InsertResult(arg.getDocuments().size()));
}
Also used : KvDocument(com.torodb.kvdocument.values.KvDocument) InsertResult(com.torodb.mongodb.commands.signatures.general.InsertCommand.InsertResult) AttributeReference(com.torodb.core.language.AttributeReference) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) UserException(com.torodb.core.exceptions.user.UserException)

Example 5 with IndexFieldInfo

use of com.torodb.torod.IndexFieldInfo in project torodb by torodb.

the class UpdateImplementation method apply.

@Override
public Status<UpdateResult> apply(Request req, Command<? super UpdateArgument, ? super UpdateResult> command, UpdateArgument arg, WriteMongodTransaction context) {
    UpdateStatus updateStatus = new UpdateStatus();
    try {
        if (!context.getTorodTransaction().existsCollection(req.getDatabase(), arg.getCollection())) {
            context.getTorodTransaction().createIndex(req.getDatabase(), arg.getCollection(), Constants.ID_INDEX, ImmutableList.<IndexFieldInfo>of(new IndexFieldInfo(new AttributeReference(Arrays.asList(new Key[] { new ObjectKey(Constants.ID) })), FieldIndexOrdering.ASC.isAscending())), true);
        }
        for (UpdateStatement updateStatement : arg.getStatements()) {
            BsonDocument query = updateStatement.getQuery();
            UpdateAction updateAction = UpdateActionTranslator.translate(updateStatement.getUpdate());
            Cursor<ToroDocument> candidatesCursor;
            switch(query.size()) {
                case 0:
                    {
                        candidatesCursor = context.getTorodTransaction().findAll(req.getDatabase(), arg.getCollection()).asDocCursor();
                        break;
                    }
                case 1:
                    {
                        try {
                            candidatesCursor = findByAttribute(context.getTorodTransaction(), req.getDatabase(), arg.getCollection(), query);
                        } catch (CommandFailed ex) {
                            return Status.from(ex);
                        }
                        break;
                    }
                default:
                    {
                        return Status.from(ErrorCode.COMMAND_FAILED, "The given query is not supported right now");
                    }
            }
            if (candidatesCursor.hasNext()) {
                try {
                    Stream<List<ToroDocument>> candidatesbatchStream;
                    if (updateStatement.isMulti()) {
                        candidatesbatchStream = StreamSupport.stream(Spliterators.spliteratorUnknownSize(candidatesCursor.batch(100), Spliterator.ORDERED), false);
                    } else {
                        candidatesbatchStream = Stream.of(ImmutableList.of(candidatesCursor.next()));
                    }
                    Stream<KvDocument> updatedCandidates = candidatesbatchStream.map(candidates -> {
                        updateStatus.increaseCandidates(candidates.size());
                        context.getTorodTransaction().delete(req.getDatabase(), arg.getCollection(), candidates);
                        return candidates;
                    }).flatMap(l -> l.stream()).map(candidate -> {
                        try {
                            updateStatus.increaseUpdated();
                            return update(updateAction, candidate);
                        } catch (UserException userException) {
                            throw new UserWrappedException(userException);
                        }
                    });
                    context.getTorodTransaction().insert(req.getDatabase(), arg.getCollection(), updatedCandidates);
                } catch (UserWrappedException userWrappedException) {
                    throw userWrappedException.getCause();
                }
            } else if (updateStatement.isUpsert()) {
                KvDocument toInsertCandidate;
                if (updateAction instanceof SetDocumentUpdateAction) {
                    toInsertCandidate = ((SetDocumentUpdateAction) updateAction).getNewValue();
                } else {
                    toInsertCandidate = update(updateAction, new ToroDocument(-1, (KvDocument) MongoWpConverter.translate(query)));
                }
                if (!toInsertCandidate.containsKey(Constants.ID)) {
                    KvDocument.Builder builder = new KvDocument.Builder();
                    for (DocEntry<?> entry : toInsertCandidate) {
                        builder.putValue(entry.getKey(), entry.getValue());
                    }
                    builder.putValue(Constants.ID, MongoWpConverter.translate(objectIdFactory.consumeObjectId()));
                    toInsertCandidate = builder.build();
                }
                updateStatus.increaseCandidates(1);
                updateStatus.increaseCreated(toInsertCandidate.get(Constants.ID));
                Stream<KvDocument> toInsertCandidates = Stream.of(toInsertCandidate);
                context.getTorodTransaction().insert(req.getDatabase(), arg.getCollection(), toInsertCandidates);
            }
        }
    } catch (UserException ex) {
        //TODO: Improve error reporting
        return Status.from(ErrorCode.COMMAND_FAILED, ex.getLocalizedMessage());
    }
    mongodMetrics.getUpdateModified().mark(updateStatus.updated);
    mongodMetrics.getUpdateMatched().mark(updateStatus.candidates);
    mongodMetrics.getUpdateUpserted().mark(updateStatus.upsertResults.size());
    return Status.ok(new UpdateResult(updateStatus.updated, updateStatus.candidates, ImmutableList.copyOf(updateStatus.upsertResults)));
}
Also used : Request(com.eightkdata.mongowp.server.api.Request) UpdateActionTranslator(com.torodb.mongodb.language.UpdateActionTranslator) Arrays(java.util.Arrays) UpdatedToroDocumentBuilder(com.torodb.mongodb.language.update.UpdatedToroDocumentBuilder) FieldIndexOrdering(com.torodb.core.transaction.metainf.FieldIndexOrdering) Spliterators(java.util.Spliterators) BsonDocument(com.eightkdata.mongowp.bson.BsonDocument) WriteTorodbCommandImpl(com.torodb.mongodb.commands.impl.WriteTorodbCommandImpl) UpdateAction(com.torodb.mongodb.language.update.UpdateAction) UpdateStatement(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateStatement) Singleton(javax.inject.Singleton) ToroDocument(com.torodb.core.document.ToroDocument) UpdateResult(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateResult) ArrayList(java.util.ArrayList) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) Inject(javax.inject.Inject) KvValue(com.torodb.kvdocument.values.KvValue) ImmutableList(com.google.common.collect.ImmutableList) MongoWpConverter(com.torodb.kvdocument.conversion.mongowp.MongoWpConverter) StreamSupport(java.util.stream.StreamSupport) Builder(com.torodb.core.language.AttributeReference.Builder) ErrorCode(com.eightkdata.mongowp.ErrorCode) CommandFailed(com.eightkdata.mongowp.exceptions.CommandFailed) UpdateException(com.torodb.core.exceptions.user.UpdateException) SharedWriteTorodTransaction(com.torodb.torod.SharedWriteTorodTransaction) AttributeReference(com.torodb.core.language.AttributeReference) Constants(com.torodb.mongodb.language.Constants) Cursor(com.torodb.core.cursors.Cursor) KvDocument(com.torodb.kvdocument.values.KvDocument) UpsertResult(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpsertResult) Command(com.eightkdata.mongowp.server.api.Command) UserException(com.torodb.core.exceptions.user.UserException) SetDocumentUpdateAction(com.torodb.mongodb.language.update.SetDocumentUpdateAction) ObjectIdFactory(com.torodb.mongodb.language.ObjectIdFactory) DocEntry(com.torodb.kvdocument.values.KvDocument.DocEntry) MongodMetrics(com.torodb.mongodb.core.MongodMetrics) WriteMongodTransaction(com.torodb.mongodb.core.WriteMongodTransaction) List(java.util.List) Stream(java.util.stream.Stream) Status(com.eightkdata.mongowp.Status) UserWrappedException(com.torodb.core.exceptions.UserWrappedException) UpdateArgument(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateArgument) Spliterator(java.util.Spliterator) Key(com.torodb.core.language.AttributeReference.Key) KvDocument(com.torodb.kvdocument.values.KvDocument) UpdateStatement(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateStatement) UpdateAction(com.torodb.mongodb.language.update.UpdateAction) SetDocumentUpdateAction(com.torodb.mongodb.language.update.SetDocumentUpdateAction) AttributeReference(com.torodb.core.language.AttributeReference) UpdatedToroDocumentBuilder(com.torodb.mongodb.language.update.UpdatedToroDocumentBuilder) Builder(com.torodb.core.language.AttributeReference.Builder) ObjectKey(com.torodb.core.language.AttributeReference.ObjectKey) DocEntry(com.torodb.kvdocument.values.KvDocument.DocEntry) BsonDocument(com.eightkdata.mongowp.bson.BsonDocument) UserWrappedException(com.torodb.core.exceptions.UserWrappedException) ToroDocument(com.torodb.core.document.ToroDocument) CommandFailed(com.eightkdata.mongowp.exceptions.CommandFailed) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) Stream(java.util.stream.Stream) IndexFieldInfo(com.torodb.torod.IndexFieldInfo) UserException(com.torodb.core.exceptions.user.UserException) UpdateResult(com.torodb.mongodb.commands.signatures.general.UpdateCommand.UpdateResult) SetDocumentUpdateAction(com.torodb.mongodb.language.update.SetDocumentUpdateAction)

Aggregations

AttributeReference (com.torodb.core.language.AttributeReference)8 IndexFieldInfo (com.torodb.torod.IndexFieldInfo)8 UserException (com.torodb.core.exceptions.user.UserException)5 ObjectKey (com.torodb.core.language.AttributeReference.ObjectKey)5 FieldIndexOrdering (com.torodb.core.transaction.metainf.FieldIndexOrdering)4 IndexOptions (com.torodb.mongodb.commands.pojos.index.IndexOptions)4 ArrayList (java.util.ArrayList)4 CommandFailed (com.eightkdata.mongowp.exceptions.CommandFailed)2 UnsupportedCompoundIndexException (com.torodb.core.exceptions.user.UnsupportedCompoundIndexException)2 UnsupportedUniqueIndexException (com.torodb.core.exceptions.user.UnsupportedUniqueIndexException)2 KvDocument (com.torodb.kvdocument.values.KvDocument)2 AscIndexType (com.torodb.mongodb.commands.pojos.index.type.AscIndexType)2 DescIndexType (com.torodb.mongodb.commands.pojos.index.type.DescIndexType)2 IndexType (com.torodb.mongodb.commands.pojos.index.type.IndexType)2 CreateIndexesResult (com.torodb.mongodb.commands.signatures.admin.CreateIndexesCommand.CreateIndexesResult)2 ErrorCode (com.eightkdata.mongowp.ErrorCode)1 Status (com.eightkdata.mongowp.Status)1 BsonDocument (com.eightkdata.mongowp.bson.BsonDocument)1 Command (com.eightkdata.mongowp.server.api.Command)1 Request (com.eightkdata.mongowp.server.api.Request)1