in pgjdbc/src/main/java/org/postgresql/core/v3/QueryExecutorImpl.java [1581:1712]
private void sendBind(SimpleQuery query, SimpleParameterList params, @Nullable Portal portal,
boolean noBinaryTransfer) throws IOException {
//
// Send Bind.
//
String statementName = query.getStatementName();
byte[] encodedStatementName = query.getEncodedStatementName();
byte[] encodedPortalName = (portal == null ? null : portal.getEncodedPortalName());
if (LOGGER.isLoggable(Level.FINEST)) {
StringBuilder sbuf = new StringBuilder(" FE=> Bind(stmt=" + statementName + ",portal=" + portal);
for (int i = 1; i <= params.getParameterCount(); ++i) {
sbuf.append(",$").append(i).append("=<")
.append(params.toString(i,true))
.append(">,type=").append(Oid.toString(params.getTypeOID(i)));
}
sbuf.append(")");
LOGGER.log(Level.FINEST, sbuf.toString());
}
// Total size = 4 (size field) + N + 1 (destination portal)
// + N + 1 (statement name)
// + 2 (param format code count) + N * 2 (format codes)
// + 2 (param value count) + N (encoded param value size)
// + 2 (result format code count, 0)
long encodedSize = 0;
for (int i = 1; i <= params.getParameterCount(); ++i) {
if (params.isNull(i)) {
encodedSize += 4;
} else {
encodedSize += (long) 4 + params.getV3Length(i);
}
}
Field[] fields = query.getFields();
if (!noBinaryTransfer && query.needUpdateFieldFormats() && fields != null) {
for (Field field : fields) {
if (useBinary(field)) {
field.setFormat(Field.BINARY_FORMAT);
query.setHasBinaryFields(true);
}
}
}
// If text-only results are required (e.g. updateable resultset), and the query has binary columns,
// flip to text format.
if (noBinaryTransfer && query.hasBinaryFields() && fields != null) {
for (Field field : fields) {
if (field.getFormat() != Field.TEXT_FORMAT) {
field.setFormat(Field.TEXT_FORMAT);
}
}
query.resetNeedUpdateFieldFormats();
query.setHasBinaryFields(false);
}
// This is not the number of binary fields, but the total number
// of fields if any of them are binary or zero if all of them
// are text.
int numBinaryFields = !noBinaryTransfer && query.hasBinaryFields() && fields != null
? fields.length : 0;
encodedSize = 4
+ (encodedPortalName == null ? 0 : encodedPortalName.length) + 1
+ (encodedStatementName == null ? 0 : encodedStatementName.length) + 1
+ 2 + params.getParameterCount() * 2
+ 2 + encodedSize
+ 2 + numBinaryFields * 2;
// backend's MaxAllocSize is the largest message that can
// be received from a client. If we have a bigger value
// from either very large parameters or incorrect length
// descriptions of setXXXStream we do not send the bind
// messsage.
//
if (encodedSize > 0x3fffffff) {
throw new PGBindException(new IOException(GT.tr(
"Bind message length {0} too long. This can be caused by very large or incorrect length specifications on InputStream parameters.",
encodedSize)));
}
pgStream.sendChar('B'); // Bind
pgStream.sendInteger4((int) encodedSize); // Message size
if (encodedPortalName != null) {
pgStream.send(encodedPortalName); // Destination portal name.
}
pgStream.sendChar(0); // End of portal name.
if (encodedStatementName != null) {
pgStream.send(encodedStatementName); // Source statement name.
}
pgStream.sendChar(0); // End of statement name.
pgStream.sendInteger2(params.getParameterCount()); // # of parameter format codes
for (int i = 1; i <= params.getParameterCount(); ++i) {
pgStream.sendInteger2(params.isBinary(i) ? 1 : 0); // Parameter format code
}
pgStream.sendInteger2(params.getParameterCount()); // # of parameter values
// If an error occurs when reading a stream we have to
// continue pumping out data to match the length we
// said we would. Once we've done that we throw
// this exception. Multiple exceptions can occur and
// it really doesn't matter which one is reported back
// to the caller.
//
PGBindException bindException = null;
for (int i = 1; i <= params.getParameterCount(); ++i) {
if (params.isNull(i)) {
pgStream.sendInteger4(-1); // Magic size of -1 means NULL
} else {
pgStream.sendInteger4(params.getV3Length(i)); // Parameter size
try {
params.writeV3Value(i, pgStream); // Parameter value
} catch (PGBindException be) {
bindException = be;
}
}
}
pgStream.sendInteger2(numBinaryFields); // # of result format codes
for (int i = 0; fields != null && i < numBinaryFields; ++i) {
pgStream.sendInteger2(fields[i].getFormat());
}
pendingBindQueue.add(portal == null ? UNNAMED_PORTAL : portal);
if (bindException != null) {
throw bindException;
}
}