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 ,
1824Query * 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)
3947query_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 ,
43110int cursorOptions ,
44111ParamListInfo boundParams )
@@ -47,7 +114,6 @@ PlannedStmt *sr_planner(Query *parse,
47114Jsonb * out_jsonb ;
48115Jsonb * out_jsonb2 ;
49116int query_hash ;
50- RangeVar * sr_plans_table_rv ;
51117Relation sr_plans_heap ;
52118Relation query_index_rel ;
53119HeapTuple tuple ;
@@ -58,19 +124,42 @@ PlannedStmt *sr_planner(Query *parse,
58124Datum search_values [6 ];
59125static bool search_nulls [6 ]= {false, false, false, false, false, false};
60126bool find_ok = false;
61- LOCKMODE heap_lock = AccessShareLock ;
127+ LOCKMODE heap_lock = AccessShareLock ;
62128Oid query_index_rel_oid ;
63- Oid sr_plans_oid ;
129+ Oid sr_plans_oid ;
130+ Oid schema_oid ;
131+ char * schema_name ;
64132IndexScanDesc query_index_scan ;
65133ScanKeyData key ;
134+ List * func_name_list ;
66135
67- if (sr_plan_write_mode )
136+ if (sr_plan_write_mode )
68137heap_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+
70154if (!sr_plan_fake_func )
71155{
72156Oid 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 */
82171sr_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+
87175if (!OidIsValid (sr_plans_oid ))
88176/* Just call standard_planner() if table doesn't exist. */
89177return 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" ))));
95184if (query_index_rel_oid == InvalidOid )
96185{
97186heap_close (sr_plans_heap ,heap_lock );
98- elog (WARNING ,"Not foundsr_plans_query_hash_idx index" );
187+ elog (WARNING ,"Not found%s index" , SR_PLANS_TABLE_QUERY_INDEX_NAME );
99188return standard_planner (parse ,cursorOptions ,boundParams );
100189}
101190
@@ -121,8 +210,7 @@ PlannedStmt *sr_planner(Query *parse,
121210HeapTuple local_tuple ;
122211local_tuple = index_getnext (query_index_scan ,ForwardScanDirection );
123212
124- if (local_tuple == NULL )
125- break ;
213+ if (local_tuple == NULL )break ;
126214
127215heap_deform_tuple (local_tuple ,sr_plans_heap -> rd_att ,
128216search_values ,search_nulls );
@@ -138,7 +226,7 @@ PlannedStmt *sr_planner(Query *parse,
138226
139227if (find_ok )
140228{
141- elog (WARNING ,"Ok we find saved plan." );
229+ elog (LOG ,"Ok we find saved plan." );
142230out_jsonb2 = (Jsonb * )DatumGetPointer (PG_DETOAST_DATUM (search_values [3 ]));
143231if (query_params != NULL )
144232pl_stmt = jsonb_to_node_tree (out_jsonb2 ,& replace_fake );
@@ -354,11 +442,11 @@ sr_plan_invalid_table(PG_FUNCTION_ARGS)
354442FmgrInfo flinfo ;
355443ExprContext econtext ;
356444TupleTableSlot * slot = NULL ;
357- RangeVar * sr_plans_table_rv ;
358445Relation sr_plans_heap ;
359446Datum search_values [6 ];
360447static bool search_nulls [6 ];
361448static bool search_replaces [6 ];
449+ Oid sr_plans_oid ;
362450HeapScanDesc heapScan ;
363451Jsonb * jsonb ;
364452JsonbValue relation_key ;
@@ -368,9 +456,13 @@ sr_plan_invalid_table(PG_FUNCTION_ARGS)
368456if (!CALLED_AS_EVENT_TRIGGER (fcinfo ))/* internal error */
369457elog (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+
374466relation_key .type = jbvString ;
375467relation_key .val .string .len = strlen ("relationOids" );
376468relation_key .val .string .val = "relationOids" ;