From 9a4554fcfec8465ce0cdf4d90958e31fc5d98dc9 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 24 Apr 2023 10:17:45 +0300 Subject: [PATCH] Add pool_discard_query option (#488) --- documentation/configuration.md | 21 +++++++++++++++++++++ sources/config_reader.c | 8 ++++++++ sources/pool.c | 4 ++++ sources/pool.h | 1 + sources/reset.c | 14 ++++++++++++-- sources/rules.c | 12 +++++++++++- 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/documentation/configuration.md b/documentation/configuration.md index 31b8b660..f4ae4dff 100644 --- a/documentation/configuration.md +++ b/documentation/configuration.md @@ -685,6 +685,27 @@ from the pool. `pool_discard no` +#### pool\_smart\_discard *yes|no* + +When this parameter is enabled, Odyssey sends smart discard query instead of default `DISCARD ALL` when it +returns connection to the pool. Its default value may be overwritten by pool\_discard\_string setting. + +#### pool\_discard\_string *string* + +When resetting a database connection, a pre-defined query string is sent to the server. This query string consists of a set of SQL statements that will be executed during a `DISCARD ALL` command, except for `DEALLOCATE ALL`. The default query string includes the following statements: + +```sql +SET SESSION AUTHORIZATION DEFAULT; +RESET ALL; +CLOSE ALL; +UNLISTEN *; +SELECT pg_advisory_unlock_all(); +DISCARD PLANS; +DISCARD SEQUENCES;DISCARD TEMP; +``` + +This sequence of statements is designed to reset the connection to a clean state, without affecting the authentication credentials of the session. By executing these queries, any open transactions will be closed, locks will be released, and any cached execution plans and sequences will be discarded. + #### pool\_cancel *yes|no* Server pool auto-cancel. diff --git a/sources/config_reader.c b/sources/config_reader.c index 9567bec6..f13e7ce4 100644 --- a/sources/config_reader.c +++ b/sources/config_reader.c @@ -97,6 +97,7 @@ typedef enum { OD_LPOOL_TTL, OD_LPOOL_DISCARD, OD_LPOOL_SMART_DISCARD, + OD_LPOOL_DISCARD_QUERY, OD_LPOOL_CANCEL, OD_LPOOL_ROLLBACK, OD_LPOOL_RESERVE_PREPARED_STATEMENT, @@ -249,6 +250,7 @@ static od_keyword_t od_config_keywords[] = { od_keyword("pool_timeout", OD_LPOOL_TIMEOUT), od_keyword("pool_ttl", OD_LPOOL_TTL), od_keyword("pool_discard", OD_LPOOL_DISCARD), + od_keyword("pool_discard_query", OD_LPOOL_DISCARD_QUERY), od_keyword("pool_smart_discard", OD_LPOOL_SMART_DISCARD), od_keyword("pool_cancel", OD_LPOOL_CANCEL), od_keyword("pool_rollback", OD_LPOOL_ROLLBACK), @@ -1360,6 +1362,12 @@ static int od_config_reader_rule_settings(od_config_reader_t *reader, reader, &rule->pool->smart_discard)) return NOT_OK_RESPONSE; continue; + /* pool_discard_query */ + case OD_LPOOL_DISCARD_QUERY: + if (!od_config_reader_string( + reader, &rule->pool->discard_query)) + return NOT_OK_RESPONSE; + continue; /* pool_cancel */ case OD_LPOOL_CANCEL: if (!od_config_reader_yes_no(reader, diff --git a/sources/pool.c b/sources/pool.c index 0ebf85c3..a85ec140 100644 --- a/sources/pool.c +++ b/sources/pool.c @@ -20,6 +20,7 @@ od_rule_pool_t *od_rule_pool_alloc() pool->discard = 1; pool->smart_discard = 0; + pool->discard_query = NULL; pool->cancel = 1; pool->rollback = 1; @@ -34,6 +35,9 @@ int od_rule_pool_free(od_rule_pool_t *pool) if (pool->type) { free(pool->type); } + if (pool->discard_query) { + free(pool->discard_query); + } free(pool); return OK_RESPONSE; } diff --git a/sources/pool.h b/sources/pool.h index 2ec815d3..351d8b4f 100644 --- a/sources/pool.h +++ b/sources/pool.h @@ -33,6 +33,7 @@ struct od_rule_pool { char *type; char *routing_type; + char *discard_query; int size; int timeout; diff --git a/sources/reset.c b/sources/reset.c index ff4424b7..d835e80b 100644 --- a/sources/reset.c +++ b/sources/reset.c @@ -129,8 +129,9 @@ int od_reset(od_server_t *server) goto error; } - /* send smard DISCARD ALL */ - if (route->rule->pool->smart_discard) { + /* send smart discard */ + if (route->rule->pool->smart_discard && + route->rule->pool->discard_query == NULL) { char query_discard[] = "SET SESSION AUTHORIZATION DEFAULT;RESET ALL;CLOSE ALL;UNLISTEN *;SELECT pg_advisory_unlock_all();DISCARD PLANS;DISCARD SEQUENCES;DISCARD TEMP;"; rc = od_backend_query(server, "reset-discard-smart", @@ -139,6 +140,15 @@ int od_reset(od_server_t *server) if (rc == NOT_OK_RESPONSE) goto error; } + if (route->rule->pool->discard_query != NULL) { + rc = od_backend_query(server, "reset-discard-smart-string", + route->rule->pool->discard_query, NULL, + strlen(route->rule->pool->discard_query) + + 1, + wait_timeout, 1); + if (rc == NOT_OK_RESPONSE) + goto error; + } /* ready */ return 1; diff --git a/sources/rules.c b/sources/rules.c index 724b9707..bdd247f6 100644 --- a/sources/rules.c +++ b/sources/rules.c @@ -745,7 +745,7 @@ int od_pool_validate(od_logger_t *logger, od_rule_pool_t *pool, char *db_name, return NOT_OK_RESPONSE; } - // reserve prepare statemetn feature + // reserve prepare statement feature if (pool->reserve_prepared_statement && pool->pool == OD_RULE_POOL_SESSION) { od_error( @@ -771,6 +771,16 @@ int od_pool_validate(od_logger_t *logger, od_rule_pool_t *pool, char *db_name, return NOT_OK_RESPONSE; } + if (pool->discard_query && pool->reserve_prepared_statement) { + if (strcasestr(pool->discard_query, "DEALLOCATE ALL")) { + od_error( + logger, "rules", NULL, NULL, + "rule '%s.%s': cannot support prepared statements when 'DEALLOCATE ALL' present in discard string", + db_name, user_name); + return NOT_OK_RESPONSE; + } + } + return OK_RESPONSE; }