assert(joinNode != null);
// Clone the original
JoinNode clonedTree = (JoinNode) joinNode.clone();
// Split join tree into a set of subtrees. The join type for all nodes in a subtree is the same
List<JoinNode> subTrees = clonedTree.extractSubTrees();
assert(!subTrees.isEmpty());
// Generate possible join orders for each sub-tree separately
ArrayList<ArrayList<JoinNode>> joinOrderList = generateJoinOrders(subTrees);
// Reassemble the all possible combinations of the sub-tree and queue them
ArrayDeque<JoinNode> joinOrders = new ArrayDeque<JoinNode>();