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 ; }
Attach a PROJECT node at the top of the plan tree .