diff --git a/src/backend/columnar/columnar_metadata.c b/src/backend/columnar/columnar_metadata.c index 0b4f2400c..b0565a666 100644 --- a/src/backend/columnar/columnar_metadata.c +++ b/src/backend/columnar/columnar_metadata.c @@ -1993,9 +1993,10 @@ ColumnarNamespaceId(void) static uint64 LookupStorageId(RelFileLocator relfilelocator) { - Oid relationId = RelidByRelfilenumber(RelationTablespace_compat(relfilelocator), - RelationPhysicalIdentifierNumber_compat( - relfilelocator)); + Oid relationId = RelidByRelfilenumberWithTempTables(RelationTablespace_compat( + relfilelocator), + RelationPhysicalIdentifierNumber_compat( + relfilelocator)); Relation relation = relation_open(relationId, AccessShareLock); uint64 storageId = ColumnarStorageGetStorageId(relation, false); @@ -2123,3 +2124,85 @@ GetFirstRowNumberAttrIndexInColumnarStripe(TupleDesc tupleDesc) ? (Anum_columnar_stripe_first_row_number - 1) : tupleDesc->natts - 1; } + + +/* + * Map a relation's (tablespace, relfilenumber) to a relation's oid and cache + * the result. + * PG18 and latest PG minors have excluded temporary tables from RelidByRelfilenumber, + * so we need to handle them here. + * Relevant PG commit: https://github.com/postgres/postgres/commit/dcdc95cb4 + * This function does an extra search if relid is InvalidOid, for temp tables only. + * Code is mostly copy-paste from PG's RelidByRelfilenumber. + * Returns InvalidOid if no relation matching the criteria could be found. + */ +Oid +RelidByRelfilenumberWithTempTables(Oid reltablespace, RelFileNumber relfilenumber) +{ + Oid relid; + +#if PG_VERSION_NUM >= PG_VERSION_16 + relid = RelidByRelfilenumber(reltablespace, relfilenumber); +#else + relid = RelidByRelfilenode(reltablespace, relfilenumber); +#endif + + if (relid == InvalidOid) + { + ScanKeyData skey[2]; + HeapTuple ntp; + + /* pg_class will show 0 when the value is actually MyDatabaseTableSpace */ + if (reltablespace == MyDatabaseTableSpace) + { + reltablespace = 0; + } + + /* check for plain relations by looking in pg_class */ + Relation relation = table_open(RelationRelationId, AccessShareLock); + + ScanKeyInit(&skey[0], + Anum_pg_class_reltablespace, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(reltablespace)); + ScanKeyInit(&skey[1], + Anum_pg_class_relfilenode, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relfilenumber)); + + SysScanDesc scandesc = systable_beginscan(relation, + ClassTblspcRelfilenodeIndexId, + true, + NULL, + 2, + skey); + + bool found = false; + + while (HeapTupleIsValid(ntp = systable_getnext(scandesc))) + { + Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp); + + if (found) + { + elog(ERROR, + "unexpected duplicate for tablespace %u, relfilenumber %u", + reltablespace, relfilenumber); + } + found = true; + + Assert(classform->reltablespace == reltablespace); + Assert(classform->relfilenode == relfilenumber); + + if (classform->relpersistence == RELPERSISTENCE_TEMP) + { + relid = classform->oid; + } + } + + systable_endscan(scandesc); + table_close(relation, AccessShareLock); + } + + return relid; +} diff --git a/src/backend/columnar/columnar_writer.c b/src/backend/columnar/columnar_writer.c index 1bdc612c1..8b9842663 100644 --- a/src/backend/columnar/columnar_writer.c +++ b/src/backend/columnar/columnar_writer.c @@ -183,10 +183,10 @@ ColumnarWriteRow(ColumnarWriteState *writeState, Datum *columnValues, bool *colu writeState->stripeSkipList = stripeSkipList; writeState->compressionBuffer = makeStringInfo(); - Oid relationId = RelidByRelfilenumber(RelationTablespace_compat( - writeState->relfilelocator), - RelationPhysicalIdentifierNumber_compat( - writeState->relfilelocator)); + Oid relationId = RelidByRelfilenumberWithTempTables(RelationTablespace_compat( + writeState->relfilelocator), + RelationPhysicalIdentifierNumber_compat( + writeState->relfilelocator)); Relation relation = relation_open(relationId, NoLock); writeState->emptyStripeReservation = ReserveEmptyStripe(relation, columnCount, chunkRowCount, @@ -404,10 +404,10 @@ FlushStripe(ColumnarWriteState *writeState) elog(DEBUG1, "Flushing Stripe of size %d", stripeBuffers->rowCount); - Oid relationId = RelidByRelfilenumber(RelationTablespace_compat( - writeState->relfilelocator), - RelationPhysicalIdentifierNumber_compat( - writeState->relfilelocator)); + Oid relationId = RelidByRelfilenumberWithTempTables(RelationTablespace_compat( + writeState->relfilelocator), + RelationPhysicalIdentifierNumber_compat( + writeState->relfilelocator)); Relation relation = relation_open(relationId, NoLock); /* diff --git a/src/include/columnar/columnar_metadata.h b/src/include/columnar/columnar_metadata.h index 64867ae2f..3f93dec19 100644 --- a/src/include/columnar/columnar_metadata.h +++ b/src/include/columnar/columnar_metadata.h @@ -65,5 +65,7 @@ extern List * StripesForRelfilelocator(RelFileLocator relfilelocator); extern void ColumnarStorageUpdateIfNeeded(Relation rel, bool isUpgrade); extern List * ExtractColumnarRelOptions(List *inOptions, List **outColumnarOptions); extern void SetColumnarRelOptions(RangeVar *rv, List *reloptions); +extern Oid RelidByRelfilenumberWithTempTables(Oid reltablespace, RelFileNumber + relfilenumber); #endif /* COLUMNAR_METADATA_H */ diff --git a/src/include/pg_version_compat.h b/src/include/pg_version_compat.h index a30925e4e..5ceb966a3 100644 --- a/src/include/pg_version_compat.h +++ b/src/include/pg_version_compat.h @@ -521,7 +521,6 @@ get_guc_variables_compat(int *gucCount) #define RelationPhysicalIdentifierBackend_compat(a) (a->smgr_rnode.node) typedef RelFileNode RelFileLocator; typedef Oid RelFileNumber; -#define RelidByRelfilenumber(a, b) RelidByRelfilenode(a, b) #define float_abs(a) Abs(a)