コード例 #1
0
  @Override
  public void write(DataOutput out) throws IOException {
    int numCol = colType.length;
    boolean[] nullBits = new boolean[numCol];
    int[] colLength = new int[numCol];
    byte[] enumType = new byte[numCol];
    int[] padLength = new int[numCol];
    byte[] padbytes = new byte[8];

    /**
     * Compute the total payload and header length header = total length (4 byte), Version (2 byte),
     * Error (1 byte), #col (2 byte) col type array = #col * 1 byte null bit array = ceil(#col/8)
     */
    int datlen = 4 + 2 + 1 + 2;
    datlen += numCol;
    datlen += getNullByteArraySize(numCol);

    for (int i = 0; i < numCol; i++) {
      /* Get the enum type */
      DBType coldbtype;
      switch (DataType.get(colType[i])) {
        case BIGINT:
          coldbtype = DBType.BIGINT;
          break;
        case BOOLEAN:
          coldbtype = DBType.BOOLEAN;
          break;
        case FLOAT8:
          coldbtype = DBType.FLOAT8;
          break;
        case INTEGER:
          coldbtype = DBType.INTEGER;
          break;
        case REAL:
          coldbtype = DBType.REAL;
          break;
        case SMALLINT:
          coldbtype = DBType.SMALLINT;
          break;
        case BYTEA:
          coldbtype = DBType.BYTEA;
          break;
        default:
          coldbtype = DBType.TEXT;
      }
      enumType[i] = (byte) (coldbtype.ordinal());

      /* Get the actual value, and set the null bit */
      if (colValue[i] == null) {
        nullBits[i] = true;
        colLength[i] = 0;
      } else {
        nullBits[i] = false;

        /*
         * For fixed length type, we get the fixed length.
         * For var len binary format, the length is in the col value.
         * For text format, we must convert encoding first.
         */
        if (!coldbtype.isVarLength()) {
          colLength[i] = coldbtype.getTypeLength();
        } else if (!isTextForm(colType[i])) {
          colLength[i] = ((byte[]) colValue[i]).length;
        } else {
          colLength[i] = ((String) colValue[i]).getBytes(CHARSET).length;
        }

        /* calculate and add the type alignment padding */
        padLength[i] = roundUpAlignment(datlen, coldbtype.getAlignment()) - datlen;
        datlen += padLength[i];

        /* for variable length type, we add a 4 byte length header */
        if (coldbtype.isVarLength()) {
          datlen += 4;
        }
      }
      datlen += colLength[i];
    }

    /*
     * Add the final alignment padding for the next record
     */
    int endpadding = roundUpAlignment(datlen, 8) - datlen;
    datlen += endpadding;

    /* Construct the packet header */
    out.writeInt(datlen);
    out.writeShort(VERSION);
    out.writeByte(errorFlag);
    out.writeShort(numCol);

    /* Write col type */
    for (int i = 0; i < numCol; i++) {
      out.writeByte(enumType[i]);
    }

    /* Nullness */
    byte[] nullBytes = boolArrayToByteArray(nullBits);
    out.write(nullBytes);

    /* Column Value */
    for (int i = 0; i < numCol; i++) {
      if (!nullBits[i]) {
        /* Pad the alignment byte first */
        if (padLength[i] > 0) {
          out.write(padbytes, 0, padLength[i]);
        }

        /* Now, write the actual column value */
        switch (DataType.get(colType[i])) {
          case BIGINT:
            out.writeLong(((Long) colValue[i]));
            break;
          case BOOLEAN:
            out.writeBoolean(((Boolean) colValue[i]));
            break;
          case FLOAT8:
            out.writeDouble(((Double) colValue[i]));
            break;
          case INTEGER:
            out.writeInt(((Integer) colValue[i]));
            break;
          case REAL:
            out.writeFloat(((Float) colValue[i]));
            break;
          case SMALLINT:
            out.writeShort(((Short) colValue[i]));
            break;

            /* For BYTEA format, add 4byte length header at the beginning  */
          case BYTEA:
            out.writeInt(colLength[i]);
            out.write((byte[]) colValue[i]);
            break;

            /* For text format, add 4byte length header. string is already '\0' terminated */
          default:
            {
              out.writeInt(colLength[i]);
              byte[] data = ((String) colValue[i]).getBytes(CHARSET);
              out.write(data);
              break;
            }
        }
      }
    }

    /* End padding */
    out.write(padbytes, 0, endpadding);
  }