Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

TRUNCATE fails with `schema "ag_catalog" does not exist` in databases without AGE, when AGE is in shared_preload_libraries

未关闭 适合新手
#2,520 3 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@crdv7 已经在做这个了。

开始于 2026年9月24日。

  • #2578 来自 @crdv7 —— 未关闭

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
78/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
c, postgresql
领域
backend, databases

调研方向

从 src/backend/catalog/ag_catalog.c 中的 ag_ProcessUtility_hook() 的 T_TruncateStmt 分支开始,然后阅读 is_age_extension_exists() 以及附近受保护的 hook 路径。在预加载 age 的情况下,在没有 AGE 的数据库中重现 TRUNCATE,并在安装了 AGE 的数据库中验证行为。完成的标准是:未扩展的数据库可以正常执行 truncate,且不会出现 ag_catalog 错误,同时 AGE 图表仍保留现有行为。

由索引模型根据 Issue 内容生成。

描述

Summary

When age is in shared_preload_libraries, TRUNCATE fails in any database that does not have the AGE extension installed:

ERROR:  schema "ag_catalog" does not exist

This makes AGE unsafe to preload on a shared PostgreSQL cluster: a single database wanting graph support breaks TRUNCATE for every other database in the instance.

This is the same class of problem as #2180 (fixed for the object_access_hook path by #2161), but on a different code path that was added later and does not have the guard.

Environment

  • PostgreSQL 18.6 (Debian 18.6-1.pgdg13+2), x86_64
  • Apache AGE 1.8.0 (postgresql-18-pgdg-age, PGDG apt)
  • shared_preload_libraries = age

Reproduction

$ psql -U postgres -c "CREATE DATABASE app;"
CREATE DATABASE

$ psql -U postgres -d app -c "CREATE TABLE t (i int);"
CREATE TABLE

$ psql -U postgres -d app -c "TRUNCATE t;"
ERROR:  schema "ag_catalog" does not exist

The database app never had CREATE EXTENSION age run in it.

Installing the extension in that database makes it work again:

$ psql -U postgres -d app -c "CREATE EXTENSION age;"
CREATE EXTENSION

$ psql -U postgres -d app -c "TRUNCATE t;"
TRUNCATE TABLE

Only TRUNCATE is affected. CREATE TABLE / INSERT / UPDATE / DELETE / CREATE INDEX / ALTER TABLE / VACUUM / ANALYZE / REINDEX / CLUSTER / DROP TABLE / COPY / CREATE EXTENSION <other> / pg_dump / pg_restore all behave normally in the same database.

Root cause

ag_ProcessUtility_hook() in src/backend/catalog/ag_catalog.c handles T_TruncateStmt and calls get_graph_oid_for_table() — which resolves ag_catalog — without first checking whether the AGE extension exists in the current database:

case T_TruncateStmt:
    {
        TruncateStmt *tstmt = (TruncateStmt *) parsetree;
        ListCell *lc;

        foreach(lc, tstmt->relations)
        {
            RangeVar *rv = (RangeVar *) lfirst(lc);
            Oid rel_oid = RangeVarGetRelid(rv, AccessShareLock, true);

            if (OidIsValid(rel_oid))
            {
                Oid graph_oid = get_graph_oid_for_table(rel_oid);   /* <-- resolves ag_catalog */

                if (OidIsValid(graph_oid))
                {
                    increment_graph_version(graph_oid);
                }
            }
        }
    }
    break;

The file already provides the guard for exactly this purpose — is_age_extension_exists(), with the comment:

We don't want most of hooks to do anything if the "age" extension isn't created.

but in the PG18 branch it is only called from is_age_drop() and object_access() — the T_TruncateStmt branch (lines 172–202) calls get_graph_oid_for_table() with no guard at all. Since shared_preload_libraries loads the library instance-wide, the hook runs in every database, including those where ag_catalog does not exist.

Suggested fix

Bail out early in the T_TruncateStmt branch, consistent with how the other hooks guard themselves:

case T_TruncateStmt:
    {
        TruncateStmt *tstmt = (TruncateStmt *) parsetree;
        ListCell *lc;

        if (!is_age_extension_exists())
            break;
        ...
    }

Guarding the whole switch (or the hook entry point) would also work and would protect any future branch from the same mistake.

Impact / workaround

Workaround is to run CREATE EXTENSION age in every database of the instance, including template1 so that newly created databases inherit it. That is fragile: databases created with TEMPLATE template0 — which pg_dump/pg_restore output commonly uses — do not inherit it, and TRUNCATE starts failing there with an error that gives no hint that AGE is involved.

Happy to submit a PR if the maintainers agree with the approach.

主要语言
C
星标
4.9k
派生
532
平均合并
8 天 15 小时
30 天内合并 PR
3

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

apache/age 的其他 Issue

查看 apache/age 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。