gt:                 for (int j = 0; j < leftOperandList.size(); j++) {
context: /*
   * This file is part of Splice Machine.
   * Splice Machine is free software: you can redistribute it and/or modify it under the terms of the
   * GNU Affero General Public License as published by the Free Software Foundation, either
   * version 3, or (at your option) any later version.
   * Splice Machine is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
   * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   * See the GNU Affero General Public License for more details.
   * You should have received a copy of the GNU Affero General Public License along with Splice Machine.
   * If not, see <http://www.gnu.org/licenses/>.
   *
   * Some parts of this source code are based on Apache Derby, and the following notices apply to
   * Apache Derby:
   *
   * Apache Derby is a subproject of the Apache DB project, and is licensed under
   * the Apache License, Version 2.0 (the "License"); you may not use these files
   * except in compliance with the License. You may obtain a copy of the License at:
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software distributed
   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
   * specific language governing permissions and limitations under the License.
   *
   * Splice Machine, Inc. has modified the Apache Derby code in this file.
   *
   * All such Splice Machine modifications are Copyright 2012 - 2020 Splice Machine, Inc.,
   * and are licensed to you under the GNU Affero General Public License.
   */
  
  package com.splicemachine.db.impl.sql.compile;
  
  import com.splicemachine.db.iapi.error.StandardException;
  import com.splicemachine.db.iapi.reference.ClassName;
  import com.splicemachine.db.iapi.reference.SQLState;
  import com.splicemachine.db.iapi.services.classfile.VMOpcode;
  import com.splicemachine.db.iapi.services.compiler.LocalField;
  import com.splicemachine.db.iapi.services.compiler.MethodBuilder;
  import com.splicemachine.db.iapi.services.loader.ClassFactory;
  import com.splicemachine.db.iapi.services.sanity.SanityManager;
  import com.splicemachine.db.iapi.sql.compile.C_NodeTypes;
  import com.splicemachine.db.iapi.sql.compile.NodeFactory;
  import com.splicemachine.db.iapi.sql.compile.Optimizable;
  import com.splicemachine.db.iapi.types.*;
  
  import java.lang.reflect.Modifier;
  import java.sql.Types;
  import java.util.ArrayList;
  import java.util.Objects;
  
  /**
   * An InListOperatorNode represents an IN list.
   *
   */
  
  public final class InListOperatorNode extends BinaryListOperatorNode
  {
      private boolean isOrdered;
      private boolean sortDescending;
  
      /**
       * Initializer for a InListOperatorNode
       *
       * @param leftOperand        The left operand of the node
       * @param rightOperandList    The right operand list of the node
       */
  
      public void init(Object leftOperand, Object rightOperandList) throws StandardException
      {
          init(leftOperand, rightOperandList, "IN", "in");
      }
  
      /**
       * Convert this object to a String.  See comments in QueryTreeNode.java
       * for how this should be done for tree printing.
       *
       * @return    This object as a String
       */
  
      public String toString()
      {
          if (SanityManager.DEBUG)
          {
              return "isOrdered: " + isOrdered + "\n" +
                  super.toString();
          }
          else
          {
              return "";
          }
      }
  
      /**
       * Create a shallow copy of this InListOperatorNode whose operands are
       * the same as this node's operands.  Copy over all other necessary
       * state, as well.
       */
      protected InListOperatorNode shallowCopy() throws StandardException
      {
          InListOperatorNode ilon =
               (InListOperatorNode)getNodeFactory().getNode(
                  C_NodeTypes.IN_LIST_OPERATOR_NODE,
                  leftOperandList,
                  rightOperandList,
                  getContextManager());
  
          ilon.copyFields(this);
          ilon.markAsOrdered(isOrdered);
  
          if (sortDescending)
              ilon.markSortDescending();
  
          return ilon;
      }
  
      /**
       * Preprocess an expression tree.  We do a number of transformations
       * here (including subqueries, IN lists, LIKE and BETWEEN) plus
       * subquery flattening.
       * NOTE: This is done before the outer ResultSetNode is preprocessed.
       *
       * @param    numTables            Number of tables in the DML Statement
       * @param    outerFromList        FromList from outer query block
       * @param    outerSubqueryList    SubqueryList from outer query block
       * @param    outerPredicateList    PredicateList from outer query block
       *
       * @return        The modified expression
       *
       * @exception StandardException        Thrown on error
       */
      public ValueNode preprocess(int numTables,
                                  FromList outerFromList,
                                  SubqueryList outerSubqueryList,
                                  PredicateList outerPredicateList)
                      throws StandardException {
          super.preprocess(numTables,
              outerFromList, outerSubqueryList,
              outerPredicateList);
          
          return convertToAndedEqualityProbePredicate();
      }
      
      public ValueNode convertToAndedEqualityProbePredicate()
                      throws StandardException
      {
          /* Check for the degenerate case of a single element in the IN list.
           * If found, then convert to "=".
           */
          if (rightOperandList.size() == 1 && singleLeftOperand)
          {
              ValueNode value = (ValueNode)rightOperandList.elementAt(0);
              if ((value instanceof CharConstantNode) && (getLeftOperand() instanceof ColumnReference)) {
                  DataTypeDescriptor targetType = getLeftOperand().getTypeServices();
                  if (targetType.getTypeName().equals(TypeId.CHAR_NAME)) {
                      int maxSize = getLeftOperand().getTypeServices().getMaximumWidth();
                      ValueNodeList.rightPadCharConstantNode((CharConstantNode) value, maxSize);
                  }
              }
              BinaryComparisonOperatorNode equal =
                  (BinaryComparisonOperatorNode) getNodeFactory().getNode(
                          C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,
                          getLeftOperand(),
                          value,
                          getContextManager());
              /* Set type info for the operator node */
              equal.bindComparisonOperator();
              equal.setOuterJoinLevel(getOuterJoinLevel());
              return equal;
          }
          else if (allLeftOperandsContainColumnReferences() &&
                   rightOperandList.containsOnlyConstantAndParamNodes())
          {
              boolean DB2CompatibilityMode = getCompilerContext().getVarcharDB2CompatibilityMode();
  
              /* At this point we have an IN-list made up of constant and/or
               * parameter values.  Ex.:
               *
               *  select id, name from emp where id in (34, 28, ?)
               * or
               *  select id, name from emp where id + 3 in (34, 28, ?)
               *
               * Since the optimizer does not recognize InListOperatorNodes
               * as potential start/stop keys for indexes, it (the optimizer)
               * may estimate that the cost of using any of the indexes would
               * be too high.  So we could--and probably would--end up doing
               * a table scan on the underlying base table. But if the number
               * of rows in the base table is significantly greater than the
               * number of values in the IN-list, scanning the base table can
               * be overkill and can lead to poor performance.  And further,
               * choosing to use an index but then scanning the entire index
               * can be slow, too. DERBY-47.
               *
               * What we do, then, is create an "IN-list probe predicate",
               * which is an internally generated equality predicate with a
               * parameter value on the right.  So for the queries shown above
               * the probe predicates would be "id = ?" and "id+3 = ?".  We then replace
               * this InListOperatorNode with the probe predicate during
               * optimization.  The optimizer in turn recognizes the probe
               * predicate, which is disguised to look like a typical binary
               * equality, as a potential start/stop key for any indexes.
               * This start/stop key potential then factors into the estimated
               * cost of probing the indexes, which leads to a more reasonable
               * estimate and thus makes it more likely that the optimizer
               * will choose to use an index vs a table scan.  That done, we
               * then use the probe predicate to perform multiple execution-
               * time "probes" on the index--instead of doing a range index
               * scan--which eliminates unnecessary scanning. For more see
               * execute/MultiProbeTableScanResultSet.java.
               *
               * With this approach we know that regardless of how large the
               * base table is, we'll only have to probe the index a max of
               * N times, where "N" is the size of the IN-list. If N is
               * significantly less than the number of rows in the table, or
               * is significantly less than the number of rows between the
               * min value and the max value in the IN-list, this selective
               * probing can save us a lot of time.
               *
               * Note: We will do fewer than N probes if there are duplicates
               * in the list.
               *
               * Note also that, depending on the relative size of the IN-list
               * verses the number of rows in the table, it may actually be
               * better to just do a table scan--especially if there are fewer
               * rows in the table than there are in the IN-list.  So even though
               * we create a "probe predicate" and pass it to the optimizer, it
               * (the optimizer) may still choose to do a table scan.  If that
               * happens then we'll "revert" the probe predicate back to its
               * original form (i.e. to this InListOperatorNode) during code
               * generation, and then we'll use it as a regular IN-list
               * restriction when it comes time to execute.
               */
  
              boolean allConstants = rightOperandList.containsAllConstantNodes();
  
              /* If we have all constants then sort them now.  This allows us to
               * skip the sort at execution time (we have to sort them so that
               * we can eliminate duplicate IN-list values).  If we have one
               * or more parameter nodes then we do *not* sort the values here
               * because we do not (and cannot) know what values the parameter(s)
               * will have.  In that case we'll sort the values at execution
               * time.
               */
              // Disable sorting of multicolumn IN lists here for now.
              // These will typically long lists, and using bubble sort
              // is not good.  The probe values will end up getting
              // sorted, and duplicates removed, at execution time.
              if (allConstants && leftOperandList.size() == 1) {
                  /* When sorting or choosing min/max in the list, if types
                   * are not an exact match then we have to use the *dominant*
                   * type across all values, where "all values" includes the
                   * left operand.  Otherwise we can end up with incorrect
                   * results.
                   *
                   * Note that it is *not* enough to just use the left operand's
                   * type as the judge because we have no guarantee that the
                   * left operand has the dominant type.  If, for example, the
                   * left operand has type INTEGER and all (or any) values in
                   * the IN list have type DECIMAL, use of the left op's type
                   * would lead to comparisons with truncated values and could
                   * therefore lead to an incorrect sort order. DERBY-2256.
                   */
                  ArrayList targetTypes = new ArrayList<DataTypeDescriptor>();
                  
  