pg: respect format codes from Bind message when sending results

From https://www.postgresql.org/docs/9.1/static/protocol-message-formats.html:

  Bind (F)

  ...

  After the last parameter, the following fields appear:

  Int16

    The number of result-column format codes that follow (denoted R
    below). This can be zero to indicate that there are no result
    columns or that the result columns should all use the default
    format (text); or one, in which case the specified format code is
    applied to all result columns (if any); or it can equal the actual
    number of result columns of the query.

  Int16[R]

    The result-column format codes. Each must presently be zero (text)
    or one (binary).

Also fix testBinaryTypes test:

- force binary by setting prepareThreshold to -1
- handle REAL type as float

Without the fix the corrected test testBinaryTypes fails:

  05:25:02 21:55:02.666 org.h2.test.unit.TestPgServer Expected: 12345678 actual: 825373492
  Exception in thread "main" java.lang.AssertionError: Expected: 12345678 actual: 825373492
      at org.h2.test.TestBase.fail(TestBase.java:464)
      at org.h2.test.TestBase.assertEquals(TestBase.java:617)
      at org.h2.test.unit.TestPgServer.testBinaryTypes(TestPgServer.java:404)
      at org.h2.test.unit.TestPgServer.test(TestPgServer.java:51)
      at org.h2.test.unit.TestPgServer.main(TestPgServer.java:41)
上级 89c07ea5
......@@ -368,7 +368,7 @@ public class PgServerThread implements Runnable {
ResultSet rs = prep.getResultSet();
// the meta-data is sent in the prior 'Describe'
while (rs.next()) {
sendDataRow(rs);
sendDataRow(rs, p.resultColumnFormat);
}
sendCommandComplete(prep, 0);
} catch (Exception e) {
......@@ -414,7 +414,7 @@ public class PgServerThread implements Runnable {
try {
sendRowDescription(meta);
while (rs.next()) {
sendDataRow(rs);
sendDataRow(rs, null);
}
sendCommandComplete(stat, 0);
} catch (Exception e) {
......@@ -495,20 +495,31 @@ public class PgServerThread implements Runnable {
sendMessage();
}
private void sendDataRow(ResultSet rs) throws Exception {
private void sendDataRow(ResultSet rs, int[] formatCodes) throws Exception {
ResultSetMetaData metaData = rs.getMetaData();
int columns = metaData.getColumnCount();
startMessage('D');
writeShort(columns);
for (int i = 1; i <= columns; i++) {
writeDataColumn(rs, i, PgServer.convertType(metaData.getColumnType(i)));
int pgType = PgServer.convertType(metaData.getColumnType(i));
boolean text = formatAsText(pgType);
if (formatCodes != null) {
if (formatCodes.length == 0) {
text = true;
} else if (formatCodes.length == 1) {
text = formatCodes[0] == 0;
} else if (i - 1 < formatCodes.length) {
text = formatCodes[i - 1] == 0;
}
}
writeDataColumn(rs, i, pgType, text);
}
sendMessage();
}
private void writeDataColumn(ResultSet rs, int column, int pgType)
private void writeDataColumn(ResultSet rs, int column, int pgType, boolean text)
throws Exception {
if (formatAsText(pgType)) {
if (text) {
// plain text
switch (pgType) {
case PgServer.PG_TYPE_BOOL:
......
......@@ -369,8 +369,14 @@ public class TestPgServer extends TestBase {
"-pgPort", "5535", "-pgDaemon", "-key", "test", "mem:test");
server.start();
try {
Properties props = new Properties();
props.setProperty("user", "sa");
props.setProperty("password", "sa");
// force binary
props.setProperty("prepareThreshold", "-1");
Connection conn = DriverManager.getConnection(
"jdbc:postgresql://localhost:5535/test", "sa", "sa");
"jdbc:postgresql://localhost:5535/test", props);
Statement stat = conn.createStatement();
stat.execute(
......@@ -386,7 +392,7 @@ public class TestPgServer extends TestBase {
ps.setLong(4, 1234567890123L);
ps.setDouble(5, 123.456);
ps.setFloat(6, 123.456f);
ps.setDouble(7, 123.456);
ps.setFloat(7, 123.456f);
ps.setBoolean(8, true);
ps.setByte(9, (byte) 0xfe);
ps.setBytes(10, new byte[] { 'a', (byte) 0xfe, '\127' });
......@@ -400,7 +406,7 @@ public class TestPgServer extends TestBase {
assertEquals(1234567890123L, rs.getLong(4));
assertEquals(123.456, rs.getDouble(5));
assertEquals(123.456f, rs.getFloat(6));
assertEquals(123.456, rs.getDouble(7));
assertEquals(123.456f, rs.getFloat(7));
assertEquals(true, rs.getBoolean(8));
assertEquals((byte) 0xfe, rs.getByte(9));
assertEquals(new byte[] { 'a', (byte) 0xfe, '\127' },
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论