diff --git a/src/helma/objectmodel/db/Node.java b/src/helma/objectmodel/db/Node.java index c0264b55..8b82d67f 100644 --- a/src/helma/objectmodel/db/Node.java +++ b/src/helma/objectmodel/db/Node.java @@ -746,6 +746,25 @@ public class Node implements INode, Serializable { return retval; } + public Node getGroupbySubnode (String sid, Relation rel) { + loadNodes (); + if (subnodes.contains (sid)) { + Node node = new Node (this, sid, nmgr, null); + DbMapping dbm = new DbMapping (); + dbm.setSubnodeMapping (rel.other); + dbm.setSubnodeRelation (rel.getGroupbySubnodeRelation()); + dbm.setPropertyMapping (rel.other); + dbm.setPropertyRelation (rel.getGroupbyPropertyRelation()); + node.setDbMapping (dbm); + String snrel = "WHERE "+rel.groupby +"='"+sid+"'"; + if (dbm.getSubnodeRelation().direction == Relation.BACKWARD) + snrel += " AND "+dbm.getSubnodeRelation().remoteField+"='"+getNonVirtualHomeID()+"'"; + node.setSubnodeRelation (snrel); + return node; + } + return null; + } + public boolean remove () { checkWriteLock (); if (anonymous) @@ -1639,5 +1658,22 @@ public class Node implements INode, Serializable { return cacheNode; } + // walk down node path to the first non-virtual node and return its id. + // limit max depth to 3, since there shouldn't be more then 2 layers of virtual nodes. + public String getNonVirtualHomeID () { + INode node = this; + for (int i=0; i<3; i++) { + if (node == null) break; + if (node.getState() != Node.VIRTUAL) + return node.getID (); + node = node.getParent (); + } + return null; + } + + public void dumpSubnodes () { + System.err.println (subnodes); + } + } diff --git a/src/helma/objectmodel/db/NodeManager.java b/src/helma/objectmodel/db/NodeManager.java index 55e6de60..74fbf42a 100644 --- a/src/helma/objectmodel/db/NodeManager.java +++ b/src/helma/objectmodel/db/NodeManager.java @@ -135,6 +135,7 @@ public final class NodeManager { return null; Key key = Key.makeKey (dbmap, kstr); + Transactor tx = (Transactor) Thread.currentThread (); // tx.timer.beginEvent ("getNode "+kstr); @@ -497,7 +498,7 @@ public final class NodeManager { } else { String q = "SELECT "+idfield+" FROM "+table; if (subrel.direction == Relation.BACKWARD) { - String homeid = home.getState() == Node.VIRTUAL ? home.parentID : home.getID (); + String homeid = home.getNonVirtualHomeID (); // home.getState() == Node.VIRTUAL ? home.parentID : home.getID (); q += " WHERE "+subrel.remoteField+" = '"+homeid+"'"; } // set order, if specified and if not using subnode's relation @@ -678,6 +679,7 @@ public final class NodeManager { } private Node getNodeByRelation (DbWrapper db, DbTxn txn, Node home, String kstr, Relation rel) throws Exception { + Node node = null; if (rel != null && rel.virtual && home.getState() != INode.VIRTUAL) { Key k = home.getKey ().getVirtualKey (kstr); @@ -687,6 +689,7 @@ public final class NodeManager { node.setString ("prototype", rel.prototype); return node; } + // if subnodes are stored in embedded db we have to actually assign it the virtual node, // otherwise it and its subnodes will be lost across restarts. if (rel.other == null || (!rel.other.isRelational() && !home.getDbMapping().isRelational())) { @@ -707,14 +710,9 @@ public final class NodeManager { dbm.setPropertyRelation (rel.getVirtualPropertyRelation()); node.setDbMapping (dbm); } + } else if (rel != null && rel.groupby != null) { - node = new Node (home, kstr, safe, rel.prototype); - DbMapping dbm = new DbMapping (); - dbm.setSubnodeMapping (rel.other); - dbm.setSubnodeRelation (rel.getGroupbySubnodeRelation()); - dbm.setPropertyMapping (rel.other); - dbm.setPropertyRelation (rel.getGroupbyPropertyRelation()); - node.setDbMapping (dbm); + return home.getGroupbySubnode (kstr, rel); } else if (rel == null || rel.other == null || !rel.other.isRelational ()) { node = db.getNode (txn, kstr); node.nmgr = safe; @@ -805,6 +803,7 @@ public final class NodeManager { return sbuf.toString (); } + }