docs: protected Columns determineProjectedColumns( PlanNode optimizedPlan,
                                                   final ScanQueryContext context ) {
          final PlanHints hints = context.getHints();
  
          // Look for which columns to include in the results; this will be defined by the highest PROJECT node ...
          PlanNode project = optimizedPlan;
          if (project.getType() != Type.PROJECT) {
              project = optimizedPlan.findAtOrBelow(Traversal.LEVEL_ORDER, Type.PROJECT);
          }
          if (project != null) {
              List<Column> columns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class);
              List<String> columnTypes = project.getPropertyAsList(Property.PROJECT_COLUMN_TYPES, String.class);
              // Determine whether to include the full-text search scores in the results ...
              boolean includeFullTextSearchScores = hints.hasFullTextSearch;
              if (!includeFullTextSearchScores) {
                  for (PlanNode select : optimizedPlan.findAllAtOrBelow(Type.SELECT)) {
                      Constraint constraint = select.getProperty(Property.SELECT_CRITERIA, Constraint.class);
                      if (QueryUtil.includeFullTextScores(constraint)) {
                          includeFullTextSearchScores = true;
                          break;
                      }
                  }
              }
              // The projected columns may not include all of the selectors from the child of the PROJECT node.
              // So, we need to figure out the selector indexes based upon the ResultColumn for the child ...
              Columns childColumns = context.columnsFor(project.getFirstChild());
              return new ResultColumns(columns, columnTypes, includeFullTextSearchScores, childColumns);
          }
          // Look for a SOURCE ...
          if (optimizedPlan.getType() == Type.SOURCE) {
              PlanNode source = optimizedPlan;
              List<Schemata.Column> schemataColumns = source.getPropertyAsList(Property.SOURCE_COLUMNS, Schemata.Column.class);
              List<Column> columns = new ArrayList<>(schemataColumns.size());
              List<String> columnTypes = new ArrayList<>(schemataColumns.size());
              SelectorName selector = source.getSelectors().iterator().next();
              for (Schemata.Column schemataColumn : schemataColumns) {
                  Column column = new Column(selector, schemataColumn.getName(), schemataColumn.getName());
                  columns.add(column);
                  columnTypes.add(schemataColumn.getPropertyTypeName());
              }
              return new ResultColumns(columns, columnTypes, hints.hasFullTextSearch, null);
          }
          return ResultColumns.EMPTY;
      }