/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.translator.mongodb;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Iterator;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.teiid.CommandContext;
import org.teiid.cdk.api.TranslationUtility;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.language.Command;
import org.teiid.mongodb.MongoDBConnection;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.UpdateExecution;
import com.mongodb.*;
@SuppressWarnings("nls")
public class TestMongoDBUpdateExecution {
private MongoDBExecutionFactory translator;
private TranslationUtility utility;
@Before
public void setUp() throws Exception {
this.translator = new MongoDBExecutionFactory();
this.translator.start();
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("northwind.ddl")), "sakila", "northwind");
this.utility = new TranslationUtility(metadata);
}
@Test
public void testSimpleInsertNoAssosiations() throws Exception {
String query = "insert into Customers (CustomerID,CompanyName,ContactName,"
+ "ContactTitle,Address,City,Region,"
+ "PostalCode,Country,Phone,Fax) VALUES ('11', 'jboss', 'teiid', 'Mr.Lizard', "
+ "'jboss.org', 'internet', 'all', '1111', 'US', '555-1212', '555-1212')";
DBCollection dbCollection = helpUpdate(query, new String[]{"Customers"}, null, null);
BasicDBObject result = new BasicDBObject();
result.append("_id", "11");
result.append("CompanyName", "jboss");
result.append("ContactName" , "teiid");
result.append("ContactTitle","Mr.Lizard");
result.append("Address","jboss.org");
result.append("City","internet");
result.append("Region","all");
result.append("PostalCode","1111");
result.append( "Country","US");
result.append("Phone","555-1212");
result.append("Fax","555-1212");
Mockito.verify(dbCollection).insert(result, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.never()).update(new BasicDBObject(), result, false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testEmbeddableInsert() throws Exception {
String query = "INSERT INTO Categories (CategoryID, CategoryName, Description, Picture) " +
"VALUES (12, 'mongo', 'mongo with sql', null)";
DBCollection dbCollection = helpUpdate(query, new String[]{"Categories"}, null, null);
BasicDBObject result = new BasicDBObject();
result.append("_id", 12);
result.append("CategoryName", "mongo");
result.append("Description" , "mongo with sql");
result.append("Picture",null);
Mockito.verify(dbCollection).insert(result, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.never()).update(new BasicDBObject(), result, false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testMergeInsert() throws Exception {
// tests one-to-many situation
String query = "INSERT INTO OrderDetails (odID, ProductID, UnitPrice, Quantity, Discount) " +
"VALUES (14, 15, 34.50, 10, 12)";
BasicDBObject match = new BasicDBObject("_id", 14);
DBCollection dbCollection = helpUpdate(query, new String[]{"Orders"}, match, null);
BasicDBObject details = new BasicDBObject();
BasicDBObject pk = new BasicDBObject();
pk.append("odID", 14);
pk.append("ProductID", 15);
details.append("UnitPrice", 34.50);
details.append("Quantity", 10);
details.append("Discount", 12.0);
details.append("_id", pk);
details = new BasicDBObject("OrderDetails", details);
Mockito.verify(dbCollection, Mockito.never()).insert(details, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$push", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-one mapping update merge case;
public void testMergeInsertOne2One() throws Exception {
String query = "INSERT INTO address (cust_id, street, zip) VALUES (100, '123 Street', '90210')";
BasicDBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, null);
BasicDBObject details = new BasicDBObject();
details.append("street", "123 Street");
details.append("zip", "90210");
details = new BasicDBObject("address", details);
Mockito.verify(dbCollection, Mockito.never()).insert(details, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-many mapping update merge case;
public void testMergeInsertOne2Many() throws Exception {
String query = "INSERT INTO Notes (CustomerId, PostDate, Comment) VALUES (100, null, 'Hello')";
BasicDBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, null);
BasicDBObject details = new BasicDBObject();
details.append("PostDate", null);
details.append("Comment", "Hello");
details = new BasicDBObject("Notes", details);
Mockito.verify(dbCollection, Mockito.never()).insert(details, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$push", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-one mapping update merge case;
public void testMergeDeleteOne2OneonPK() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM address WHERE cust_id = 100";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBObject address = new BasicDBObject();
address.append("street", "123 Street").append("zip", "90210").append("_id", new DBRef(null, "customer", 100));
results.add(new BasicDBObject("_id", 100).append("address", address));
DBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, results);
BasicDBObject details = new BasicDBObject("address", "");
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$unset", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-one mapping update merge case;
public void testMergeDeleteOne2OneonNonPK() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM address WHERE street = 'Highway 100'";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBObject address = new BasicDBObject();
address.append("street", "123 Street").append("zip", "90210").append("_id", new DBRef(null, "customer", 100));
results.add(new BasicDBObject("_id", 100).append("address", address));
DBObject match = QueryBuilder.start("address.street").is("Highway 100").get();
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, results);
BasicDBObject details = new BasicDBObject("address", "");
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$unset", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-one mapping update merge case;
public void testMergeDeleteOne2OneAllRows() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM address";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBObject address = new BasicDBObject();
address.append("street", "123 Street").append("zip", "90210").append("_id", new DBRef(null, "customer", 100));
results.add(new BasicDBObject("_id", 100).append("address", address));
DBObject match = QueryBuilder.start("address").exists(true).get();
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, results);
BasicDBObject details = new BasicDBObject("address", "");
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$unset", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test(expected=TranslatorException.class) // one-2-one mapping update merge case;
public void testMergeDeleteOne2ManyWithORClause() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM Notes WHERE CustomerId = 100 OR Comment IN ('Hello', 'Hola')";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("Comment", "Hello").append("PostDate", "{ts '2014-07-15 09:06:04'}"));
row.add(new BasicDBObject("Comment", "Hola").append("PostDate", "{ts '2013-07-15 09:06:04'}"));
results.add(new BasicDBObject("_id", 100).append("Notes", row));
BasicDBList commentIN = new BasicDBList();
commentIN.add("Hello");
commentIN.add("Hola");
DBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, results);
BasicDBObject details = new BasicDBObject("Notes", QueryBuilder.start("Comment").in(commentIN).get());
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$pull", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-one mapping update merge case;
public void testMergeDeleteOne2ManyWithIN() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM Notes WHERE Comment IN ('Hello', 'Hola')";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("Comment", "Hello").append("PostDate", "{ts '2014-07-15 09:06:04'}"));
row.add(new BasicDBObject("Comment", "Hola").append("PostDate", "{ts '2013-07-15 09:06:04'}"));
results.add(new BasicDBObject("_id", 100).append("Notes", row));
BasicDBList commentIN = new BasicDBList();
commentIN.add("Hello");
commentIN.add("Hola");
DBObject match = QueryBuilder.start("Notes").exists(true).get();
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, results);
BasicDBObject details = new BasicDBObject("Notes", QueryBuilder.start("Comment").in(commentIN).get());
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$pull", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-one mapping update merge case;
public void testMergeDeleteOne2ManyNonFK() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM Notes WHERE Comment = 'Hello'";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("Comment", "Hello").append("PostDate", "{ts '2014-07-15 09:06:04'}"));
row.add(new BasicDBObject("Comment", "Hola").append("PostDate", "{ts '2013-07-15 09:06:04'}"));
results.add(new BasicDBObject("_id", 100).append("Notes", row));
DBObject match = QueryBuilder.start("Notes").exists(true).get();
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, match, results);
BasicDBObject details = new BasicDBObject("Notes", new BasicDBObject("Comment", "Hello"));
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$pull", details), false, true, WriteConcern.ACKNOWLEDGED);
}
private DBCollection helpUpdate(String query, String[] expectedCollection, DBObject match_result, ArrayList<DBObject> results) throws TranslatorException {
Command cmd = this.utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
CommandContext cc = Mockito.mock(CommandContext.class);
Mockito.stub(context.getCommandContext()).toReturn(cc);
MongoDBConnection connection = Mockito.mock(MongoDBConnection.class);
DB db = Mockito.mock(DB.class);
DBCollection dbCollection = Mockito.mock(DBCollection.class);
for(String collection:expectedCollection) {
Mockito.stub(db.getCollection(collection)).toReturn(dbCollection);
}
Mockito.stub(db.collectionExists(Mockito.anyString())).toReturn(true);
Mockito.stub(connection.getDatabase()).toReturn(db);
Mockito.stub(db.getCollectionFromString(Mockito.anyString())).toReturn(dbCollection);
Mockito.stub(dbCollection.findOne(Mockito.any(BasicDBObject.class))).toReturn(match_result);
WriteResult result = Mockito.mock(WriteResult.class);
Mockito.stub(result.getN()).toReturn(1);
Mockito.stub(dbCollection.insert(Mockito.any(BasicDBObject.class), Mockito.any(WriteConcern.class)))
.toReturn(result);
Mockito.stub(dbCollection.update(Mockito.any(BasicDBObject.class),
Mockito.any(BasicDBObject.class),
Mockito.eq(false),
Mockito.eq(true),
Mockito.any(WriteConcern.class))).toReturn(result);
if (results != null) {
Cursor out = new ResultsCursor(results);
for (DBObject obj:results) {
Mockito.stub(dbCollection.aggregate(Mockito.anyList(), Mockito.any(AggregationOptions.class))).toReturn(out);
Mockito.stub(dbCollection.aggregate(Mockito.anyList(), Mockito.any(AggregationOptions.class))).toReturn(out);
}
}
UpdateExecution execution = this.translator.createUpdateExecution(cmd, context, this.utility.createRuntimeMetadata(), connection);
execution.execute();
return dbCollection;
}
private static class ResultsCursor implements Cursor {
private Iterator<DBObject> rows;
ResultsCursor (ArrayList<DBObject> rows){
this.rows = rows.iterator();
}
@Override
public void remove() {
this.rows.remove();
}
@Override
public DBObject next() {
return rows.next();
}
@Override
public boolean hasNext() {
return this.rows.hasNext();
}
@Override
public ServerAddress getServerAddress() {
return null;
}
@Override
public long getCursorId() {
return 0;
}
@Override
public void close() {
}
}
@Test
public void testUpdateEmbeddable() throws Exception {
// check to make sure about multiple updates
String query = "UPDATE Categories SET CategoryName='JBOSS' WHERE CategoryID = 11";
BasicDBObject match = new BasicDBObject("_id", 11);
BasicDBObject details = new BasicDBObject();
details.append("CategoryName", "JBOSS");
details = new BasicDBObject("$set", details);
ArrayList<DBObject> results = new ArrayList<DBObject>();
results.add(new BasicDBObject("_id", 11).append("key", "value"));
DBCollection dbCollection = helpUpdate(query, new String[]{"Categories", "Products"}, match, results);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, details, false, true, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(
new BasicDBObject("CategoryID", 11), new BasicDBObject("$set", new BasicDBObject("Categories", new BasicDBObject("key","value"))),
false, true, WriteConcern.ACKNOWLEDGED);
}
@Ignore // the composite key with nesting is not going to work when both keys are not in the parent.
@Test // one to many
public void testDeleteMergeOneToManyOnPK() throws Exception {
String query = "DELETE FROM OrderDetails WHERE ProductID = 14 and odID = 1";
DBCollection dbCollection = helpUpdate(query, new String[]{"Orders"}, new BasicDBObject("oid", 1), null);
DBObject match = QueryBuilder.start().and(new BasicDBObject("_id.ProductID", 14), new BasicDBObject("_id.odID", 1)).get();
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.times(1)).update(
new BasicDBObject("_id", 1), new BasicDBObject("$pull", new BasicDBObject("OrderDetails", match)),
false, true, WriteConcern.ACKNOWLEDGED);
}
@Ignore // the composite key with nesting is not going to work when both keys are not in the parent.
@Test // one to many
public void testDeleteMergeOneToManyOnPKANDColumn() throws Exception {
String query = "DELETE FROM OrderDetails WHERE ProductID = 14 and UnitPrice > 23.89";
DBCollection dbCollection = helpUpdate(query, new String[]{"Orders"}, QueryBuilder.start().exists("OrderDetails").get(), null);
QueryBuilder qb = QueryBuilder.start("OrderDetails").exists(true);
QueryBuilder pullQuery = new QueryBuilder();
pullQuery.and(new BasicDBObject("_id.ProductID", 14), QueryBuilder.start("UnitPrice").greaterThan(23.89).get());
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.times(1)).update(
qb.get(), new BasicDBObject("$pull", new BasicDBObject("OrderDetails", pullQuery.get())),
false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one to many
@Ignore
public void testMergeOne2ManyUpdateComplexKey() throws Exception {
String query = "UPDATE OrderDetails SET UnitPrice = 12.50 WHERE ProductID = 14 and odID = 1";
BasicDBObject pk= new BasicDBObject("ProductID", 14);
BasicDBObject pk2= new BasicDBObject("ProductID", 15);
BasicDBList result = new BasicDBList();
result.add(new BasicDBObject().append("_id", pk).append("UnitPrice", 99.00).append("Quantity", 11));
result.add(new BasicDBObject().append("_id", pk2).append("UnitPrice", 0.99).append("Quantity", 12));
BasicDBObject row = new BasicDBObject("OrderDetails", result).append("_id", 1);
ArrayList<DBObject> results = new ArrayList<DBObject>();
results.add(row);
DBCollection dbCollection = helpUpdate(query, new String[]{"Orders"}, new BasicDBObject("oid", 1), results );
// { "$set" : { "OrderDetails" : [ { "_id" : 1 , "ProductID" : 14 , "odID" : 1 , "UnitPrice" : 12.5}]}},
BasicDBList expected = new BasicDBList();
expected.add(new BasicDBObject("_id", pk).append("UnitPrice", 12.50).append("Quantity", 11));
expected.add(new BasicDBObject().append("_id", pk2).append("UnitPrice", 0.99).append("Quantity", 12));
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.times(1)).update(
new BasicDBObject("_id", 1), new BasicDBObject("$set", new BasicDBObject("OrderDetails", expected)),
false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void tesNestedEmbeddingInsert() throws Exception {
String query = "insert into T1 (e1, e2, e3) VALUES (1, 2, 3)";
BasicDBObject match = new BasicDBObject();
match.append("_id", 2);
DBCollection dbCollection = helpUpdate(query, new String[]{"T1", "T2"}, match, null);
BasicDBObject row = new BasicDBObject();
row.append("e1", 1);
row.append("e3", 3);
row.append("_id", 2);
row.append("T2", match);
Mockito.verify(dbCollection).insert(row, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.never()).update(match, row, false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
@Ignore
public void tesNestedEmbeddingUpdate() throws Exception {
String query = "UPDATE T3 SET e2 = 2, e3 = 3 WHERE e1 = 1";
BasicDBObject t3_match = new BasicDBObject();
t3_match.append("_id", 1);
ArrayList<DBObject> results = new ArrayList<DBObject>();
results.add(new BasicDBObject("_id", 1).append("key", "value"));
DBCollection dbCollection = helpUpdate(query, new String[]{"T3", "T2", "T1"}, t3_match, results);
BasicDBObject t3_row = new BasicDBObject();
t3_row.append("e2", 2);
t3_row.append("e3", 3);
BasicDBObject t2_match = new BasicDBObject();
t2_match.append("e1", 1);
BasicDBObject t1row = new BasicDBObject("T2", results.get(0));
BasicDBObject t2row = new BasicDBObject("T3", results.get(0));
BasicDBObject t1_match = new BasicDBObject();
t1_match.append("e1", 1);
Mockito.verify(dbCollection, Mockito.never()).insert(t3_row, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(t3_match, new BasicDBObject("$set", t3_row), false, true, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(t2_match, new BasicDBObject("$set", t2row), false, true, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(t1_match, new BasicDBObject("$set", t1row), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
@Ignore
public void tesNestedEmbeddingUpdateInMiddle() throws Exception {
String query = "UPDATE T2 SET e2 = 2, e3 = 3 WHERE e1 = 1";
BasicDBObject match = new BasicDBObject();
match.append("_id", 1);
ArrayList<DBObject> results = new ArrayList<DBObject>();
results.add(new BasicDBObject("_id", 1).append("key", "value"));
DBCollection dbCollection = helpUpdate(query, new String[]{"T2", "T1", "T3"}, match, results);
BasicDBObject row = new BasicDBObject();
row.append("e2", 2);
row.append("e3", 3);
BasicDBObject t2_match = new BasicDBObject();
t2_match.append("e1.$id", 1);
BasicDBObject t2row = new BasicDBObject("T2", results.get(0));
Mockito.verify(dbCollection, Mockito.never()).insert(row, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", row), false, true, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(t2_match, new BasicDBObject("$set", t2row), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeInsert() throws Exception {
String query = "INSERT INTO customer (customer_id, name) VALUES (1, 'jboss')";
BasicDBObject customer_result = new BasicDBObject();
customer_result.append("name", "jboss");
customer_result.append("_id", 1);
BasicDBObject match = new BasicDBObject();
match.append("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"customer"}, null, null);
Mockito.verify(dbCollection).insert(customer_result, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.never()).update(new BasicDBObject(), match, false, true, WriteConcern.ACKNOWLEDGED);
// { "$push" : { "rental" : { "amount" : "3.99" , "customer_id" : { "$ref" : "customer" , "$id" : 1} , "_id" : 1}}},
BasicDBObject rental = new BasicDBObject();
rental.append("amount", 3.99);
//rental.append("customer_id", new DBRef(null, "customer", 1));
rental.append("_id", 2);
BasicDBObject rentalresult = new BasicDBObject("rental", rental);
query = "INSERT INTO rental (rental_id, amount, customer_id) VALUES (2, 3.99, 1)";
dbCollection = helpUpdate(query, new String[]{"customer"}, customer_result, null);
Mockito.verify(dbCollection, Mockito.never()).insert(customer_result, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$push", rentalresult), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testArrayInsert() throws Exception {
String query = "insert into ArrayTest(id,column1) VALUES (1, ('jboss', 'teiid', 'Mr.Lizard'))";
DBCollection dbCollection = helpUpdate(query, new String[]{"ArrayTest"}, null, null);
BasicDBList col1 = new BasicDBList();
col1.add("jboss");
col1.add("teiid");
col1.add("Mr.Lizard");
BasicDBObject result = new BasicDBObject();
result.append("id", 1);
result.append("column1", col1);
Mockito.verify(dbCollection).insert(result, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.never()).update(new BasicDBObject(), result, false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testArrayUpdate() throws Exception {
String query = "UPDATE ArrayTest SET column1 = ('jboss', 'teiid', 'Mr.Lizard') WHERE id = 1";
BasicDBObject match = new BasicDBObject("id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"ArrayTest"}, match, null);
BasicDBList col1 = new BasicDBList();
col1.add("jboss");
col1.add("teiid");
col1.add("Mr.Lizard");
BasicDBObject details = new BasicDBObject();
details.append("column1", col1);
details = new BasicDBObject("$set", details);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, details, false, true, WriteConcern.ACKNOWLEDGED);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// NEW Tests based on N1, N2, N3, N4, N5, N6, N7
// N1 -> N2 -> N3
// N1 -> N2 -> N4[]
// N1 -> N5[] -> N6
// N1 -> N5[] -> N7[]
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
@Test // one to many
public void testMergeDelete_one_2_many_all() throws Exception {
String query = "DELETE FROM N5";
BasicDBObject N5ROW1 = new BasicDBObject().append("e1", 3).append("e3", 3);
BasicDBObject N5ROW2 = new BasicDBObject().append("e1", 3).append("e3", 3);
BasicDBList N5Rows = new BasicDBList();
N5Rows.add(N5ROW1);
N5Rows.add(N5ROW2);
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
N1ROWS.add(new BasicDBObject("_id", 1).append("N5", N5Rows));
DBObject match = QueryBuilder.start("N5").exists(true).get();
DBCollection dbCollection = helpUpdate(query, new String[] { "N1" }, match, N1ROWS);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$pull", new BasicDBObject("N5", new BasicDBObject())),
false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testMergeDelete_one_2_many_usingFK() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM N5 WHERE e2 = 100";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("e1", 1).append("e3", 5));
row.add(new BasicDBObject("e1", 2).append("e3", 5));
results.add(new BasicDBObject("_id", 100).append("N5", row));
BasicDBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, results);
BasicDBObject details = new BasicDBObject("N5", new BasicDBList());
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testMergeDelete_one_2_many_usingFK2() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM N5 WHERE e2 = 100 and e1=1";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("_id", 1).append("e3", 5));
row.add(new BasicDBObject("_id", 2).append("e3", 5));
results.add(new BasicDBObject("_id", 100).append("N5", row));
BasicDBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, results);
BasicDBList expected = new BasicDBList();
expected.add(new BasicDBObject("_id", 2).append("e3", 5));
BasicDBObject details = new BasicDBObject("N5", expected);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeDelete_one_2_many_many() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM N7 WHERE e2 = 5 and e1=7";
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
BasicDBList N5ROW = new BasicDBList();
N5ROW.add(5);
N5ROW.add(51);
BasicDBList N5ROW2 = new BasicDBList();
N5ROW2.add(50);
N5ROW2.add(5);
BasicDBList N5_N7ROW = new BasicDBList();
N5_N7ROW.add(new BasicDBObject("_id", 7).append("e3", 7));
BasicDBList N5_N7ROW_ARRAY1 = new BasicDBList();
N5_N7ROW_ARRAY1.add(N5_N7ROW);
BasicDBList N5_N7ROW2 = new BasicDBList();
N5_N7ROW2.add(new BasicDBObject("_id", 5).append("e3", 7));
N5_N7ROW2.add(new BasicDBObject("_id", 7).append("e3", 7));
BasicDBList N5_N7ROW_ARRAY2 = new BasicDBList();
N5_N7ROW_ARRAY2.add(new BasicDBList());
N5_N7ROW_ARRAY2.add(N5_N7ROW2);
N1ROWS.add(new BasicDBObject("_id", 1).append("N5", N5ROW).append("N5_N7", N5_N7ROW_ARRAY1));
N1ROWS.add(new BasicDBObject("_id", 2).append("N5", N5ROW2).append("N5_N7", N5_N7ROW_ARRAY2));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, N1ROWS);
ArgumentCaptor<BasicDBObject> matchCaptor = ArgumentCaptor.forClass(BasicDBObject.class);
ArgumentCaptor<BasicDBObject> updateCaptor = ArgumentCaptor.forClass(BasicDBObject.class);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.times(2)).update(matchCaptor.capture(), updateCaptor.capture(), Mockito.eq(false),
Mockito.eq(true), Mockito.eq(WriteConcern.ACKNOWLEDGED));
assertEquals(new BasicDBObject("_id", 1), matchCaptor.getAllValues().get(0));
assertEquals(new BasicDBObject("_id", 2), matchCaptor.getAllValues().get(1));
BasicDBList EXPECTED_N5_N7ROW2 = new BasicDBList();
EXPECTED_N5_N7ROW2.add(new BasicDBObject("_id", 5).append("e3", 7));
BasicDBList EXPECTED_N5_N7ROW2_ARRAY = new BasicDBList();
EXPECTED_N5_N7ROW2_ARRAY.add(EXPECTED_N5_N7ROW2);
assertEquals(new BasicDBObject("$set", new BasicDBObject("N5.0.N7", new BasicDBList())),
updateCaptor.getAllValues().get(0));
assertEquals(new BasicDBObject("$set", new BasicDBObject("N5.1.N7", EXPECTED_N5_N7ROW2)),
updateCaptor.getAllValues().get(1));
}
@Test
public void testMergeDelete_one_2_one_2_many() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM N4 WHERE e2 = 100 and e1=1";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("_id", 1).append("e3", 5));
row.add(new BasicDBObject("_id", 2).append("e3", 5));
results.add(new BasicDBObject("_id", 100).append("N2_N4", row));
BasicDBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, results);
BasicDBList expected = new BasicDBList();
expected.add(new BasicDBObject("_id", 2).append("e3", 5));
BasicDBObject details = new BasicDBObject("N2.N4", expected);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testMergeDelete_one_2_one_many_onFK() throws Exception {
// tests one-to-many situation
String query = "DELETE FROM N4 WHERE e2 = 100";
ArrayList<DBObject> results = new ArrayList<DBObject>();
BasicDBList row = new BasicDBList();
row.add(new BasicDBObject("e1", 1).append("e3", 5));
row.add(new BasicDBObject("e1", 2).append("e3", 5));
results.add(new BasicDBObject("_id", 100).append("N2_N4", row));
BasicDBObject match = new BasicDBObject("_id", 100);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, results);
BasicDBObject details = new BasicDBObject("N2.N4", new BasicDBList());
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", details), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testUpdate() throws Exception {
String query = "UPDATE N1 SET e2 = 2, e3 = 3 WHERE e1 = 1";
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, null);
BasicDBObject details = new BasicDBObject();
details.append("e2", 2);
details.append("e3", 3);
details = new BasicDBObject("$set", details);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, details, false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testMergeUpdate_one_2_one() throws Exception {
String query = "UPDATE N2 SET e2 = 2 WHERE e2 = 3";
BasicDBObject N2ROW = new BasicDBObject().append("e2", 3).append("e3", 2);
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
N1ROWS.add(new BasicDBObject("_id", 1).append("N2", N2ROW));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[] { "N1" }, match, N1ROWS);
BasicDBObject N2UPDATE = new BasicDBObject();
N2UPDATE.append("N2", new BasicDBObject().append("e2", 2).append("e3", 2));
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", N2UPDATE), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test // one-2-many mapping update merge case;
public void testMergeUpdate_one_2_many() throws Exception {
// tests one-to-many situation
String query = "UPDATE N5 SET e3 = 5 WHERE e1 = 1";
// { "$project" : { "N5" : "$N5" , "_id" : "$_id"}}
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
BasicDBList N5ROW = new BasicDBList();
N5ROW.add(new BasicDBObject("_id", 1).append("e2", 1).append("e3", 1));
N5ROW.add(new BasicDBObject("_id", 2).append("e2", 1).append("e3", 2));
N1ROWS.add(new BasicDBObject("_id", 1).append("e2", 1).append("e3", 1).append("N5", N5ROW));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, N1ROWS);
BasicDBList expected = new BasicDBList();
expected.add(new BasicDBObject("_id", 1).append("e2", 1).append("e3", 5));
expected.add(new BasicDBObject("_id", 2).append("e2", 1).append("e3", 2));
BasicDBObject update = new BasicDBObject("N5", expected);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", update), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeInsert_one_2_one() throws Exception {
DBObject n1_match = QueryBuilder.start().and( QueryBuilder.start("N2").exists(true).get(), new BasicDBObject("_id", 1)).get();
BasicDBObject match = new BasicDBObject();
match.append("_id", 1);
BasicDBObject n3 = new BasicDBObject();
n3.append("e2", 3);
n3.append("e3", 3);
BasicDBObject result = new BasicDBObject("N2.N3", n3);
String query = "INSERT INTO N3 (e1, e2, e3) VALUES (1,3,3)";
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, null);
Mockito.verify(dbCollection, Mockito.never()).insert(n1_match, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(n1_match, new BasicDBObject("$set", result), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeUpdate_one_2_one_2_one() throws Exception {
String query = "UPDATE N3 SET e2 = 2 WHERE e1 = 1 and e2 = 3";
//{ "$project" : { "N2_N3" : "$N2.N3" , "N2" : "$N2._id" , "_id" : "$_id"}}
BasicDBObject N3ROW = new BasicDBObject().append("e2", 3).append("e3", 3);
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
N1ROWS.add(new BasicDBObject("_id", 1).append("N2_N3", N3ROW));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[] { "N1" }, match, N1ROWS);
BasicDBObject N3UPDATE = new BasicDBObject();
N3UPDATE.append("N2.N3", new BasicDBObject().append("e2", 2).append("e3", 3));
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", N3UPDATE), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeDelete_one_2_one_2_one() throws Exception {
String query = "DELETE FROM N3 WHERE e1 = 1 and e2 = 3";
//{ "$project" : { "N2_N3" : "$N2.N3" , "N2" : "$N2._id" , "_id" : "$_id"}}
BasicDBObject N3ROW = new BasicDBObject().append("e2", 3).append("e3", 3);
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
N1ROWS.add(new BasicDBObject("_id", 1).append("N2_N3", N3ROW));
DBObject match = QueryBuilder.start().and(new BasicDBObject("_id", 1), new BasicDBObject("N2.N3.e2", 3)).get();
DBCollection dbCollection = helpUpdate(query, new String[] { "N1" }, match, N1ROWS);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$unset", new BasicDBObject("N2.N3", "")), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeUpdate_one_2_one_2_many() throws Exception {
String query = "UPDATE N4 SET e3 = 5 WHERE e1 = 1";
BasicDBList N4ROW = new BasicDBList();
N4ROW.add(new BasicDBObject("_id", 1).append("e3", 1));
N4ROW.add(new BasicDBObject("_id", 2).append("e3", 2));
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
N1ROWS.add(new BasicDBObject("_id", 1).append("N2_N4", N4ROW));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[] { "N1" }, match, N1ROWS);
BasicDBList expected = new BasicDBList();
expected.add(new BasicDBObject("_id", 1).append("e3", 5));
expected.add(new BasicDBObject("_id", 2).append("e3", 2));
BasicDBObject N4UPDATE = new BasicDBObject("N2.N4", expected);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(match, new BasicDBObject("$set", N4UPDATE), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeUpdate_one_2_many_2_one() throws Exception {
String query = "UPDATE N6 SET e3 = 5 WHERE e1 = 5";
// { "$project" : { "N5_N6" : "$N5.N6" , "N5" : "$N5._id" , "_id" : "$_id"}}
// { "_id" : 1, "N5" : [ 5, 51 ], "N5_N6" : [ { "e2" : 6, "e3" : 6 }, { "e2" : 0, "e3" : 6 } ] }
// N5.e1 = N6.e1
// N5.e2 = N1.e1
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
BasicDBList N5ROW = new BasicDBList();
N5ROW.add(5);
N5ROW.add(51);
BasicDBList N5ROW2 = new BasicDBList();
N5ROW2.add(50);
N5ROW2.add(5);
BasicDBList N5_N6ROW = new BasicDBList();
N5_N6ROW.add(new BasicDBObject("e2", 6).append("e3", 6));
N5_N6ROW.add(new BasicDBObject("e2", 0).append("e3", 6));
BasicDBList N5_N6ROW2 = new BasicDBList();
N5_N6ROW2.add(new BasicDBObject("e2", 1).append("e3", 1));
N5_N6ROW2.add(new BasicDBObject("e2", 2).append("e3", 2));
N1ROWS.add(new BasicDBObject("_id", 1).append("N5", N5ROW).append("N5_N6", N5_N6ROW));
N1ROWS.add(new BasicDBObject("_id", 2).append("N5", N5ROW2).append("N5_N6", N5_N6ROW2));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, N1ROWS);
// one from each of the N5_N6 array is updated.
BasicDBObject expected1 = new BasicDBObject("e2", 6).append("e3", 5);
BasicDBObject expected2 = new BasicDBObject("e2", 2).append("e3", 5);
ArgumentCaptor<BasicDBObject> matchCaptor = ArgumentCaptor.forClass(BasicDBObject.class);
ArgumentCaptor<BasicDBObject> updateCaptor = ArgumentCaptor.forClass(BasicDBObject.class);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.times(2)).update(matchCaptor.capture(), updateCaptor.capture(), Mockito.eq(false),
Mockito.eq(true), Mockito.eq(WriteConcern.ACKNOWLEDGED));
assertEquals(new BasicDBObject("_id", 1), matchCaptor.getAllValues().get(0));
assertEquals(new BasicDBObject("_id", 2), matchCaptor.getAllValues().get(1));
assertEquals(new BasicDBObject("$set", new BasicDBObject("N5.0.N6", expected1)),
updateCaptor.getAllValues().get(0));
assertEquals(new BasicDBObject("$set", new BasicDBObject("N5.1.N6", expected2)),
updateCaptor.getAllValues().get(1));
}
@Test
public void testNestedMergeUpdate_one_2_many_2_many() throws Exception {
String query = "UPDATE N7 SET e3 = 5 WHERE e1 = 5";
// { "$project" : { "N5_N7" : "$N5.N7" , "N5" : "$N5._id" , "_id" : "$_id"}}
// { "_id" : 1, "N5" : [ 5, 51 ], "N5_N7" : [ [ { "e3" : 7, "_id" : 7 } ]] ] }
// { "_id" : 1, "N5" : [ 50, 5 ], "N5_N7" : [ [ { "e3" : 7, "_id" : 7 } ], [ { "e3" : 7, "_id" : 5 }, { "e3" : 7, "_id" : 7 } ] ] }
// N5.e1 = N7.e2
// N5.e2 = N1.e1
ArrayList<DBObject> N1ROWS = new ArrayList<DBObject>();
BasicDBList N5ROW = new BasicDBList();
N5ROW.add(5);
N5ROW.add(51);
BasicDBList N5ROW2 = new BasicDBList();
N5ROW2.add(50);
N5ROW2.add(5);
BasicDBList N5_N7ROW = new BasicDBList();
N5_N7ROW.add(new BasicDBObject("_id", 7).append("e3", 7));
BasicDBList N5_N7ROW_ARRAY1 = new BasicDBList();
N5_N7ROW_ARRAY1.add(N5_N7ROW);
BasicDBList N5_N7ROW2 = new BasicDBList();
N5_N7ROW2.add(new BasicDBObject("_id", 5).append("e3", 7));
N5_N7ROW2.add(new BasicDBObject("_id", 7).append("e3", 7));
BasicDBList N5_N7ROW_ARRAY2 = new BasicDBList();
N5_N7ROW_ARRAY2.add(new BasicDBList());
N5_N7ROW_ARRAY2.add(N5_N7ROW2);
N1ROWS.add(new BasicDBObject("_id", 1).append("N5", N5ROW).append("N5_N7", N5_N7ROW_ARRAY1));
N1ROWS.add(new BasicDBObject("_id", 2).append("N5", N5ROW2).append("N5_N7", N5_N7ROW_ARRAY2));
BasicDBObject match = new BasicDBObject("_id", 1);
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, N1ROWS);
ArgumentCaptor<BasicDBObject> matchCaptor = ArgumentCaptor.forClass(BasicDBObject.class);
ArgumentCaptor<BasicDBObject> updateCaptor = ArgumentCaptor.forClass(BasicDBObject.class);
Mockito.verify(dbCollection, Mockito.never()).insert(new BasicDBObject(), WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection, Mockito.times(1)).update(matchCaptor.capture(), updateCaptor.capture(), Mockito.eq(false),
Mockito.eq(true), Mockito.eq(WriteConcern.ACKNOWLEDGED));
assertEquals(new BasicDBObject("_id", 2), matchCaptor.getAllValues().get(0));
BasicDBList EXPECTED_N5_N7ROW2 = new BasicDBList();
EXPECTED_N5_N7ROW2.add(new BasicDBObject("_id", 5).append("e3", 5));
EXPECTED_N5_N7ROW2.add(new BasicDBObject("_id", 7).append("e3", 7));
BasicDBList EXPECTED_N5_N7ROW2_ARRAY = new BasicDBList();
EXPECTED_N5_N7ROW2_ARRAY.add(EXPECTED_N5_N7ROW2);
assertEquals(new BasicDBObject("$set", new BasicDBObject("N5.1.N7", EXPECTED_N5_N7ROW2)),
updateCaptor.getAllValues().get(0));
}
@Test
public void testNestedMergeInsert_One_2_One_Many() throws Exception {
DBObject n1_match = QueryBuilder.start().and(QueryBuilder.start("N2").exists(true).get(),
new BasicDBObject("_id", 2)).get();
BasicDBObject match = new BasicDBObject();
match.append("_id", 3);
BasicDBObject n4 = new BasicDBObject();
n4.append("e3", 3);
n4.append("_id",1);
BasicDBObject result = new BasicDBObject("N2.N4", n4);
String query = "INSERT INTO N4 (e1, e2, e3) VALUES (1,2,3)";
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, null);
Mockito.verify(dbCollection, Mockito.never()).insert(n1_match, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(n1_match, new BasicDBObject("$push", result), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeInsert_One_2_Many_one() throws Exception {
DBObject n1_match = QueryBuilder.start().and(QueryBuilder.start("N5").exists(true).get(),
new BasicDBObject("N5._id", 1)).get();
BasicDBObject match = new BasicDBObject();
match.append("_id", 3);
BasicDBObject n6 = new BasicDBObject();
n6.append("e2", 2);
n6.append("e3", 3);
BasicDBObject result = new BasicDBObject("N5.$.N6", n6);
String query = "INSERT INTO N6 (e1, e2, e3) VALUES (1,2,3)";
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, null);
Mockito.verify(dbCollection, Mockito.never()).insert(n1_match, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(n1_match, new BasicDBObject("$set", result), false, true, WriteConcern.ACKNOWLEDGED);
}
@Test
public void testNestedMergeInsert_One_2_Many_Many() throws Exception {
DBObject n1_match = QueryBuilder.start().and(QueryBuilder.start("N5").exists(true).get(),
new BasicDBObject("N5._id", 2)).get();
BasicDBObject match = new BasicDBObject();
match.append("_id", 3);
BasicDBObject n7 = new BasicDBObject();
n7.append("e3", 3);
n7.append("_id",1);
BasicDBObject result = new BasicDBObject("N5.$.N7", n7);
String query = "INSERT INTO N7 (e1, e2, e3) VALUES (1,2,3)";
DBCollection dbCollection = helpUpdate(query, new String[]{"N1"}, match, null);
Mockito.verify(dbCollection, Mockito.never()).insert(n1_match, WriteConcern.ACKNOWLEDGED);
Mockito.verify(dbCollection).update(n1_match, new BasicDBObject("$push", result), false, true, WriteConcern.ACKNOWLEDGED);
}
}