Fix bug in query cache.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Mon, 4 Jul 2022 05:23:48 +0000 (14:23 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Mon, 4 Jul 2022 06:09:34 +0000 (15:09 +0900)
[pgpool-general: 8285] Timestamp cast not cached

reported that query like "Select '2022-02-18
07:00:00.006547’::timestamp" is not cached.

The function non_immutable_function_call_walker() which judges whether
the query contains non immutable functions mistakenly assumes that any
query including cast to timestamp etc. should not to be cached. These
codes were originally added to detect CURRENT_TIMESTAMP etc. as they
are transformed to type cast in raw parser. Unfortunately this is
overkill since "'2022-02-18 07:00:00.006547’::timestamp" is also
transformed to a type cast.

Fortunately Pgpool-II 3.7 and after imported PostgreSQL 10 or newer
parser, which transforms CURRENT_TIMESTAMP etc. to SQLValueFunction.

As a result, the type cast handling code in
non_immutable_function_call_walker() is not necessary anymore. So this
commit removed the code.

Note: an interested thing in the report is, "Select '2022-02-18
07:00:00.006547’::timestamp" is not cached while "Select '2022-02-18
07:00:00.006547’::date" is cached. Why? Well
non_immutable_function_call_walker() (wrongly) assumes that the type
cache is always created by SystemTypeName (a parser's function), which
always adds pg_catalog schema. This only happens when the type name is
a reserved keyword. TIMESTAMP is a reserved keyword (and TIME too). So
non_immutable_function_call_walker() catches TIMESTAMP cast as
expected, but DATE is not a reserved keyword and it is transformed to
type name without "pg_catalog" schema. So
non_immutable_function_call_walker() misses it, and it is cached.

src/utils/pool_select_walker.c

index a663e6523de6635653323d9054e3bbff6faf70f4..6d799daec26105340c95b438ef7cbea21d0c7ce4 100644 (file)
@@ -1013,7 +1013,17 @@ static bool non_immutable_function_call_walker(Node *node, void *context)
                        }
                }
        }
-       else if (IsA(node, TypeCast))
+
+       /* Before Pgpool-II 3.7 there was no SQLValueFunction in the parser.  For
+        * the older versions (3.6 or before), we need to check type cast and
+        * typename instead.  If they are some type casts described below, we
+        * assume that this SELECT cannot be cached since they might be a
+        * transformed CURRENT_TIMESTAMP etc.  Of course this could be overkill as
+        * "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
        {
                /* CURRENT_DATE, CURRENT_TIME, LOCALTIMESTAMP, LOCALTIME etc.*/
                TypeCast        *tc = (TypeCast *) node;
@@ -1028,6 +1038,7 @@ static bool non_immutable_function_call_walker(Node *node, void *context)
                        return false;
                }
        }
+#endif
        else if (IsA(node, SQLValueFunction))
        {
                /*