Commit Graph

75 Commits (26c79eb215cd1a8022fee209e1df9601626d2f89)

Author SHA1 Message Date
Jack Christensen 26c79eb215 Handle writes that could deadlock with reads from the server
This commit adds a background reader that can optionally buffer reads.
It is used whenever a potentially blocking write is made to the server.
The background reader is started on a slight delay so there should be no
meaningful performance impact as it doesn't run for quick queries and
its overhead is minimal relative to slower queries.
2023-06-12 09:39:26 -05:00
Jack Christensen 85136a8efe Restore pgx v4 style CopyFrom implementation
This approach uses an extra goroutine to write while the main goroutine
continues to read. This avoids the need to use non-blocking I/O.
2023-06-12 09:39:26 -05:00
Jack Christensen 4410fc0a65 Remove nbconn
The non-blocking IO system was designed to solve three problems:

1. Deadlock that can occur when both sides of a connection are blocked
   writing because all buffers between are full.
2. The inability to use a write deadline with a TLS.Conn without killing
   the connection.
3. Efficiently check if a connection has been closed before writing.
   This reduces the cases where the application doesn't know if a query
   that does a INSERT/UPDATE/DELETE was actually sent to the server or
   not.

However, the nbconn package is extraordinarily complex, has been a
source of very tricky bugs, and has OS specific code paths. It also does
not work at all with underlying net.Conn implementations that do not
have platform specific non-blocking IO syscall support and do not
properly implement deadlines. In particular, this is the case with
golang.org/x/crypto/ssh.

I believe the deadlock problem can be solved with a combination of a
goroutine for CopyFrom like v4 used and a watchdog for regular queries
that uses time.AfterFunc.

The write deadline problem actually should be ignorable. We check for
context cancellation before sending a query and the actual Write should
be almost instant as long as the underlying connection is not blocked.
(We should only have to wait until it is accepted by the OS, not until
it is fully sent.)

Efficiently checking if a connection has been closed is probably the
hardest to solve without non-blocking reads. However, the existing code
only solves part of the problem. It can detect a closed or broken
connection the OS knows about, but it won't actually detect other types
of broken connections such as a network interruption. This is currently
implemented in CheckConn and called automatically when checking a
connection out of the pool that has been idle for over one second. I
think that changing CheckConn to a very short deadline read and changing
the pool to do an actual Ping would be an acceptable solution.

Remove nbconn and non-blocking code. This does not leave the system in
an entirely working state. In particular, CopyFrom is broken, deadlocks
can occur for extremely large queries or batches, and PgConn.CheckConn
is now a `select 1` ping. These will be resolved in subsequent commits.
2023-06-12 09:39:26 -05:00
Nicola Murino 229d2aaa49 TestConnCopyFromBinary: increase context timeout 2023-06-03 06:45:28 -05:00
Nicola Murino 28bd5b3843 TestConnectTimeoutStuckOnTLSHandshake: allow more time to complete
to avoid random errors in Windows CI
2023-06-03 06:45:28 -05:00
Nicola Murino fb47e1abbb TestContextWatcherStress: reduce sleep counts 2023-06-03 06:45:28 -05:00
Nicola Murino c861bce438 CancelRequest: don't try to read the reply
Postgres will just process the request and close the connection
2023-06-03 06:45:28 -05:00
Nicola Murino ef363b59ab skipping some config parsing tests on Windows
this should be investigated and fixed
2023-06-03 06:45:28 -05:00
Jack Christensen 0ec512b504 Fix: possible fail in goroutine after test has completed 2023-05-29 10:43:15 -05:00
Jack Christensen f93b42b6ac Allow more time for TestConnExecBatchHuge 2023-05-29 10:35:38 -05:00
Jack Christensen 9f00b6f750 Use context timeouts in more tests
Tests should timeout in a reasonable time if something is stuck. In
particular this is important when testing deadlock conditions such as
can occur with the copy protocol if both the client and the server are
blocked writing until the other side does a read.
2023-05-29 10:25:57 -05:00
Jack Christensen b3739c1289 pgconn.CheckConn locks connection
This ensures that a closed connection at the pgconn layer is not
considered okay when the background closing of the net.Conn is still in
progress.

This also means that CheckConn cannot be called when the connection is
locked (for example, by in an progress query). But that seems
reasonable. It's not exactly clear that that would have ever worked
anyway.

https://github.com/jackc/pgx/issues/1618#issuecomment-1563702231
2023-05-26 06:03:25 -05:00
Evan Jones 11d892dfcf pgconn.CancelRequest: Fix unix sockets: don't use RemoteAddr()
The tests for cancelling requests were failing when using unix
sockets. The reason is that net.Conn.RemoteAddr() calls getpeername()
to get the address. For Unix sockets, this returns the address that
was passed to bind() by the *server* process, not the address that
was passed to connect() by the *client*. For postgres, this is always
relative to the server's directory, so is a path like:

    ./.s.PGSQL.5432

Since it does not return the full absolute path, this function cannot
connect, so it cannot cancel requests. To fix it, use the connection's
config for Unix sockets. I think this should be okay, since a system
using unix sockets should not have "fallbacks". If that is incorrect,
we will need to save the address on PgConn.

Fixes the following failed tests when using Unix sockets:

--- FAIL: TestConnCancelRequest (2.00s)
    pgconn_test.go:2056:
          Error Trace:  /Users/evan.jones/pgx/pgconn/pgconn_test.go:2056
                              /Users/evan.jones/pgx/pgconn/asm_arm64.s:1172
          Error:        Received unexpected error:
                        dial unix ./.s.PGSQL.5432: connect: no such file or directory
          Test:         TestConnCancelRequest
    pgconn_test.go:2063:
          Error Trace:  /Users/evan.jones/pgx/pgconn/pgconn_test.go:2063
          Error:        Object expected to be of type *pgconn.PgError, but was <nil>
          Test:         TestConnCancelRequest
--- FAIL: TestConnContextCanceledCancelsRunningQueryOnServer (5.10s)
    pgconn_test.go:2109:
          Error Trace:  /Users/evan.jones/pgx/pgconn/pgconn_test.go:2109
          Error:        Received unexpected error:
                        timeout: context already done: context deadline exceeded
          Test:         TestConnContextCanceledCancelsRunningQueryOnServer
2023-05-20 08:08:47 -05:00
Jack Christensen f17c743c3c Unwatch at end of test
https://github.com/jackc/pgx/issues/1505
2023-02-14 09:03:41 -06:00
Jack Christensen eee854fb06 iobufpool uses *[]byte instead of []byte to reduce allocations 2023-01-28 08:02:49 -06:00
Alexey Palazhchenko f839d501a7 Apply `gofmt -s`
And add CI check for that.
2023-01-24 07:55:00 -06:00
Alexey Palazhchenko f581584148 Use Go 1.19's lists for proper formatting 2023-01-23 19:54:30 -06:00
Mark Chambers 672431c0bd Replace deprecated "io/ioutil"
ioutil.TempFile: Deprecated: As of Go 1.17, this function simply calls os.CreateTemp.

ioutil.ReadFile: Deprecated: As of Go 1.16, this function simply calls os.ReadFile.
2023-01-16 20:06:01 -06:00
Jack Christensen a95cfe5cc5 Fix connect with multiple hostnames when one can't be resolved
If multiple hostnames are provided and one cannot be resolved the others
should still be tried.

Longterm, it would be nice for the connect process to return a list of
errors rather than just one.

fixes https://github.com/jackc/pgx/issues/1464
2023-01-14 09:19:00 -06:00
Alejandro Do Nascimento Mora c4ac6d810f Use DefaultQueryExecMode in CopyFrom
CopyFrom had to create a prepared statement to get the OIDs of the data
types that were going to be copied into the table. Every COPY operation
required an extra round trips to retrieve the type information. There
was no way to customize this behavior.

By leveraging the QueryExecMode feature, like in `Conn.Query`, users can
specify if they want to cache the prepared statements, execute
them on every request (like the old behavior), or bypass the prepared
statement relying on the pgtype.Map to get the type information.

The `QueryExecMode` behave exactly like in `Conn.Query` in the way the
data type OIDs are fetched, meaning that:

- `QueryExecModeCacheStatement`: caches the statement.
- `QueryExecModeCacheDescribe`: caches the statement and assumes they do
  not change.
- `QueryExecModeDescribeExec`: gets the statement description on every
  execution. This is like to the old behavior of `CopyFrom`.
- `QueryExecModeExec` and `QueryExecModeSimpleProtocol`: maintain the
  same behavior as before, which is the same as `QueryExecModeDescribeExec`.
  It will keep getting the statement description on every execution

The `QueryExecMode` can only be set via
`ConnConfig.DefaultQueryExecMode`, unlike `Conn.Query` there's no
support for specifying the `QueryExecMode` via optional arguments
in the function signature.
2022-12-23 13:22:26 -06:00
Alejandro Do Nascimento Mora e58381ac94 Enable some CopyFrom tests for cockroachDB
CockroachDB added support for COPY in version 20.2.

https://www.cockroachlabs.com/docs/v20.2/copy-from

There are some limitations on the implementation, that's why not all the
existing tests were enabled.
2022-12-12 18:22:32 -06:00
Jack Christensen 6f90866f58 Expose underlying pgconn GetSSLPassword support to pgx
pgconn supports a GetSSLPassword function but the pgx connection
functions did not expose a means of using it.

See PR #1233 for more context.
2022-11-03 20:09:52 -05:00
Jack Christensen 6b52e0b5e0 Contributing guide now includes instructions to test client ssl auth 2022-10-29 19:00:29 -05:00
Jack Christensen 55b5067ddd Improve testing / contributing instructions
* Extract CONTRIBUTING.md
* Add instructions and scripts to setup standalone PostgreSQL server
  that tests the various connection and authentication types.
2022-10-29 17:14:09 -05:00
Jack Christensen 1ec3816a20 pgconn and pgproto use same environment variable for tests as pgx 2022-10-29 13:23:25 -05:00
Jack Christensen c9c166b8b2 Fix TestConnCopyFromDataWriteAfterErrorAndReturn always being skipped 2022-10-29 13:17:52 -05:00
Jack Christensen 9a207178f6 Fix TestConnCheckConn always being skipped 2022-10-29 13:16:05 -05:00
Jack Christensen 3feeddd9f1 Fix tests when PGUSER is different than OS user 2022-10-29 13:12:03 -05:00
Jack Christensen 72c89108ad Fix tests when PGPORT set to non-default value 2022-10-29 13:06:53 -05:00
Jack Christensen 305c4ddbc7 Move and rename test 2022-10-01 10:09:57 -05:00
Jack Christensen fb83fb0cc3 Skip TestCopyFrom on CockroachDB 2022-10-01 10:08:03 -05:00
Tommy Reilly c48dd7e1f8 Add a test case demonstrating I/O race with CopyFrom 2022-10-01 10:07:38 -05:00
Jack Christensen cd8b29b0fe Fix flickering on TestConnectTimeoutStuckOnTLSHandshake
Ensure that even if the outer function finishes the goroutine can still
send an error.
2022-09-24 12:54:59 -05:00
Jack Christensen 1a314bda3b pgconn.Timeout() no longer considers `context.Canceled` as a timeout error.
https://github.com/jackc/pgconn/issues/81
2022-09-17 10:18:06 -05:00
Jack Christensen 782133158f Test sending CopyData before CopyFrom responds with error 2022-09-03 09:31:41 -05:00
Jack Christensen bb6c997102 Add NewCommandTag
Useful for mocking and testing.

https://github.com/jackc/pgx/issues/1273#issuecomment-1224154013
2022-08-23 19:39:15 -05:00
Jack Christensen ae65a8007b Use higher pgconn.FieldDescription with string Name
Instead of using pgproto3.FieldDescription through pgconn and pgx. This
lets the lowest level pgproto3 still be as memory efficient as possible.

https://github.com/jackc/pgx/pull/1281
2022-08-20 10:04:18 -05:00
Jack Christensen dbee461dc9 Update previous pgconn merge for v5 2022-08-19 17:42:04 -05:00
Jack Christensen ef5655c563 Merge remote-tracking branch 'pgconn/master' into v5-dev 2022-08-19 17:36:29 -05:00
Jack Christensen 8eae4a2a3e Merge remote-tracking branch 'pgconn/master' into v5-dev 2022-08-13 10:19:49 -05:00
Jack Christensen 8f0c9557e4 Merge remote-tracking branch 'pgconn/master' into v5-dev 2022-08-06 06:33:10 -05:00
Jack Christensen 0f7b95c3a4 Merge remote-tracking branch 'pgconn/master' into v5-dev 2022-07-12 06:45:54 -05:00
Jack Christensen 3dc9d17757 Document new ResultReader.Values behavior 2022-07-11 21:17:45 -05:00
Jack Christensen f0cd9cb867 Update CommandTag comment 2022-07-11 21:09:55 -05:00
Jack Christensen aaacdbf3ea Use string internally for CommandTag 2022-07-11 21:09:03 -05:00
Jack Christensen e7aa76ccf9 SendBatch now uses pipeline mode to prepare and describe statements
Previously, a batch with 10 unique parameterized statements executed
100 times would entail 11 network round trips. 1 for each prepare /
describe and 1 for executing them all. Now pipeline mode is used to
prepare / describe all statements in a single network round trip. So it
would only take 2 round trips.
2022-07-09 09:32:36 -05:00
Jack Christensen ba58e3d5d2 Fix pipeline prepare query without row results 2022-07-09 08:32:12 -05:00
Jack Christensen a86f4f3db9 Add deallocate to pipeline mode 2022-07-07 19:32:01 -05:00
Jack Christensen f7433cc5f2 Fix typo 2022-07-04 06:20:15 -05:00
Jack Christensen f635b43a6b Use bigint in tests for CockroachDB compatibility
CRDB automatically changes int4 to int8.
2022-07-02 22:00:42 -05:00