The following patch changes the DAS to assume a primary key field of "ID" in the absence of any configuration.
Brent
Index: src/test/java/org/apache/tuscany/das/rdb/test/CrudWithChangeHistory.java =================================================================== --- src/test/java/org/apache/tuscany/das/rdb/test/CrudWithChangeHistory.java (revision 392391) +++ src/test/java/org/apache/tuscany/das/rdb/test/CrudWithChangeHistory.java (working copy) @@ -26,10 +26,13 @@ * */ +import java.util.Iterator; + import org.apache.tuscany.das.rdb.ApplyChangesCommand; import org.apache.tuscany.das.rdb.Command; import org.apache.tuscany.das.rdb.SDODataTypes; import org.apache.tuscany.das.rdb.test.data.CustomerData; +import org.apache.tuscany.das.rdb.test.data.OrderDetailsData; import org.apache.tuscany.das.rdb.test.framework.DasTest; import commonj.sdo.DataObject; @@ -43,6 +46,7 @@ { super.setUp(); new CustomerData( getAutoConnection() ).refresh(); + new OrderDetailsData( getAutoConnection() ).refresh(); } protected void tearDown() @@ -251,4 +255,126 @@ } + + public void testReadModifyApplyWithAssumedID() throws Exception { + + //Read customer with particular ID + Command select = Command.FACTORY + .createCommand("Select * from CUSTOMER"); + select.setConnection(getConnection()); + DataObject root = select.executeQuery(); + + DataObject customer = root.getDataObject("CUSTOMER[1]"); + + //Modify customer + customer.set("LASTNAME", "Pavick"); + + DataObject customerForDelete = root.getDataObject("CUSTOMER[2]"); + String deletedLastName = customerForDelete.getString("LASTNAME"); + customerForDelete.delete(); + + DataObject newCustomer = root.createDataObject("CUSTOMER"); + newCustomer.set("LASTNAME", "NewCustomer"); + newCustomer.setInt("ID", 9000); + + //Build apply changes command + ApplyChangesCommand apply = Command.FACTORY.createApplyChangesCommand(); + apply.setConnection(getConnection()); + + //Flush changes + apply.execute(root); + + //Verify the change + root = select.executeQuery(); + assertEquals("Pavick", getCustomerByLastName(root, "Pavick").getString("LASTNAME")); + assertEquals("NewCustomer", getCustomerByLastName(root, "NewCustomer").getString("LASTNAME")); + assertNull(getCustomerByLastName(root, deletedLastName)); + + } + + + public void testReadModifyApplyWithAssumedIDFailure() throws Exception { + + Command select = Command.FACTORY + .createCommand("Select * from ORDERDETAILS"); + select.setConnection(getConnection()); + DataObject root = select.executeQuery(); + + DataObject od = root.getDataObject("ORDERDETAILS[1]"); + + //Modify customer + od.setInt("PRODUCTID", 72); + + //Build apply changes command + ApplyChangesCommand apply = Command.FACTORY.createApplyChangesCommand(); + apply.setConnection(getConnection()); + + //Flush changes -- This should fail because Order Details does not have a column that + // we can assume to be an ID + try { + apply.execute(root); + } catch (RuntimeException ex) { + assertTrue(ex.getMessage().contains("changed in the DataGraph but is not present in the Config")); + } + + } + + public void testReadModifyApplyWithAssumedIDFailure2() throws Exception { + + Command select = Command.FACTORY + .createCommand("Select * from ORDERDETAILS"); + select.setConnection(getConnection()); + DataObject root = select.executeQuery(); + + DataObject od = root.getDataObject("ORDERDETAILS[1]"); + od.delete(); + + //Build apply changes command + ApplyChangesCommand apply = Command.FACTORY.createApplyChangesCommand(); + apply.setConnection(getConnection()); + + //Flush changes -- This should fail because Order Details does not have a column that + // we can assume to be an ID + try { + apply.execute(root); + } catch (RuntimeException ex) { + assertTrue(ex.getMessage().contains("changed in the DataGraph but is not present in the Config")); + } + + } + public void testReadModifyApplyWithAssumedIDFailure3() throws Exception { + + Command select = Command.FACTORY + .createCommand("Select * from ORDERDETAILS"); + select.setConnection(getConnection()); + DataObject root = select.executeQuery(); + + DataObject od = root.createDataObject("ORDERDETAILS"); + + //Modify customer + od.setInt("PRODUCTID", 72); + od.setInt("ORDERID", 500); + + //Build apply changes command + ApplyChangesCommand apply = Command.FACTORY.createApplyChangesCommand(); + apply.setConnection(getConnection()); + + //Flush changes -- This should fail because Order Details does not have a column that + // we can assume to be an ID + try { + apply.execute(root); + } catch (RuntimeException ex) { + assertTrue(ex.getMessage().contains("changed in the DataGraph but is not present in the Config")); + } + + } + private DataObject getCustomerByLastName(DataObject root, String name) { + Iterator i = root.getList("CUSTOMER").iterator(); + while ( i. hasNext()) { + DataObject obj = (DataObject)i.next(); + if (name.equals(obj.getString("LASTNAME"))) + return obj; + } + return null; + } } Index: src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java =================================================================== --- src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java (revision 392391) +++ src/test/java/org/apache/tuscany/das/rdb/test/RelationshipTests.java (working copy) @@ -77,8 +77,8 @@ // Set minimum metadata necessary to describe relationship // Maybe something like this ... select.addRelationship("CUSTOMER.ID", "ANORDER.CUSTOMER_ID"); - select.addPrimaryKey("CUSTOMER.ID"); - select.addPrimaryKey("ANORDER.ID"); +// select.addPrimaryKey("CUSTOMER.ID"); +// select.addPrimaryKey("ANORDER.ID"); DataObject root = select.executeQuery(); @@ -191,5 +191,75 @@ "CUSTOMER[1]/orders").size()); } + + public void testRelationshipModificationWithoutConfig() throws Exception { + // Read some customers and related orders + Command select = Command.FACTORY + .createCommand("SELECT * FROM CUSTOMER LEFT JOIN ANORDER ON CUSTOMER.ID = ANORDER.CUSTOMER_ID"); + select.setConnection(getConnection()); + + // Set minimum metadata necessary to describe relationship + // Maybe something like this ... +// select.addRelationship("CUSTOMER.ID", "ANORDER.CUSTOMER_ID"); +// select.addPrimaryKey("CUSTOMER.ID"); +// select.addPrimaryKey("ANORDER.ID"); + + DataObject root = select.executeQuery(); + + DataObject cust1 = root.getDataObject("CUSTOMER[1]"); + DataObject cust2 = root.getDataObject("CUSTOMER[2]"); + + // Save IDs + Integer cust1ID = (Integer) cust1.get("ID"); + Integer cust2ID = (Integer) cust2.get("ID"); + // save order count + Integer cust1OrderCount = new Integer(cust1.getList("ANORDER").size()); + Integer cust2OrderCount = new Integer(cust2.getList("ANORDER").size()); + + // Move an order to cust1 from cust2 + DataObject order = (DataObject) cust2.getList("ANORDER").get(0); + cust1.getList("ANORDER").add(order); + + // Build apply changes command + ApplyChangesCommand apply = Command.FACTORY + .createApplyChangesCommand(); + apply.setConnection(getConnection()); + + // Manually create and add commands + Command update = Command.FACTORY + .createCommand("update ANORDER set CUSTOMER_ID = :CUSTOMER_ID where ID = :ID"); + update.addParameter("CUSTOMER_ID", SDODataTypes.INTEGER); + update.addParameter("ID", SDODataTypes.INTEGER); + update.addRelationship("CUSTOMER.ID", "ANORDER.CUSTOMER_ID"); + update.addPrimaryKey("CUSTOMER.ID"); + update.addPrimaryKey("ANORDER.ID"); + apply.addUpdateCommand(order.getType(), update); + + // Flush changes + apply.execute(root); + + // verify cust1 relationship updates + select = Command.FACTORY + .createCommand("SELECT * FROM CUSTOMER LEFT JOIN ANORDER ON CUSTOMER.ID = ANORDER.CUSTOMER_ID where CUSTOMER.ID = :ID"); + select.setConnection(getConnection()); + select.setParameterValue("ID", cust1ID); + + select.addRelationship("CUSTOMER.ID", "ANORDER.CUSTOMER_ID"); + select.addPrimaryKey("CUSTOMER.ID"); + select.addPrimaryKey("ANORDER.ID"); + root = select.executeQuery(); + + assertEquals(cust1OrderCount.intValue() + 1, root.getList( + "CUSTOMER[1]/ANORDER").size()); + + // verify cust2 relationship updates + select.setParameterValue("ID", cust2ID); + root = select.executeQuery(); + + assertEquals(cust2OrderCount.intValue() - 1, root.getList( + "CUSTOMER[1]/ANORDER").size()); + + } + } Index: src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java =================================================================== --- src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java (revision 395356) +++ src/main/java/org/apache/tuscany/das/rdb/impl/ChangeFactory.java (working copy) @@ -100,8 +100,16 @@ if ( createCommand == null ) { Table table = mapping.getTable(changedObject.getType().getName()); - if (table == null ) - throw new RuntimeException("Table " + changedObject.getType().getName() + " was changed in the DataGraph but is not present in the Config"); + if (table == null ) { + if (changedObject.getType().getProperty("ID") != null ) { + // If the table is not defined in the config, assume it has a primary key of "ID" + mapping.addPrimaryKey(changedObject.getType().getName() + ".ID"); + table = mapping.getTableByPropertyName(changedObject.getType().getName()); + } else { + throw new RuntimeException("Table " + changedObject.getType().getName() + " was changed in the DataGraph but is not present in the Config"); + } + } + String createStatement = table.getCreate(); if ( createStatement == null ) { @@ -124,8 +132,16 @@ if ( deleteCommand == null ) { Table table = mapping.getTable(changedObject.getType().getName()); - if (table == null ) - throw new RuntimeException("Table " + table + " was changed in the DataGraph but is not present in the Config"); + if (table == null ) { + if (changedObject.getType().getProperty("ID") != null ) { + // If the table is not defined in the config, assume it has a primary key of "ID" + mapping.addPrimaryKey(changedObject.getType().getName() + ".ID"); + table = mapping.getTableByPropertyName(changedObject.getType().getName()); + } else { + throw new RuntimeException("Table " + changedObject.getType().getName() + " was changed in the DataGraph but is not present in the Config"); + } + } + String deleteStatement = table.getDelete(); if ( deleteStatement == null ) { deleteCommand = getCudGenerator().getDeleteCommand(table); @@ -145,8 +161,15 @@ if ( updateCommand == null ) { Table table = mapping.getTableByPropertyName(changedObject.getType().getName()); - if (table == null ) - throw new RuntimeException("Table " + table + " was changed in the DataGraph but is not present in the Config"); + if (table == null ) { + if (changedObject.getType().getProperty("ID") != null ) { + // If the table is not defined in the config, assume it has a primary key of "ID" + mapping.addPrimaryKey(changedObject.getType().getName() + ".ID"); + table = mapping.getTableByPropertyName(changedObject.getType().getName()); + } else { + throw new RuntimeException("Table " + changedObject.getType().getName() + " was changed in the DataGraph but is not present in the Config"); + } + } String updateStatement = table.getUpdate(); if ( updateStatement == null ) { updateCommand = getCudGenerator().getUpdateCommand(mapping, changedObject,table);