Skip to content

Bind does not generate the result column format encoding in pg-protocol #3487

Open
@fqazi

Description

@fqazi

While running some tests for CockroachDB we noticed that the binary encoding flag passed during the bind operation does not follow the Postgres specifications for the result-column format. This problem reproduces easily on Postgres as well, since the binary flag is not being encoded correctly at:

writer.addInt16(binary ? ParamType.BINARY : ParamType.STRING)

This violates the specification (https://www.postgresql.org/docs/current/protocol-message-formats.html#PROTOCOL-MESSAGE-FORMATS-BIND), which says for the result column formats:

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).

The pg-protocol code incorrectly only puts a single Int16 for the binary encoding case, which leads to a protocol violation error on Postgres.

const pg = require('pg');
const fs = require('fs');

const config = {
  user: 'blah2',
  database: 'postgres',
  host: process.env.PGHOST || 'localhost',
  port: process.env.PGPORT || '5432',
};
const assert             = require('assert');

const client = new pg.Client(config);
client.connect()

describe('regression tests', () => {
  it('allows you to switch between format modes for arrays', () => {
// pg-node has a regression where the binary encoding
    // is sending incorrect data. See:
   return  client.query({
            text: 'SELECT CAST($1 AS INT[]) as b',
            values: [[1, 2, 8]],
            binary: false,
          }).then(r => {
            return client.query({
              text: 'SELECT CAST($1 AS INT[]) as a',
              values: [[4, 5, 6]],
              binary: true,
            });
          }).then(results => {
            assert.deepEqual([4, 5, 6], results.rows[0].a);
          });
  })

Running this test we get the following output when the binary encoding is sued:

  1) regression tests
       allows you to switch between format modes for arrays:
     error: insufficient data left in message
      at node_modules/pg/lib/client.js:526:17
      at process.processTicksAndRejections (node:internal/process/task_queues:105:5)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions