diff --git a/src/backend/columnar/columnar_metadata.c b/src/backend/columnar/columnar_metadata.c index cd62c8b0c..5bb396baa 100644 --- a/src/backend/columnar/columnar_metadata.c +++ b/src/backend/columnar/columnar_metadata.c @@ -2054,6 +2054,27 @@ Datum columnar_relation_storageid(PG_FUNCTION_ARGS) { Oid relationId = PG_GETARG_OID(0); + + /* Keep in sync with columnar.storage view filter (exclude other sessions' temps). */ +#if PG_VERSION_NUM >= PG_VERSION_18 + + /* PG18+: avoid relation_open() on other sessions' temp tables. */ + HeapTuple classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(relationId)); + if (!HeapTupleIsValid(classtup)) + { + PG_RETURN_NULL(); /* invalid/gone OID */ + } + Form_pg_class cls = (Form_pg_class) GETSTRUCT(classtup); + bool reject = (cls->relpersistence == RELPERSISTENCE_TEMP) && + isOtherTempNamespace(cls->relnamespace); + ReleaseSysCache(classtup); + + if (reject) + { + PG_RETURN_NULL(); /* function is STRICT; callers just skip */ + } +#endif + Relation relation = relation_open(relationId, AccessShareLock); if (!object_ownercheck(RelationRelationId, relationId, GetUserId())) diff --git a/src/backend/columnar/sql/citus_columnar--13.2-1--14.0-1.sql b/src/backend/columnar/sql/citus_columnar--13.2-1--14.0-1.sql index 016c78f6b..dc8318898 100644 --- a/src/backend/columnar/sql/citus_columnar--13.2-1--14.0-1.sql +++ b/src/backend/columnar/sql/citus_columnar--13.2-1--14.0-1.sql @@ -1,2 +1,44 @@ -- citus_columnar--13.2-1--14.0-1 -- bump version to 14.0-1 + +CREATE OR REPLACE VIEW columnar.storage WITH (security_barrier) AS + SELECT c.oid::regclass AS relation, + columnar.get_storage_id(c.oid) AS storage_id + FROM pg_catalog.pg_class c + JOIN pg_catalog.pg_am am ON c.relam = am.oid + WHERE am.amname = 'columnar' + -- exclude other sessions' temp rels, but keep *my* temp tables + AND (c.relpersistence <> 't' + OR c.relnamespace = pg_catalog.pg_my_temp_schema()) + AND pg_catalog.pg_has_role(c.relowner, 'USAGE'); +COMMENT ON VIEW columnar.storage IS 'Columnar relation ID to storage ID mapping.'; +GRANT SELECT ON columnar.storage TO PUBLIC; + +-- re-emit dependent views with OR REPLACE so they stay bound cleanly +CREATE OR REPLACE VIEW columnar.stripe WITH (security_barrier) AS + SELECT relation, storage.storage_id, stripe_num, file_offset, data_length, + column_count, chunk_row_count, row_count, chunk_group_count, first_row_number + FROM columnar_internal.stripe stripe, columnar.storage storage + WHERE stripe.storage_id = storage.storage_id; +COMMENT ON VIEW columnar.stripe + IS 'Columnar stripe information for tables on which the current user has ownership privileges.'; +GRANT SELECT ON columnar.stripe TO PUBLIC; + +CREATE OR REPLACE VIEW columnar.chunk_group WITH (security_barrier) AS + SELECT relation, storage.storage_id, stripe_num, chunk_group_num, row_count + FROM columnar_internal.chunk_group cg, columnar.storage storage + WHERE cg.storage_id = storage.storage_id; +COMMENT ON VIEW columnar.chunk_group + IS 'Columnar chunk group information for tables on which the current user has ownership privileges.'; +GRANT SELECT ON columnar.chunk_group TO PUBLIC; + +CREATE OR REPLACE VIEW columnar.chunk WITH (security_barrier) AS + SELECT relation, storage.storage_id, stripe_num, attr_num, chunk_group_num, + minimum_value, maximum_value, value_stream_offset, value_stream_length, + exists_stream_offset, exists_stream_length, value_compression_type, + value_compression_level, value_decompressed_length, value_count + FROM columnar_internal.chunk chunk, columnar.storage storage + WHERE chunk.storage_id = storage.storage_id; +COMMENT ON VIEW columnar.chunk + IS 'Columnar chunk information for tables on which the current user has ownership privileges.'; +GRANT SELECT ON columnar.chunk TO PUBLIC;