...somehow. Postgres doesn't support them and converts them into a
simple empty array. However this is not really our concern: the syntax
we return is valid.
Close#788
I'm still fought whether docs should be in the C module or in the .rst.
I'd prefer the first because DRY, but writing multiline strings in C
really sucks.
The FreeBSD-related condition which enables custom round() implementation is incorrect: one must include <sys/param.h> to get __FreeBSD_version value, and since it's not included here, the check succeeds while it shouldn't. Before it worked somehow, but since python 3.7 it results in conflicting declarations of round(). The condition is also no longer needed since FreeBSD 5.3 is unsupported for 12 years.
Added tests to check bad types, which discovered the above problem: on
type error we would have decref'd on exit something that was only
borrowed (because we wouldn't have performed matching increfs).
Fixed several shortcomings highlighted in #576 and not fixed as
requested.
Also fixed broken behaviour of ignoring the algorithm if the connection
is missing.
It was registered as side effect of an excessive definition that got
cleaned up in 338dbe70a6.
Looking at other removed redundant type oids, this was the only one
missing from the `string_types` map.
Close#578.
Should close#558, but I'm curious to know if a number is returned
for interval < 1 day too (which wouldn't trigger the overflow, but will
finish parsing with part=0).
The wrong associations are overwritten in the typecaster map by the
right ones, so they have been harmless to date, but only because of the
order of creation of the adapters.
It fails on Py3 after receiving a SIGABRT. Because we don't handle it
here it will resurface later with nonsense such as:
SystemError: <some function> returned a result with an error set
Close#551
Some extra bonus refactoring to improve the function readability (don't
reuse names for variables with different refcount rules, don't pass
separate obj/self, async pass-through...)
From the DB-API (https://www.python.org/dev/peps/pep-0249/):
OperationalError
Exception raised for errors that are related to the database's
operation and not necessarily under the control of the programmer,
e.g. an unexpected disconnect occurs, [...]
Additionally, psycopg2 was inconsistent, at least in the async case:
depending on how the "connection closed" error was reported from the
kernel to libpq, it would sometimes raise OperationalError and
sometimes DatabaseError. Now it always raises OperationalError.
There's a race condition that only seems to happen over Unix-domain
sockets. Sometimes, the closed socket is reported by the kernel to
libpq like this (captured with strace):
sendto(3, "Q\0\0\0\34select pg_backend_pid()\0", 29, MSG_NOSIGNAL, NULL, 0) = 29
recvfrom(3, "E\0\0\0mSFATAL\0C57P01\0Mterminating "..., 16384, 0, NULL, NULL) = 110
recvfrom(3, 0x12d0330, 16384, 0, 0, 0) = -1 ECONNRESET (Connection reset by peer)
That is, psycopg2/libpq sees no error when sending the first query
after the connection is closed, but gets an error reading the result.
In that case, everything worked fine.
But sometimes, the error manifests like this:
sendto(3, "Q\0\0\0\34select pg_backend_pid()\0", 29, MSG_NOSIGNAL, NULL, 0) = -1 EPIPE (Broken pipe)
recvfrom(3, "E\0\0\0mSFATAL\0C57P01\0Mterminating "..., 16384, 0, NULL, NULL) = 110
recvfrom(3, "", 16274, 0, NULL, NULL) = 0
recvfrom(3, "", 16274, 0, NULL, NULL) = 0
i.e. libpq received an error when sending the query. This manifests as
a slightly different exception from a slightly different place. More
importantly, in this case connection.closed is left at 0 rather than
being set to 2, and that is the bug I'm fixing here.
Note that we see almost identical behaviour for sync and async
connections, and the fixes are the same. So I added extremely similar
test cases.
Finally, there is still a bug here: for async connections, we
sometimes raise DatabaseError (incorrect) and sometimes raise
OperationalError (correct). Will fix that next.
(almost... except for micros rounding)
While this is probably an improvement on the previous implementation,
I am largely waving a dead chicken at windows, which keeps failing to
pass the seconds overflow test. If it doesn't pass now either I'll start
blaming Python's timedelta.
When moving from autocommit True -> False reset only the server
parameters that were actually specified by psycopg to honour the
serssion characteristics.
Added function 'timeradd'.
Changed second parameter of 'gettimeofday' to void since not used in
function and MSVC timezone definition is not a struct).
Store the state in the connection object and set the params on BEGIN
Some tests fail: a few can be fixed reading transaction_* instead of
default_transaction_*; but the behaviour of tx characteristics with
autocommit is effectively changed. It may be addressed by setting
default_transaction_* if autocommit is set.
Store the encode/decode functions for the right codec in the connection.
The Python encoding name has been dropped of the connection to avoid the
temptation to use it...
Code paths to read encoding on connection and to store the new
connection in the structure after changing it in the backend unified
into a single function.
A replication connection - marked by the use of the keyword "replication"
in the DSN - does not support SET commands. Trying to sent "SET datestyle"
will result in an exception.
PGRES_COPY_BOTH was introduced in 9.1: we can ifdef the hell out of
pgpath, but we may as well bury the dead horses instead of beating
them.
They smell funny, too.
Stops warning (caused by command line definition of PG_VERSION, so it
could have been avoided otherwise), but the file comment says:
Note that the definitions here are not intended to be exposed to clients
of the frontend interface libraries --- so we don't worry much about
polluting the namespace with lots of stuff...
so it doesn't seem a good idea gulping it.
Would help using adapt(unicode) to quote strings without a connection,
see ticket #331.
Currently in heisenbug state: if test_connection_wins_anyway and
test_encoding_default run (in this order), the latter fail because the
returned value is "'\xe8 '", with an extra space. Skipping the first
test, the second succeed.
The bad value is returned by the libpq:
ql = PQescapeString(to+eq+1, from, len);
just returns len = 2 and an extra space in the string... meh.