Skip to content

Commit 8ef8e46

Browse files
Remove wrong assertion in interpolate lookup
interpolate() declares its prev and next parameters as RECORD, which accepts any composite value, including one of a named composite type. The lookup path asserted that the fetched sample always carries the anonymous RECORD type id, so passing a named composite aborts the backend in assertion-enabled builds. The assertion contradicts the call it precedes: the type id and typmod are passed to lookup_rowtype_tupdesc(), which resolves named composite types as well, and the element types are validated right afterwards. The same pattern is used without an assertion in compression.c.
1 parent 0a51c86 commit 8ef8e46

4 files changed

Lines changed: 45 additions & 1 deletion

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes: #10399 Assertion failure in interpolate when the lookup argument is a named composite type

tsl/src/nodes/gapfill/interpolate.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ gapfill_fetch_sample(GapFillState *state, GapFillInterpolateColumnState *column,
114114
}
115115

116116
/* Extract type information from the tuple itself */
117-
Assert(RECORDOID == HeapTupleHeaderGetTypeId(th));
118117
tupdesc = lookup_rowtype_tupdesc(HeapTupleHeaderGetTypeId(th), HeapTupleHeaderGetTypMod(th));
119118

120119
/* Build a temporary HeapTuple control structure */

tsl/test/shared/expected/gapfill_bug.out

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,30 @@ DROP FUNCTION gf_userfn.time_bucket_gapfill(int, text);
585585
DROP FUNCTION gf_userfn.locf(int);
586586
DROP FUNCTION gf_userfn.interpolate(int);
587587
DROP SCHEMA gf_userfn;
588+
-- interpolate lookup queries may return a named composite type, not only an anonymous record
589+
CREATE TYPE gf_interp_sample AS (time int, value int);
590+
SELECT
591+
time_bucket_gapfill(1,time,1,5),
592+
interpolate(min(time),prev=>(SELECT ROW(0,0)::gf_interp_sample))
593+
FROM (VALUES (3),(4)) v(time)
594+
GROUP BY 1;
595+
time_bucket_gapfill | interpolate
596+
---------------------+-------------
597+
1 | 1
598+
2 | 2
599+
3 | 3
600+
4 | 4
601+
602+
SELECT
603+
time_bucket_gapfill(1,time,1,5),
604+
interpolate(min(time),next=>(SELECT ROW(9,9)::gf_interp_sample))
605+
FROM (VALUES (1),(2)) v(time)
606+
GROUP BY 1;
607+
time_bucket_gapfill | interpolate
608+
---------------------+-------------
609+
1 | 1
610+
2 | 2
611+
3 | 3
612+
4 | 4
613+
614+
DROP TYPE gf_interp_sample;

tsl/test/shared/sql/gapfill_bug.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,20 @@ DROP FUNCTION gf_userfn.time_bucket_gapfill(int, text);
342342
DROP FUNCTION gf_userfn.locf(int);
343343
DROP FUNCTION gf_userfn.interpolate(int);
344344
DROP SCHEMA gf_userfn;
345+
346+
-- interpolate lookup queries may return a named composite type, not only an anonymous record
347+
CREATE TYPE gf_interp_sample AS (time int, value int);
348+
349+
SELECT
350+
time_bucket_gapfill(1,time,1,5),
351+
interpolate(min(time),prev=>(SELECT ROW(0,0)::gf_interp_sample))
352+
FROM (VALUES (3),(4)) v(time)
353+
GROUP BY 1;
354+
355+
SELECT
356+
time_bucket_gapfill(1,time,1,5),
357+
interpolate(min(time),next=>(SELECT ROW(9,9)::gf_interp_sample))
358+
FROM (VALUES (1),(2)) v(time)
359+
GROUP BY 1;
360+
361+
DROP TYPE gf_interp_sample;

0 commit comments

Comments
 (0)