/**
   * For convenience, serialization is accomplished with this single method, but deserialization is
   * piecemeal via the static methods userParamsFromBuffer and planArrayFromBuffer with no dummy
   * "AdHocPlannedStmtBatch receiver" instance required.
   */
  public ByteBuffer flattenPlanArrayToBuffer() throws IOException {
    int size = 0; // sizeof batch

    ParameterSet userParamCache = null;
    if (work.userParamSet == null) {
      userParamCache = ParameterSet.emptyParameterSet();
    } else {
      Object[] typedUserParams = new Object[work.userParamSet.length];
      int ii = 0;
      for (AdHocPlannedStatement cs : plannedStatements) {
        for (VoltType paramType : cs.core.parameterTypes) {
          if (ii >= typedUserParams.length) {
            String errorMsg =
                "Too few actual arguments were passed for the parameters in the sql statement(s): ("
                    + typedUserParams.length
                    + " vs. "
                    + ii
                    + ")";
            // Volt-TYPE-Exception is slightly cheating, here, should there be a more general
            // VoltArgumentException?
            throw new VoltTypeException(errorMsg);
          }
          typedUserParams[ii] =
              ParameterConverter.tryToMakeCompatible(
                  paramType.classFromType(), work.userParamSet[ii]);
          // System.out.println("DEBUG typed parameter: " + work.userParamSet[ii] +
          //         "using type: " + paramType + "as: " + typedUserParams[ii]);
          ii++;
        }
      }
      // Each parameter referenced in each statements should be represented
      // exactly once in userParams.
      if (ii < typedUserParams.length) {
        // Volt-TYPE-Exception is slightly cheating, here, should there be a more general
        // VoltArgumentException?
        String errorMsg =
            "Too many actual arguments were passed for the parameters in the sql statement(s): ("
                + typedUserParams.length
                + " vs. "
                + ii
                + ")";
        throw new VoltTypeException(errorMsg);
      }
      userParamCache = ParameterSet.fromArrayNoCopy(typedUserParams);
    }
    size += userParamCache.getSerializedSize();

    size += 2; // sizeof batch
    for (AdHocPlannedStatement cs : plannedStatements) {
      size += cs.getSerializedSize();
    }

    ByteBuffer buf = ByteBuffer.allocate(size);
    userParamCache.flattenToBuffer(buf);
    buf.putShort((short) plannedStatements.size());
    for (AdHocPlannedStatement cs : plannedStatements) {
      cs.flattenToBuffer(buf);
    }
    return buf;
  }
 /** Deserialize the second part of the statement batch -- the statements. */
 public static AdHocPlannedStatement[] planArrayFromBuffer(ByteBuffer buf) throws IOException {
   short csCount = buf.getShort();
   AdHocPlannedStatement[] statements = new AdHocPlannedStatement[csCount];
   for (int i = 0; i < csCount; ++i) {
     AdHocPlannedStatement cs = AdHocPlannedStatement.fromBuffer(buf);
     statements[i] = cs;
   }
   return statements;
 }