if (rel.order != null) q.append (" ORDER BY "+rel.order);
if (rel.order != null) { q.append (" ORDER BY "); q.append (rel.order); }
    public void prefetchNodes (Node home, Relation rel, Key[] keys) throws Exception {	DbMapping dbm = rel.otherType;	if (dbm == null || !dbm.isRelational ()) {	    // this does nothing for objects in the embedded database	    return;	} else {	    int missing = cache.containsKeys (keys);	    if (missing > 0) {	        Connection con = dbm.getConnection ();	        Statement stmt = con.createStatement ();	        String[] columns = dbm.getColumns ();	        StringBuffer q = dbm.getSelect ();	        try {	            String idfield = rel.groupby != null ? rel.groupby : dbm.getIDField ();	            boolean needsQuotes = dbm.needsQuotes (idfield);	            q.append ("WHERE ");	            q.append (idfield);	            q.append (" IN (");	            boolean first = true;	            for (int i=0; i<keys.length; i++) {	                if (keys[i] != null) {	                    if (!first)	                        q.append (',');	                    else	                        first = false;	                    if (needsQuotes) {	                        q.append ("'");	                        q.append (escape (keys[i].getID ()));	                        q.append ("'");	                    } else {	                        q.append (keys[i].getID ());	                    }	                }	            }	            q.append (") ");	            if (rel.groupby != null) {	                q.append (rel.renderConstraints (home, home.getNonVirtualParent ()));	                if (rel.order != null)	                    q.append (" ORDER BY "+rel.order);	            }	            if (logSql)	               app.logEvent ("### prefetchNodes: "+q.toString());	            ResultSet rs = stmt.executeQuery (q.toString());;	            String groupbyProp = null;	            HashMap groupbySubnodes = null;	            if (rel.groupby != null) {	                groupbyProp = dbm.columnNameToProperty (rel.groupby);	                groupbySubnodes = new HashMap();	            }	            String accessProp = null;	            if (rel.accessor != null && !rel.usesPrimaryKey ())	                accessProp = dbm.columnNameToProperty (rel.accessor);	            while (rs.next ()) {	                // create new Nodes.	                Node node = new Node (dbm, rs, columns, safe);	                Key primKey = node.getKey ();	                // for grouped nodes, collect subnode lists for the intermediary	                // group nodes.	                String groupName = null;	                if (groupbyProp != null) {	                    groupName = node.getString (groupbyProp);	                    List sn = (List) groupbySubnodes.get (groupName);	                    if (sn == null) {	                        sn = new ExternalizableVector ();	                        groupbySubnodes.put (groupName, sn);	                    }	                    sn.add (new NodeHandle (primKey));	                }	                // if relation doesn't use primary key as accessor, get accessor value	                String accessName = null;	                if (accessProp != null) {	                    accessName = node.getString (accessProp);	                }	                // register new nodes with the cache. If an up-to-date copy	                // existed in the cache, use that.	                synchronized (cache) {	                    Node oldnode = (Node) cache.put (primKey, node);	                    if (oldnode != null && oldnode.getState() != INode.INVALID) {	                        // found an ok version in the cache, use it.	                        cache.put (primKey, oldnode);	                    } else if (accessName != null) {	                        // put the node into cache with its secondary key	                        if (groupName != null)	                            cache.put (new SyntheticKey (new SyntheticKey (home.getKey(), groupName), accessName), node);	                        else	                            cache.put (new SyntheticKey (home.getKey(), accessName), node);	                    }	                }	            }	            // If these are grouped nodes, build the intermediary group nodes	            // with the subnod lists we created	            if (groupbyProp != null) {	                for (Iterator i=groupbySubnodes.keySet().iterator(); i.hasNext(); ) {	                    String groupname = (String) i.next();	                    if (groupname == null) continue;	                    Node groupnode = home.getGroupbySubnode (groupname, true);	                    cache.put (groupnode.getKey(), groupnode);	                    groupnode.setSubnodes ((List) groupbySubnodes.get(groupname));	                    groupnode.lastSubnodeFetch = System.currentTimeMillis ();	                }	            }	        } finally {	            if (stmt != null)  try {	                stmt.close ();	            } catch (Exception ignore) {}	        }	    }	}    }