protected PlanNode attachProject( QueryContext context,
                                      PlanNode plan,
                                      List<? extends Column> columns,
                                      Map<SelectorName, Table> selectors ) {
        PlanNode projectNode = new PlanNode(Type.PROJECT);

        List<Column> newColumns = new LinkedList<Column>();
        List<String> newTypes = new ArrayList<String>();
        final boolean multipleSelectors = selectors.size() > 1;
        final boolean qualifyExpandedColumns = context.getHints().qualifyExpandedColumnNames;
        if (columns == null || columns.isEmpty()) {
            // SELECT *, so find all of the columns that are available from all the sources ...
            for (Map.Entry<SelectorName, Table> entry : selectors.entrySet()) {
                SelectorName tableName = entry.getKey();
                Table table = entry.getValue();
                // Add the selector that is being used ...
                projectNode.addSelector(tableName);
                // Compute the columns from this selector ...
                allColumnsFor(table, tableName, newColumns, newTypes, qualifyExpandedColumns);
            }
        } else {
            // Add the selector used by each column ...
            for (Column column : columns) {
                SelectorName tableName = column.selectorName();
                // Add the selector that is being used ...
                projectNode.addSelector(tableName);

                // Verify that each column is available in the appropriate source ...
                Table table = selectors.get(tableName);
                if (table == null) {
                    context.getProblems().addError(GraphI18n.tableDoesNotExist, tableName);
                } else {
                    // Make sure that the column is in the table ...
                    String columnName = column.getPropertyName();
                    if ("*".equals(columnName) || columnName == null) {
                        // This is a 'SELECT *' on this source, but this source is one of multiple sources ...
                        // See https://issues.apache.org/jira/browse/JCR-3313; TCK test expects 'true' for last param
                        allColumnsFor(table, tableName, newColumns, newTypes, qualifyExpandedColumns);
                    } else {
                        // This is a particular column, so add it ...
                        if (!newColumns.contains(column)) {
                            if (multipleSelectors && column.getPropertyName().equals(column.getColumnName())) {
                                column = column.withColumnName(column.getSelectorName() + "." + column.getColumnName());
                            }
                            newColumns.add(column);
                            org.modeshape.jcr.query.validate.Schemata.Column schemaColumn = table.getColumn(columnName);
                            if (schemaColumn != null) {
                                newTypes.add(schemaColumn.getPropertyTypeName());
                            } else {
                                newTypes.add(context.getTypeSystem().getDefaultType());
                            }
                        }
                    }
                    boolean validateColumnExistance = context.getHints().validateColumnExistance && !table.hasExtraColumns();
                    boolean columnNameIsWildcard = columnName == null || "*".equals(columnName);
                    if (!columnNameIsWildcard && table.getColumn(columnName) == null && validateColumnExistance) {
                        context.getProblems().addError(GraphI18n.columnDoesNotExistOnTable, columnName, tableName);
                    }
                }
            }
        }
        projectNode.setProperty(Property.PROJECT_COLUMNS, newColumns);
        projectNode.setProperty(Property.PROJECT_COLUMN_TYPES, newTypes);
        projectNode.addLastChild(plan);
        return projectNode;
    }
protected PlanNode attachProject ( QueryContext context , PlanNode plan , List < ? extends Column > columns , Map < SelectorName , Table > selectors ) { PlanNode projectNode = new PlanNode ( Type . PROJECT ) ; List < Column > newColumns = new LinkedList < Column > ( ) ; List < String > newTypes = new ArrayList < String > ( ) ; final boolean multipleSelectors = selectors . size ( ) > 1 ; final boolean qualifyExpandedColumns = context . getHints ( ) . qualifyExpandedColumnNames ; if ( columns == null || columns . isEmpty ( ) ) { for ( Map . Entry < SelectorName , Table > entry : selectors . entrySet ( ) ) { SelectorName tableName = entry . getKey ( ) ; Table table = entry . getValue ( ) ; projectNode . addSelector ( tableName ) ; allColumnsFor ( table , tableName , newColumns , newTypes , qualifyExpandedColumns ) ; } } else { for ( Column column : columns ) { SelectorName tableName = column . selectorName ( ) ; projectNode . addSelector ( tableName ) ; Table table = selectors . get ( tableName ) ; if ( table == null ) { context . getProblems ( ) . addError ( GraphI18n . tableDoesNotExist , tableName ) ; } else { String columnName = column . getPropertyName ( ) ; if ( "*" . equals ( columnName ) || columnName == null ) { allColumnsFor ( table , tableName , newColumns , newTypes , qualifyExpandedColumns ) ; } else { if ( ! newColumns . contains ( column ) ) { if ( multipleSelectors && column . getPropertyName ( ) . equals ( column . getColumnName ( ) ) ) { column = column . withColumnName ( column . getSelectorName ( ) + "." + column . getColumnName ( ) ) ; } newColumns . add ( column ) ; org . modeshape . jcr . query . validate . Schemata . Column schemaColumn = table . getColumn ( columnName ) ; if ( schemaColumn != null ) { newTypes . add ( schemaColumn . getPropertyTypeName ( ) ) ; } else { newTypes . add ( context . getTypeSystem ( ) . getDefaultType ( ) ) ; } } } boolean validateColumnExistance = context . getHints ( ) . validateColumnExistance && ! table . hasExtraColumns ( ) ; boolean columnNameIsWildcard = columnName == null || "*" . equals ( columnName ) ; if ( ! columnNameIsWildcard && table . getColumn ( columnName ) == null && validateColumnExistance ) { context . getProblems ( ) . addError ( GraphI18n . columnDoesNotExistOnTable , columnName , tableName ) ; } } } } projectNode . setProperty ( Property . PROJECT_COLUMNS , newColumns ) ; projectNode . setProperty ( Property . PROJECT_COLUMN_TYPES , newTypes ) ; projectNode . addLastChild ( plan ) ; return projectNode ; }
Attach a PROJECT node at the top of the plan tree.

@param context the context in which the query is being planned
@param plan the existing plan
@param columns the columns being projected; may be null
@param selectors the selectors keyed by their alias or name
@return the updated plan