* RelationBuildDesc * * Build a relation descriptor. The caller must hold at least * AccessShareLock on the target relid. * * The new descriptor is inserted into the hash table if insertIt is true. * * Returns NULL if no pg_class row could be found for the given relid * (suggesting we are trying to access a just-deleted relation). * Any other error is reported via elog. */
| 1042 | * Any other error is reported via elog. |
| 1043 | */ |
| 1044 | static Relation |
| 1045 | RelationBuildDesc(Oid targetRelId, bool insertIt) |
| 1046 | { |
| 1047 | int in_progress_offset; |
| 1048 | Relation relation; |
| 1049 | Oid relid; |
| 1050 | HeapTuple pg_class_tuple; |
| 1051 | Form_pg_class relp; |
| 1052 | |
| 1053 | /* |
| 1054 | * This function and its subroutines can allocate a good deal of transient |
| 1055 | * data in CurrentMemoryContext. Traditionally we've just leaked that |
| 1056 | * data, reasoning that the caller's context is at worst of transaction |
| 1057 | * scope, and relcache loads shouldn't happen so often that it's essential |
| 1058 | * to recover transient data before end of statement/transaction. However |
| 1059 | * that's definitely not true when debug_discard_caches is active, and |
| 1060 | * perhaps it's not true in other cases. |
| 1061 | * |
| 1062 | * When debug_discard_caches is active or when forced to by |
| 1063 | * RECOVER_RELATION_BUILD_MEMORY=1, arrange to allocate the junk in a |
| 1064 | * temporary context that we'll free before returning. Make it a child of |
| 1065 | * caller's context so that it will get cleaned up appropriately if we |
| 1066 | * error out partway through. |
| 1067 | */ |
| 1068 | #ifdef MAYBE_RECOVER_RELATION_BUILD_MEMORY |
| 1069 | MemoryContext tmpcxt = NULL; |
| 1070 | MemoryContext oldcxt = NULL; |
| 1071 | |
| 1072 | if (RECOVER_RELATION_BUILD_MEMORY || debug_discard_caches > 0) |
| 1073 | { |
| 1074 | tmpcxt = AllocSetContextCreate(CurrentMemoryContext, |
| 1075 | "RelationBuildDesc workspace", |
| 1076 | ALLOCSET_DEFAULT_SIZES); |
| 1077 | oldcxt = MemoryContextSwitchTo(tmpcxt); |
| 1078 | } |
| 1079 | #endif |
| 1080 | |
| 1081 | /* Register to catch invalidation messages */ |
| 1082 | if (in_progress_list_len >= in_progress_list_maxlen) |
| 1083 | { |
| 1084 | int allocsize; |
| 1085 | |
| 1086 | allocsize = in_progress_list_maxlen * 2; |
| 1087 | in_progress_list = repalloc(in_progress_list, |
| 1088 | allocsize * sizeof(*in_progress_list)); |
| 1089 | in_progress_list_maxlen = allocsize; |
| 1090 | } |
| 1091 | in_progress_offset = in_progress_list_len++; |
| 1092 | in_progress_list[in_progress_offset].reloid = targetRelId; |
| 1093 | retry: |
| 1094 | in_progress_list[in_progress_offset].invalidated = false; |
| 1095 | |
| 1096 | /* |
| 1097 | * find the tuple in pg_class corresponding to the given relation id |
| 1098 | */ |
| 1099 | pg_class_tuple = ScanPgRelation(targetRelId, true, false); |
| 1100 | |
| 1101 | /* |
no test coverage detected