Fix query cache to not cache timestamptz and timetz cast.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Tue, 5 Jul 2022 05:06:10 +0000 (14:06 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Tue, 5 Jul 2022 05:06:10 +0000 (14:06 +0900)
Even if query is constant + cast (like '2022-07-05
14:07:00'::timestamptz), the result can be changed by SET TIME ZONE
command etc. and the result should not be cached.
Also regression test data added.

Discussion: https://www.pgpool.net/pipermail/pgpool-general/2022-July/008353.html

src/rewrite/pool_timestamp.c
src/test/regression/tests/006.memqcache/test.sh
src/utils/pool_select_walker.c

index 07143dadf8ad705ee74d5a5a8f0e569fb243d52f..6c3752f36f0400f54261e0998cb84fa8d1e224f1 100644 (file)
@@ -307,7 +307,9 @@ isSystemType(Node *node, const char *name)
                strcmp("pg_catalog", strVal(linitial(typename->names))) == 0 &&
                strcmp(name, strVal(lsecond(typename->names))) == 0)
                return true;
-
+       else if (list_length(typename->names) == 1 &&
+                        strcmp(name, strVal(linitial(typename->names))) == 0)
+               return true;
        return false;
 }
 
index 6a5a11814570a2e79cc610de5629bba6d969a241..781849def0fe22330e7617ad82568ec72f355f36 100755 (executable)
@@ -70,6 +70,16 @@ EXPLAIN ANALYZE INSERT INTO explain_analyze VALUES(1);
 SELECT * FROM explain_analyze;
 SELECT CURRENT_TIMESTAMP;
 SELECT CURRENT_USER;
+SELECT '2022-07-05 10:00:00'::TIMESTAMP;
+SELECT '2022-07-05 10:00:00'::TIMESTAMP;
+SELECT '2022-07-05 10:00:00'::TIME;
+SELECT '2022-07-05 10:00:00'::TIME;
+SELECT '2022-07-05 10:00:00'::DATE;
+SELECT '2022-07-05 10:00:00'::DATE;
+SELECT '2022-07-05 10:00:00'::TIMESTAMPTZ;
+SELECT '2022-07-05 10:00:00'::TIMESTAMPTZ;
+SELECT '2022-07-05 10:00:00'::TIMETZ;
+SELECT '2022-07-05 10:00:00'::TIMETZ;
 EOF
 
        success=true
@@ -83,6 +93,12 @@ EOF
        grep "fetched from cache" log/pgpool.log | grep explain_analyze > /dev/null && success=false
        grep "fetched from cache" log/pgpool.log | grep CURRENT_TIMESTAMP > /dev/null && success=false
        grep "fetched from cache" log/pgpool.log | grep CURRENT_USER > /dev/null && success=false
+       grep "fetched from cache" log/pgpool.log | grep 'TIMESTAMP;' > /dev/null || success=false
+       grep "fetched from cache" log/pgpool.log | grep 'TIME;' > /dev/null || success=false
+       grep "fetched from cache" log/pgpool.log | grep 'DATE;' > /dev/null || success=false
+       grep "fetched from cache" log/pgpool.log | grep 'TIMESTAMPTZ;' > /dev/null && success=false
+       grep "fetched from cache" log/pgpool.log | grep 'TIMETZ;' > /dev/null && success=false
+
        if [ $success = false ];then
                ./shutdownall
                exit 1
index c2e724b2075d520e92345106e8a8ccbb03006cea..9cb5583bc94853c01f06e9743f9ea90a6d5b76af 100644 (file)
@@ -1039,23 +1039,18 @@ non_immutable_function_call_walker(Node *node, void *context)
         * "SELECT '2022-07-04 09:00:00'::TIMESTAMP" could be regarded as
         * non-cachable for example. But there's nothing we can do here.
         */
-#ifdef NOT_USED
-       else if (IsA(node, TypeCast) && PG
+       else if (IsA(node, TypeCast))
        {
-               /* CURRENT_DATE, CURRENT_TIME, LOCALTIMESTAMP, LOCALTIME etc. */
+               /* TIMESTAMP WITH TIME ZONE and TIME WITH TIME ZONE should not be cached. */
                TypeCast   *tc = (TypeCast *) node;
 
-               if ((isSystemType((Node *) tc->typeName, "date") ||
-                        isSystemType((Node *) tc->typeName, "timestamp") ||
-                        isSystemType((Node *) tc->typeName, "timestamptz") ||
-                        isSystemType((Node *) tc->typeName, "time") ||
-                        isSystemType((Node *) tc->typeName, "timetz")))
+               if (isSystemType((Node *) tc->typeName, "timestamptz") ||
+                       isSystemType((Node *) tc->typeName, "timetz"))
                {
                        ctx->has_non_immutable_function_call = true;
                        return false;
                }
        }
-#endif
        else if (IsA(node, SQLValueFunction))
        {
                /*