Enhance columnar_relation_storageid to handle temp tables in PG18+

m3hm3t/pg18_columnar_access_temp_err
Mehmet Yilmaz 2025-10-24 11:42:10 +00:00
parent 2e4cb36bb2
commit f77667857c
7 changed files with 32 additions and 56 deletions

View File

@ -2024,6 +2024,26 @@ Datum
columnar_relation_storageid(PG_FUNCTION_ARGS) columnar_relation_storageid(PG_FUNCTION_ARGS)
{ {
Oid relationId = PG_GETARG_OID(0); Oid relationId = PG_GETARG_OID(0);
#if PG_VERSION_NUM >= PG_VERSION_18
/*
* PG18+: avoid relation_open() on other sessions' temp tables.
* Return NULL so callers/views just skip them (function is STRICT).
*/
HeapTuple classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId));
if (!HeapTupleIsValid(classtup))
PG_RETURN_NULL();
Form_pg_class cls = (Form_pg_class) GETSTRUCT(classtup);
if (cls->relpersistence == RELPERSISTENCE_TEMP &&
isOtherTempNamespace(cls->relnamespace))
{
ReleaseSysCache(classtup);
PG_RETURN_NULL();
}
ReleaseSysCache(classtup);
#endif
Relation relation = relation_open(relationId, AccessShareLock); Relation relation = relation_open(relationId, AccessShareLock);
if (!object_ownercheck(RelationRelationId, relationId, GetUserId())) if (!object_ownercheck(RelationRelationId, relationId, GetUserId()))

View File

@ -214,8 +214,8 @@ SELECT COUNT(*) FROM columnar_temp WHERE i < 5;
4 4
(1 row) (1 row)
SELECT COALESCE(columnar_test_helpers.get_storage_id_if_visible('columnar_temp'::regclass), 0) SELECT columnar.get_storage_id(oid) AS columnar_temp_storage_id
AS columnar_temp_storage_id \gset FROM pg_class WHERE relname='columnar_temp' \gset
BEGIN; BEGIN;
DROP TABLE columnar_temp; DROP TABLE columnar_temp;
-- show that we drop stripes properly -- show that we drop stripes properly

View File

@ -11,19 +11,10 @@ $$ LANGUAGE SQL;
INSERT INTO t2 SELECT i, f(i) FROM generate_series(1, 5) i; INSERT INTO t2 SELECT i, f(i) FROM generate_series(1, 5) i;
-- there are no subtransactions, so above statement should batch -- there are no subtransactions, so above statement should batch
-- INSERTs inside the UDF and create on stripe per table. -- INSERTs inside the UDF and create on stripe per table.
WITH rels(rel) AS ( SELECT relname, count(*) FROM columnar.stripe a, pg_class b
VALUES ('t1'::regclass), ('t2'::regclass) WHERE columnar.get_storage_id(b.oid)=a.storage_id AND relname IN ('t1', 't2')
), GROUP BY relname
sids AS ( ORDER BY relname;
SELECT rel, columnar.get_storage_id(rel) AS sid
FROM rels
)
SELECT c.relname, COUNT(*) AS count
FROM columnar_internal.stripe st
JOIN sids s ON st.storage_id = s.sid
JOIN pg_catalog.pg_class c ON c.oid = s.rel
GROUP BY c.relname
ORDER BY c.relname;
relname | count relname | count
--------------------------------------------------------------------- ---------------------------------------------------------------------
t1 | 1 t1 | 1

View File

@ -146,15 +146,3 @@ BEGIN
RETURN NEXT; RETURN NEXT;
END LOOP; END LOOP;
END; $$ language plpgsql; END; $$ language plpgsql;
CREATE OR REPLACE FUNCTION get_storage_id_if_visible(rel regclass)
RETURNS bigint
LANGUAGE sql STABLE AS $$
SELECT CASE
WHEN c.relpersistence = 't'
AND c.relnamespace <> pg_catalog.pg_my_temp_schema()
THEN NULL -- other sessions temp → dont touch
ELSE columnar.get_storage_id(c.oid)
END
FROM pg_catalog.pg_class c
WHERE c.oid = $1::oid
$$;

View File

@ -174,8 +174,8 @@ INSERT INTO columnar_temp SELECT i FROM generate_series(1,5) i;
-- test basic select -- test basic select
SELECT COUNT(*) FROM columnar_temp WHERE i < 5; SELECT COUNT(*) FROM columnar_temp WHERE i < 5;
SELECT COALESCE(columnar_test_helpers.get_storage_id_if_visible('columnar_temp'::regclass), 0) SELECT columnar.get_storage_id(oid) AS columnar_temp_storage_id
AS columnar_temp_storage_id \gset FROM pg_class WHERE relname='columnar_temp' \gset
BEGIN; BEGIN;
DROP TABLE columnar_temp; DROP TABLE columnar_temp;

View File

@ -15,20 +15,10 @@ INSERT INTO t2 SELECT i, f(i) FROM generate_series(1, 5) i;
-- there are no subtransactions, so above statement should batch -- there are no subtransactions, so above statement should batch
-- INSERTs inside the UDF and create on stripe per table. -- INSERTs inside the UDF and create on stripe per table.
WITH rels(rel) AS ( SELECT relname, count(*) FROM columnar.stripe a, pg_class b
VALUES ('t1'::regclass), ('t2'::regclass) WHERE columnar.get_storage_id(b.oid)=a.storage_id AND relname IN ('t1', 't2')
), GROUP BY relname
sids AS ( ORDER BY relname;
SELECT rel, columnar.get_storage_id(rel) AS sid
FROM rels
)
SELECT c.relname, COUNT(*) AS count
FROM columnar_internal.stripe st
JOIN sids s ON st.storage_id = s.sid
JOIN pg_catalog.pg_class c ON c.oid = s.rel
GROUP BY c.relname
ORDER BY c.relname;
SELECT * FROM t1 ORDER BY a; SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2 ORDER BY a; SELECT * FROM t2 ORDER BY a;

View File

@ -158,16 +158,3 @@ BEGIN
RETURN NEXT; RETURN NEXT;
END LOOP; END LOOP;
END; $$ language plpgsql; END; $$ language plpgsql;
CREATE OR REPLACE FUNCTION get_storage_id_if_visible(rel regclass)
RETURNS bigint
LANGUAGE sql STABLE AS $$
SELECT CASE
WHEN c.relpersistence = 't'
AND c.relnamespace <> pg_catalog.pg_my_temp_schema()
THEN NULL -- other sessions temp → dont touch
ELSE columnar.get_storage_id(c.oid)
END
FROM pg_catalog.pg_class c
WHERE c.oid = $1::oid
$$;