in server/pxf-api/src/main/java/org/greenplum/pxf/api/io/GPDBWritable.java [335:484]
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(databaseEncoding).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: {
byte[] data = ((String) colValue[i]).getBytes(databaseEncoding);
out.writeInt(colLength[i]);
out.write(data);
break;
}
}
}
}
/* End padding */
out.write(padbytes, 0, endpadding);
}