summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuo Ishii2024-10-21 10:17:56 +0000
committerTatsuo Ishii2024-10-21 10:17:56 +0000
commitc5c1ca6b37fdc0b25b5507abfbdadd40bc2e81a7 (patch)
treebbe796763f6ea5ac65cb39a561c23c559a0954bb /src
parentb58a3c6304d31c76416ebf253e69086dadc186bc (diff)
Feature: new PGPOOL SET CACHE DELETE command.
The new PGPOOl SET command allows to delete query cache by specifying the previous query used to create the query cache entry. example usage is: PGPOOL SET CACHE DELETE 'SELECT * FROM t1;' This command is particularly useful for queries that are not invalidated by the auto cache invalidation feature because the query does not have any reference to tables.
Diffstat (limited to 'src')
-rw-r--r--src/include/parser/nodes.h1
-rw-r--r--src/include/query_cache/pool_memqcache.h2
-rw-r--r--src/parser/gram.y14
-rw-r--r--src/protocol/pool_proto_modules.c13
-rw-r--r--src/query_cache/pool_memqcache.c53
5 files changed, 83 insertions, 0 deletions
diff --git a/src/include/parser/nodes.h b/src/include/parser/nodes.h
index 734faa48f..1d5bb3ed6 100644
--- a/src/include/parser/nodes.h
+++ b/src/include/parser/nodes.h
@@ -34,6 +34,7 @@ typedef enum NodeTag
/* pgpool Extension */
T_PgpoolVariableSetStmt,
T_PgpoolVariableShowStmt,
+ T_PgpoolQueryCacheStmt,
#include "nodetags.h"
} NodeTag;
diff --git a/src/include/query_cache/pool_memqcache.h b/src/include/query_cache/pool_memqcache.h
index 5a0a1fce9..042121fc4 100644
--- a/src/include/query_cache/pool_memqcache.h
+++ b/src/include/query_cache/pool_memqcache.h
@@ -307,4 +307,6 @@ extern void pool_init_whole_cache_blocks(void);
extern void clear_query_cache(void);
+extern bool query_cache_delete_by_stmt(char *query, POOL_CONNECTION_POOL * backend);
+
#endif /* POOL_MEMQCACHE_H */
diff --git a/src/parser/gram.y b/src/parser/gram.y
index a39f98991..61663cce2 100644
--- a/src/parser/gram.y
+++ b/src/parser/gram.y
@@ -1655,6 +1655,13 @@ VariableSetStmt:
n->is_local = false;
$$ = (Node *) n;
}
+ | PGPOOL set_rest_more
+ {
+ VariableSetStmt *n = $2;
+ n->type = T_PgpoolQueryCacheStmt; /* Hack to keep changes minimum */
+ n->is_local = false;
+ $$ = (Node *) n;
+ }
| SET set_rest
{
VariableSetStmt *n = $2;
@@ -1834,6 +1841,13 @@ set_rest_more: /* Generic SET syntaxes: */
n->args = list_make1(makeStringConst($3, @3));
$$ = n;
}
+ /* PGPOOL CACHE DELETE */
+ | SET CACHE DELETE_P Sconst
+ {
+ VariableSetStmt *n = makeNode(VariableSetStmt);
+ n->name = $4; /* query to delete query cache */
+ $$ = n;
+ }
;
var_name: ColId { $$ = $1; }
diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c
index df8d27e0c..4988325dc 100644
--- a/src/protocol/pool_proto_modules.c
+++ b/src/protocol/pool_proto_modules.c
@@ -450,7 +450,20 @@ SimpleQuery(POOL_CONNECTION * frontend,
pool_set_skip_reading_from_backends();
return POOL_CONTINUE;
}
+ if (IsA(node, PgpoolQueryCacheStmt))
+ {
+ VariableSetStmt *vnode = (VariableSetStmt *) node;
+ if (query_cache_delete_by_stmt(vnode->name, backend))
+ elog(NOTICE, "query cache deleted. query: \"%s\"", vnode->name);
+ else
+ elog(NOTICE, "query cache does not exist for query: \"%s\"", vnode->name);
+ pool_ps_idle_display(backend);
+ send_complete_and_ready(frontend, backend, "SET", -1);
+ pool_query_context_destroy(query_context);
+ pool_set_skip_reading_from_backends();
+ return POOL_CONTINUE;
+ }
if (IsA(node, PgpoolVariableSetStmt))
{
VariableSetStmt *vnode = (VariableSetStmt *) node;
diff --git a/src/query_cache/pool_memqcache.c b/src/query_cache/pool_memqcache.c
index 4c55f0fc4..7f824fe22 100644
--- a/src/query_cache/pool_memqcache.c
+++ b/src/query_cache/pool_memqcache.c
@@ -4731,3 +4731,56 @@ InvalidateQueryCache(int tableoid, int dboid)
pool_semaphore_unlock(QUERY_CACHE_STATS_SEM);
POOL_SETMASK(&oldmask);
}
+
+/*
+ * Public API to invalidate query cache specified by query string. Returns
+ * true for successfully query cache invalidation. If the query cache was not
+ * found, returns false. Note that this function does not remove any entry in
+ * a table oid file. That may leave a garbage in the file (which is ignored
+ * by the auto cache invalidation) but it's not worth the trouble to remove
+ * the entry since it's relatively expensive. It needs to rewrite the whole
+ * file in the worst case.
+ */
+bool query_cache_delete_by_stmt(char *query, POOL_CONNECTION_POOL * backend)
+{
+ bool rtn = true;
+ pool_sigset_t oldmask;
+
+ char key[MAX_KEY];
+ POOL_CACHEID *cacheid;
+
+ POOL_SETMASK2(&BlockSig, &oldmask);
+ pool_shmem_lock(POOL_MEMQ_EXCLUSIVE_LOCK);
+
+ /* encode md5key */
+ encode_key(query, key, backend);
+
+ if (pool_is_shmem_cache())
+
+ {
+ POOL_QUERY_HASH hashkey;
+
+ memcpy(hashkey.query_hash, key, POOL_MD5_HASHKEYLEN);
+ cacheid = pool_hash_search(&hashkey);
+ if (cacheid == NULL)
+ rtn = false;
+ else
+ pool_delete_item_shmem_cache(cacheid);
+ }
+#ifdef USE_MEMCACHED
+ else
+ {
+ if (delete_cache_on_memcached(key) == 0)
+ rtn = false;
+ }
+#else
+ {
+ ereport(WARNING,
+ (errmsg("failed to delete query cache on memcached, memcached support is not enabled")));
+ }
+#endif
+ pool_semaphore_unlock(QUERY_CACHE_STATS_SEM);
+ POOL_SETMASK(&oldmask);
+
+ return rtn;
+}