yegor256/pgtk

Pgtk::Stash caches non-deterministic queries (CURRENT_TIMESTAMP, RANDOM, etc.)

Open

#378 创建于 2026年6月6日

在 GitHub 查看
 (1 评论) (0 反应) (0 负责人)Ruby (6 fork)github user discovery
bughelp wanted

仓库指标

Star
 (8 star)
PR 合并指标
 (PR 指标待抓取)

描述

Description

Pgtk::Stash#select skips caching only for queries containing NOW() (with spaces):

cache(pure, key, params, result, ret, tables, marks) unless pure.include?(" NOW() ")

This misses many other non-deterministic SQL functions, which get cached with incorrect (stale) results:

Expression Cached? Correct?
NOW() (with spaces) No Yes
CURRENT_TIMESTAMP Yes No — bug
CURRENT_DATE Yes No — bug
CURRENT_TIME Yes No — bug
LOCALTIMESTAMP Yes No — bug
RANDOM() Yes No — bug
GEN_RANDOM_UUID() Yes No — bug
CLOCK_TIMESTAMP() Yes No — bug
NOW() (no spaces: NOW()) Yes No — bug

The check is also whitespace-sensitive: SELECT NOW() is skipped, but SELECT NOW() with exactly no space before the paren passes through.

Impact

  • Queries using any non-deterministic function besides NOW() return stale cached data
  • Example: SELECT CURRENT_TIMESTAMP returns the same timestamp on every call
  • Example: SELECT RANDOM() FROM generate_series(1,10) returns the same values every call
  • The cache silently serves incorrect data with no indication of staleness

Suggested fix

Replace the single NOW() check with a regex covering the common non-deterministic expressions:

NONDETERMINISTIC = /\b(NOW|CURRENT_TIMESTAMP|CURRENT_DATE|CURRENT_TIME|LOCALTIMESTAMP|LOCALTIME|RANDOM|GEN_RANDOM_UUID|CLOCK_TIMESTAMP|TIMEZONE)\s*\(/i

def select(pure, params, result)
  # ...
  cache(pure, key, params, result, ret, tables, marks) unless pure.match?(NONDETERMINISTIC)
  # ...
end

Related previous work

This is a continuation of the same caching-correctness theme addressed in earlier issues:

  • #368 — Stash table_mod non-monotonic stamp
  • #364 — Stash skips invalidation for tables with underscores/digits
  • #336 — Stash persistently-stale empty SELECT

Unlike those issues (which were about cache invalidation), this one is about cache prevention — queries that should never be cached in the first place because they are non-deterministic by nature.

贡献者指南