docs: 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;
      }