Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

GPORCA shared-CTE plan references out-of-range attnum: EXPLAIN fails with "invalid attnum 7 for relation share2_ref3", execution PANICs segments (SIGSEGV in hashtext)

Aperta
#2,088 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 3 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
42/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
c, postgresql, sql
Ambito
backend, databases

Direzione di ricerca

Start by reproducing the reported failure using the SQL in the issue with optimizer = on, running EXPLAIN only; compare with the successful plan using optimizer = off. Trace GPORCA's shared-CTE planning for the window CTE referenced twice and aggregated, focusing on how the producer and consumer handle unused columns and rn. Done means EXPLAIN succeeds and consumers reference only attributes emitted by the shared producer, or the planner safely falls back.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Apache Cloudberry version
PostgreSQL 14.4 (Apache Cloudberry 2.1.0-incubating build bdf90c5518f) on x86_64-pc-linux-gnu,
compiled by gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-11), 64-bit compiled on Apr 17 2026 21:12:00

16 primary segments with mirrors, optimizer = on (default).

What happened

A query that references a window-function CTE twice in a self-join, aggregates
over that self-join, and whose CTE input contains a LEFT JOIN to another CTE,
produces a GPORCA plan whose shared-scan consumer refers to an attribute the
shared producer does not emit.

  • EXPLAIN fails with an internal error from the plan deparser:
    ERROR: invalid attnum 7 for relation "share2_ref3" (ruleutils.c:7296).
  • Executing the statement bypasses that check. On a 16-segment cluster it
    crashed 10 primaries with SIGSEGV in hash_bytes (called from hashtext
    while building a hash join) and raised
    ERROR XX001: compressed pglz data is corrupt on 2 others. The remaining
    segments returned canceling MPP operation. Mirrors were promoted and a
    full gprecoverseg was needed.
  • With SET optimizer = off the same statement plans and runs; the CTE is
    inlined twice and there is no shared scan.

The underlying data is not corrupt. The synthetic tables below reproduce the
EXPLAIN error with the identical relation name and attnum.

Severity

I want to flag this as a cluster-health issue rather than a wrong-plan
issue. A single read-only SELECT, run by an unprivileged user with no
special settings, PANICked 10 of 16 primary segments simultaneously. The
postmasters reset, FTS promoted the mirrors, and the cluster then needed a
multi-hour gprecoverseg with full copies for some segments. Every
in-flight query on the cluster failed with it. Because the trigger is a plan
shape and not a data condition, any user who can run this query shape can
take down most of the cluster, and the only guard today is EXPLAIN-ing first
or running with optimizer = off.

Impact observed

Segment log, one of ten identical entries, all for the same session, command
and slice, within 200 ms of each other:

PANIC  XX000  Unexpected internal error: Segment process received signal SIGSEGV
1    0xd704a5 postgres StandardHandlerForSigillSigsegvSigbus_OnMainThread + 0x155
2    0x7f90cf43fc30 libc.so.6 <symbol not found> + 0xcf43fc30
3    0x113f038 postgres hash_bytes + 0x18
4    0x817bb4 postgres hashtext + 0x54
5    0xd72710 postgres FunctionCall1Coll + 0x40
6    0xa209f7 postgres ExecHashGetHashValue + 0x207
7    0xa24477 postgres MultiExecHash + 0x467
...
21   0x9fd001 postgres standard_ExecutorRun + 0x751
22   0x9fd1a5 postgres ExecutorRun + 0xc5
24   0xc1c8f0 postgres PortalRun + 0x190
26   0xc1a648 postgres PostgresMain + 0x2358
LOG  server process was terminated by signal 11: Segmentation fault

On two further segments the same slice raised instead:

ERROR  XX001  compressed pglz data is corrupt   (toast_compression.c:98)

The consistent reading is that the consumer fetched "attribute 7" from a
shared tuple that did not carry it and hashed whatever bytes were there as
the text join key. The two outcomes depend only on whether the garbage header
happened to have the compression bit set.

The original statement was the same shape with a STRING_AGG and a few
filters, over an append-optimized, range-partitioned table and a heap
materialized view.

What you think should happen instead

Either a plan whose shared-scan consumers only reference attributes the
producer emits, or a fallback to the PostgreSQL planner. A plan that the
deparser rejects as internally inconsistent should never reach the executor.

How to reproduce

Everything below is EXPLAIN only. Please do not execute the SELECT itself
with optimizer = on on a cluster you care about.

CREATE TABLE t_events (
    id    bigint,
    uid   bigint,
    ts    timestamp,
    grp   int,
    k     text,
    note  text
) DISTRIBUTED BY (id);

INSERT INTO t_events
SELECT g,
       1000000 + (g % 5000),
       timestamp '2026-01-01' + (g % 50) * interval '12 hours' + (g % 7) * interval '5 minutes',
       CASE WHEN g % 3 = 0 THEN 7 ELSE 1 END,
       'k' || (g % 200),
       CASE WHEN g % 4 = 0 THEN 'x=' || md5(g::text) ELSE 'none' END
FROM generate_series(1, 20000) g;

CREATE TABLE t_dim (
    k    text,
    cat  int,
    grp  int,
    d    date,
    cnt  int
) DISTRIBUTED BY (k);

INSERT INTO t_dim
SELECT 'k' || (g % 200), (ARRAY[1, 5, 14])[1 + g % 3], 7, date '2026-01-01' + (g % 25), g % 3
FROM generate_series(1, 5000) g;

ANALYZE t_events;
ANALYZE t_dim;

SET optimizer = on;

EXPLAIN
WITH w AS (
  SELECT k, MIN(cat) mc FROM t_dim GROUP BY 1
), s AS (
  SELECT e.id, e.uid, e.ts, e.ts::date p, COALESCE(w.mc, -1) mc, e.k gk
  FROM t_events e LEFT JOIN w ON w.k = e.k
), o AS (
  SELECT s.*, ROW_NUMBER() OVER (PARTITION BY p, gk ORDER BY ts, id) rn FROM s
),
q AS (
  SELECT o.p, o.gk, COUNT(*) n
  FROM o JOIN (SELECT p, gk FROM o WHERE rn = 1) f ON f.p = o.p AND f.gk = o.gk
  GROUP BY 1, 2
)
SELECT COUNT(*) FROM q;

Result:

ERROR:  invalid attnum 7 for relation "share2_ref3" (ruleutils.c:7296)

o has seven columns; attribute 7 is rn, the window result that the second
consumer filters on (WHERE rn = 1).

With SET optimizer = off the same statement produces a plan in which o is
inlined twice, each copy with its own WindowAgg over a Redistribute Motion,
and no Share Input Scan.

What is and is not required (minimisation ladder of 29 variants)

Required, removing any one of these makes it plan:

  1. The LEFT JOIN from the window CTE's input (s) to the aggregated CTE
    w. Dropping the join (making mc a constant) makes it plan. We did not
    isolate whether the join must go through a CTE or whether an inline
    subquery would do; the only inline variant we tried also had fewer columns
    in o, which independently makes it plan (see 4).
  2. The window CTE o referenced twice, joined to itself.
  3. An aggregation (GROUP BY) over that self-join. The identical self-join
    with a plain COUNT(*) and no GROUP BY, or with a join filter but no
    aggregation, plans fine.
  4. Unused columns in o. With uid and ts present in s (and therefore in
    o) it fails even when nothing downstream reads them and the window
    ORDER BY is just id. Removing those two columns, so o has five
    attributes, makes it plan.

Not required: the second join key, STRING_AGG (with or without ORDER BY),
a CASE on the joined column, a join filter between the two consumers,
WHERE filters on either table, the MIN aggregate in w (a plain filtered
scan behaves the same), append-optimized column storage, and range
partitioning. The original tables were AOCO and partitioned; plain heap tables
reproduce it identically.

Operating System

RHEL 9 family, x86_64 (build compiled with gcc 11.5.0 20240719, Red Hat 11.5.0-11).

Anything else

Workaround in use: SET optimizer = off for the session, or materialise the window CTE into a
temporary table so it is referenced once.

Are you willing to submit PR?
  • Yes, I am willing to submit a PR!
Code of Conduct
  • I agree to follow this project's Code of Conduct
Lingua principale
C
Stelle
1.4k
Fork
260
Merge medio
4g 52m
PR unite (30g)
51

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/cloudberry

Tutte le issue di apache/cloudberry

Issue simili

Altre issue su C

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.