From 4ef917e1c643fa32cdffb005f75e886a51f873ea Mon Sep 17 00:00:00 2001 From: Tony Locke Date: Thu, 22 Feb 2024 17:59:26 +0000 Subject: [PATCH] Use unsigned 16 bit integer in protocol In the Front End / Back End protocol we previously used a signed int where we should have used an unsigned int. This has the effect of doubling the number of parameters that can be sent. --- pg8000/core.py | 10 +++++----- test/native/test_query.py | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/pg8000/core.py b/pg8000/core.py index 3e55957..8375b95 100644 --- a/pg8000/core.py +++ b/pg8000/core.py @@ -28,7 +28,7 @@ def pack_funcs(fmt): i_pack, i_unpack = pack_funcs("i") -h_pack, h_unpack = pack_funcs("h") +H_pack, H_unpack = pack_funcs("H") ii_pack, ii_unpack = pack_funcs("ii") ihihih_pack, ihihih_unpack = pack_funcs("ihihih") ci_pack, ci_unpack = pack_funcs("ci") @@ -623,7 +623,7 @@ def handle_BACKEND_KEY_DATA(self, data, context): self._backend_key_data = data def handle_ROW_DESCRIPTION(self, data, context): - count = h_unpack(data)[0] + count = H_unpack(data)[0] idx = 2 columns = [] input_funcs = [] @@ -656,7 +656,7 @@ def handle_ROW_DESCRIPTION(self, data, context): def send_PARSE(self, statement_name_bin, statement, oids=()): val = bytearray(statement_name_bin) val.extend(statement.encode(self._client_encoding) + NULL_BYTE) - val.extend(h_pack(len(oids))) + val.extend(H_pack(len(oids))) for oid in oids: val.extend(i_pack(0 if oid == -1 else oid)) @@ -762,7 +762,7 @@ def send_BIND(self, statement_name_bin, params): """https://www.postgresql.org/docs/current/protocol-message-formats.html""" retval = bytearray( - NULL_BYTE + statement_name_bin + h_pack(0) + h_pack(len(params)) + NULL_BYTE + statement_name_bin + H_pack(0) + H_pack(len(params)) ) for value in params: @@ -772,7 +772,7 @@ def send_BIND(self, statement_name_bin, params): val = value.encode(self._client_encoding) retval.extend(i_pack(len(val))) retval.extend(val) - retval.extend(h_pack(0)) + retval.extend(H_pack(0)) self._send_message(BIND, retval) _write(self._sock, FLUSH_MSG) diff --git a/test/native/test_query.py b/test/native/test_query.py index e882ef5..afe56c8 100644 --- a/test/native/test_query.py +++ b/test/native/test_query.py @@ -225,3 +225,12 @@ def test_not_parsed_if_no_params(mocker, con): mock_to_statement = mocker.patch("pg8000.native.to_statement") con.run("ROLLBACK") mock_to_statement.assert_not_called() + + +def test_max_parameters(con): + SIZE = 60000 + kwargs = {f"param_{i}": 1 for i in range(SIZE)} + con.run( + f"SELECT 1 WHERE 1 IN ({','.join([f':param_{i}' for i in range(SIZE)])})", + **kwargs, + )