예제 #1
0
  public void flattenToBuffer(ByteBuffer buf) throws IOException {

    buf.putShort((short) m_params.length);

    for (int i = 0; i < m_params.length; i++) {
      Object obj = m_params[i];
      if ((obj == null) || (obj == JSONObject.NULL)) {
        VoltType type = VoltType.NULL;
        buf.put(type.getValue());
        continue;
      }

      Class<?> cls = obj.getClass();
      if (cls.isArray()) {

        // Since arrays of bytes could be varbinary or strings,
        // and they are the only kind of array needed by the EE,
        // special case them as the VARBINARY type.
        if (obj instanceof byte[]) {
          final byte[] b = (byte[]) obj;
          // commented out this bit... presumably the EE will do this check upon recipt
          /*if (b.length > VoltType.MAX_VALUE_LENGTH) {
              throw new IOException("Value of byte[] larger than allowed max string or varbinary " + VoltType.MAX_VALUE_LENGTH_STR);
          }*/
          buf.put(VoltType.VARBINARY.getValue());
          buf.putInt(b.length);
          buf.put(b);
          continue;
        }

        // Same as before, but deal with the fact it is coming in as a unmanaged bytebuffer
        if (obj instanceof BBContainer) {
          final BBContainer cont = (BBContainer) obj;
          final ByteBuffer paramBuf = cont.b();
          buf.put(VoltType.VARBINARY.getValue());
          buf.putInt(paramBuf.remaining());
          buf.put(paramBuf);
          continue;
        }

        buf.put(ARRAY);

        VoltType type;
        try {
          type = VoltType.typeFromClass(cls.getComponentType());
        } catch (VoltTypeException e) {
          obj = getAKosherArray((Object[]) obj);
          cls = obj.getClass();
          type = VoltType.typeFromClass(cls.getComponentType());
        }

        buf.put(type.getValue());
        switch (type) {
          case SMALLINT:
            SerializationHelper.writeArray((short[]) obj, buf);
            break;
          case INTEGER:
            SerializationHelper.writeArray((int[]) obj, buf);
            break;
          case BIGINT:
            SerializationHelper.writeArray((long[]) obj, buf);
            break;
          case FLOAT:
            SerializationHelper.writeArray((double[]) obj, buf);
            break;
          case STRING:
            if (m_encodedStringArrays[i] == null) {
              // should not happen
              throw new IOException("String array not encoded");
            }
            // This check used to be done by FastSerializer.writeArray(), but things changed?
            if (m_encodedStringArrays[i].length > Short.MAX_VALUE) {
              throw new IOException(
                  "Array exceeds maximum length of " + Short.MAX_VALUE + " bytes");
            }
            buf.putShort((short) m_encodedStringArrays[i].length);
            for (int zz = 0; zz < m_encodedStringArrays[i].length; zz++) {
              SerializationHelper.writeVarbinary(m_encodedStringArrays[i][zz], buf);
            }
            break;
          case TIMESTAMP:
            SerializationHelper.writeArray((TimestampType[]) obj, buf);
            break;
          case DECIMAL:
            // converted long128 in serializer api
            SerializationHelper.writeArray((BigDecimal[]) obj, buf);
            break;
          case VOLTTABLE:
            SerializationHelper.writeArray((VoltTable[]) obj, buf);
            break;
          case VARBINARY:
            SerializationHelper.writeArray((byte[][]) obj, buf);
            break;
          case GEOGRAPHY_POINT:
            SerializationHelper.writeArray((GeographyPointValue[]) obj, buf);
            break;
          case GEOGRAPHY:
            SerializationHelper.writeArray((GeographyValue[]) obj, buf);
            break;
          default:
            throw new RuntimeException("FIXME: Unsupported type " + type);
        }
        continue;
      }

      // Handle NULL mappings not encoded by type.min_value convention
      if (obj == VoltType.NULL_TIMESTAMP) {
        buf.put(VoltType.TIMESTAMP.getValue());
        buf.putLong(VoltType.NULL_BIGINT); // corresponds to EE value.h isNull()
        continue;
      } else if (obj == VoltType.NULL_STRING_OR_VARBINARY) {
        buf.put(VoltType.STRING.getValue());
        buf.putInt(VoltType.NULL_STRING_LENGTH);
        continue;
      } else if (obj == VoltType.NULL_DECIMAL) {
        buf.put(VoltType.DECIMAL.getValue());
        VoltDecimalHelper.serializeNull(buf);
        continue;
      } else if (obj == VoltType.NULL_POINT) {
        buf.put(VoltType.GEOGRAPHY_POINT.getValue());
        GeographyPointValue.serializeNull(buf);
        continue;
      } else if (obj == VoltType.NULL_GEOGRAPHY) {
        buf.put(VoltType.GEOGRAPHY.getValue());
        buf.putInt(VoltType.NULL_STRING_LENGTH);
        continue;
      } else if (obj instanceof BBContainer) {
        final BBContainer cont = (BBContainer) obj;
        final ByteBuffer paramBuf = cont.b();
        buf.put(VoltType.VARBINARY.getValue());
        buf.putInt(paramBuf.remaining());
        buf.put(paramBuf);
        continue;
      }

      VoltType type = VoltType.typeFromClass(cls);
      buf.put(type.getValue());
      switch (type) {
        case TINYINT:
          buf.put((Byte) obj);
          break;
        case SMALLINT:
          buf.putShort((Short) obj);
          break;
        case INTEGER:
          buf.putInt((Integer) obj);
          break;
        case BIGINT:
          buf.putLong((Long) obj);
          break;
        case FLOAT:
          if (cls == Float.class) buf.putDouble(((Float) obj).doubleValue());
          else if (cls == Double.class) buf.putDouble(((Double) obj).doubleValue());
          else throw new RuntimeException("Can't cast parameter type to Double");
          break;
        case STRING:
          if (m_encodedStrings[i] == null) {
            // should not happen
            throw new IOException("String not encoded: " + (String) obj);
          }
          SerializationHelper.writeVarbinary(m_encodedStrings[i], buf);
          break;
        case TIMESTAMP:
          long micros = timestampToMicroseconds(obj);
          buf.putLong(micros);
          break;
        case DECIMAL:
          VoltDecimalHelper.serializeBigDecimal((BigDecimal) obj, buf);
          break;
        case VOLTTABLE:
          ((VoltTable) obj).flattenToBuffer(buf);
          break;
        case GEOGRAPHY_POINT:
          ((GeographyPointValue) obj).flattenToBuffer(buf);
          break;
        case GEOGRAPHY:
          GeographyValue gv = (GeographyValue) obj;
          buf.putInt(gv.getLengthInBytes());
          gv.flattenToBuffer(buf);
          break;
        default:
          throw new RuntimeException("FIXME: Unsupported type " + type);
      }
    }
  }
예제 #2
0
  private static OneParamInfo readOneParameter(ByteBuffer in) throws IOException {
    Object value;
    int len;
    byte[] encodedString = null;
    byte[][] encodedStringArray = null;

    byte nextTypeByte = in.get();
    if (nextTypeByte == ARRAY) {
      VoltType nextType = null;
      byte etype = in.get();
      try {
        nextType = VoltType.get(etype);
      } catch (AssertionError ae) {
        throw new RuntimeException("ParameterSet doesn't support type " + etype);
      }
      if (nextType == null) {
        value = null;
      } else if (nextType == VoltType.STRING) {
        encodedStringArray = (byte[][]) SerializationHelper.readArray(byte[].class, in);
        String[] sval = new String[encodedStringArray.length];
        for (int i = 0; i < encodedStringArray.length; ++i) {
          if (encodedStringArray[i] == null) {
            sval[i] = null;
          } else {
            sval[i] = new String(encodedStringArray[i], Constants.UTF8ENCODING);
          }
        }
        value = sval;
      } else {
        value = SerializationHelper.readArray(nextType.classFromType(), in);
      }
    } else {
      VoltType nextType;
      try {
        nextType = VoltType.get(nextTypeByte);
      } catch (AssertionError ae) {
        throw new RuntimeException("ParameterSet doesn't support type " + nextTypeByte);
      }
      switch (nextType) {
        case NULL:
          value = null;
          break;
        case TINYINT:
          value = in.get();
          break;
        case SMALLINT:
          value = in.getShort();
          break;
        case INTEGER:
          value = in.getInt();
          break;
        case BIGINT:
          value = in.getLong();
          break;
        case FLOAT:
          value = in.getDouble();
          break;
        case STRING:
          len = in.getInt();
          if (len == VoltType.NULL_STRING_LENGTH) {
            value = VoltType.NULL_STRING_OR_VARBINARY;
          } else {
            encodedString = new byte[len];
            in.get(encodedString);
            value = new String(encodedString, Constants.UTF8ENCODING);
          }
          break;
        case VARBINARY:
          len = in.getInt();
          if (len == VoltType.NULL_STRING_LENGTH) {
            value = VoltType.NULL_STRING_OR_VARBINARY;
          } else {
            encodedString = new byte[len];
            in.get(encodedString);
            value = encodedString;
          }
          break;
        case TIMESTAMP:
          final long micros = in.getLong();
          value = new TimestampType(micros);
          break;
        case VOLTTABLE:
          final int tableSize = in.getInt();
          byte[] tableBytes = new byte[tableSize];
          in.get(tableBytes);
          value =
              PrivateVoltTableFactory.createVoltTableFromBuffer(ByteBuffer.wrap(tableBytes), false);
          break;
        case DECIMAL:
          {
            BigDecimal decimal_val = SerializationHelper.getBigDecimal(in);
            if (decimal_val == null) {
              value = VoltType.NULL_DECIMAL;
            } else {
              value = decimal_val;
            }
            break;
          }
        case GEOGRAPHY_POINT:
          value = GeographyPointValue.unflattenFromBuffer(in);
          if (value == null) {
            value = VoltType.NULL_POINT;
          }
          break;
        case GEOGRAPHY:
          len = in.getInt();
          if (len == VoltType.NULL_STRING_LENGTH) {
            value = VoltType.NULL_GEOGRAPHY;
          } else {
            value = GeographyValue.unflattenFromBuffer(in);
          }
          break;
        case BOOLEAN:
          value = in.get();
          break;
        default:
          throw new RuntimeException("ParameterSet doesn't support type " + nextType);
      }
    }

    OneParamInfo retval = new OneParamInfo();
    retval.value = value;
    retval.encodedString = encodedString;
    retval.encodedStringArray = encodedStringArray;
    return retval;
  }