]> git.ipfire.org Git - thirdparty/psycopg.git/log
thirdparty/psycopg.git
3 years agofeat: add ConnectionInfo.pipeline_status
Daniele Varrazzo [Sun, 3 Apr 2022 21:33:55 +0000 (23:33 +0200)] 
feat: add ConnectionInfo.pipeline_status

3 years agodocs: clean up a couple of sentences
Daniele Varrazzo [Sun, 3 Apr 2022 23:26:42 +0000 (01:26 +0200)] 
docs: clean up a couple of sentences

- New version scheme is "starting from PG 10", not "after PG 10" (also,
  chunky bit moved from docstring to docs as for most other docs).
- The transaction status is of the session, not the server.

3 years agoMerge branch 'executemany-pipeline'
Daniele Varrazzo [Sat, 2 Apr 2022 23:23:30 +0000 (01:23 +0200)] 
Merge branch 'executemany-pipeline'

3 years agofeat: add PipelineAborted exception 260/head
Daniele Varrazzo [Sat, 2 Apr 2022 23:06:17 +0000 (01:06 +0200)] 
feat: add PipelineAborted exception

It is a condition that likely will have to be managed, so let's not
clobber it with other OperationalError.

3 years agofix: don't fail assert if fetching without result in pipeline mode
Daniele Varrazzo [Sat, 2 Apr 2022 01:44:26 +0000 (03:44 +0200)] 
fix: don't fail assert if fetching without result in pipeline mode

The error can be triggered easily by the user. The condition is handled
just naturally by all the methods calling _fetch_pipeline().

3 years agofix: consistent sync/exit and error management in pipeline contexts
Daniele Varrazzo [Tue, 29 Mar 2022 23:57:06 +0000 (01:57 +0200)] 
fix: consistent sync/exit and error management in pipeline contexts

Don't clobber an exception on exit of the nested block too. In order to
simplify the code, make the pipeline count the number of time it is
entered, and call _exit() only the last time it exits.

Drop assert that we have left pipeline mode leaving the block. If we get
in unrecoverable state, we will have not. By now we should probably just
close the connection; however, leaving it this way is a better
indication that the connection is broken because of something about
pipeline mode; closing it would hide it, and even if we raised a
warning, it would be much easier to miss it than to miss the exceptions
raised in broken state.

3 years agofix: forbid COPY in pipeline mode
Daniele Varrazzo [Tue, 29 Mar 2022 23:54:56 +0000 (01:54 +0200)] 
fix: forbid COPY in pipeline mode

COPY is not supported. Attempting it puts the connection in
unrecoverable state, with pipeline sync failing and pipeline exit
complaining that there are still results. So let's try to not get in
that state.

3 years agofix: restore sending a Sync on block exit but not on executemany end
Daniele Varrazzo [Tue, 29 Mar 2022 20:03:49 +0000 (22:03 +0200)] 
fix: restore sending a Sync on block exit but not on executemany end

It was removed a few commits ago, but as Denis suggests, it makes sense
to keep it. Reintroduce it (and test for it), but make sure executemany
doesn't send extra sync.

3 years agotest: add test to verify the number of roundtrips in pipelined executemany
Daniele Varrazzo [Tue, 29 Mar 2022 19:36:46 +0000 (21:36 +0200)] 
test: add test to verify the number of roundtrips in pipelined executemany

Add fixture to access the trace data as Python object. I think it's cute <3

3 years agotest: add fixture to write tests based on libpq trace data
Daniele Varrazzo [Tue, 29 Mar 2022 19:35:48 +0000 (21:35 +0200)] 
test: add fixture to write tests based on libpq trace data

3 years agofix: make no-tuple results available after executemany returning
Daniele Varrazzo [Tue, 29 Mar 2022 12:29:11 +0000 (14:29 +0200)] 
fix: make no-tuple results available after executemany returning

There could be useful info there, if the user asks for it. Now this
doesn't slow down the happy execute path, because the default of
returning is False.

3 years agofix: only flush the pipeline after executemany if returning
Daniele Varrazzo [Tue, 29 Mar 2022 12:26:26 +0000 (14:26 +0200)] 
fix: only flush the pipeline after executemany if returning

This has the side effect of breaking rowcount, as before, but can send
many executemany in the same pipeline.

`rowcount` is correct if `returning=True` is set instead, which is a
thing we can at least document, and makes sense: "if you want a result,
you flush the pipeline, dude".

3 years agorefactor: rename pipeline.communicate() -> sync()
Daniele Varrazzo [Tue, 29 Mar 2022 12:21:03 +0000 (14:21 +0200)] 
refactor: rename pipeline.communicate() -> sync()

This has the async/sync interface, is is more apt to expose it as public
interface to say "call this to restore the state" (as the changed tests
does).

Expose the try/finally logic behind sync() as the _sync_gen() method,
which can be useful to call if sync has to be performed inside a lock.

3 years agofix: keep Cursor._execmany_returning set until reset
Denis Laxalde [Tue, 29 Mar 2022 07:44:35 +0000 (09:44 +0200)] 
fix: keep Cursor._execmany_returning set until reset

Cursor's _execmany_returning attribute is now initialized at _reset()
and set during _executemany_gen_pipeline(). This way, the attribute is
kept for further results fetch that may occur outside executemany()
context: namely, this is needed because _execmany_returning is used by
_set_results_from_pipeline() which would be called by fetch*() methods.

As a consequence, in _fetch_pipeline(), actual fetch is skipped when
coming from executemany(..., returning=False) as the pgresult would
never be set. This ensures a consistent behavior by raising "no result
available" when calling fetch*() from a non-returning executemany().

3 years agofix: sync and fetch nested pipelines when they exit
Denis Laxalde [Tue, 29 Mar 2022 07:07:44 +0000 (09:07 +0200)] 
fix: sync and fetch nested pipelines when they exit

When running a nested pipeline, typically in executemany(), we now call
Pipeline.communicate() at exit similarly to a single (unnested) pipeline
but still keep the surrounding pipeline open (in contrast with unnested
one).

This resolves the issue around rowcount with returning executemany().
Accordingly, we check that rowcount is correct in test_executemany()
pipeline tests and drop the previous xfailed test.

3 years agorefactor: move final pipeline steps into a communicate() method
Denis Laxalde [Tue, 29 Mar 2022 06:53:57 +0000 (08:53 +0200)] 
refactor: move final pipeline steps into a communicate() method

3 years agotest: add missing returning=True to executemany() in pipeline tests
Denis Laxalde [Tue, 29 Mar 2022 07:00:07 +0000 (09:00 +0200)] 
test: add missing returning=True to executemany() in pipeline tests

Query in test_executemany() has a returning clause and we fetch results
from cursor after execution, so it seems the returning option to
executemany() is needed. These tests probably do not fail because of the
TODO in Cursor._set_results_from_pipeline().

3 years agodocs: add news entry about executemany() speedup
Daniele Varrazzo [Mon, 28 Mar 2022 18:07:32 +0000 (20:07 +0200)] 
docs: add news entry about executemany() speedup

3 years agotest: add xfailing test for rowcount in pipelined executemany
Daniele Varrazzo [Mon, 28 Mar 2022 18:03:55 +0000 (20:03 +0200)] 
test: add xfailing test for rowcount in pipelined executemany

3 years agofix: drop unneeded flush after executemany
Daniele Varrazzo [Mon, 28 Mar 2022 16:11:06 +0000 (18:11 +0200)] 
fix: drop unneeded flush after executemany

As per @dlax analysis, it is not needed. It was part of an attempt to
fix the problem of rowcount broken when executemany is called from within
a pipeline block, but that doesn't work anyway.

3 years agofix: fix 'executemany()' when pipeline mode is not available
Daniele Varrazzo [Sun, 27 Mar 2022 17:57:17 +0000 (19:57 +0200)] 
fix: fix 'executemany()' when pipeline mode is not available

3 years agoperf: base executemany on pipeline
Daniele Varrazzo [Sun, 27 Mar 2022 03:55:51 +0000 (05:55 +0200)] 
perf: base executemany on pipeline

This changeset also fix several glitches of executemany() run in
pipeline mode, around the management of returned value and rowcount.
These glitches still appear if executemany() is run in an explicit
pipeline() block, because certain events only happen at (outermost)
pipeline block exit.

Related to: #145.

3 years agoMerge branch 'pipeline4'
Daniele Varrazzo [Sat, 2 Apr 2022 23:22:44 +0000 (01:22 +0200)] 
Merge branch 'pipeline4'

3 years agofix: don't clobber exceptions exiting the pipeline block 175/head
Daniele Varrazzo [Sun, 27 Mar 2022 19:47:11 +0000 (21:47 +0200)] 
fix: don't clobber exceptions exiting the pipeline block

Problem found thanks to random failures in unrelated tests, e.g.
https://github.com/psycopg/psycopg/actions/runs/2048536089

3 years agofeat: add pretty repr to Pipeline objects
Daniele Varrazzo [Sun, 27 Mar 2022 20:04:47 +0000 (22:04 +0200)] 
feat: add pretty repr to Pipeline objects

3 years agofeat: add 'Pipeline.is_supported()'
Daniele Varrazzo [Sun, 27 Mar 2022 17:18:17 +0000 (19:18 +0200)] 
feat: add 'Pipeline.is_supported()'

This makes easier to write conditional code depending on whether we
support pipeline mode or not.

3 years agotest: do not catch OperationalError in test_pipeline_errors_processed_at_exit
Denis Laxalde [Sun, 27 Mar 2022 16:02:53 +0000 (18:02 +0200)] 
test: do not catch OperationalError in test_pipeline_errors_processed_at_exit

Co-authored-by: Daniele Varrazzo <daniele.varrazzo@gmail.com>
3 years agofix: better error on exit of a pipeline with broken connection
Daniele Varrazzo [Sun, 27 Mar 2022 15:35:06 +0000 (17:35 +0200)] 
fix: better error on exit of a pipeline with broken connection

Raise an OperationalError with a message "the connection is closed" rather
than "connection pointer is NULL". The exception class was right already.

3 years agorefactor: move pipeline finalisation code to Pipeline.__exit__
Daniele Varrazzo [Sun, 27 Mar 2022 15:01:11 +0000 (17:01 +0200)] 
refactor: move pipeline finalisation code to Pipeline.__exit__

This code has more internal knowledge of the Pipeline object than the
Connection object.

For some reason I don't understand, had to declare 'command_queue' and
'result_queue' types explicitly to the class definition. Leaving just the
definitions in '__init__()' causes mypy (0.940) to complain in 'cursor.py'.

3 years agotest: add support for using executemany() in pipeline demo
Denis Laxalde [Sun, 27 Mar 2022 12:17:39 +0000 (14:17 +0200)] 
test: add support for using executemany() in pipeline demo

3 years agofeat: let Connection.pipeline() return the Pipeline object
Denis Laxalde [Sun, 27 Mar 2022 10:56:40 +0000 (12:56 +0200)] 
feat: let Connection.pipeline() return the Pipeline object

In tests, add a type annotation on 'conn'/'aconn' fixture so that mypy
understands that pipeline() yields a Pipeline object.

3 years agofix: guard connection._pipeline using the connection lock
Daniele Varrazzo [Sat, 26 Mar 2022 18:02:32 +0000 (19:02 +0100)] 
fix: guard connection._pipeline using the connection lock

3 years agofix: allow re-entering pipeline mode
Daniele Varrazzo [Sat, 26 Mar 2022 17:56:31 +0000 (18:56 +0100)] 
fix: allow re-entering pipeline mode

3 years agorefactor: add and use `Cursor._set_results_from_pipeline()`
Daniele Varrazzo [Sun, 27 Mar 2022 02:48:18 +0000 (04:48 +0200)] 
refactor: add and use `Cursor._set_results_from_pipeline()`

This is a cleaner interface between the cursor and the pipeline.

3 years agorefactor: Pipeline classes moved to their module
Denis Laxalde [Sun, 27 Mar 2022 10:41:56 +0000 (12:41 +0200)] 
refactor: Pipeline classes moved to their module

3 years agotest: add support for trace file to pipeline demo
Daniele Varrazzo [Sat, 26 Mar 2022 17:08:53 +0000 (18:08 +0100)] 
test: add support for trace file to pipeline demo

3 years agoAdd support for pipeline mode in execute()/fetch*()
Denis Laxalde [Mon, 11 Oct 2021 15:16:39 +0000 (17:16 +0200)] 
Add support for pipeline mode in execute()/fetch*()

When activated on the connection, a pipeline active pipeline handles
a queue of commands to send and a queue of results to process.

The command queue simply contains Callable[[], None], which are built
from partial applications of pgconn.send_*() methods et al.

The queue of results to process either contains a None, when respective
command returns no tuple, or a tuple with respective cursor and query
information needed to maintain automatic prepared statement.

Everywhere we run the execute() generator in non-pipeline mode, we now
enqueue items in the pipeline queues. Then we run
pipeline_communicate(), through the _communicate_gen() method of
BasePipeline, in BaseCursor._execute(many)_gen().

Since pipeline_communicate() may not fetch all results, we need a
dedicated fetch (forced) step upon call to cursor.fetch*(); this is done
by Cursor._fetch_pipeline() called in fetch*() methods. This calls
PQsendFlushRequest() in order to avoid blocking on PQgetResult().

At exit of pipeline mode, we unconditionally emit a PQpipelineSync()
call in order to restore the connection in a usable state in case of
error and we force results fetch after sending any pending commands
(e.g. commands not emitted through an execute() call).

The pipeline-demo.py test script is updated to include examples using
the high-level API. This only works with the 'python' of libpq bindings
because we monkeypatch the pgconn attribute of the connection.

3 years agoAvoid multiple commands in transaction code
Denis Laxalde [Thu, 2 Dec 2021 14:13:08 +0000 (15:13 +0100)] 
Avoid multiple commands in transaction code

In pipeline mode, command strings containing multiple SQL commands are
disallowed so we remove all such usages from transaction code.

Accordingly, all generator methods in transaction classes now do not
return anything (the result was not used previously anyways).

In tests, the 'commands' list defined in patch_exec() is now filled by
appending instead of inserting so that we keep the natural order of
commands in assertions.

3 years agoSimplify query preparation cases
Denis Laxalde [Thu, 2 Dec 2021 15:28:29 +0000 (16:28 +0100)] 
Simplify query preparation cases

Eliminate on 'if' in order to only emit a single
self._send_query_prepared() call.

3 years agoReturn PIPELINE_SYNC result alone in generators.fetch_many()
Denis Laxalde [Tue, 30 Nov 2021 14:47:59 +0000 (15:47 +0100)] 
Return PIPELINE_SYNC result alone in generators.fetch_many()

3 years agoHandle pipeline-mode errors when checking results
Denis Laxalde [Mon, 11 Oct 2021 15:16:39 +0000 (17:16 +0200)] 
Handle pipeline-mode errors when checking results

In BaseCursor._check_result(), we now handle FATAL_ERROR and (the
pipeline-mode specific error) PIPELINE_ABORTED in preparation for
supporting the pipeline mode where we'd check results upon fetch*()
instead of upon execute() currently.

Similarly, BaseCursor._raise_for_result() handles PIPELINE_ABORTED
result status.

3 years agoRaise NotSupportedError when using a server-side cursor in pipeline mode
Denis Laxalde [Wed, 6 Oct 2021 11:37:43 +0000 (13:37 +0200)] 
Raise NotSupportedError when using a server-side cursor in pipeline mode

3 years agoRaise a ProgrammingError when using cursor.stream() in pipeline mode
Denis Laxalde [Wed, 6 Oct 2021 08:34:16 +0000 (10:34 +0200)] 
Raise a ProgrammingError when using cursor.stream() in pipeline mode

As suggested at [1], stream() and pipeline mode are different use cases.

[1]: https://github.com/psycopg/psycopg/pull/93#discussion_r722666980

3 years agoAdd Connection.pipeline() context manager and Pipeline object
Denis Laxalde [Wed, 8 Dec 2021 10:39:44 +0000 (11:39 +0100)] 
Add Connection.pipeline() context manager and Pipeline object

On the connection, we store the pipeline object as _pipeline attribute
when in pipeline mode or None otherwise.

3 years agoAdd pipeline_communicate() generator
Denis Laxalde [Mon, 11 Oct 2021 09:35:06 +0000 (11:35 +0200)] 
Add pipeline_communicate() generator

This generator will be used as the send operations during execute()
step when the connection is in pipeline mode. It can consume results or
send queries depending on socket read/write ready state. Queries to be
sent are in a queue of Callable[[], None] which are built from partial
application of pgconn.send_query() and similar functions.

We add a couple of unit tests, in test_generators.py along with a test
script is taken from PostgreSQL sources. It demonstrates the use of
pipeline mode where query-send and results-fetch steps are interleaved
without any sync point emitted. (In this test, this works because the
output buffer gets full.) The test writes data to logs. Typically, we'd
get:

    enter pipeline
    sent BEGIN TRANSACTION
    sent DROP TABLE IF EXISTS pq_pipeline_demo
    sent CREATE UNLOGGED TABLE pq_pipeline_demo( id serial primary key, itemno integer, int8filler int8)
    prepare INSERT INTO pq_pipeline_demo(itemno, int8filler) VALUES ($1, $2) as 'prepare'
    sent prepared 'prepare' with [b'10000', b'4611686018427387904']
    sent prepared 'prepare' with [b'9999', b'4611686018427387904']
    sent prepared 'prepare' with [b'9998', b'4611686018427387904']
    sent prepared 'prepare' with [b'9997', b'4611686018427387904']
    sent prepared 'prepare' with [b'9996', b'4611686018427387904']
    sent prepared 'prepare' with [b'9995', b'4611686018427387904']
    sent prepared 'prepare' with [b'9994', b'4611686018427387904']
    sent prepared 'prepare' with [b'9993', b'4611686018427387904']
    sent prepared 'prepare' with [b'9992', b'4611686018427387904']
    ...
    sent prepared 'prepare' with [b'9690', b'4611686018427387904']
    sent prepared 'prepare' with [b'9689', b'4611686018427387904']
    sent prepared 'prepare' with [b'9688', b'4611686018427387904']
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    ...
    got COMMAND_OK results
    got COMMAND_OK results
    sent prepared 'prepare' with [b'9687', b'4611686018427387904']
    sent prepared 'prepare' with [b'9686', b'4611686018427387904']
    sent prepared 'prepare' with [b'9685', b'4611686018427387904']
    sent prepared 'prepare' with [b'9684', b'4611686018427387904']
    sent prepared 'prepare' with [b'9683', b'4611686018427387904']
    ...
    sent prepared 'prepare' with [b'2', b'4611686018427387904']
    sent prepared 'prepare' with [b'1', b'4611686018427387904']
    sent COMMIT
    pipeline sync sent
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    got COMMAND_OK results
    ...
    got COMMAND_OK results
    got COMMAND_OK results
    got PIPELINE_SYNC results
    exit pipeline

We can see that commands are sent, until the output buffer is full (the
connection is then Read-ready only), then results are fetched, until
more commands can be sent, and the cycle repeat.

3 years agodocs: add ConnectionTimeout documentation
Daniele Varrazzo [Sat, 2 Apr 2022 22:58:05 +0000 (00:58 +0200)] 
docs: add ConnectionTimeout documentation

3 years agodocs: add page with misc objects documentation
Daniele Varrazzo [Sat, 2 Apr 2022 22:55:18 +0000 (00:55 +0200)] 
docs: add page with misc objects documentation

Sorry that I broke some links, but the connection page was becoming
unwieldy.

3 years agoci: print versions of depending packages on psycopg-binary build
Daniele Varrazzo [Thu, 31 Mar 2022 19:34:27 +0000 (21:34 +0200)] 
ci: print versions of depending packages on psycopg-binary build

Only on manylinux and musllinux images for the moment.

See #262

3 years agochore: upgrade cibuildwheel to 2.3.1
Daniele Varrazzo [Wed, 30 Mar 2022 15:08:43 +0000 (17:08 +0200)] 
chore: upgrade cibuildwheel to 2.3.1

3 years agobuild: upgrade system packages before building psycopg-binary
Daniele Varrazzo [Wed, 30 Mar 2022 14:53:30 +0000 (16:53 +0200)] 
build: upgrade system packages before building psycopg-binary

See #262

3 years agochore: bump version number to 3.0.11
Daniele Varrazzo [Tue, 29 Mar 2022 21:06:52 +0000 (23:06 +0200)] 
chore: bump version number to 3.0.11

3 years agoci: upgrade black
Daniele Varrazzo [Tue, 29 Mar 2022 01:21:40 +0000 (03:21 +0200)] 
ci: upgrade black

This version is not affected by https://github.com/psf/black/issues/2964
and doesn't require pinning click.

3 years agofix: default executemany to not fetching results
Daniele Varrazzo [Mon, 28 Mar 2022 16:54:26 +0000 (18:54 +0200)] 
fix: default executemany to not fetching results

This is a change from before, but the feature has not been released yet,
so we are still in time to change it.

The change addresses some uneasy feeling about unexpected increased
memory usage (see #164) and may prove a win in combination with the
optimization happening in pipeline mode.

So, if the user is not asking for it, let's not provide it.

3 years agoci: pin click dependency to fix black
Daniele Varrazzo [Mon, 28 Mar 2022 18:35:46 +0000 (20:35 +0200)] 
ci: pin click dependency to fix black

See https://github.com/psf/black/issues/2964

3 years agodocs: use monotype style for parameter names
Daniele Varrazzo [Mon, 28 Mar 2022 17:45:26 +0000 (19:45 +0200)] 
docs: use monotype style for parameter names

The convention of using italic is more a math thing. In the currently
rendered docs, ``param`` also get rendered in bold rather than italic,
so there is just no connection to anything else on the page.

A :param:`name` role would be nice. Maybe rendered in
monospace+italic...

3 years agotest: display the version of the server tests are run against
Daniele Varrazzo [Sun, 27 Mar 2022 18:52:57 +0000 (20:52 +0200)] 
test: display the version of the server tests are run against

3 years agodocs: fix grammar, to allow to connect -> connecting
Daniele Varrazzo [Sun, 27 Mar 2022 16:32:03 +0000 (18:32 +0200)] 
docs: fix grammar, to allow to connect -> connecting

Fixed by @xenups. Proposed together with a bunch of unrelated changes
probably suggested by some useless AI tool; singling this out.

Close #250.

3 years agofeat(copy): allow bytearray/memoryview as copy.write() input
Daniele Varrazzo [Sat, 26 Mar 2022 00:56:49 +0000 (01:56 +0100)] 
feat(copy): allow bytearray/memoryview as copy.write() input

The C implementation can deal with these types efficiently and it may
save a memcopy if that's what the user has available.

Close #254

3 years agorefactor: use TypeAlias
Daniele Varrazzo [Sat, 26 Mar 2022 02:28:19 +0000 (03:28 +0100)] 
refactor: use TypeAlias

Upgrade mypy min requirements to 0.940, which is the first supporting
TypeAlias after a few broken releases.

3 years agodocs: add back lost comment and extend it with new knowledge
Daniele Varrazzo [Sat, 26 Mar 2022 01:32:31 +0000 (02:32 +0100)] 
docs: add back lost comment and extend it with new knowledge

3 years agoperf: release the GIL in copy-related libpq functions
Daniele Varrazzo [Sat, 26 Mar 2022 00:18:05 +0000 (01:18 +0100)] 
perf: release the GIL in copy-related libpq functions

Tests have shown that these functions may do a considerable amount of
work, although purely CPU.

3 years agoMerge branch 'fix-255'
Daniele Varrazzo [Sat, 26 Mar 2022 01:11:25 +0000 (02:11 +0100)] 
Merge branch 'fix-255'

3 years agofix(copy): chunk large buffers before queuing, not after 256/head
Daniele Varrazzo [Fri, 25 Mar 2022 15:57:28 +0000 (16:57 +0100)] 
fix(copy): chunk large buffers before queuing, not after

This is conceptually a better place to do it, because the queue has the
function of applying backpressure on the data generator. Splitting large
buffers later would flood the libpq without effectively slowing down the
producer.

Also, reduce the size of the chunks appended to the libpq from 1Mb to
128K. This makes an *immense* difference: the too large chunk probably
triggers some quadraticity in the libpq. The test script found in #255,
piped in `ts -s`, shows that pushing a block of data of about 1Gb size
(which will fail in Postgres anyway), with the smaller size, will take
about 9s. With the larger size, it takes 4.10m to get to waiting for
PQputCopyEnd, and other almost 6 minutes to receive the error message
from the server.

    00:00:47 putting 1048576 (or less) bytes in queue size 1023
    00:00:47 writing copy end
    00:00:47 got 1048576 bytes from queue size 1023
    ...
    00:01:25 got 1048576 bytes from queue size 640
    ...
    00:01:54 got 1048576 bytes from queue size 512
    ...
    00:03:00 got 1048576 bytes from queue size 256
    ...
    00:04:12 got 0 bytes from queue size 0
    00:04:12 wait for copy end
    00:09:59 Traceback (most recent call last):
    ...

Adding a few prints (see #255 for details) also shows that the time
spent in PQputCopyData increases, going from ~15 entries/sec processed
when the writer has just finished pushing data in the queue, down to ~4
items/sec towards the end.

Considering that a reduction of 10-20% of the input size causes a
decrease of the processing time of about 50%, there is definitely
something quadratic going on there. It might be possible to improve the
libpq, but for the moment it's better to try and coexist nicely with the
current state.

3 years agofix(copy): split large buffers before sending them to PQputCopyData
Daniele Varrazzo [Thu, 24 Mar 2022 13:01:58 +0000 (14:01 +0100)] 
fix(copy): split large buffers before sending them to PQputCopyData

Sending excessively large data doesn't allow the libpq to flush its
content to the server, ending up in an infinite loop.

Close #255

3 years agofix(copy): propagate errors raised in the worker thread
Daniele Varrazzo [Thu, 24 Mar 2022 15:52:05 +0000 (16:52 +0100)] 
fix(copy): propagate errors raised in the worker thread

Previously, an error in the worker thread was printed to stderr, but
processing continued, for no result but no exception.

Problem found in #255, but unrelated to it.

3 years agodocs: drop outdated docstring description
Daniele Varrazzo [Tue, 22 Mar 2022 16:02:55 +0000 (17:02 +0100)] 
docs: drop outdated docstring description

3 years agobuild(docs): don't exit with success if building html docs failed
Daniele Varrazzo [Sun, 20 Mar 2022 11:32:36 +0000 (12:32 +0100)] 
build(docs): don't exit with success if building html docs failed

Responsible of 2020-03-19 docs downtime. See #252.

This commit is expected to fail linting if committed before
17f9703380ed4aed3ce88ba1e9f68a46b911dede and to succeed when rebased
after it.

...it doesn't: can't quite trigger a failure in Github Actions, although,
locally, "it fails correctly". Merging anyway.

3 years agofix: fix loading of text arrays with dimension information
Daniele Varrazzo [Sun, 20 Mar 2022 00:32:25 +0000 (01:32 +0100)] 
fix: fix loading of text arrays with dimension information

The dimension information is a prefix such as ``[0:2]=`` in front of the
array. We just discard it when loading to lists, because for Python they
are always 0-based.

https://www.postgresql.org/docs/14/arrays.html#ARRAYS-IO

Close #253.

3 years agofix: install typing_extensions on Python < 3.10
Daniele Varrazzo [Sat, 19 Mar 2022 22:11:07 +0000 (23:11 +0100)] 
fix: install typing_extensions on Python < 3.10

For some reasons tests pass, but it's necessary.

Close #252.

3 years agoMerge branch 'pgconn-in-exception'
Daniele Varrazzo [Sat, 19 Mar 2022 15:06:55 +0000 (16:06 +0100)] 
Merge branch 'pgconn-in-exception'

3 years agodocs: document PGconn needs_password and used_password attributes
Denis Laxalde [Sat, 19 Mar 2022 08:46:58 +0000 (09:46 +0100)] 
docs: document PGconn needs_password and used_password attributes

This improves the documentation of Error class, which refers to those
in the new pgconn attribute documentation.

3 years agodocs: specify that ANY() is available in psycopg2 too
Daniele Varrazzo [Fri, 18 Mar 2022 16:00:51 +0000 (17:00 +0100)] 
docs: specify that ANY() is available in psycopg2 too

3 years agodoc: give more context to disconnection detection recipe
poulpe [Thu, 17 Mar 2022 13:18:46 +0000 (14:18 +0100)] 
doc: give more context to disconnection detection recipe

3 years agodocs: add docs for `Error.pgconn` and `Error.pgresult`
Daniele Varrazzo [Sun, 13 Mar 2022 00:10:46 +0000 (00:10 +0000)] 
docs: add docs for `Error.pgconn` and `Error.pgresult`

3 years agofeat: add `Error.pgresult` property
Daniele Varrazzo [Sat, 12 Mar 2022 22:57:55 +0000 (22:57 +0000)] 
feat: add `Error.pgresult` property

It might be useful for the same reason `pgconn` is.

For symmetry convert `pgconn` to a read-only attribute too.

3 years agofeat: add `Error.pgconn` attribute
Daniele Varrazzo [Fri, 11 Mar 2022 19:48:08 +0000 (19:48 +0000)] 
feat: add `Error.pgconn` attribute

Might be useful to investigate errors such as bad/missing password. See #242
for details.

3 years agodoc: fix duplications in class exceptions table titles
Daniele Varrazzo [Sun, 13 Mar 2022 00:29:09 +0000 (00:29 +0000)] 
doc: fix duplications in class exceptions table titles

3 years agofix(c): fix portable endian aliases on different BSD flavours
Daniele Varrazzo [Fri, 11 Mar 2022 20:07:03 +0000 (20:07 +0000)] 
fix(c): fix portable endian aliases on different BSD flavours

See the commit at:
https://github.com/linux-sunxi/sunxi-tools/commit/384ff6473455da1a24b5037b358591f44f3bbf57

Close #241

3 years agochore: bump version number to 3.0.10
Daniele Varrazzo [Thu, 3 Mar 2022 01:53:41 +0000 (01:53 +0000)] 
chore: bump version number to 3.0.10

3 years agodoc: fix typo in comment
Daniele Varrazzo [Wed, 2 Mar 2022 23:48:15 +0000 (23:48 +0000)] 
doc: fix typo in comment

3 years agofix: don't raise error accessing Cursor.description after COPY_OUT
Daniele Varrazzo [Wed, 2 Mar 2022 00:48:30 +0000 (00:48 +0000)] 
fix: don't raise error accessing Cursor.description after COPY_OUT

COPY_OUT result advertises the number of columns but not their names (or
types). Use a surrogate name for description (which is more useful than
returning `None`, because at lest it tells how many columns were
emitted).

Close #235.

3 years agoMerge branch 'fix-231'
Daniele Varrazzo [Wed, 2 Mar 2022 02:53:06 +0000 (02:53 +0000)] 
Merge branch 'fix-231'

3 years agotest(win32): skip Ctrl-C test on Windows
Daniele Varrazzo [Wed, 2 Mar 2022 00:57:51 +0000 (00:57 +0000)] 
test(win32): skip Ctrl-C test on Windows

As much as I've tried, haven't been able to send a Ctrl-C. Tests fail on
"ctrl-c not received".

3 years agofix: Cancel query on Ctrl-C
Daniele Varrazzo [Tue, 22 Feb 2022 03:02:13 +0000 (04:02 +0100)] 
fix: Cancel query on Ctrl-C

On KeyboardInterrupt, send a cancel to the server and keep waiting for
the result of the cancel, which is expected to raise a QueryCanceled,
then re-raise KeyboardInterrupt.

Before this, the connection was left in ACTIVE state, so it couldn't be rolled
back.

Only fixed on sync connections. Left a failing test for async
connections; the test fails with an output from the script such as:

    error ignored in rollback on <psycopg.AsyncConnection [ACTIVE] ...>:
    sending query failed: another command is already in progress
    Traceback (most recent call last):
      File "<string>", line 27, in <module>
      File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
        return loop.run_until_complete(main)
      File "/usr/lib/python3.8/asyncio/base_events.py", line 603, in run_until_complete
        self.run_forever()
      File "/usr/lib/python3.8/asyncio/base_events.py", line 570, in run_forever
        self._run_once()
      File "/usr/lib/python3.8/asyncio/base_events.py", line 1823, in _run_once
        event_list = self._selector.select(timeout)
      File "/usr/lib/python3.8/selectors.py", line 468, in select
        fd_event_list = self._selector.poll(timeout, max_ev)
    KeyboardInterrupt

And the except branch in `AsyncConnection.wait()` is not reached.

See #231

3 years agochore(pool): bump to next rev release
Daniele Varrazzo [Sat, 19 Feb 2022 18:04:28 +0000 (19:04 +0100)] 
chore(pool): bump to next rev release

3 years agodocs: declare psycopg 3.0.9 released
Daniele Varrazzo [Sat, 19 Feb 2022 17:52:18 +0000 (18:52 +0100)] 
docs: declare psycopg 3.0.9 released

3 years agochore(pool): Bump pool version to 3.1.1 pool-3.1.1
Daniele Varrazzo [Sat, 19 Feb 2022 17:23:48 +0000 (18:23 +0100)] 
chore(pool):  Bump pool version to 3.1.1

3 years agorefactor(pool): update some debug logging
Daniele Varrazzo [Sat, 19 Feb 2022 17:19:31 +0000 (18:19 +0100)] 
refactor(pool): update some debug logging

Drop debug logging on `MaintenanceTask.init()`, which is not
particularly useful. Add debug entries on tasks `run()` early bailout,
which is a more interesting condition to follow (and would have allowed
to spot #230 more easily).

3 years agoMerge branch 'fix-230'
Daniele Varrazzo [Sat, 19 Feb 2022 17:03:55 +0000 (18:03 +0100)] 
Merge branch 'fix-230'

Close #230.

3 years agofix(pool): set the open flag before starting the maintenance tasks
Daniele Varrazzo [Sat, 19 Feb 2022 16:34:37 +0000 (17:34 +0100)] 
fix(pool): set the open flag before starting the maintenance tasks

Failing to do so we might trigger the test in `MaintenanceTask.run()`
and find the pool closed, so discard the operation. It usually doesn't
happen, but with a few combination of IO operation it does happen: see
https://github.com/psycopg/psycopg/issues/230 for details.

3 years agotest(pool): add test to show deadlock on logging
Daniele Varrazzo [Sat, 19 Feb 2022 14:39:37 +0000 (15:39 +0100)] 
test(pool): add test to show deadlock on logging

This deadlock seems reproducible at least on Python 3.8 and 3.10 on
Linux. It is caused by the logging statement in
``MaintenanceTask.__init__``: even just a ``print()`` there causes the lock.

See https://github.com/psycopg/psycopg/issues/230 for more details.

3 years agochore(pool): bump to next pool version
Daniele Varrazzo [Sat, 19 Feb 2022 14:38:48 +0000 (15:38 +0100)] 
chore(pool): bump to next pool version

3 years agoMore regular and compact auto-generated exceptions
Daniele Varrazzo [Sat, 12 Feb 2022 17:55:09 +0000 (18:55 +0100)] 
More regular and compact auto-generated exceptions

Also drop unneeded flake8 config file.

3 years agoSet up the sqlstate-exception mapping using init_subclass
Daniele Varrazzo [Fri, 11 Feb 2022 22:16:51 +0000 (23:16 +0100)] 
Set up the sqlstate-exception mapping using init_subclass

3 years agoMerge branch 'fix-225'
Daniele Varrazzo [Fri, 11 Feb 2022 20:33:14 +0000 (21:33 +0100)] 
Merge branch 'fix-225'

3 years agoAdd doc section to refer to the exceptions list
Daniele Varrazzo [Fri, 11 Feb 2022 19:32:55 +0000 (20:32 +0100)] 
Add doc section to refer to the exceptions list

Also clarify Error.sqlstate and further errors doc cleanup.

3 years agoSet Error.sqlcode when unknown codes are received
Daniele Varrazzo [Fri, 11 Feb 2022 19:27:40 +0000 (20:27 +0100)] 
Set Error.sqlcode when unknown codes are received

Close #225.

3 years agoMake the tzdata package a dependency on Windows
Daniele Varrazzo [Wed, 9 Feb 2022 21:03:35 +0000 (22:03 +0100)] 
Make the tzdata package a dependency on Windows

The package replaces the missing system tz database and allows to avoid
the warning and return timestamps in the client timezone instead of in
UTC.

Close #223

3 years agoSet workflows to cancel jobs on the same branch
Daniele Varrazzo [Fri, 11 Feb 2022 00:41:09 +0000 (01:41 +0100)] 
Set workflows to cancel jobs on the same branch

Docs at https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency

3 years agoMerge pull request #224 from The-One-And-Only-H/asyncio-fix
Daniele Varrazzo [Fri, 11 Feb 2022 00:10:36 +0000 (01:10 +0100)] 
Merge pull request #224 from The-One-And-Only-H/asyncio-fix

Fix failures caused by the pytest-asyncio now raising a warning when a sync
function is marked asyncio.