Optimize query cache invalidation for ALTER ROLE.
authorTatsuo Ishii <ishii@postgresql.org>
Tue, 22 Oct 2024 22:47:37 +0000 (07:47 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Tue, 22 Oct 2024 23:50:16 +0000 (08:50 +0900)
Commit 6b7d585eb1c693e4ffb5b8e6ed9aa0f067fa1b89 invalidates query
cache if any ALTER ROLE/USER statement is used. Actually this is an
overkill. Because following queries do not affect the privilege of the
role.

- ALTER ROLE user WITH [ENCRYPTED] PASSWORD
- ALTER ROLE user WITH CONNECTION LIMIT

So do not invalidate query cache if those commands are used.

Backpatch-through: v4.1
Discussion: https://www.pgpool.net/pipermail/pgpool-hackers/2024-October/004532.html

doc.ja/src/sgml/memcache.sgml
doc/src/sgml/memcache.sgml
src/protocol/CommandComplete.c
src/test/regression/tests/006.memqcache/expected.n
src/test/regression/tests/006.memqcache/expected.r
src/test/regression/tests/006.memqcache/expected.s
src/test/regression/tests/006.memqcache/test.sh

index a6f690306df37ce3d6d2cedd67182822fcba2fa6..f1e364d05c94aafce1d50fa92f061ebd43703b71 100644 (file)
@@ -59,7 +59,7 @@
    以下のコマンドはクエリキャッシュとデータベース内容の整合性を失わせる可能性があるので、実行されるとクエリキャッシュをすべて削除します。
    <programlisting>
     ALTER DATABASE
-    ALTER ROLE
+    ALTER ROLE or USER (WITH CONNECTION LIMITとWITH [ENCRYPTED] PASSWORDを除く)
     ALTER TABLE
     REVOKE
    </programlisting>
index 171a4a28ad8bb6849f18f868567c3f5d53a096c2..3df4b57dd8757513eb6c612255c78deeca294828 100644 (file)
@@ -49,7 +49,7 @@
    they are executed:
    <programlisting>
     ALTER DATABASE
-    ALTER ROLE
+    ALTER ROLE or USER (except WITH CONNECTION LIMIT and WITH [ENCRYPTED] PASSWORD)
     ALTER TABLE
     REVOKE
    </programlisting>
index 92e1e99a9a2a96808ce1ee0ec279dc93cf2965d3..8dbe3ebe5018029793b9b62b802eb06754953d48 100644 (file)
@@ -46,6 +46,7 @@ static int    forward_empty_query(POOL_CONNECTION * frontend, char *packet, int pac
 static int     forward_packet_to_frontend(POOL_CONNECTION * frontend, char kind, char *packet, int packetlen);
 static void process_clear_cache(POOL_CONNECTION_POOL * backend);
 static void clear_query_cache(void);
+static bool check_alter_role_statement(AlterRoleStmt *stmt);
 
 POOL_STATUS
 CommandComplete(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend, bool command_complete)
@@ -476,11 +477,44 @@ handle_query_context(POOL_CONNECTION_POOL * backend)
                process_clear_cache(backend);
        }
        else if (IsA(node, AlterTableStmt) || IsA(node, AlterDatabaseStmt) ||
-                        IsA(node, AlterDatabaseSetStmt) || IsA(node, AlterRoleStmt))
+                        IsA(node, AlterDatabaseSetStmt))
        {
                /* Clear query cache */
                process_clear_cache(backend);
        }
+       else if (IsA(node, AlterRoleStmt))
+       {
+               if (check_alter_role_statement(castNode(AlterRoleStmt, node)))
+               {
+                       /* Clear query cache */
+                       process_clear_cache(backend);
+               }
+       }
+}
+
+/*
+ * Check whether the ALTER ROLE statement needs query cache invalidation.
+ * stmt must be AlterRoleStmt.
+ */
+static bool
+check_alter_role_statement(AlterRoleStmt *stmt)
+{
+       ListCell        *l;
+
+       foreach(l, stmt->options)
+       {
+               DefElem *elm = (DefElem *) lfirst(l);
+
+               /*
+                * We want to detect other than ALTER ROLE foo WITH PASSWORD or
+                * WITH CONNECTION LIMIT case.  It does not change any privilege of the
+                * role.
+                */
+               if (strcmp(elm->defname, "password") &&
+                       strcmp(elm->defname, "connectionlimit"))
+                       return true;
+       }
+       return false;
 }
 
 /*
index 00e3bc9d8807932f36702f0fc0ce040f97154559..df85bcee94da3c80ad090d155fba81eb7d6fb17a 100644 (file)
@@ -567,3 +567,32 @@ NOTICE:  DB node id: 0 statement: SELECT * FROM t1;
  2 |  
 (1 row)
 
+--
+-- ALTER ROLE WITH ENCRYPTED PASSWORD and
+-- ALTER ROLE WITH CONNECTION LIMIT 10
+-- do not invalidate query cache
+SELECT 10;
+NOTICE:  DB node id: 0 statement: SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
+SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
+ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+NOTICE:  DB node id: 0 statement: ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+ALTER ROLE
+ALTER ROLE foo WITH CONNECTION LIMIT 10;
+NOTICE:  DB node id: 0 statement: ALTER ROLE foo WITH CONNECTION LIMIT 10;
+ALTER ROLE
+SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
index fc7f3303706c1760b5c183a4b3891836fe3fc582..ebf84694cd2ce43bca8e8d50861a1cf5fdcea99b 100644 (file)
@@ -625,3 +625,34 @@ NOTICE:  DB node id: 0 statement: SELECT * FROM t1;
  2 |  
 (1 row)
 
+--
+-- ALTER ROLE WITH ENCRYPTED PASSWORD and
+-- ALTER ROLE WITH CONNECTION LIMIT 10
+-- do not invalidate query cache
+SELECT 10;
+NOTICE:  DB node id: 0 statement: SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
+SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
+ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+NOTICE:  DB node id: 0 statement: ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+NOTICE:  DB node id: 1 statement: ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+ALTER ROLE
+ALTER ROLE foo WITH CONNECTION LIMIT 10;
+NOTICE:  DB node id: 0 statement: ALTER ROLE foo WITH CONNECTION LIMIT 10;
+NOTICE:  DB node id: 1 statement: ALTER ROLE foo WITH CONNECTION LIMIT 10;
+ALTER ROLE
+SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
index 00e3bc9d8807932f36702f0fc0ce040f97154559..df85bcee94da3c80ad090d155fba81eb7d6fb17a 100644 (file)
@@ -567,3 +567,32 @@ NOTICE:  DB node id: 0 statement: SELECT * FROM t1;
  2 |  
 (1 row)
 
+--
+-- ALTER ROLE WITH ENCRYPTED PASSWORD and
+-- ALTER ROLE WITH CONNECTION LIMIT 10
+-- do not invalidate query cache
+SELECT 10;
+NOTICE:  DB node id: 0 statement: SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
+SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
+ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+NOTICE:  DB node id: 0 statement: ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+ALTER ROLE
+ALTER ROLE foo WITH CONNECTION LIMIT 10;
+NOTICE:  DB node id: 0 statement: ALTER ROLE foo WITH CONNECTION LIMIT 10;
+ALTER ROLE
+SELECT 10;
+ ?column? 
+----------
+       10
+(1 row)
+
index 05f9e26a1496de08e67e5d7391cf6ae56625efd8..e3dd7e32e4b55049a1bb8a1c8cec6cbf91eaf0c0 100755 (executable)
@@ -439,6 +439,18 @@ EOF
 #      $PGPROTO -d test -f ../alter_database2.data |& del_details_from_error >> result
 #      $PGPROTO -d test -f ../alter_database3.data |& del_details_from_error >> result
 
+               $PSQL -a test >> result 2>&1 <<EOF
+--
+-- ALTER ROLE WITH ENCRYPTED PASSWORD and
+-- ALTER ROLE WITH CONNECTION LIMIT 10
+-- do not invalidate query cache
+SELECT 10;
+SELECT 10;
+ALTER ROLE foo WITH ENCRYPTED PASSWORD 'foo';
+ALTER ROLE foo WITH CONNECTION LIMIT 10;
+SELECT 10;
+EOF
+
        ./shutdownall
 
        cd ..