code: @Override
  	public Plan createPlan(QueryData data, Transaction tx) {
  		// Step 1: Create a plan for each mentioned table or view
  		List<Plan> plans = new ArrayList<Plan>();
  		for (String tblname : data.tables()) {
  			String viewdef = VanillaDb.catalogMgr().getViewDef(tblname, tx);
  			if (viewdef != null)
  				plans.add(VanillaDb.newPlanner().createQueryPlan(viewdef, tx));
  			else
  				plans.add(new TablePlan(tblname, tx));
  		}
  		// Step 2: Create the product of all table plans
  		Plan p = plans.remove(0);
  		for (Plan nextplan : plans)
  			p = new ProductPlan(p, nextplan);
  		// Step 3: Add a selection plan for the predicate
  		p = new SelectPlan(p, data.pred());
  		// Step 4: Add a group-by plan if specified
  		if (data.groupFields() != null) {
  			p = new GroupByPlan(p, data.groupFields(), data.aggregationFn(), tx);
  		}
  		// Step 5: Project onto the specified fields
  		p = new ProjectPlan(p, data.projectFields());
  		// Step 6: Add a sort plan if specified
  		if (data.sortFields() != null)
  			p = new SortPlan(p, data.sortFields(), data.sortDirections(), tx);
  		// Step 7: Add a explain plan if the query is explain statement
  		if (data.isExplain())
  			p = new ExplainPlan(p);
  		return p;
  	}
docs: Creates a query plan as follows. It first takes the product of all tables
  and views; it then selects on the predicate; and finally it projects on
  the field list.