docs: protected ArrayList<String> reflect() {
          Map<String, SQLStmt> stmtMap = new HashMap<>();
  
          // fill in the sql for single statement procs
          if (m_catProc.getHasjava() == false) {
              try {
                  for (int i = 0; i < m_catProc.getStatements().size(); i++) {
                      Statement statement = m_catProc.getStatements().get(VoltDB.ANON_STMT_NAME + String.valueOf(i));
                      String s = statement.getSqltext();
                      SQLStmt stmt = new SQLStmt(s);
  
                      QueuedSQL singleStmt = new QueuedSQL();
                      singleStmt.stmt = stmt;
                      m_sqlStmts.add(singleStmt);
                      stmtMap.put(VoltDB.ANON_STMT_NAME + String.valueOf(i), stmt);
  
                      int numParams = m_catProc.getParameters().size();
                      m_paramTypes = new Class<?>[numParams];
  
                      for (ProcParameter param : m_catProc.getParameters()) {
                          VoltType type = VoltType.get((byte) param.getType());
                          if (param.getIsarray()) {
                              m_paramTypes[param.getIndex()] = type.vectorClassFromType();
                              continue;
                          }
                          // Paul doesn't understand why single-statement procedures
                          // need to have their input parameter types widened here.
                          // Is it not better to catch too-wide values in the ProcedureRunner
                          // (ParameterConverter.tryToMakeCompatible) before falling through to the EE?
                          if (type == VoltType.INTEGER) {
                              type = VoltType.BIGINT;
                          } else if (type == VoltType.SMALLINT) {
                              type = VoltType.BIGINT;
                          } else if (type == VoltType.TINYINT) {
                              type = VoltType.BIGINT;
                          } else if (type == VoltType.NUMERIC) {
                              type = VoltType.FLOAT;
                          }
  
                          m_paramTypes[param.getIndex()] = type.classFromType();
                      }
                  }
              } catch (Exception e) {
                  // shouldn't throw anything outside of the compiler
                  e.printStackTrace();
              }
          } else {
              // this is where, in the case of java procedures, m_procMethod is set
              for (final Method m : m_procedure.getClass().getDeclaredMethods()) {
                  String name = m.getName();
                  if (name.equals("run")) {
                      if (Modifier.isPublic(m.getModifiers()) == false) {
                          continue;
                      }
                      m_procMethod = m;
                      m_paramTypes = m.getParameterTypes();
                      break;
                  }
              }
  
              if (m_procMethod == null) {
                  throw new RuntimeException("No \"run\" method found in: " + m_procedure.getClass().getName());
              }
              // iterate through the fields and deal with sql statements
              try {
                  stmtMap = ProcedureCompiler.getValidSQLStmts(null, m_procedureName, m_procedure.getClass(), m_procedure,
                          true);
              } catch (Exception e) {
                  // shouldn't happen here because it passed the compiler
                  VoltDB.crashLocalVoltDB("getValidSQLStmts threw exception during ProcedureRunner loading", true, e);
              }
          }
  
          ArrayList<String> stmtNames = new ArrayList<String>(stmtMap.entrySet().size());
          for (final Entry<String, SQLStmt> entry : stmtMap.entrySet()) {
              String name = entry.getKey();
              stmtNames.add(name);
              // Label the SQLStmts with its variable name.
              // This is useful for multi-partition stored procedures.
              // When a statement is sent to another site for execution,
              // that SP site can use this name to find the correct place to
              // update the statistics numbers.
              entry.getValue().setStmtName(name);
              Statement s = m_catProc.getStatements().get(name);
              if (s != null) {
                  /*
                   * Cache all the information we need about the statements in this stored
                   * procedure locally instead of pulling them from the catalog on
                   * a regular basis.
                   */
                  SQLStmt stmt = entry.getValue();
                  // done in a static method in an abstract class so users don't call it
                  initSQLStmt(stmt, s);
                  //LOG.fine("Found statement " + name);
              }
          }
          return stmtNames;
      }