gt:                     if (returnInt == null) {
context: /**
   * Copyright (c) 2009--2016 Red Hat, Inc.
   *
   * This software is licensed to you under the GNU General Public License,
   * version 2 (GPLv2). There is NO WARRANTY for this software, express or
   * implied, including the implied warranties of MERCHANTABILITY or FITNESS
   * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
   * along with this software; if not, see
   * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
   *
   * Red Hat trademarks are not licensed under GPLv2. No permission is
   * granted to use or replicate Red Hat trademarks that are incorporated
   * in this software or its documentation.
   */
  package com.redhat.rhn.common.db.datasource;
  
  import com.redhat.rhn.common.ObjectCreateWrapperException;
  import com.redhat.rhn.common.RhnRuntimeException;
  import com.redhat.rhn.common.db.NamedPreparedStatement;
  import com.redhat.rhn.common.hibernate.HibernateFactory;
  import com.redhat.rhn.common.hibernate.HibernateHelper;
  import com.redhat.rhn.common.hibernate.HibernateRuntimeException;
  import com.redhat.rhn.common.translation.SqlExceptionTranslator;
  import com.redhat.rhn.common.util.MethodUtil;
  import com.redhat.rhn.common.util.StringUtil;
  
  import org.apache.log4j.Logger;
  import org.hibernate.HibernateException;
  import org.hibernate.Session;
  
  import java.io.Serializable;
  import java.lang.reflect.Method;
  import java.math.BigDecimal;
  import java.sql.CallableStatement;
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import java.sql.ResultSetMetaData;
  import java.sql.SQLException;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map;
  
  /**
   * A cached set of query/elaborator strings and the parameterMap hash maps.
   *
   * @version $Rev$
   */
  public class CachedStatement implements Serializable {
  
      /**
       * Comment for <code>serialVersionUID</code>
       */
      private static final long serialVersionUID = -6256397039512492616L;
  
      /**
       * Logger for this class
       */
      private static Logger log = Logger.getLogger(CachedStatement.class);
  
      /**
       * The size above which queries are split into multiple queries, each of
       * this size.
       */
      public static final int BATCH_SIZE = 500;
  
      /*
       * This is the original config for this query as specified in the mode query
       * xml file. It is intended to be immutable.
       */
      private ParsedQuery protoQuery;
  
      /*
       * This is the sql statement that will be executed. This query may get
       * modified up until the time it is executed. Just prior to execution, the
       * only remaining substitution to be made is the optional "in" clause list.
       * This "in" clause list is substituted in the execute() method in a local
       * variable and should never be stored in this variable.
       */
      private String sqlStatement;
  
      private String name;
  
      private Map<String, List<Integer>> qMap;
  
      private List<String> params;
  
      // This is only set if the current CachedStatement is a duplicate of an
      // existing one with the %s expanded out.
      private CachedStatement parentStatement;
      private RestartData restartData = null;
  
      // We could (and probably should) cache the ResultSet metadata here as
      // well. There is no reason that the first call to each statement
      // couldn't do the work to determine what is returned.
  
      /**
       * Create a CachedStatement for a query
       * @param parsedQuery This immutable query definition.
       */
      /* package */ CachedStatement(ParsedQuery parsedQuery) {
          this.protoQuery = parsedQuery;
          this.name = parsedQuery.getName();
          this.qMap = new HashMap<String, List<Integer>>();
          this.params = new ArrayList<String>(parsedQuery.getParameterList());
          this.sqlStatement = parsedQuery.getSqlStatement();
      }
  
      /**
       * Create a CachedStatement for a query, this one being an elaborator query.
       * This is only used in executeElaboratorBatch() call below
       * @param newName The name for this query.
       * @param parsedQuery This immutable query definition.
       * @param orig The parent query.
       */
      private CachedStatement(String newName, ParsedQuery parsedQuery, List<String> paramsIn,
              CachedStatement orig) {
          this(parsedQuery);
          parentStatement = orig;
          this.name = newName;
          this.params = paramsIn;
      }
  
      /**
       * Returns the arity of the statement
       * @return number of parameters
       */
      public int getArity() {
          return protoQuery.getParameterList() == null ? 0 :
                  protoQuery.getParameterList().size();
      }
  
      /**
       * Get the query's alias
       * @return the querys alias
       */
      public String getAlias() {
          return protoQuery.getAlias();
      }
  
      /**
       * Get the query's name
       * @return the querys name
       */
      public String getName() {
          return name;
      }
  
      /**
       * Get the query string
       * @return the query string
       */
      public String getQuery() {
          return sqlStatement;
      }
  
      /**
       * Get the original query string
       * @return the original query, before the named bind parameters were
       * removed.
       */
      public String getOrigQuery() {
          return protoQuery.getSqlStatement();
      }
  
      /**
       * Get the column used to relate driving queries and elaborators
       * @return column name.
       */
      public String getColumn() {
          return protoQuery.getElaboratorJoinColumn();
      }
  
      /**
       * Modify the sql statement by replacing the specified token with the
       * specified list of String values.
       * @param replaceToken The text in the sql statement to be replaced.
       * @param valueList The list of String values to be quoted and concatenated
       * together in a comma-separated list that replaces the replaceToken.
       * @param querySanitizer An optional sanitizer used to check each value.
       */
      public void modifyQuery(String replaceToken, List<String> valueList,
              QuerySanitizer querySanitizer) {
          if (replaceToken == null) {
              throw new IllegalArgumentException(
                      "Bad modify query call - replaceToken required.");
          }
          if (valueList == null || valueList.isEmpty()) {
              throw new IllegalArgumentException("Bad modify query call for token '" +
                      replaceToken +
                      "' - list of replacement values must contain at least one value.");
          }
          StringBuilder sb = new StringBuilder();
          boolean firstValue = true;
          for (String value : valueList) {
              if (!firstValue) {
                  sb.append(", ");
              }
              else {
                  firstValue = false;
              }
              if (querySanitizer != null && !querySanitizer.isSanitary(value)) {
                  throw new IllegalArgumentException(
                          "Attempt to modify query for token '" + replaceToken +
                                  "' with value that did not pass sanitary check.  Value: " +
                                  value);
              }
              sb.append("'").append(value).append("'");
          }
          this.modifyQuery(replaceToken, sb.toString());
      }
  
      private void modifyQuery(String replaceToken, String replacementString) {
          sqlStatement = sqlStatement.replace(replaceToken, replacementString);
      }
  
      int executeUpdate(Map<String, ?> parameters) {
          return executeUpdate(parameters, null);
      }
  
      int executeUpdate(Map<String, ?> parameters, List<?> inClause) {
          Integer res = (Integer) internalExecute(parameters, inClause, null);
          return res.intValue();
      }
  
      DataResult<Object> execute(Map<String, ?> parameters, Mode mode) {
          return (DataResult<Object>) internalExecute(parameters, null, mode);
      }
  
      DataResult<Object> execute(List<?> parameters, Mode mode) {
          return (DataResult<Object>) internalExecute(null, parameters, mode);
      }
  
      DataResult<Object> execute(Map<String, ?> parameters, List<?> inClause,
              Mode mode) {
          return (DataResult<Object>) internalExecute(parameters, inClause, mode);
      }
  
      private Object internalExecute(Map<String, ?> parameters, List<?> inClause,
              Mode mode) {
  
          storeForRestart(parameters, inClause, mode);
          this.sqlStatement = NamedPreparedStatement.replaceBindParams(sqlStatement, qMap);
  
          if (sqlStatement.indexOf("%s") > 0) {
              if (inClause == null || inClause.isEmpty()) {
                  return new DataResult<Object>(mode);
              }
              // one of these two items is the return value. Ugly, but...
              Integer returnInt = null;
              DataResult<Object> returnDataResult = null;
  
              int subStart = 0;
              while (subStart < inClause.size()) {
                  int subLength = subStart + BATCH_SIZE >= inClause.size() ?
                          inClause.size() - subStart : BATCH_SIZE;
  
                  List<?> subClause = inClause.subList(subStart, subStart + subLength);
                  String finalQuery =
                          sqlStatement.replaceAll("%s", commaSeparatedList(subClause));
                  Object resultObj = execute(finalQuery, qMap, parameters, mode, null);
                  subStart += subLength;
  
                  if (resultObj instanceof DataResult) {
                      if (returnDataResult == null) {
                          returnDataResult = (DataResult<Object>) resultObj;
                      }
                      else {
                          returnDataResult.addDataResult((DataResult<Object>) resultObj);
                      }
                  }
                  else {
  