]> git.ipfire.org Git - thirdparty/psycopg.git/log
thirdparty/psycopg.git
4 years agoSplit the pool package objects in modules
Daniele Varrazzo [Thu, 25 Feb 2021 19:36:48 +0000 (20:36 +0100)] 
Split the pool package objects in modules

4 years agoMove task implementations to the pool object
Daniele Varrazzo [Thu, 25 Feb 2021 19:11:56 +0000 (20:11 +0100)] 
Move task implementations to the pool object

4 years agoMake psycopg3.pool a package
Daniele Varrazzo [Thu, 25 Feb 2021 17:31:16 +0000 (18:31 +0100)] 
Make psycopg3.pool a package

4 years agoUse the daemon param at constructor rather than the attribute
Daniele Varrazzo [Tue, 23 Feb 2021 22:39:44 +0000 (23:39 +0100)] 
Use the daemon param at constructor rather than the attribute

4 years agoUse the connections in the pool uniformly
Daniele Varrazzo [Mon, 22 Feb 2021 03:20:33 +0000 (04:20 +0100)] 
Use the connections in the pool uniformly

I feel this is a better use than using some more than other (e.g. in
term of bloat of the connections associated with the resources) and
gives a more predictable performance of the connection (there won't be
some cold, some hot).

Now there aren't really "unused connections" to single out in order to
shrink the pool. So keep a tally of the number of connections unused and
use a worker thread to close some if there are above minconn unused in a
period.

4 years agoChange state in critical section on pool.close()
Daniele Varrazzo [Mon, 22 Feb 2021 01:49:16 +0000 (02:49 +0100)] 
Change state in critical section on pool.close()

Nothing bad should happen, because what maintains the state respect the
_closed state. However because the logic is complex make it more
defensive.

4 years agoMake any pool task schedulable
Daniele Varrazzo [Mon, 22 Feb 2021 01:33:36 +0000 (02:33 +0100)] 
Make any pool task schedulable

Added interface to the pool to schedule a task in the future.

4 years agoDon't lose pool connections giving them to a clients already timed out
Daniele Varrazzo [Mon, 22 Feb 2021 01:05:14 +0000 (02:05 +0100)] 
Don't lose pool connections giving them to a clients already timed out

4 years agoAllow proxy tests to fail on Travis
Daniele Varrazzo [Sun, 21 Feb 2021 13:04:10 +0000 (14:04 +0100)] 
Allow proxy tests to fail on Travis

Don't know why it fails, it requires interactive investigation there.
Make sure tests can run connecting on TCP socket and avoid SSH in the
proxy anyway. Not that any of this worked...

4 years agoWait worker thread to stop on pool close
Daniele Varrazzo [Sun, 21 Feb 2021 12:41:02 +0000 (13:41 +0100)] 
Wait worker thread to stop on pool close

4 years agoDon't print warning gc'ing a pool in incomplete state
Daniele Varrazzo [Sun, 21 Feb 2021 12:07:58 +0000 (13:07 +0100)] 
Don't print warning gc'ing a pool in incomplete state

4 years agopool.close() called on del, idemptotent
Daniele Varrazzo [Sun, 21 Feb 2021 03:48:03 +0000 (04:48 +0100)] 
pool.close() called on del, idemptotent

4 years agoAdd separate setup_timeout param for pool
Daniele Varrazzo [Sun, 21 Feb 2021 03:47:20 +0000 (04:47 +0100)] 
Add separate setup_timeout param for pool

Allow 0 too, which would fill the pool in background.

4 years agoDrop _sec suffix from pool timeouts
Daniele Varrazzo [Sun, 21 Feb 2021 03:28:01 +0000 (04:28 +0100)] 
Drop _sec suffix from pool timeouts

Python is consistent enough to use seconds everywhere timeouts are
involved.

4 years agoAdd pool reconnection retry
Daniele Varrazzo [Sun, 21 Feb 2021 03:26:00 +0000 (04:26 +0100)] 
Add pool reconnection retry

4 years agoDon't try to rollback on exit if the connection is bad
Daniele Varrazzo [Sun, 21 Feb 2021 03:20:38 +0000 (04:20 +0100)] 
Don't try to rollback on exit if the connection is bad

4 years agoUse a weak reference to avoid loops between pool and maintenance tasks
Daniele Varrazzo [Sun, 21 Feb 2021 01:17:41 +0000 (02:17 +0100)] 
Use a weak reference to avoid loops between pool and maintenance tasks

4 years agoAdd scheduler class
Daniele Varrazzo [Sat, 20 Feb 2021 23:07:10 +0000 (00:07 +0100)] 
Add scheduler class

To be used in the connection pool to implement reconnection with
backoff, maybe periodic tasks.

4 years agoAdd test for pool kwargs
Daniele Varrazzo [Sat, 20 Feb 2021 03:36:13 +0000 (04:36 +0100)] 
Add test for pool kwargs

4 years agoDefault number of pool workers bumped to 3
Daniele Varrazzo [Sat, 20 Feb 2021 03:31:02 +0000 (04:31 +0100)] 
Default number of pool workers bumped to 3

4 years agoShrink the pool when connections have been idle long enough
Daniele Varrazzo [Sat, 20 Feb 2021 03:16:27 +0000 (04:16 +0100)] 
Shrink the pool when connections have been idle long enough

Pool behaviour on start changed: block on __init__ until minconn
connections have been obtained or raise PoolTimeout if timeout_sec have
passed. Not doing so makes complicated to understand, when a connection
is requested, if it's done during initialisation, and avoid an unneeded
grow request.

4 years agoDon't waste a worker thread adding a connection to the pool
Daniele Varrazzo [Sat, 20 Feb 2021 00:47:00 +0000 (01:47 +0100)] 
Don't waste a worker thread adding a connection to the pool

4 years agoForce pool num_workers to be > 0
Daniele Varrazzo [Sat, 20 Feb 2021 00:19:35 +0000 (01:19 +0100)] 
Force pool num_workers to be > 0

it might work with num_workers = 0, however it's not trivial, there is
some deadlock to avoid at creation time.

4 years agoAllow the pool to grow
Daniele Varrazzo [Fri, 19 Feb 2021 23:35:27 +0000 (00:35 +0100)] 
Allow the pool to grow

4 years agoMake the pool maintenance tasks base class abstract
Daniele Varrazzo [Sun, 14 Feb 2021 02:33:19 +0000 (03:33 +0100)] 
Make the pool maintenance tasks base class abstract

4 years agoDelete an eventual task-pool loop in StopWorker too
Daniele Varrazzo [Sun, 14 Feb 2021 02:27:30 +0000 (03:27 +0100)] 
Delete an eventual task-pool loop in StopWorker too

4 years agoAdd pool docstrings
Daniele Varrazzo [Sun, 14 Feb 2021 02:25:56 +0000 (03:25 +0100)] 
Add pool docstrings

4 years agoAdd connection pool close()
Daniele Varrazzo [Sun, 14 Feb 2021 01:22:20 +0000 (02:22 +0100)] 
Add connection pool close()

When the pool is closed, raise an exception in the thread of the clients
already waiting and refuse new requests. Let the current request finish
anyway.

4 years agoMake sure the pool can be deleted with no warning
Daniele Varrazzo [Sat, 13 Feb 2021 23:45:50 +0000 (00:45 +0100)] 
Make sure the pool can be deleted with no warning

Make sure to delete reference loops between the pool and the maintenance
tasks after they have run.

Do not raise a warning if a connection in a pool is deleted without
being closed as this is a normal condition (imagining a pool being
created as a global object).

4 years agoAdd pool context test
Daniele Varrazzo [Sat, 13 Feb 2021 22:51:02 +0000 (23:51 +0100)] 
Add pool context test

4 years agoAwake the pool client outside the critical section
Daniele Varrazzo [Sat, 13 Feb 2021 22:42:00 +0000 (23:42 +0100)] 
Awake the pool client outside the critical section

4 years agoReset the connection status returning it to the pool
Daniele Varrazzo [Sat, 13 Feb 2021 22:07:54 +0000 (23:07 +0100)] 
Reset the connection status returning it to the pool

4 years agoAdd basic pool functionality test for queuing and timeout
Daniele Varrazzo [Sat, 13 Feb 2021 17:02:08 +0000 (18:02 +0100)] 
Add basic pool functionality test for queuing and timeout

4 years agoDisplay the name in the connection pool repr
Daniele Varrazzo [Sat, 13 Feb 2021 16:17:28 +0000 (17:17 +0100)] 
Display the name in the connection pool repr

4 years agoAdd ConnectionPool class sketch
Daniele Varrazzo [Sat, 13 Feb 2021 03:06:54 +0000 (04:06 +0100)] 
Add ConnectionPool class sketch

It has a pool of connections alright, workers, clients waiting list.

Only minconn implemented, no maintenance thread etc. It's a start.

4 years ago@logilab is backing psycopg3!
Daniele Varrazzo [Mon, 8 Mar 2021 21:37:50 +0000 (22:37 +0100)] 
@logilab is backing psycopg3!

Merci beaucoup!

4 years agoWelcoming @dalibo as backer
Daniele Varrazzo [Mon, 8 Mar 2021 21:29:45 +0000 (22:29 +0100)] 
Welcoming @dalibo as backer

Vive la France!

4 years agoFix concurrency test
Daniele Varrazzo [Sat, 6 Mar 2021 02:08:54 +0000 (03:08 +0100)] 
Fix concurrency test

It was blocking because the committer was a too busy loop never yielding
to the other worker.

4 years agoUse gather instead of wait in tests to be coro friendly
Daniele Varrazzo [Sat, 6 Mar 2021 02:08:33 +0000 (03:08 +0100)] 
Use gather instead of wait in tests to be coro friendly

4 years agoBump mypy version
Daniele Varrazzo [Sat, 6 Mar 2021 01:09:39 +0000 (02:09 +0100)] 
Bump mypy version

4 years agoci: get token to rebuild docs from secrets
Daniele Varrazzo [Sat, 6 Mar 2021 00:26:55 +0000 (01:26 +0100)] 
ci: get token to rebuild docs from secrets

4 years agoMerge branch 'ci-gh-actions'
Daniele Varrazzo [Sat, 6 Mar 2021 00:13:59 +0000 (01:13 +0100)] 
Merge branch 'ci-gh-actions'

4 years agoYaml lint
Daniele Varrazzo [Tue, 2 Mar 2021 11:38:05 +0000 (12:38 +0100)] 
Yaml lint

4 years agoRun leak tests with both text and binary output
Daniele Varrazzo [Fri, 5 Mar 2021 17:46:30 +0000 (18:46 +0100)] 
Run leak tests with both text and binary output

At the moment the output text is actually skipped but it will run once
text input is no more xfailed.

4 years agoFix binary argument of conn.cursor() in tests
Denis Laxalde [Tue, 2 Mar 2021 11:12:31 +0000 (12:12 +0100)] 
Fix binary argument of conn.cursor() in tests

Argument 'binary' of connection.cursor() should be a bool.
This follows up on 467d20bd0315a62b4c7377d8a0b170ece08ef99c (change from
'format' to 'binary').

4 years agoci: consistent uppercase in steps titles 36/head
Daniele Varrazzo [Tue, 2 Mar 2021 02:10:07 +0000 (03:10 +0100)] 
ci: consistent uppercase in steps titles

4 years agoci: Test with Python 3.9 and PostgreSQL 13
Daniele Varrazzo [Tue, 2 Mar 2021 01:49:30 +0000 (02:49 +0100)] 
ci: Test with Python 3.9 and PostgreSQL 13

Test different combination of Python and Postgres in the different
implementation to cover more cases.

4 years agoci: Allow lint and test on any branch
Daniele Varrazzo [Tue, 2 Mar 2021 01:41:39 +0000 (02:41 +0100)] 
ci: Allow lint and test on any branch

4 years agoci: colour tests output
Daniele Varrazzo [Tue, 2 Mar 2021 01:30:53 +0000 (02:30 +0100)] 
ci: colour tests output

4 years agotox: use the github action "python" value as toxenv name
Daniele Varrazzo [Tue, 2 Mar 2021 01:28:50 +0000 (02:28 +0100)] 
tox: use the github action "python" value as toxenv name

4 years agoci; Use PG* env vars to define the connection string
Daniele Varrazzo [Tue, 2 Mar 2021 00:55:16 +0000 (01:55 +0100)] 
ci; Use PG* env vars to define the connection string

4 years agoci: Fix test dsn
Daniele Varrazzo [Tue, 2 Mar 2021 00:23:11 +0000 (01:23 +0100)] 
ci: Fix test dsn

The github runner /etc/host file is pretty broken and localhost resolves
to ipv6, so use 127.0.0.1 to connect.

4 years agoci: sort out connection to postgresql service
Riccardo Magliocchetti [Mon, 1 Mar 2021 08:56:13 +0000 (09:56 +0100)] 
ci: sort out connection to postgresql service

4 years agoci: split tests in one job for each implementation
Riccardo Magliocchetti [Mon, 1 Mar 2021 08:37:33 +0000 (09:37 +0100)] 
ci: split tests in one job for each implementation

To simplify the matrix

4 years agoci: move tests to gh actions
Riccardo Magliocchetti [Sun, 28 Feb 2021 19:05:24 +0000 (20:05 +0100)] 
ci: move tests to gh actions

4 years agoci: move docs building to gh actions
Riccardo Magliocchetti [Sun, 28 Feb 2021 18:26:56 +0000 (19:26 +0100)] 
ci: move docs building to gh actions

4 years agoci: move lint task to gh actions
Riccardo Magliocchetti [Sun, 28 Feb 2021 18:26:27 +0000 (19:26 +0100)] 
ci: move lint task to gh actions

4 years agoUpdate script to trigger docs rebuild to use travis-ci.com
Daniele Varrazzo [Mon, 1 Mar 2021 00:38:37 +0000 (01:38 +0100)] 
Update script to trigger docs rebuild to use travis-ci.com

4 years agoRetry server-side cursor tests on del
Daniele Varrazzo [Sun, 28 Feb 2021 14:12:18 +0000 (15:12 +0100)] 
Retry server-side cursor tests on del

Warnings seem unreliably to receive. Also print any eventual unexpected
warning: pytest doesn't do it automatically.

4 years agoAdd fixture to help retrying flaky tests
Daniele Varrazzo [Sun, 28 Feb 2021 14:11:13 +0000 (15:11 +0100)] 
Add fixture to help retrying flaky tests

Tried to use a couple of pytest plugins for retrying but they don't work
well with asyncio.

4 years agoMake the DBAPI errors appear defined in the psycopg3 module
Daniele Varrazzo [Sun, 28 Feb 2021 02:17:54 +0000 (03:17 +0100)] 
Make the DBAPI errors appear defined in the psycopg3 module

4 years agoDrop psycopg3.pq.PQerror
Daniele Varrazzo [Sun, 28 Feb 2021 02:15:30 +0000 (03:15 +0100)] 
Drop psycopg3.pq.PQerror

Use an OperationalError instead (of which PQerror was a subclass), which
is better documented.

4 years agoAdd doc example about how to detect a disconnection
Daniele Varrazzo [Sun, 28 Feb 2021 01:35:23 +0000 (02:35 +0100)] 
Add doc example about how to detect a disconnection

4 years agoAdd Connection.fileno()
Daniele Varrazzo [Sun, 28 Feb 2021 00:36:34 +0000 (01:36 +0100)] 
Add Connection.fileno()

4 years agoFix return error without exception on PQsocket call of broken connection
Daniele Varrazzo [Sun, 21 Feb 2021 01:16:28 +0000 (02:16 +0100)] 
Fix return error without exception on PQsocket call of broken connection

Still some weirdness here around: the method raises an exception on my
box (both with unix and tcp socket) but it seems to raise still a valid
number on certain databases on Travis. Make sure, in the test, at least
that it is a reasonable value.

4 years agoFix documentation of Cursor.pgresult
Daniele Varrazzo [Wed, 24 Feb 2021 18:42:50 +0000 (19:42 +0100)] 
Fix documentation of Cursor.pgresult

4 years agoMerge branch 'row-factory'
Daniele Varrazzo [Wed, 24 Feb 2021 18:33:51 +0000 (19:33 +0100)] 
Merge branch 'row-factory'

4 years agoAdd tuple_row test 32/head
Daniele Varrazzo [Wed, 24 Feb 2021 18:22:50 +0000 (19:22 +0100)] 
Add tuple_row test

4 years agoMake the nametuple_row() test independent from other tests
Daniele Varrazzo [Wed, 24 Feb 2021 18:19:16 +0000 (19:19 +0100)] 
Make the nametuple_row() test independent from other tests

4 years agoAdd test for row_factory with cursor.stream()
Daniele Varrazzo [Wed, 24 Feb 2021 18:07:21 +0000 (19:07 +0100)] 
Add test for row_factory with cursor.stream()

4 years agoOptimise the cython path around the use of row_maker
Daniele Varrazzo [Wed, 24 Feb 2021 15:50:00 +0000 (16:50 +0100)] 
Optimise the cython path around the use of row_maker

4 years agoMake cursor.row_factory writable
Daniele Varrazzo [Wed, 24 Feb 2021 15:14:13 +0000 (16:14 +0100)] 
Make cursor.row_factory writable

4 years agoMake the row_maker non-optional
Daniele Varrazzo [Wed, 24 Feb 2021 14:23:23 +0000 (15:23 +0100)] 
Make the row_maker non-optional

Use the `tuple` type as return value for `tuple_row()`, which has a
valid interface and can also be used in the Cython code to fast-path the
case where the tuples created internally are good enough.

4 years agoFix use of TypeInfo with connections using dict_row
Daniele Varrazzo [Wed, 24 Feb 2021 03:02:57 +0000 (04:02 +0100)] 
Fix use of TypeInfo with connections using dict_row

Actually always use dict_row as it makes things easier (we do create a
dict out of the query to pass kwargs...)

Relax the RowFactory signature to make it accept `dict_row()` and
`namedtuple_row()` too.

4 years agoAdd public package attributes
Daniele Varrazzo [Wed, 24 Feb 2021 02:14:10 +0000 (03:14 +0100)] 
Add public package attributes

They are useful to allow people to annotate programs with psycopg3 types.

4 years agoFix type specification for `namedtuple_row()`
Daniele Varrazzo [Wed, 24 Feb 2021 02:11:26 +0000 (03:11 +0100)] 
Fix type specification for `namedtuple_row()`

4 years agoFix row factory docs examples
Daniele Varrazzo [Wed, 24 Feb 2021 02:09:26 +0000 (03:09 +0100)] 
Fix row factory docs examples

4 years agoMake the row_factory attribute non-nullable
Daniele Varrazzo [Wed, 24 Feb 2021 02:05:15 +0000 (03:05 +0100)] 
Make the row_factory attribute non-nullable

Added a `tuple_row()` factory for completeness. Note that it returns None, not
a callable, and the row_maker on the Transformer hasn't changed. The
signature of RowFactory now allows that.

This
makes simpler to specify the row_factory option on `conn.cursor()`: None
means default (the connection `row_factory`), specifying `tuple_row()`
overrides it to the normal tuplish behaviour.

4 years agoDrop row_factory param from Connection.execute()
Daniele Varrazzo [Wed, 24 Feb 2021 02:01:30 +0000 (03:01 +0100)] 
Drop row_factory param from Connection.execute()

The method is not present on cursor.execute: either it's on both or on
none. Erring on the side of a less complex interface for the moment...

4 years agoAdd namedtuple_row row factory
Denis Laxalde [Tue, 23 Feb 2021 17:52:12 +0000 (18:52 +0100)] 
Add namedtuple_row row factory

Implementation for namedtuple class cache and fields name sanitizing is
taken from psycogp2.

4 years agoDocument row factories
Denis Laxalde [Fri, 12 Feb 2021 14:55:14 +0000 (15:55 +0100)] 
Document row factories

We document the row_factory argument of *Connection.execute() as well as
the row_factory attribute on Connection.

We add a new page in advanced section explaining the concepts of row
factories, providing examples and documenting built-in row factories.

4 years agoFix guard for platforms missing epoll
Daniele Varrazzo [Tue, 16 Feb 2021 21:31:02 +0000 (22:31 +0100)] 
Fix guard for platforms missing epoll

See #34

4 years agoDon't use epoll module definitions if it's not the default selector
Daniele Varrazzo [Tue, 16 Feb 2021 19:04:49 +0000 (20:04 +0100)] 
Don't use epoll module definitions if it's not the default selector

Close #34

4 years agoMove docs example statement where it makes more sense
Daniele Varrazzo [Tue, 16 Feb 2021 19:04:19 +0000 (20:04 +0100)] 
Move docs example statement where it makes more sense

4 years agoStart a 'psycopg3.rows' module with dict_row()
Denis Laxalde [Fri, 12 Feb 2021 16:03:47 +0000 (17:03 +0100)] 
Start a 'psycopg3.rows' module with dict_row()

4 years agoMerge pull request #33 from dlax/tox-docs
Daniele Varrazzo [Fri, 12 Feb 2021 16:01:50 +0000 (17:01 +0100)] 
Merge pull request #33 from dlax/tox-docs

add a tox environment to build the docs

4 years agoAdd a tox environment to build the docs 33/head
Denis Laxalde [Fri, 12 Feb 2021 13:06:00 +0000 (14:06 +0100)] 
Add a tox environment to build the docs

4 years agoMake lru_cache usage in libpq_docs compatible with python 3.7
Denis Laxalde [Fri, 12 Feb 2021 13:00:04 +0000 (14:00 +0100)] 
Make lru_cache usage in libpq_docs compatible with python 3.7

The "user_function" version (allowing uncalled lru_cache) is only
available since python 3.8.

4 years agoAdd row_factory as connection attribute and connect argument
Denis Laxalde [Fri, 12 Feb 2021 09:31:30 +0000 (10:31 +0100)] 
Add row_factory as connection attribute and connect argument

When passing 'row_factory' to connect(), respective attribute will be
set on the connection instance. This will be used as default at cursor
creation and can be overridden with conn.cursor(row_factory=...) or
conn.execute(row_factory=...).

We use a '_null_row_factory' marker to handle None-value passed to
.cursor() or .execute() for disabling the default row factory.

4 years agoFix server-side cursors docs typos
Daniele Varrazzo [Fri, 12 Feb 2021 10:08:55 +0000 (11:08 +0100)] 
Fix server-side cursors docs typos

Reported by @lelit, thank you!

4 years agoLet Transformer.make_row property's setter accept None
Denis Laxalde [Fri, 12 Feb 2021 08:34:46 +0000 (09:34 +0100)] 
Let Transformer.make_row property's setter accept None

4 years agoAdd tests to verify broken queries or other statements in server-side cursors
Daniele Varrazzo [Fri, 12 Feb 2021 02:35:04 +0000 (03:35 +0100)] 
Add tests to verify broken queries or other statements in server-side cursors

Enforce passing a single statement by making sure to use the advanced
query protocol.

4 years agoSet up row maker and loaders only once in a server-side cursor lifetime
Daniele Varrazzo [Fri, 12 Feb 2021 02:21:35 +0000 (03:21 +0100)] 
Set up row maker and loaders only once in a server-side cursor lifetime

It wasn't happening once per movement, as I was fearing, but it was happening
exactly twice: once on DECLARE, once on describe_portal(). We actually
don't care about the DECLARE result: it was being set on the cursor only
to detect errors, so now that's done manually.

4 years agoFix setting row maker on nextset()
Daniele Varrazzo [Fri, 12 Feb 2021 01:44:06 +0000 (02:44 +0100)] 
Fix setting row maker on nextset()

The test was broken and didn't test that the row_factory function was
really called.

4 years agoMerge branch 'master' into row-factory
Daniele Varrazzo [Fri, 12 Feb 2021 01:36:01 +0000 (02:36 +0100)] 
Merge branch 'master' into row-factory

4 years agoMerge branch 'tx-no-auto-loaders'
Daniele Varrazzo [Fri, 12 Feb 2021 01:27:58 +0000 (02:27 +0100)] 
Merge branch 'tx-no-auto-loaders'

4 years agoDon't recalculate loaders when not needed
Daniele Varrazzo [Fri, 12 Feb 2021 01:23:16 +0000 (02:23 +0100)] 
Don't recalculate loaders when not needed

The case it's not needed is when the new result is guaranteed to have
the same fields as the previous one. This happens querying in single-row
mode and on server-side cursors fetch.

4 years agoDropped Transformer.pgresult setter, use set_result
Daniele Varrazzo [Fri, 12 Feb 2021 01:08:18 +0000 (02:08 +0100)] 
Dropped Transformer.pgresult setter, use set_result

Can pass a boolean to tell it to skip setting row loaders

4 years agoFix fetch*() return type annotation on server-side cursors
Daniele Varrazzo [Thu, 11 Feb 2021 21:04:32 +0000 (22:04 +0100)] 
Fix fetch*() return type annotation on server-side cursors

4 years agoAdd tests to verify row_factory works with server-side cursors too
Daniele Varrazzo [Thu, 11 Feb 2021 20:59:03 +0000 (21:59 +0100)] 
Add tests to verify row_factory works with server-side cursors too