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