#include "postgres.h" #include "fmgr.h" #include "catalog/namespace.h" #include "optimizer/plancat.h" #include "optimizer/planner.h" #include "utils/builtins.h" #include "utils/guc.h" PG_MODULE_MAGIC; void _PG_init(void); void _PG_fini(void); static char *ignore_index = NULL; static void my_get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel); /* * Get control during planner's get_relation_info() function, which sets up * a RelOptInfo struct based on the system catalog contents. We can modify * the struct contents to cause the planner to work with a hypothetical * situation rather than what's actually in the catalogs. * * This simplistic example just removes any index that matches ignore_index * by name. */ static void my_get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel) { RangeVar *relrv; Oid indexoid; ListCell *ilist; ListCell *prev; /* Do nothing unless ignore_index has been set */ if (ignore_index == NULL || *ignore_index == '\0') return; /* * Look up the index. No complaint if not found. * * Note: doing this lookup again each time is a bit inefficient, but * for the contexts in which this plugin would be used, it probably * isn't worth making this faster. */ relrv = makeRangeVarFromNameList(stringToQualifiedNameList(ignore_index)); indexoid = RangeVarGetRelid(relrv, true); if (!OidIsValid(indexoid)) return; /* If it's in the rel's list of indexes, delete it */ prev = NULL; foreach(ilist, rel->indexlist) { IndexOptInfo *ind = (IndexOptInfo *) lfirst(ilist); if (ind->indexoid == indexoid) { rel->indexlist = list_delete_cell(rel->indexlist, ilist, prev); break; /* can't be more than 1 match */ } prev = ilist; } } /* * _pg_init() - library load-time initialization * * DO NOT make this static nor change its name! */ void _PG_init(void) { /* Get into the hooks we need to be in all the time */ get_relation_info_hook = my_get_relation_info; /* Make ignore_index accessible through GUC */ DefineCustomStringVariable("ignore_index", "Name of an index to ignore", "", &ignore_index, PGC_USERSET, NULL, NULL); } /* * _PG_fini() - library unload-time finalization * * DO NOT make this static nor change its name! */ void _PG_fini(void) { /* Get out of all the hooks (just to be sure) */ get_relation_info_hook = NULL; }