/** * Creates projection list for scan. If the projection contains expressions, then the input * references from those expressions are extracted and that list of references becomes the * projection list. * * @param origScan row scan underneath the project * @param projRel ProjectRel that we will be creating the projection for * @param projectedColumns returns a list of the projected column ordinals, if it is possible to * project * @param preserveExprCondition condition that identifies special expressions that should be * preserved in the projection * @param defaultExpr expression to be used in the projection if no fields or special columns are * selected * @param newProjList returns a new projection RelNode corresponding to a projection that now * references a rowscan that is projecting the input references that were extracted from the * original projection expressions; if the original expression didn't contain expressions, * then this list is returned empty * @return true if columns in projection list from the scan need to be renamed */ public boolean createProjectionList( FennelRel origScan, ProjectRel projRel, List<Integer> projectedColumns, PushProjector.ExprCondition preserveExprCondition, RexNode defaultExpr, List<ProjectRel> newProjList) { // REVIEW: what about AnonFields? int n = projRel.getChildExps().length; RelDataType rowType = origScan.getRowType(); RelDataType projType = projRel.getRowType(); RelDataTypeField[] projFields = projType.getFields(); List<Integer> tempProjList = new ArrayList<Integer>(); boolean needRename = false; for (int i = 0; i < n; ++i) { RexNode exp = projRel.getChildExps()[i]; List<String> origFieldName = new ArrayList<String>(); Integer projIndex = mapProjCol(exp, origFieldName, rowType); if (projIndex == null) { // there are expressions in the projection; we need to extract // all input references and any special expressions from the // projection PushProjector pushProject = new PushProjector(projRel, null, origScan, preserveExprCondition); ProjectRel newProject = pushProject.convertProject(defaultExpr); if (newProject == null) { // can't do any further projection return false; } newProjList.add(newProject); // using the input references we just extracted, it should now // be possible to create a projection for the row scan needRename = createProjectionList( origScan, (ProjectRel) newProject.getChild(), projectedColumns, preserveExprCondition, defaultExpr, newProjList); assert (projectedColumns.size() > 0); return needRename; } String projFieldName = projFields[i].getName(); if (!projFieldName.equals(origFieldName.get(0))) { needRename = true; } tempProjList.add(projIndex); } // now that we've determined it is possible to project, add the // ordinals to the return list projectedColumns.addAll(tempProjList); return needRename; }
/** * Creates new RelNodes replacing/removing the original project/row scan * * @param projectedScan new scan that is now projected * @param origProject original projection * @param needRename true if fields from the row scan need to be renamed * @param newProject projection that contains the new projection expressions, in the case where * the original projection cannot be removed because it projects expressions * @return new RelNode */ public RelNode createNewRelNode( RelNode projectedScan, ProjectRel origProject, boolean needRename, ProjectRel newProject) { RelNode scanRel; if (needRename) { // Replace calling convention with FENNEL_EXEC_CONVENTION RelTraitSet traits = RelOptUtil.clone(origProject.getTraits()); traits.setTrait(CallingConventionTraitDef.instance, FennelRel.FENNEL_EXEC_CONVENTION); if (!traits.equals(projectedScan.getTraits())) { RelNode mergedProjectedScan = convert(projectedScan, traits); RelOptPlanner planner = projectedScan.getCluster().getPlanner(); // register projectedScan == mergedProjectedScan // so mergedProjectedScan will have a set later on projectedScan = planner.ensureRegistered(mergedProjectedScan, projectedScan); } scanRel = new FennelRenameRel( origProject.getCluster(), projectedScan, RelOptUtil.getFieldNames(origProject.getRowType()), traits); } else { scanRel = projectedScan; } if (newProject == null) { return scanRel; } else { // in the case where the projection had expressions, put the // new, modified projection on top of the projected row scan return (ProjectRel) CalcRel.createProject( scanRel, newProject.getProjectExps(), RelOptUtil.getFieldNames(newProject.getRowType())); } }