/* * In need some cases, we need to transform the fecthing of a relation for overcoming the problem of traversing lazy relations * If we encounter an eager relation after traversing lazy relations, we transform the eager relation pretends to be a lazy one * so its columns are not traversed */ private Fetching getFetchingForRelationNode(RelationNode relationNode) { Fetching fetch = relationNode.getTableRelation().getFetching(); if (fetch.equals(Fetching.EAGER)) { TableNode parentTableNode = relationNode.getParentTable(); RelationNode parentRelNode = (RelationNode) parentTableNode.getParent(); if (parentRelNode == null) return fetch; if (startedALazySelect(parentRelNode)) return fetch; if (parentRelNode.getTableRelation().getFetching().equals(Fetching.LAZY)) { relationNode.setMarkedAsLazy(true); return Fetching.LAZY; } } return fetch; }
/* * Determines whether we reached the current relation node through a lazy relation in the past */ private boolean traversedLazyRelation(Fetching currFetching, RelationNode relationNode) { TableNode parentTableNode = relationNode.getParentTable(); RelationNode parentRelNode = (RelationNode) parentTableNode.getParent(); if (parentRelNode == null) // in case the parent table was the base table return false; boolean parentRelIsLazy = parentRelNode.getTableRelation().getFetching().equals(Fetching.LAZY); if (startedALazySelect(parentRelNode)) return false; boolean traversedLazyRel = parentRelIsLazy || parentRelNode.isMarkedAsLazy(); // Can not traverse an eager relation after traversing a Lazy one except in a lazy Select. return currFetching != null && currFetching.equals(Fetching.EAGER) && traversedLazyRel; }
/* * Implements the relational tree traversal */ public void visit(TableNode tableNode, boolean baseTable) { ctx.createTableContext(tableNode); if (baseTable) ctx.setBaseTable(tableNode.getTable()); if (baseTable) onVisitBaseTable(tableNode); else { onVisitRelatedTable(tableNode); } if (inRecursiveRelation(tableNode)) { ctx.setVisitedRecursion(tableNode.getTable()); if (ctx.isInLazyQuery()) ctx.setVisitedTable(tableNode.getTable(), tableNode); } // Add if (shouldStopVisiting(tableNode)) return; ctx.setVisitedTable(tableNode.getTable(), tableNode); for (RelationNode relationNode : tableNode.getChildren()) { if (eligibleForVisitation(relationNode, tableNode)) { // relationNode.setRelContextManager(ctx); //pass the context to the node Fetching relationFecthing = getFetchingForRelationNode(relationNode); if (fetching == null || fetching.equals(relationFecthing) || allowedForVisitation(relationNode)) { if (traversedLazyRelation( relationFecthing, relationNode)) // stop if we reached the tableNode by traversing a relation with lazy // fetching continue; for (TableNode childTableNode : relationNode.getChildren()) { visit(childTableNode, false); } onVisitedTableRelation(relationNode); } } } }