use of com.torodb.core.language.AttributeReference 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.core.language.AttributeReference 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)));
}
use of com.torodb.core.language.AttributeReference in project torodb by torodb.
the class UpdateActionTranslator method translateMultiply.
private static void translateMultiply(CompositeUpdateAction.Builder builder, BsonDocument argument) throws UpdateException {
for (Entry<?> entry : argument) {
Collection<AttributeReference> attRefs = parseAttributeReference(entry.getKey());
KvValue<?> translatedValue = MongoWpConverter.translate(entry.getValue());
if (!(translatedValue instanceof KvNumeric)) {
throw new UpdateException("Cannot multiply with a " + "non-numeric argument");
}
builder.add(new MultiplyUpdateAction(attRefs, (KvNumeric<?>) translatedValue), false);
}
}
use of com.torodb.core.language.AttributeReference in project torodb by torodb.
the class UpdateActionTranslator method parseAttributeReference.
private static void parseAttributeReference(String[] tokens, int depth, List<AttributeReference.Key<?>> keys, Collection<AttributeReference> attRefs) {
if (tokens.length == depth) {
attRefs.add(new AttributeReference(keys));
} else {
String nextKey = tokens[depth];
keys.add(new AttributeReference.ObjectKey(nextKey));
parseAttributeReference(tokens, depth + 1, keys, attRefs);
keys.remove(keys.size() - 1);
try {
int keyAsInt = Integer.parseInt(nextKey);
keys.add(new AttributeReference.ArrayKey(keyAsInt));
parseAttributeReference(tokens, depth + 1, keys, attRefs);
keys.remove(keys.size() - 1);
} catch (NumberFormatException ex) {
//the key is not an array key candidate
}
}
}
use of com.torodb.core.language.AttributeReference in project torodb by torodb.
the class UpdateActionTranslator method translateIncrement.
private static void translateIncrement(CompositeUpdateAction.Builder builder, BsonDocument argument) throws UpdateException {
for (Entry<?> entry : argument) {
Collection<AttributeReference> attRefs = parseAttributeReference(entry.getKey());
KvValue<?> translatedValue = MongoWpConverter.translate(entry.getValue());
if (!(translatedValue instanceof KvNumeric)) {
throw new UpdateException("Cannot increment with a " + "non-numeric argument");
}
builder.add(new IncrementUpdateAction(attRefs, (KvNumeric<?>) translatedValue), false);
}
}
Aggregations