11#include "sr_plan.h"
22#include "commands/event_trigger.h"
3+ #include "commands/extension.h"
4+ #include "catalog/pg_extension.h"
5+ #include "catalog/indexing.h"
6+ #include "access/sysattr.h"
7+ #include "access/xact.h"
8+ #include "utils/lsyscache.h"
39
410PG_MODULE_MAGIC ;
511
@@ -17,6 +23,8 @@ PlanCacheRelCallback(Datum arg, Oid relid);*/
1723void sr_analyze (ParseState * pstate ,
1824 Query * query );
1925
26+ static Oid get_sr_plan_schema (void );
27+ static Oid sr_get_relname_oid (Oid schema_oid , const char * relname );
2028bool sr_query_walker (Query * node , void * context );
2129bool sr_query_expr_walker (Node * node , void * context );
2230void * replace_fake (void * node );
@@ -39,6 +47,65 @@ void sr_analyze(ParseState *pstate, Query *query)
3947 query_text = pstate -> p_sourcetext ;
4048}
4149
50+ /*
51+ * Return sr_plan schema's Oid or InvalidOid if that's not possible.
52+ */
53+ static Oid
54+ get_sr_plan_schema (void )
55+ {
56+ Oid result ;
57+ Relation rel ;
58+ SysScanDesc scandesc ;
59+ HeapTuple tuple ;
60+ ScanKeyData entry [1 ];
61+ Oid ext_schema ;
62+ LOCKMODE heap_lock = AccessShareLock ;
63+
64+ /* It's impossible to fetch sr_plan's schema now */
65+ if (!IsTransactionState ())
66+ return InvalidOid ;
67+
68+ ext_schema = get_extension_oid ("sr_plan" , true);
69+ if (ext_schema == InvalidOid )
70+ return InvalidOid ; /* exit if sr_plan does not exist */
71+
72+ ScanKeyInit (& entry [0 ],
73+ ObjectIdAttributeNumber ,
74+ BTEqualStrategyNumber , F_OIDEQ ,
75+ ObjectIdGetDatum (ext_schema ));
76+
77+ rel = heap_open (ExtensionRelationId , heap_lock );
78+ scandesc = systable_beginscan (rel , ExtensionOidIndexId , true,
79+ NULL , 1 , entry );
80+
81+ tuple = systable_getnext (scandesc );
82+
83+ /* We assume that there can be at most one matching tuple */
84+ if (HeapTupleIsValid (tuple ))
85+ result = ((Form_pg_extension ) GETSTRUCT (tuple ))-> extnamespace ;
86+ else
87+ result = InvalidOid ;
88+
89+ systable_endscan (scandesc );
90+
91+ heap_close (rel , heap_lock );
92+
93+ return result ;
94+ }
95+
96+ /*
97+ * Return Oid of relation in sr_plan extension schema or
98+ * InvalidOid if that's not possible.
99+ */
100+
101+ static Oid sr_get_relname_oid (Oid schema_oid , const char * relname )
102+ {
103+ if (schema_oid == InvalidOid ) schema_oid = get_sr_plan_schema ();
104+ if (schema_oid == InvalidOid ) return InvalidOid ;
105+
106+ return get_relname_relid (relname , schema_oid );
107+ }
108+
42109PlannedStmt * sr_planner (Query * parse ,
43110 int cursorOptions ,
44111 ParamListInfo boundParams )
@@ -47,7 +114,6 @@ PlannedStmt *sr_planner(Query *parse,
47114 Jsonb * out_jsonb ;
48115 Jsonb * out_jsonb2 ;
49116 int query_hash ;
50- RangeVar * sr_plans_table_rv ;
51117 Relation sr_plans_heap ;
52118 Relation query_index_rel ;
53119 HeapTuple tuple ;
@@ -58,19 +124,42 @@ PlannedStmt *sr_planner(Query *parse,
58124 Datum search_values [6 ];
59125 static bool search_nulls [6 ] = {false, false, false, false, false, false};
60126 bool find_ok = false;
61- LOCKMODE heap_lock = AccessShareLock ;
127+ LOCKMODE heap_lock = AccessShareLock ;
62128 Oid query_index_rel_oid ;
63- Oid sr_plans_oid ;
129+ Oid sr_plans_oid ;
130+ Oid schema_oid ;
131+ char * schema_name ;
64132 IndexScanDesc query_index_scan ;
65133 ScanKeyData key ;
134+ List * func_name_list ;
66135
67- if (sr_plan_write_mode )
136+ if (sr_plan_write_mode )
68137 heap_lock = RowExclusiveLock ;
69138
139+ schema_oid = get_sr_plan_schema ();
140+ if (!OidIsValid (schema_oid ))
141+ {
142+ /* Just call standard_planner() if schema doesn't exist. */
143+ return standard_planner (parse , cursorOptions , boundParams );
144+ }
145+
146+ if (sr_plan_fake_func )
147+ {
148+ HeapTuple ftup ;
149+ ftup = SearchSysCache1 (PROCOID , ObjectIdGetDatum (sr_plan_fake_func ));
150+ if (!HeapTupleIsValid (ftup )) sr_plan_fake_func = 0 ;
151+ else ReleaseSysCache (ftup );
152+ }
153+
70154 if (!sr_plan_fake_func )
71155 {
72156 Oid args [1 ] = {ANYELEMENTOID };
73- sr_plan_fake_func = LookupFuncName (list_make1 (makeString ("_p" )), 1 , args , true);
157+
158+ schema_name = get_namespace_name (schema_oid );
159+ func_name_list = list_make2 (makeString (schema_name ), makeString ("_p" ));
160+ sr_plan_fake_func = LookupFuncName (func_name_list , 1 , args , true);
161+ list_free (func_name_list );
162+ pfree (schema_name );
74163 }
75164
76165
@@ -81,21 +170,21 @@ PlannedStmt *sr_planner(Query *parse,
81170 /* Make list with all _p functions and his position */
82171 sr_query_walker ((Query * )parse , NULL );
83172
84- sr_plans_table_rv = makeRangeVar ("public" , "sr_plans" , -1 );
85- /* First check existance of "sr_plans" table */
86- sr_plans_oid = RangeVarGetRelid (sr_plans_table_rv , heap_lock , true);
173+ sr_plans_oid = sr_get_relname_oid (schema_oid , SR_PLANS_TABLE_NAME );
174+
87175 if (!OidIsValid (sr_plans_oid ))
88176 /* Just call standard_planner() if table doesn't exist. */
89177 return standard_planner (parse , cursorOptions , boundParams );
90178
91179 /* Table "sr_plans" exists */
92- sr_plans_heap = heap_open (sr_plans_oid , NoLock );
180+ sr_plans_heap = heap_open (sr_plans_oid , heap_lock );
181+
182+ query_index_rel_oid = sr_get_relname_oid (schema_oid , SR_PLANS_TABLE_QUERY_INDEX_NAME );
93183
94- query_index_rel_oid = DatumGetObjectId (DirectFunctionCall1 (to_regclass , PointerGetDatum (cstring_to_text ("sr_plans_query_hash_idx" ))));
95184 if (query_index_rel_oid == InvalidOid )
96185 {
97186 heap_close (sr_plans_heap , heap_lock );
98- elog (WARNING , "Not found sr_plans_query_hash_idx index" );
187+ elog (WARNING , "Not found %s index" , SR_PLANS_TABLE_QUERY_INDEX_NAME );
99188 return standard_planner (parse , cursorOptions , boundParams );
100189 }
101190
@@ -121,8 +210,7 @@ PlannedStmt *sr_planner(Query *parse,
121210 HeapTuple local_tuple ;
122211 local_tuple = index_getnext (query_index_scan , ForwardScanDirection );
123212
124- if (local_tuple == NULL )
125- break ;
213+ if (local_tuple == NULL ) break ;
126214
127215 heap_deform_tuple (local_tuple , sr_plans_heap -> rd_att ,
128216 search_values , search_nulls );
@@ -138,7 +226,7 @@ PlannedStmt *sr_planner(Query *parse,
138226
139227 if (find_ok )
140228 {
141- elog (WARNING , "Ok we find saved plan." );
229+ /* elog(WARNING, "Ok we find saved plan."); */
142230 out_jsonb2 = (Jsonb * )DatumGetPointer (PG_DETOAST_DATUM (search_values [3 ]));
143231 if (query_params != NULL )
144232 pl_stmt = jsonb_to_node_tree (out_jsonb2 , & replace_fake );
@@ -354,11 +442,11 @@ sr_plan_invalid_table(PG_FUNCTION_ARGS)
354442 FmgrInfo flinfo ;
355443 ExprContext econtext ;
356444 TupleTableSlot * slot = NULL ;
357- RangeVar * sr_plans_table_rv ;
358445 Relation sr_plans_heap ;
359446 Datum search_values [6 ];
360447 static bool search_nulls [6 ];
361448 static bool search_replaces [6 ];
449+ Oid sr_plans_oid ;
362450 HeapScanDesc heapScan ;
363451 Jsonb * jsonb ;
364452 JsonbValue relation_key ;
@@ -368,9 +456,13 @@ sr_plan_invalid_table(PG_FUNCTION_ARGS)
368456 if (!CALLED_AS_EVENT_TRIGGER (fcinfo )) /* internal error */
369457 elog (ERROR , "not fired by event trigger manager" );
370458
371- sr_plans_table_rv = makeRangeVar ("public" , "sr_plans" , -1 );
372- sr_plans_heap = heap_openrv (sr_plans_table_rv , RowExclusiveLock );
373-
459+ sr_plans_oid = sr_get_relname_oid (InvalidOid , SR_PLANS_TABLE_NAME );
460+ if (sr_plans_oid == InvalidOid )
461+ {
462+ elog (ERROR , "Cannot find %s table" , SR_PLANS_TABLE_NAME );
463+ }
464+ sr_plans_heap = heap_open (sr_plans_oid , RowExclusiveLock );
465+
374466 relation_key .type = jbvString ;
375467 relation_key .val .string .len = strlen ("relationOids" );
376468 relation_key .val .string .val = "relationOids" ;
0 commit comments