* Check if some error detected. If so, emit log. This is useful when
* invalid encoding error occurs. In this case, PostgreSQL does not
* report what statement caused that error and make users confused.
+ * Also set reset_query_error to true in ERROR case. This does
+ * anything in normal query processing but when processing reset
+ * queries, this is important because it might mean DISCARD ALL
+ * command fails. If so, we need to discard the connection cache so
+ * that any session object (i.e. named statement) does not remain in
+ * the last session.
*/
- per_node_error_log(backend, i, string, "pool_send_and_wait: Error or notice message from backend: ", true);
+ if (per_node_error_log(backend, i, string, "pool_send_and_wait: Error or notice message from backend: ", true) == 'E')
+ reset_query_error = true;
}
return POOL_CONTINUE;
} PGVersion;
extern ProcessState processState;
+extern bool reset_query_error; /* true if error occurs in reset queries */
extern POOL_CONNECTION_POOL * pool_connection_pool; /* connection pool */
extern volatile sig_atomic_t backend_timer_expired; /* flag for connection
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2010 PgPool Global Development Group
+ * Copyright (c) 2003-2023 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
pid_t mypid; /* pgpool parent process id */
ProcessType processType;
ProcessState processState;
+bool reset_query_error; /* true if error returned from backend while processing reset queries */
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2019 PgPool Global Development Group
+ * Copyright (c) 2003-2023 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
if (cache_connection)
{
/*
- * For those special databases, and when frontend client exits
- * abnormally, we don't cache connection to backend.
+ * For those special databases, or when frontend client exits
+ * abnormally, we don't cache connection to backend. Also we have to
+ * check whether reset query failed. If so, the existing connection to
+ * backend may not be used and we don't want to cache the connection.
*/
if ((sp &&
(!strcmp(sp->database, "template0") ||
!strcmp(sp->database, "regression"))) ||
(*frontend != NULL &&
((*frontend)->socket_state == POOL_SOCKET_EOF ||
- (*frontend)->socket_state == POOL_SOCKET_ERROR)))
+ (*frontend)->socket_state == POOL_SOCKET_ERROR)) ||
+ reset_query_error)
cache_connection = false;
}
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2022 PgPool Global Development Group
+ * Copyright (c) 2003-2023 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
memcached_connect();
}
+ /*
+ * Reset error flag while processing reset queries.
+ * The flag is set to on inside pool_send_and_wait().
+ */
+ reset_query_error = false;
+
for (;;)
{
* Check kind and produce error message
* All data read in this function is returned to stream.
*/
-void
+char
per_node_error_log(POOL_CONNECTION_POOL * backend, int node_id, char *query, char *prefix, bool unread)
{
POOL_CONNECTION_POOL_SLOT *slot = backend->slots[node_id];
char *message;
+ char kind;
+
+ pool_read(CONNECTION(backend, node_id), &kind, sizeof(kind));
+ pool_unread(CONNECTION(backend, node_id), &kind, sizeof(kind));
+
+ if (kind != 'E' && kind != 'N')
+ {
+ return kind;
+ }
if (pool_extract_error_message(true, CONNECTION(backend, node_id), MAJOR(backend), unread, &message) == 1)
{
prefix, node_id, ntohl(slot->pid), query, message)));
pfree(message);
}
+ return kind;
}
/*