use of io.crate.protocols.postgres.types.PGType in project crate by crate.
the class Messages method sendDataRow.
/**
* Byte1('D')
* Identifies the message as a data row.
* <p>
* Int32
* Length of message contents in bytes, including self.
* <p>
* Int16
* The number of column values that follow (possibly zero).
* <p>
* Next, the following pair of fields appear for each column:
* <p>
* Int32
* The length of the column value, in bytes (this count does not include itself).
* Can be zero. As a special case, -1 indicates a NULL column value. No value bytes follow in the NULL case.
* <p>
* ByteN
* The value of the column, in the format indicated by the associated format code. n is the above length.
*/
static void sendDataRow(Channel channel, Row row, List<? extends DataType> columnTypes, @Nullable FormatCodes.FormatCode[] formatCodes) {
int length = 4 + 2;
assert columnTypes.size() == row.numColumns() : "Number of columns in the row must match number of columnTypes. Row: " + row + " types: " + columnTypes;
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
buffer.writeByte('D');
// will be set at the end
buffer.writeInt(0);
buffer.writeShort(row.numColumns());
for (int i = 0; i < row.numColumns(); i++) {
DataType dataType = columnTypes.get(i);
PGType pgType = PGTypes.get(dataType);
Object value = row.get(i);
if (value == null) {
buffer.writeInt(-1);
length += 4;
} else {
FormatCodes.FormatCode formatCode = FormatCodes.getFormatCode(formatCodes, i);
switch(formatCode) {
case TEXT:
length += pgType.writeAsText(buffer, value);
break;
case BINARY:
length += pgType.writeAsBinary(buffer, value);
break;
default:
throw new AssertionError("Unrecognized formatCode: " + formatCode);
}
}
}
buffer.setInt(1, length);
channel.write(buffer);
}
use of io.crate.protocols.postgres.types.PGType 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<Field> columns, @Nullable FormatCodes.FormatCode[] formatCodes) {
int length = 4 + 2;
int columnSize = 4 + 2 + 4 + 2 + 4 + 2;
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(// 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 idx = 0;
for (Field column : columns) {
byte[] nameBytes = column.path().outputName().getBytes(StandardCharsets.UTF_8);
length += nameBytes.length + 1;
length += columnSize;
writeCString(buffer, nameBytes);
// table_oid
buffer.writeInt(0);
// attr_num
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(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
LOGGER.trace("sentRowDescription");
}
});
}
}
use of io.crate.protocols.postgres.types.PGType in project crate by crate.
the class ConnectionContext method handleBindMessage.
/**
* Bind Message
* Header:
* | 'B' | int32 len
* <p>
* Body:
* <pre>
* | string portalName | string statementName
* | int16 numFormatCodes
* foreach
* | int16 formatCode
* | int16 numParams
* foreach
* | int32 valueLength
* | byteN value
* | int16 numResultColumnFormatCodes
* foreach
* | int16 formatCode
* </pre>
*/
private void handleBindMessage(ChannelBuffer buffer, Channel channel) {
String portalName = readCString(buffer);
String statementName = readCString(buffer);
FormatCodes.FormatCode[] formatCodes = FormatCodes.fromBuffer(buffer);
short numParams = buffer.readShort();
List<Object> params = createList(numParams);
for (int i = 0; i < numParams; i++) {
int valueLength = buffer.readInt();
if (valueLength == -1) {
params.add(null);
} else {
DataType paramType = session.getParamType(statementName, i);
PGType pgType = PGTypes.get(paramType);
FormatCodes.FormatCode formatCode = getFormatCode(formatCodes, i);
switch(formatCode) {
case TEXT:
params.add(pgType.readTextValue(buffer, valueLength));
break;
case BINARY:
params.add(pgType.readBinaryValue(buffer, valueLength));
break;
default:
Messages.sendErrorResponse(channel, new UnsupportedOperationException(String.format(Locale.ENGLISH, "Unsupported format code '%d' for param '%s'", formatCode.ordinal(), paramType.getName())));
return;
}
}
}
FormatCodes.FormatCode[] resultFormatCodes = FormatCodes.fromBuffer(buffer);
session.bind(portalName, statementName, params, resultFormatCodes);
Messages.sendBindComplete(channel);
}
use of io.crate.protocols.postgres.types.PGType in project crate by crate.
the class SQLTransportExecutor method toJdbcCompatObject.
private static Object toJdbcCompatObject(Connection connection, Object arg) {
if (arg == null) {
return null;
}
if (arg instanceof Map) {
// setObject with a Map would use hstore. But that only supports text values
try {
return toPGObjectJson(toJsonString(((Map) arg)));
} catch (SQLException | IOException e) {
throw Throwables.propagate(e);
}
}
if (arg.getClass().isArray()) {
arg = Arrays.asList((Object[]) arg);
}
if (arg instanceof Collection) {
Collection values = (Collection) arg;
if (values.isEmpty()) {
// TODO: can't insert empty list without knowing the type
return null;
}
if (values.iterator().next() instanceof Map) {
try {
return toPGObjectJson(toJsonString(values));
} catch (SQLException | IOException e) {
throw Throwables.propagate(e);
}
}
List<Object> convertedValues = new ArrayList<>(values.size());
PGType pgType = null;
for (Object value : values) {
convertedValues.add(toJdbcCompatObject(connection, value));
if (pgType == null && value != null) {
pgType = PGTypes.get(DataTypes.guessType(value));
}
}
try {
return connection.createArrayOf(pgType.typName(), convertedValues.toArray(new Object[0]));
} catch (SQLException e) {
/*
* pg error message doesn't include a stacktrace.
* Set a breakpoint in {@link io.crate.protocols.postgres.Messages#sendErrorResponse(Channel, Throwable)}
* to inspect the error
*/
throw Throwables.propagate(e);
}
}
return arg;
}
Aggregations