docs: @Override
      public void refineValueType(VoltType neededType, int neededSize)
      {
          int size_unit = 1;
          if (neededType == m_valueType) {
  
              if (neededSize == m_valueSize) {
                  return;
              }
              // Variably sized types need to fit within the target width.
              if (neededType == VoltType.VARBINARY) {
                  if ( ! Encoder.isHexEncodedString(getValue())) {
                      throw new PlanningErrorException("Value (" + getValue() +
                                                       ") has an invalid format for a constant " +
                                                       neededType.toSQLString() + " value");
                  }
                  size_unit = 2;
              }
              else {
                  assert neededType == VoltType.STRING;
              }
  
              if (getValue().length() > size_unit*neededSize ) {
                  throw new PlanningErrorException("Value (" + getValue() +
                                                   ") is too wide for a constant " +
                                                   neededType.toSQLString() +
                                                   " value of size " + neededSize);
              }
              setValueSize(neededSize);
              return;
          }
  
          if (m_isNull) {
              setValueType(neededType);
              setValueSize(neededSize);
              return;
          }
  
          // Constant's apparent type may not exactly match the target type needed.
          if (neededType == VoltType.VARBINARY &&
                  (m_valueType == VoltType.STRING || m_valueType == null)) {
              if ( ! Encoder.isHexEncodedString(getValue())) {
                  throw new PlanningErrorException("Value (" + getValue() +
                                                   ") has an invalid format for a constant " +
                                                   neededType.toSQLString() + " value");
              }
              size_unit = 2;
              if (getValue().length() > size_unit*neededSize ) {
                  throw new PlanningErrorException("Value (" + getValue() +
                                                   ") is too wide for a constant " +
                                                   neededType.toSQLString() +
                                                   " value of size " + neededSize);
              }
              setValueType(neededType);
              setValueSize(neededSize);
              return;
          }
  
          if (neededType == VoltType.STRING && m_valueType == null) {
              if (getValue().length() > size_unit*neededSize ) {
                  throw new PlanningErrorException("Value (" + getValue() +
                                                   ") is too wide for a constant " +
                                                   neededType.toSQLString() +
                                                   " value of size " + neededSize);
              }
              setValueType(neededType);
              setValueSize(neededSize);
              return;
          }
  
          if (neededType == VoltType.TIMESTAMP) {
              if (m_valueType == VoltType.STRING) {
                  try {
                      // Convert date value in whatever format is supported by
                      // TimeStampType into VoltDB native microsecond count.
                      // TODO: Should datetime string be supported as the new
                      // canonical internal format for timestamp constants?
                      // Historically, the long micros value made sense because
                      // it was initially the only way and later the most
                      // direct way to initialize timestamp values in the EE.
                      // But now that long value can not be used to "explain"
                      // an expression as a valid SQL timestamp value for DDL
                      // round trips, forcing a reverse conversion back through
                      // TimeStampType to a datetime string.
                      TimestampType ts = new TimestampType(m_value);
                      m_value = String.valueOf(ts.getTime());
                  }
                  // It couldn't be converted to timestamp.
                  catch (IllegalArgumentException e) {
                      throw new PlanningErrorException("Value (" + getValue() +
                                                       ") has an invalid format for a constant " +
                                                       neededType.toSQLString() + " value");
  
                  }
                  setValueType(neededType);
                  setValueSize(neededSize);
                  return;
              }
          }
  
          if ((neededType == VoltType.FLOAT || neededType == VoltType.DECIMAL)
                  && getValueType() != VoltType.VARBINARY) {
              if (m_valueType == null ||
                      (m_valueType != VoltType.NUMERIC && ! m_valueType.isExactNumeric())) {
                  try {
                      Double.parseDouble(getValue());
                  } catch (NumberFormatException nfe) {
                      throw new PlanningErrorException("Value (" + getValue() +
                                                       ") has an invalid format for a constant " +
                                                       neededType.toSQLString() + " value");
                  }
              }
              setValueType(neededType);
              setValueSize(neededSize);
              return;
          }
  
          if (neededType.isBackendIntegerType()) {
              long value = 0;
              try {
                  if (getValueType() == VoltType.VARBINARY) {
                      value = SQLParser.hexDigitsToLong(getValue());
                      setValue(Long.toString(value));
                  }
                  else {
                      value = Long.parseLong(getValue());
                  }
              } catch (SQLParser.Exception | NumberFormatException exc) {
                  throw new PlanningErrorException("Value (" + getValue() +
                                                   ") has an invalid format for a constant " +
                                                   neededType.toSQLString() + " value");
              }
              checkIntegerValueRange(value, neededType);
              m_valueType = neededType;
              m_valueSize = neededType.getLengthInBytesForFixedTypes();
              return;
          }
  
          // That's it for known type conversions.
          throw new PlanningErrorException("Value (" + getValue() +
                  ") has an invalid format for a constant " +
                  neededType.toSQLString() + " value");
      }