use of io.crate.metadata.RelationInfo in project crate by crate.
the class Messages method sendRowDescription.
/**
* RowDescription (B)
* <p>
* | 'T' | int32 len | int16 numCols
* <p>
* For each field:
* <p>
* | string name | int32 table_oid | int16 attr_num | int32 oid | int16 typlen | int32 type_modifier | int16 format_code
* <p>
* See https://www.postgresql.org/docs/current/static/protocol-message-formats.html
*/
static void sendRowDescription(Channel channel, Collection<Symbol> columns, @Nullable FormatCodes.FormatCode[] formatCodes, @Nullable RelationInfo relation) {
int length = 4 + 2;
int columnSize = 4 + 2 + 4 + 2 + 4 + 2;
ByteBuf buffer = channel.alloc().buffer(// use 10 as an estimate for columnName length
length + (columns.size() * (10 + columnSize)));
buffer.writeByte('T');
// will be set at the end
buffer.writeInt(0);
buffer.writeShort(columns.size());
int tableOid = 0;
if (relation != null && columns.stream().allMatch(Messages::isRefWithPosition)) {
tableOid = OidHash.relationOid(relation);
}
int idx = 0;
for (Symbol column : columns) {
byte[] nameBytes = Symbols.pathFromSymbol(column).sqlFqn().getBytes(StandardCharsets.UTF_8);
length += nameBytes.length + 1;
length += columnSize;
writeCString(buffer, nameBytes);
buffer.writeInt(tableOid);
// attr_num
if (column instanceof Reference) {
Integer position = ((Reference) column).position();
buffer.writeShort(position == null ? 0 : position);
} else {
buffer.writeShort(0);
}
PGType<?> pgType = PGTypes.get(column.valueType());
buffer.writeInt(pgType.oid());
buffer.writeShort(pgType.typeLen());
buffer.writeInt(pgType.typeMod());
buffer.writeShort(FormatCodes.getFormatCode(formatCodes, idx).ordinal());
idx++;
}
buffer.setInt(1, length);
ChannelFuture channelFuture = channel.write(buffer);
if (LOGGER.isTraceEnabled()) {
channelFuture.addListener((ChannelFutureListener) future -> LOGGER.trace("sentRowDescription"));
}
}
Aggregations