---------- * plpgsql_compile Make an execution tree for a PL/pgSQL function. * * If forValidator is true, we're only compiling for validation purposes, * and so some checks are skipped. * * Note: it's important for this to fall through quickly if the function * has already been compiled. * ---------- */
| 133 | * ---------- |
| 134 | */ |
| 135 | PLpgSQL_function * |
| 136 | plpgsql_compile(FunctionCallInfo fcinfo, bool forValidator) |
| 137 | { |
| 138 | Oid funcOid = fcinfo->flinfo->fn_oid; |
| 139 | HeapTuple procTup; |
| 140 | Form_pg_proc procStruct; |
| 141 | PLpgSQL_function *function; |
| 142 | PLpgSQL_func_hashkey hashkey; |
| 143 | bool function_valid = false; |
| 144 | bool hashkey_valid = false; |
| 145 | |
| 146 | /* |
| 147 | * Lookup the pg_proc tuple by Oid; we'll need it in any case |
| 148 | */ |
| 149 | procTup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcOid)); |
| 150 | if (!HeapTupleIsValid(procTup)) |
| 151 | elog(ERROR, "cache lookup failed for function %u", funcOid); |
| 152 | procStruct = (Form_pg_proc) GETSTRUCT(procTup); |
| 153 | |
| 154 | /* |
| 155 | * See if there's already a cache entry for the current FmgrInfo. If not, |
| 156 | * try to find one in the hash table. |
| 157 | */ |
| 158 | function = (PLpgSQL_function *) fcinfo->flinfo->fn_extra; |
| 159 | |
| 160 | recheck: |
| 161 | if (!function) |
| 162 | { |
| 163 | /* Compute hashkey using function signature and actual arg types */ |
| 164 | compute_function_hashkey(fcinfo, procStruct, &hashkey, forValidator); |
| 165 | hashkey_valid = true; |
| 166 | |
| 167 | /* And do the lookup */ |
| 168 | function = plpgsql_HashTableLookup(&hashkey); |
| 169 | } |
| 170 | |
| 171 | if (function) |
| 172 | { |
| 173 | /* We have a compiled function, but is it still valid? */ |
| 174 | if (function->fn_xmin == HeapTupleHeaderGetRawXmin(procTup->t_data) && |
| 175 | ItemPointerEquals(&function->fn_tid, &procTup->t_self)) |
| 176 | function_valid = true; |
| 177 | else |
| 178 | { |
| 179 | /* |
| 180 | * Nope, so remove it from hashtable and try to drop associated |
| 181 | * storage (if not done already). |
| 182 | */ |
| 183 | delete_function(function); |
| 184 | |
| 185 | /* |
| 186 | * If the function isn't in active use then we can overwrite the |
| 187 | * func struct with new data, allowing any other existing fn_extra |
| 188 | * pointers to make use of the new definition on their next use. |
| 189 | * If it is in use then just leave it alone and make a new one. |
| 190 | * (The active invocations will run to completion using the |
| 191 | * previous definition, and then the cache entry will just be |
| 192 | * leaked; doesn't seem worth adding code to clean it up, given |
no test coverage detected