* PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and * returns a new PLyProcedure. * * fn_oid is the OID of the function requested * fn_rel is InvalidOid or the relation this function triggers on * is_trigger denotes whether the function is a trigger function * * The reason that both fn_rel and is_trigger need to be passed is that when * trigger functions get validate
| 66 | * be used with, so no sensible fn_rel can be passed. |
| 67 | */ |
| 68 | PLyProcedure * |
| 69 | PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger) |
| 70 | { |
| 71 | bool use_cache = !(is_trigger && fn_rel == InvalidOid); |
| 72 | HeapTuple procTup; |
| 73 | PLyProcedureKey key; |
| 74 | PLyProcedureEntry *volatile entry = NULL; |
| 75 | PLyProcedure *volatile proc = NULL; |
| 76 | bool found = false; |
| 77 | |
| 78 | procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(fn_oid)); |
| 79 | if (!HeapTupleIsValid(procTup)) |
| 80 | elog(ERROR, "cache lookup failed for function %u", fn_oid); |
| 81 | |
| 82 | /* |
| 83 | * Look for the function in the cache, unless we don't have the necessary |
| 84 | * information (e.g. during validation). In that case we just don't cache |
| 85 | * anything. |
| 86 | */ |
| 87 | if (use_cache) |
| 88 | { |
| 89 | key.fn_oid = fn_oid; |
| 90 | key.fn_rel = fn_rel; |
| 91 | entry = hash_search(PLy_procedure_cache, &key, HASH_ENTER, &found); |
| 92 | proc = entry->proc; |
| 93 | } |
| 94 | |
| 95 | PG_TRY(); |
| 96 | { |
| 97 | if (!found) |
| 98 | { |
| 99 | /* Haven't found it, create a new procedure */ |
| 100 | proc = PLy_procedure_create(procTup, fn_oid, is_trigger); |
| 101 | if (use_cache) |
| 102 | entry->proc = proc; |
| 103 | } |
| 104 | else if (!PLy_procedure_valid(proc, procTup)) |
| 105 | { |
| 106 | /* Found it, but it's invalid, free and reuse the cache entry */ |
| 107 | entry->proc = NULL; |
| 108 | if (proc) |
| 109 | PLy_procedure_delete(proc); |
| 110 | proc = PLy_procedure_create(procTup, fn_oid, is_trigger); |
| 111 | entry->proc = proc; |
| 112 | } |
| 113 | /* Found it and it's valid, it's fine to use it */ |
| 114 | } |
| 115 | PG_CATCH(); |
| 116 | { |
| 117 | /* Do not leave an uninitialized entry in the cache */ |
| 118 | if (use_cache) |
| 119 | hash_search(PLy_procedure_cache, &key, HASH_REMOVE, NULL); |
| 120 | PG_RE_THROW(); |
| 121 | } |
| 122 | PG_END_TRY(); |
| 123 | |
| 124 | ReleaseSysCache(procTup); |
| 125 |
no test coverage detected