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());
}
}
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();
}
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;
}
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()));
}
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)));
}
Aggregations