docs: public static Object tryToMakeCompatible(final Class<?> expectedClz, final Object param)
      throws VoltTypeException
      {
          /* uncomment for debugging
          System.err.printf("Converting %s of type %s to type %s\n",
  
                  String.valueOf(param),
                  param == null ? "NULL" : param.getClass().getName(),
                  expectedClz.getName());
          System.err.flush();
           */
  
          // Get blatant null out of the way fast, as it avoids some inline checks
          // There are some subtle null values that aren't java null coming up, but wait until
          // after the basics to check for those.
          if (param == null) {
              return nullValueForType(expectedClz);
          }
  
          Class<?> inputClz = param.getClass();
  
          // If we make it through this first block, memoize a number value for some range checks later
          Number numberParam = null;
  
          // This first code block tries to hit as many common cases as possible
          // Specifically, it does primitive types and strings, which are the most common param types.
          // Downconversions (e.g. long => short) happen later, but can use the memoized numberParam value.
          // Notice this block switches on the type of the given value (different later).
  
          if (inputClz == Long.class) {
              if (expectedClz == long.class) return param;
              if ((Long) param == VoltType.NULL_BIGINT) return nullValueForType(expectedClz);
              if (expectedClz == Long.class) return param;
              numberParam = (Number) param;
          }
          else if (inputClz == Integer.class) {
              if (expectedClz == int.class) return param;
              if ((Integer) param == VoltType.NULL_INTEGER) return nullValueForType(expectedClz);
              if (expectedClz == Integer.class) return param;
              if (isLongClass(expectedClz)) return ((Integer) param).longValue();
              numberParam = (Number) param;
          }
          else if (inputClz == Short.class) {
              if (expectedClz == short.class) return param;
              if ((Short) param == VoltType.NULL_SMALLINT) return nullValueForType(expectedClz);
              if (expectedClz == Short.class) return param;
              if (isLongClass(expectedClz)) return ((Short) param).longValue();
              if (isIntClass(expectedClz)) return ((Short) param).intValue();
              numberParam = (Number) param;
          }
          else if (inputClz == Byte.class) {
              if (expectedClz == byte.class) return param;
              if ((Byte) param == VoltType.NULL_TINYINT) return nullValueForType(expectedClz);
              if (expectedClz == Byte.class) return param;
              if (isLongClass(expectedClz)) return ((Byte) param).longValue();
              if (isIntClass(expectedClz)) return ((Byte) param).intValue();
              if (isShortClass(expectedClz)) return ((Byte) param).shortValue();
              numberParam = (Number) param;
          }
          else if (inputClz == Double.class) {
              if (expectedClz == double.class) return param;
              if ((Double) param == VoltType.NULL_FLOAT) return nullValueForType(expectedClz);
              if (expectedClz == Double.class) return param;
          }
          else if (inputClz == String.class) {
              String stringParam = (String)param;
              if (stringParam.equals(Constants.CSV_NULL)) return nullValueForType(expectedClz);
              else if (expectedClz == String.class) return param;
              // Hack allows hex-encoded strings to be passed into byte[] params
              else if (isByteArrayClass(expectedClz)) {
                  // regular expressions can be expensive, so don't invoke SQLParser
                  // unless the param really looks like an x-quoted literal
                  if (stringParam.startsWith("X") || stringParam.startsWith("x")) {
                      String hexDigits = SQLParser.getDigitsFromHexLiteral(stringParam);
                      if (hexDigits != null) {
                          stringParam = hexDigits;
                      }
                  }
                  byte[] inpArray =  Encoder.hexDecode(stringParam);
                  if (expectedClz == byte[].class)
                      return inpArray;
                  if (expectedClz == Byte[].class)
                      return ArrayUtils.toObject(inpArray);
              }
              // We allow all values to be passed as strings for csv loading, json, etc...
              // This code handles primitive types and their wrapped types. Complex types come later.
              if (expectedClz.isPrimitive() || expectedClz == Long.class || expectedClz == Integer.class
                      || expectedClz == Byte.class || expectedClz == Double.class || expectedClz == Short.class) {
                  return convertStringToPrimitiveOrPrimitiveWrapper(stringParam, expectedClz);
              }
          }
          else if (inputClz == byte[].class) {
              if (expectedClz == byte[].class) return param;
              if (expectedClz == Byte[].class) return ArrayUtils.toObject((byte[]) param);
              // allow byte arrays to be passed into string parameters
              if (expectedClz == String.class) {
                  String value = new String((byte[]) param, Constants.UTF8ENCODING);
                  if (value.equals(Constants.CSV_NULL)) {
                      return nullValueForType(expectedClz);
                  } else {
                      return value;
                  }
              }
              if (ByteBuffer.class.isAssignableFrom(expectedClz)) {
                  return ByteBuffer.wrap((byte[])param);
              }
          }
          // null sigils. (ning - if we're not checking if the sigil matches the expected type,
          // why do we have three sigils for three types??)
          else if (param == VoltType.NULL_TIMESTAMP ||
                  param == VoltType.NULL_STRING_OR_VARBINARY ||
                  param == VoltType.NULL_GEOGRAPHY ||
                  param == VoltType.NULL_POINT ||
                  param == VoltType.NULL_DECIMAL) {
              return nullValueForType(expectedClz);
          }
          // [ENG-12522] BigDecimal should be able to be converted to long / double or other
          // primitive numeric types if possible
          // If it cannot be converted (say out of range), just display the error message.
          else if (inputClz == BigDecimal.class) {
              // Only conversion to primitive numeric types are considered
              BigDecimal pBigDecimal = (BigDecimal) param;
              if (expectedClz == BigDecimal.class) {
                  return VoltDecimalHelper.setDefaultScale(pBigDecimal);
              }
  
              if (isLongClass(expectedClz)) {
                  try {
                      long result = pBigDecimal.longValueExact();
                      return result;
                  } catch (ArithmeticException e) {}  // The error will be re-thrown below
              } else if (isDoubleClass(expectedClz)) {
                  // This conversion could potentially lose information, should a warning be
                  // given at a higher level ?
                  double result = pBigDecimal.doubleValue();
                  // The converted double could be infinity if out of range
                  if (result != Double.POSITIVE_INFINITY && result != Double.NEGATIVE_INFINITY) {
                      return result;
                  }
              } else if (isIntClass(expectedClz)) {
                  try {
                      int result = pBigDecimal.intValueExact();
                      return result;
                  } catch (ArithmeticException e) {}  // The error will be re-thrown below
              } else if (isShortClass(expectedClz)) {
                  try {
                      short result = pBigDecimal.shortValueExact();
                      return result;
                  } catch (ArithmeticException e) {} // The error will be re-thrown below
              } else if (isByteClass(expectedClz)) {
                  try {
                      byte result = pBigDecimal.byteValueExact();
                      return result;
                  } catch (ArithmeticException e) {}
              }
              throw new VoltTypeException(
                              "The provided value: (" + param.toString() +
                              ") of type: " + inputClz.getName() +
                              " is out of range for the target parameter type: " +
                              expectedClz.getName());
          }
  
          // make sure we get the array/scalar match
          if (expectedClz.isArray() != inputClz.isArray()) {
              throw new VoltTypeException(String.format("Array / Scalar parameter mismatch (%s to %s)",
                      inputClz.getName(), expectedClz.getName()));
          }
  
          // handle arrays in a factored-out method
          if (expectedClz.isArray()) {
              return tryToMakeCompatibleArray(expectedClz.getComponentType(), inputClz.getComponentType(), param);
          }
  
          // The following block switches on the type of the parameter desired.
          // It handles all of the paths not trapped in the code above. We can assume
          // values are not null and that most sane primitive stuff has been handled.
          // Downcasting is handled here (e.g. long => short).
          // Time (in many forms) and Decimal are also handled below.
  
          if (isIntClass(expectedClz) && (numberParam != null)) {
              long val = numberParam.longValue();
              if (val == VoltType.NULL_INTEGER) {
                  throw new VoltTypeException("The provided long value: ("
                          + param.toString() + ") might be interpreted as integer null. " +
                                  "Try explicitly using a int parameter.");
              }
              // if it's in the right range, crop the value and return
              if ((val <= Integer.MAX_VALUE) && (val >= Integer.MIN_VALUE))
                  return numberParam.intValue();
          }
          else if (isShortClass(expectedClz) && (numberParam != null)) {
              if ((inputClz == Long.class) || (inputClz == Integer.class)) {
                  long val = numberParam.longValue();
                  if (val == VoltType.NULL_SMALLINT) {
                      throw new VoltTypeException("The provided int or long value: ("
                              + param.toString() + ") might be interpreted as smallint null. " +
                                      "Try explicitly using a short parameter.");
                  }
                  // if it's in the right range, crop the value and return
                  if ((val <= Short.MAX_VALUE) && (val >= Short.MIN_VALUE))
                      return numberParam.shortValue();
              }
          }
          else if (isByteClass(expectedClz) && (numberParam != null)) {
              if ((inputClz == Long.class) || (inputClz == Integer.class) || (inputClz == Short.class)) {
                  long val = numberParam.longValue();
                  if (val == VoltType.NULL_TINYINT) {
                      throw new VoltTypeException("The provided short, int or long value: ("
                              + param.toString() + ") might be interpreted as tinyint null. " +
                                      "Try explicitly using a byte parameter.");
                  }
                  // if it's in the right range, crop the value and return
                  if ((val <= Byte.MAX_VALUE) && (val >= Byte.MIN_VALUE))
                      return numberParam.byteValue();
              }
          }
          else if (isDoubleClass(expectedClz) && (numberParam != null)) {
              return numberParam.doubleValue();
          }
          else if (expectedClz == TimestampType.class) {
              if (inputClz == Integer.class) return new TimestampType((Integer)param); // null values safe
              if (inputClz == Long.class) return new TimestampType((Long)param); // null values safe
              if (inputClz == TimestampType.class) return param;
              if (inputClz == Date.class) return new TimestampType((Date) param);
              // if a string is given for a date, use java's JDBC parsing
              if (inputClz == String.class) {
                  String timestring = ((String) param).trim();
                  try {
                      return new TimestampType(Long.parseLong(timestring));
                  } catch (IllegalArgumentException e) {
                      // Defer errors to the generic Exception throw below, if it's not the right format
                  }
                  try {
                      return SQLParser.parseDate(timestring);
                  }
                  catch (IllegalArgumentException e) {
                      // Defer errors to the generic Exception throw below, if it's not the right format
                  }
              }
          }
          else if (expectedClz == java.sql.Timestamp.class) {
              if (param instanceof java.sql.Timestamp) return param;
              if (param instanceof java.util.Date) return new java.sql.Timestamp(((java.util.Date) param).getTime());
              if (param instanceof TimestampType) return ((TimestampType) param).asJavaTimestamp();
              // If a string is given for a date, use java's JDBC parsing.
              if (inputClz == String.class) {
                  String longtime = ((String) param).trim();
                  try {
                      return new java.sql.Timestamp(Long.parseLong(longtime));
                  }
                  catch (IllegalArgumentException e) {
                      // Defer errors to the generic Exception throw below, if it's not the right format
                  }
                  try {
                      return java.sql.Timestamp.valueOf(longtime);
                  } catch (IllegalArgumentException e) {
                      // Defer errors to the generic Exception throw below, if it's not the right format
                  }
  
              }
          }
          else if (expectedClz == java.sql.Date.class) {
              if (param instanceof java.sql.Date) return param; // covers java.sql.Date and java.sql.Timestamp
              if (param instanceof java.util.Date) return new java.sql.Date(((java.util.Date) param).getTime());
              if (param instanceof TimestampType) return ((TimestampType) param).asExactJavaSqlDate();
              // If a string is given for a date, use java's JDBC parsing.
              if (inputClz == String.class) {
                  try {
                      return new java.sql.Date(TimestampType.millisFromJDBCformat((String) param));
                  }
                  catch (IllegalArgumentException e) {
                      // Defer errors to the generic Exception throw below, if it's not the right format
                  }
              }
          }
          else if (expectedClz == java.util.Date.class) {
              if (param instanceof java.util.Date) return param; // covers java.sql.Date and java.sql.Timestamp
              if (param instanceof TimestampType) return ((TimestampType) param).asExactJavaDate();
              // If a string is given for a date, use the default format parser for the default locale.
              if (inputClz == String.class) {
                  try {
                      return new java.util.Date(TimestampType.millisFromJDBCformat((String) param));
                  }
                  catch (IllegalArgumentException e) {
                      // Defer errors to the generic Exception throw below, if it's not the right format
                  }
              }
          }
          else if (expectedClz == BigDecimal.class) {
              if (numberParam != null) {
                  BigDecimal bd = VoltDecimalHelper.stringToDecimal(param.toString());
                  return bd;
              }
              if (inputClz == BigDecimal.class) {
                  BigDecimal bd = (BigDecimal) param;
                  bd = VoltDecimalHelper.setDefaultScale(bd);
                  return bd;
              }
              if (inputClz == Float.class || inputClz == Double.class) {
                  try {
                      return VoltDecimalHelper.deserializeBigDecimalFromString(String.format("%.12f", param));
                  } catch (IOException ex) {
                      throw new VoltTypeException(String.format("deserialize Float from string failed. (%s to %s)",
                              inputClz.getName(), expectedClz.getName()));
                  }
              }
              try {
                  return VoltDecimalHelper.deserializeBigDecimalFromString(String.valueOf(param));
              } catch (IOException ex) {
                  throw new VoltTypeException(String.format("deserialize BigDecimal from string failed. (%s to %s)",
                          inputClz.getName(), expectedClz.getName()));
              }
          } else if (expectedClz == GeographyPointValue.class) {
              // Is it a point already?  If so, just return it.
              if (inputClz == GeographyPointValue.class) {
                  return param;
              }
              // Is it a string from which we can construct a point?
              // If so, return the newly constructed point.
              if (inputClz == String.class) {
                  try {
                      GeographyPointValue pt = GeographyPointValue.fromWKT((String)param);
                      return pt;
                  } catch (IllegalArgumentException e) {
                      throw new VoltTypeException(String.format("deserialize GeographyPointValue from string failed (string %s)",
                                                                (String)param));
                  }
              }
          } else if (expectedClz == GeographyValue.class) {
              if (inputClz == GeographyValue.class) {
                  return param;
              }
              if (inputClz == String.class) {
                  String paramStr = (String)param;
                  try {
                      GeographyValue gv = GeographyValue.fromWKT(paramStr);
                      return gv;
                  } catch (IllegalArgumentException e) {
                      throw new VoltTypeException(String.format("deserialize GeographyValue from string failed (string %s)",
                                                                paramStr));
                  }
              }
          } else if (expectedClz == VoltTable.class && inputClz == VoltTable.class) {
              return param;
          } else if (expectedClz == String.class) {
              //For VARCHAR columns if not null or not an array send toString value.
              if (!param.getClass().isArray()) {
                  return String.valueOf(param);
              }
          }
          // this is for NT sysprocs with variable arguments
          // they do their own validation
          else if (expectedClz == ParameterSet.class && inputClz == ParameterSet.class) {
              return param;
          }
  
          // handle SystemProcedureExecutionContext without linking to it
          // these are used by system procedures and are ignored here
          if (expectedClz.getSimpleName().equals("SystemProcedureExecutionContext")) {
              if (expectedClz.isAssignableFrom(inputClz)) {
                  return param;
              }
          }
  
          throw new VoltTypeException(
                  "The provided value: (" + param.toString() + ") of type: " + inputClz.getName() +
                  " is not a match or is out of range for the target parameter type: " + expectedClz.getName());
      }