From: Denis Laxalde Date: Sun, 10 Oct 2021 09:27:13 +0000 (+0200) Subject: Rework PGconn.pipeline_status X-Git-Tag: 3.0~11^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99150743c9c13e621a0417f43780587040ee4e50;p=thirdparty%2Fpsycopg.git Rework PGconn.pipeline_status We make this method a property, that returns an integer value, as do other similar properties/methods on PGconn. Then, for libpq version older than 14.0, we make this property always return 0 (PQ_PIPELINE_OFF). --- diff --git a/psycopg/psycopg/pq/abc.py b/psycopg/psycopg/pq/abc.py index a7f5d847c..ae2ad8914 100644 --- a/psycopg/psycopg/pq/abc.py +++ b/psycopg/psycopg/pq/abc.py @@ -7,7 +7,7 @@ Protocol objects to represent objects exposed by different pq implementations. from typing import Any, Callable, List, Optional, Sequence, Tuple from typing import Union, TYPE_CHECKING -from ._enums import Format, PipelineStatus +from ._enums import Format from .._compat import Protocol if TYPE_CHECKING: @@ -242,7 +242,8 @@ class PGconn(Protocol): def make_empty_result(self, exec_status: int) -> "PGresult": ... - def pipeline_status(self) -> PipelineStatus: + @property + def pipeline_status(self) -> int: ... def enter_pipeline_mode(self) -> None: diff --git a/psycopg/psycopg/pq/pq_ctypes.py b/psycopg/psycopg/pq/pq_ctypes.py index 0b18f31e7..6c7b197ed 100644 --- a/psycopg/psycopg/pq/pq_ctypes.py +++ b/psycopg/psycopg/pq/pq_ctypes.py @@ -22,7 +22,7 @@ from .. import errors as e from . import _pq_ctypes as impl from .misc import PGnotify, ConninfoOption, PGresAttDesc from .misc import error_message, connection_summary -from ._enums import Format, ExecStatus, PipelineStatus +from ._enums import Format, ExecStatus if TYPE_CHECKING: from . import abc @@ -629,8 +629,11 @@ class PGconn: raise MemoryError("couldn't allocate empty PGresult") return PGresult(rv) - def pipeline_status(self) -> PipelineStatus: - return PipelineStatus(impl.PQpipelineStatus(self._pgconn_ptr)) + @property + def pipeline_status(self) -> int: + if version() < 140000: + return 0 + return impl.PQpipelineStatus(self._pgconn_ptr) def enter_pipeline_mode(self) -> None: """Enter pipeline mode. diff --git a/psycopg_c/psycopg_c/pq/pgconn.pyx b/psycopg_c/psycopg_c/pq/pgconn.pyx index c0bd78253..fe23ebb3f 100644 --- a/psycopg_c/psycopg_c/pq/pgconn.pyx +++ b/psycopg_c/psycopg_c/pq/pgconn.pyx @@ -536,15 +536,16 @@ cdef class PGconn: raise MemoryError("couldn't allocate empty PGresult") return PGresult._from_ptr(rv) - def pipeline_status(self) -> PipelineStatus: - """Return the current pipeline mode status.""" + @property + def pipeline_status(self) -> int: + """The current pipeline mode status. + + For libpq < 14.0, always return 0 (PQ_PIPELINE_OFF). + """ if libpq.PG_VERSION_NUM < 140000: - raise e.NotSupportedError( - f"PQpipelineStatus requires libpq from PostgreSQL 14," - f" {libpq.PG_VERSION_NUM} available instead" - ) + return 0 cdef int status = libpq.PQpipelineStatus(self._pgconn_ptr) - return PipelineStatus(status) + return status def enter_pipeline_mode(self) -> None: """Enter pipeline mode. diff --git a/tests/pq/test_pipeline.py b/tests/pq/test_pipeline.py index 5fe879da3..438aae3e7 100644 --- a/tests/pq/test_pipeline.py +++ b/tests/pq/test_pipeline.py @@ -5,13 +5,12 @@ from psycopg import pq @pytest.mark.libpq("< 14") -def test_unsupported(pgconn): +def test_old_libpq(pgconn): + assert pgconn.pipeline_status == 0 with pytest.raises(psycopg.NotSupportedError): pgconn.enter_pipeline_mode() with pytest.raises(psycopg.NotSupportedError): pgconn.exit_pipeline_mode() - with pytest.raises(psycopg.NotSupportedError): - pgconn.pipeline_status() with pytest.raises(psycopg.NotSupportedError): pgconn.pipeline_sync() @@ -19,6 +18,7 @@ def test_unsupported(pgconn): @pytest.mark.libpq(">= 14") def test_work_in_progress(pgconn): assert not pgconn.nonblocking + assert not pgconn.pipeline_status pgconn.enter_pipeline_mode() pgconn.send_query_params(b"select $1", [b"1"]) with pytest.raises( @@ -29,6 +29,7 @@ def test_work_in_progress(pgconn): @pytest.mark.libpq(">= 14") def test_multi_pipelines(pgconn): + assert not pgconn.pipeline_status pgconn.enter_pipeline_mode() pgconn.send_query_params(b"select $1", [b"1"]) pgconn.pipeline_sync() @@ -62,11 +63,11 @@ def test_multi_pipelines(pgconn): assert sync_result.status == pq.ExecStatus.PIPELINE_SYNC # pipeline still ON - assert pgconn.pipeline_status() == pq.PipelineStatus.ON + assert pgconn.pipeline_status == pq.PipelineStatus.ON pgconn.exit_pipeline_mode() - assert pgconn.pipeline_status() == pq.PipelineStatus.OFF + assert pgconn.pipeline_status == pq.PipelineStatus.OFF assert result1.get_value(0, 0) == b"1" assert result2.get_value(0, 0) == b"2" @@ -82,6 +83,7 @@ def table(pgconn): @pytest.mark.libpq(">= 14") def test_pipeline_abort(pgconn, table): + assert not pgconn.pipeline_status pgconn.enter_pipeline_mode() pgconn.send_query_params(b"insert into pipeline values ($1)", [b"1"]) pgconn.send_query_params(b"select no_such_function($1)", [b"1"]) @@ -107,7 +109,7 @@ def test_pipeline_abort(pgconn, table): assert pgconn.get_result() is None # pipeline should be aborted, due to previous error - assert pgconn.pipeline_status() == pq.PipelineStatus.ABORTED + assert pgconn.pipeline_status == pq.PipelineStatus.ABORTED # result from second INSERT, aborted due to previous error r = pgconn.get_result() @@ -118,7 +120,7 @@ def test_pipeline_abort(pgconn, table): assert pgconn.get_result() is None # pipeline is still aborted - assert pgconn.pipeline_status() == pq.PipelineStatus.ABORTED + assert pgconn.pipeline_status == pq.PipelineStatus.ABORTED # sync result r = pgconn.get_result() @@ -126,7 +128,7 @@ def test_pipeline_abort(pgconn, table): assert r.status == pq.ExecStatus.PIPELINE_SYNC # aborted flag is clear, pipeline is on again - assert pgconn.pipeline_status() == pq.PipelineStatus.ON + assert pgconn.pipeline_status == pq.PipelineStatus.ON # result from the third INSERT r = pgconn.get_result()