docs: private int determineIndexOrdering(StmtTableScan tableScan,
              int keyComponentCount,
              List<AbstractExpression> indexedExprs,
              List<ColumnRef> indexedColRefs,
              AccessPath retval,
              int[] orderSpoilers,
              List<AbstractExpression> bindingsForOrder)
      {
          // Organize a little bit.
          ParsedSelectStmt pss = (m_parsedStmt instanceof ParsedSelectStmt)
                                    ? ((ParsedSelectStmt)m_parsedStmt)
                                    : null;
          boolean hasOrderBy = ( m_parsedStmt.hasOrderByColumns()
                                    && ( ! m_parsedStmt.orderByColumns().isEmpty() ) );
          boolean hasWindowFunctions = (pss != null && pss.hasWindowFunctionExpression());
          //
          // If we have no statement level order by or window functions,
          // then we can't use this index for ordering, and we
          // return 0.
          //
          if (! hasOrderBy && ! hasWindowFunctions) {
              return 0;
          }
          //
          // We make a definition.  Let S1 and S2 be sequences of expressions,
          // and OS be an increasing sequence of indices into S2.  Let erase(S2, OS) be
          // the sequence of expressions which results from erasing all S2
          // expressions whose indices are in OS.  We say *S1 is a prefix of
          // S2 with OS-singular values* if S1 is a prefix of erase(S2, OS).
          // That is to say, if we erase the expressions in S2 whose indices are
          // in OS, S1 is a prefix of the result.
          //
          // What expressions must we match?
          //   1.) We have the parameters indexedExpressions and indexedColRefs.
          //       These are the expressions or column references in an index.
          //       Exactly one of them is non-null.  Since these are both an
          //       indexed sequence of expression-like things, denote the
          //       non-null one IS.
          // What expressions do we care about?  We have two kinds.
          //   1.) The expressions from the statement level order by clause, OO.
          //       This sequence of expressions must be a prefix of IS with OS
          //       singular values for some sequence OS.  The sequence OS will be
          //       called the order spoilers.  Later on we will test that the
          //       index expressions at the positions in OS can have only a
          //       single value.
          //   2.) The expressions in a window function's partition by list, WP,
          //       followed by the expressions in the window function's
          //       order by list, WO.  The partition by functions are a set not
          //       a sequence.  We need to find a sequence of expressions, S,
          //       such that S is a permutation of P and S+WO is a singular prefix
          //       of IS.
          //
          // So, in both cases, statement level order by and window function, we are looking for
          // a sequence of expressions, S1, and a list of IS indices, OS, such
          // that S1 is a prefix of IS with OS-singular values.
          //
          // If the statement level order by expression list is not a prefix of
          // the index, we still care to know about window functions.  The reverse
          // is not true.  If there are window functions but they all fail to match the index,
          // we must give up on this index, even if the statement level order
          // by list is still matching.  This is because the window functions will
          // require sorting before the statement level order by clause's
          // sort, and this window function sort will invalidate the statement level
          // order by sort.
          //
          // Note also that it's possible that the statement level order by and
          // the window function order by are compatible.  So this index may provide
          // all the sorting needed.
          //
          // There need to be enough indexed expressions to provide full sort coverage.
          // More indexed expressions are ok.
          //
          // We keep a scoreboard which keeps track of everything.  All the window
          // functions and statement level order by functions are kept in the scoreboard.
          //
          WindowFunctionScoreboard windowFunctionScores = new WindowFunctionScoreboard(m_parsedStmt, tableScan);
          // indexCtr is an index into the index expressions or columns.
          for (int indexCtr = 0; !windowFunctionScores.isDone() && indexCtr < keyComponentCount; indexCtr += 1) {
              // Figure out what to do with index expression or column at indexCtr.
              // First, fetch it out.
              AbstractExpression indexExpr = (indexedExprs == null) ? null : indexedExprs.get(indexCtr);
              ColumnRef indexColRef = (indexedColRefs == null) ? null : indexedColRefs.get(indexCtr);
              // Then see if it matches something.  If
              // this doesn't match one thing it may match
              // another.  If it doesn't match anything, it may
              // be an order spoiler, which we will maintain in
              // the scoreboard.
              windowFunctionScores.matchIndexEntry(new ExpressionOrColumn(indexCtr,
                                                                          tableScan,
                                                                          indexExpr,
                                                                          SortDirectionType.INVALID,
                                                                          indexColRef));
          }
          //
          // The result is the number of order spoilers, but
          // also the access path we have chosen, the order
          // spoilers themselves and the bindings.  Return these
          // by reference.
          //
          return windowFunctionScores.getResult(retval, orderSpoilers, bindingsForOrder);
      }