23
23
24
24
25
25
static HTAB * PLy_procedure_cache = NULL ;
26
- static HTAB * PLy_trigger_cache = NULL ;
27
26
28
27
static PLyProcedure * PLy_procedure_create (HeapTuple procTup , Oid fn_oid , bool is_trigger );
29
28
static bool PLy_procedure_argument_valid (PLyTypeInfo * arg );
@@ -37,18 +36,11 @@ init_procedure_caches(void)
37
36
HASHCTL hash_ctl ;
38
37
39
38
memset (& hash_ctl , 0 , sizeof (hash_ctl ));
40
- hash_ctl .keysize = sizeof (Oid );
39
+ hash_ctl .keysize = sizeof (PLyProcedureKey );
41
40
hash_ctl .entrysize = sizeof (PLyProcedureEntry );
42
- hash_ctl .hash = oid_hash ;
41
+ hash_ctl .hash = tag_hash ;
43
42
PLy_procedure_cache = hash_create ("PL/Python procedures" , 32 , & hash_ctl ,
44
43
HASH_ELEM | HASH_FUNCTION );
45
-
46
- memset (& hash_ctl , 0 , sizeof (hash_ctl ));
47
- hash_ctl .keysize = sizeof (Oid );
48
- hash_ctl .entrysize = sizeof (PLyProcedureEntry );
49
- hash_ctl .hash = oid_hash ;
50
- PLy_trigger_cache = hash_create ("PL/Python triggers" , 32 , & hash_ctl ,
51
- HASH_ELEM | HASH_FUNCTION );
52
44
}
53
45
54
46
/*
@@ -68,61 +60,74 @@ PLy_procedure_name(PLyProcedure *proc)
68
60
69
61
/*
70
62
* PLy_procedure_get: returns a cached PLyProcedure, or creates, stores and
71
- * returns a new PLyProcedure. fcinfo is the call info, tgreloid is the
72
- * relation OID when calling a trigger, or InvalidOid (zero) for ordinary
73
- * function calls.
63
+ * returns a new PLyProcedure.
64
+ *
65
+ * fn_oid is the OID of the function requested
66
+ * fn_rel is InvalidOid or the relation this function triggers on
67
+ * is_trigger denotes whether the function is a trigger function
68
+ *
69
+ * The reason that both fn_rel and is_trigger need to be passed is that when
70
+ * trigger functions get validated we don't know which relation(s) they'll
71
+ * be used with, so no sensible fn_rel can be passed.
74
72
*/
75
73
PLyProcedure *
76
- PLy_procedure_get (Oid fn_oid , bool is_trigger )
74
+ PLy_procedure_get (Oid fn_oid , Oid fn_rel , bool is_trigger )
77
75
{
76
+ bool use_cache = !(is_trigger && fn_rel == InvalidOid );
78
77
HeapTuple procTup ;
79
- PLyProcedureEntry * volatile entry ;
80
- bool found ;
78
+ PLyProcedureKey key ;
79
+ PLyProcedureEntry * volatile entry = NULL ;
80
+ PLyProcedure * volatile proc = NULL ;
81
+ bool found = false;
81
82
82
83
procTup = SearchSysCache1 (PROCOID , ObjectIdGetDatum (fn_oid ));
83
84
if (!HeapTupleIsValid (procTup ))
84
85
elog (ERROR , "cache lookup failed for function %u" , fn_oid );
85
86
86
- /* Look for the function in the corresponding cache */
87
- if (is_trigger )
88
- entry = hash_search (PLy_trigger_cache ,
89
- & fn_oid , HASH_ENTER , & found );
90
- else
91
- entry = hash_search (PLy_procedure_cache ,
92
- & fn_oid , HASH_ENTER , & found );
87
+ /*
88
+ * Look for the function in the cache, unless we don't have the necessary
89
+ * information (e.g. during validation). In that case we just don't cache
90
+ * anything.
91
+ */
92
+ if (use_cache )
93
+ {
94
+ key .fn_oid = fn_oid ;
95
+ key .fn_rel = fn_rel ;
96
+ entry = hash_search (PLy_procedure_cache , & key , HASH_ENTER , & found );
97
+ proc = entry -> proc ;
98
+ }
93
99
94
100
PG_TRY ();
95
101
{
96
102
if (!found )
97
103
{
98
- /* Haven't found it, create a new cache entry */
99
- entry -> proc = PLy_procedure_create (procTup , fn_oid , is_trigger );
104
+ /* Haven't found it, create a new procedure */
105
+ proc = PLy_procedure_create (procTup , fn_oid , is_trigger );
106
+ if (use_cache )
107
+ entry -> proc = proc ;
100
108
}
101
- else if (!PLy_procedure_valid (entry -> proc , procTup ))
109
+ else if (!PLy_procedure_valid (proc , procTup ))
102
110
{
103
111
/* Found it, but it's invalid, free and reuse the cache entry */
104
- PLy_procedure_delete (entry -> proc );
105
- PLy_free (entry -> proc );
106
- entry -> proc = PLy_procedure_create (procTup , fn_oid , is_trigger );
112
+ PLy_procedure_delete (proc );
113
+ PLy_free (proc );
114
+ proc = PLy_procedure_create (procTup , fn_oid , is_trigger );
115
+ entry -> proc = proc ;
107
116
}
108
117
/* Found it and it's valid, it's fine to use it */
109
118
}
110
119
PG_CATCH ();
111
120
{
112
121
/* Do not leave an uninitialised entry in the cache */
113
- if (is_trigger )
114
- hash_search (PLy_trigger_cache ,
115
- & fn_oid , HASH_REMOVE , NULL );
116
- else
117
- hash_search (PLy_procedure_cache ,
118
- & fn_oid , HASH_REMOVE , NULL );
122
+ if (use_cache )
123
+ hash_search (PLy_procedure_cache , & key , HASH_REMOVE , NULL );
119
124
PG_RE_THROW ();
120
125
}
121
126
PG_END_TRY ();
122
127
123
128
ReleaseSysCache (procTup );
124
129
125
- return entry -> proc ;
130
+ return proc ;
126
131
}
127
132
128
133
/*
0 commit comments