code: private boolean needProjectionNode (AbstractPlanNode root) {
          if (!root.planNodeClassNeedsProjectionNode()) {
              return false;
          }
          // If there is a complexGroupby at his point, it means that
          // display columns contain all the order by columns and
          // does not require another projection node on top of sort node.
  
          // If there is a complex aggregation case, the projection plan node is already added
          // right above the group by plan node. In future, we may inline that projection node.
          if (m_parsedSelect.hasComplexGroupby() || m_parsedSelect.hasComplexAgg()) {
              return false;
          }
  
          if (root instanceof AbstractReceivePlanNode &&
                  m_parsedSelect.hasPartitionColumnInGroupby()) {
              // Top aggregate has been removed, its schema is exactly the same to
              // its local aggregate node.
              return false;
          }
  
          return true;
      }
docs: Return true if the plan referenced by root node needs a
  projection node appended to the top.
  
  This method does a lot of "if this node is an
  instance of this class.... else if this node is an
  instance of this other class..."   Perhaps it could be replaced
  by a virtual method on AbstractPlanNode?
  
  @param root   The root node of a plan
  @return true if a project node is required