X-Git-Url: http://sigaev.ru/git/gitweb.cgi?p=plantuner.git;a=blobdiff_plain;f=plantuner.c;h=b22ef9cf00a6a80f84d2cefa23e96b91337ce2d5;hp=5a1d4809131a329e2e8a153644be2a27a9ee7768;hb=HEAD;hpb=e254f0c16b288a261d2ed1c7c6110223f359d3ff diff --git a/plantuner.c b/plantuner.c index 5a1d480..e454698 100644 --- a/plantuner.c +++ b/plantuner.c @@ -30,9 +30,14 @@ #include #include +#include #include +#include #include #include +#if PG_VERSION_NUM >= 160000 +#include +#endif #include #include #include @@ -47,6 +52,11 @@ PG_MODULE_MAGIC; +#if PG_VERSION_NUM >= 130000 +#define heap_open(r, l) table_open(r, l) +#define heap_close(r, l) table_close(r, l) +#endif + static int nDisabledIndexes = 0; static Oid *disabledIndexes = NULL; static char *disableIndexesOutStr = ""; @@ -55,12 +65,26 @@ static int nEnabledIndexes = 0; static Oid *enabledIndexes = NULL; static char *enableIndexesOutStr = ""; +static int nOnlyIndexes = 0; +static Oid *onlyIndexes = NULL; +static char *onlyIndexesOutStr = ""; + get_relation_info_hook_type prevHook = NULL; static bool fix_empty_table = false; +static bool plantuner_enable_inited = false; +static bool plantuner_only_inited = false; +static bool plantuner_disable_inited = false; + +typedef enum IndexListKind { + EnabledKind, + DisabledKind, + OnlyKind +} IndexListKind; static const char * -indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable) +indexesAssign(const char * newval, bool doit, GucSource source, + IndexListKind kind) { char *rawname; List *namelist; @@ -74,6 +98,37 @@ indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable) if (!SplitIdentifierString(rawname, ',', &namelist)) goto cleanup; + /* + * follow work could be done only in normal processing because of + * accsess to system catalog + */ +#if PG_VERSION_NUM >= 170000 + if (MyProcNumber == INVALID_PROC_NUMBER || +#else + if (MyBackendId == InvalidBackendId || +#endif + !IsUnderPostmaster || + !IsTransactionState()) + { + /* reset init state */ + switch(kind) + { + case EnabledKind: + plantuner_enable_inited = false; + break; + case DisabledKind: + plantuner_disable_inited = false; + break; + case OnlyKind: + plantuner_only_inited = false; + break; + default: + elog(ERROR, "wrong kind"); + } + + return newval; + } + if (doit) { nOids = list_length(namelist); @@ -83,13 +138,42 @@ indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable) (int)(sizeof(Oid) * (nOids+1))); } + switch(kind) + { + case EnabledKind: + plantuner_enable_inited = true; + break; + case DisabledKind: + plantuner_disable_inited = true; + break; + case OnlyKind: + plantuner_only_inited = true; + break; + default: + elog(ERROR, "wrong kind"); + } + foreach(l, namelist) { char *curname = (char *) lfirst(l); #if PG_VERSION_NUM >= 90200 - Oid indexOid = RangeVarGetRelid( - makeRangeVarFromNameList(stringToQualifiedNameList(curname)), - NoLock, true); + List *cur_namelist; + Oid indexOid; + +#if PG_VERSION_NUM >= 160000 + ErrorSaveContext escontext = {T_ErrorSaveContext}; + + cur_namelist = stringToQualifiedNameList(curname, (Node *) &escontext); + + /* bad name list syntax */ + if (cur_namelist == NIL) + continue; +#else + cur_namelist = stringToQualifiedNameList(curname); +#endif + + indexOid = RangeVarGetRelid(makeRangeVarFromNameList(cur_namelist), + NoLock, true); #else Oid indexOid = RangeVarGetRelid( makeRangeVarFromNameList(stringToQualifiedNameList(curname)), @@ -120,19 +204,28 @@ indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable) if (doit) { - if (isDisable) - { - nDisabledIndexes = i; - if (disabledIndexes) - free(disabledIndexes); - disabledIndexes = newOids; - } - else + switch(kind) { - nEnabledIndexes = i; - if (enabledIndexes) - free(enabledIndexes); - enabledIndexes = newOids; + case EnabledKind: + nEnabledIndexes = i; + if (enabledIndexes) + free(enabledIndexes); + enabledIndexes = newOids; + break; + case DisabledKind: + nDisabledIndexes = i; + if (disabledIndexes) + free(disabledIndexes); + disabledIndexes = newOids; + break; + case OnlyKind: + nOnlyIndexes = i; + if (onlyIndexes) + free(onlyIndexes); + onlyIndexes = newOids; + break; + default: + elog(ERROR, "wrong kind"); } } @@ -152,23 +245,56 @@ cleanup: static const char * assignDisabledIndexes(const char * newval, bool doit, GucSource source) { - return indexesAssign(newval, doit, source, true); + return indexesAssign(newval, doit, source, DisabledKind); } static const char * assignEnabledIndexes(const char * newval, bool doit, GucSource source) { - return indexesAssign(newval, doit, source, false); + return indexesAssign(newval, doit, source, EnabledKind); +} + +static const char * +assignOnlyIndexes(const char * newval, bool doit, GucSource source) +{ + return indexesAssign(newval, doit, source, OnlyKind); +} + +static void +lateInit() +{ + if (!plantuner_only_inited) + indexesAssign(onlyIndexesOutStr, true, PGC_S_USER, OnlyKind); + if (!plantuner_enable_inited) + indexesAssign(enableIndexesOutStr, true, PGC_S_USER, EnabledKind); + if (!plantuner_disable_inited) + indexesAssign(disableIndexesOutStr, true, PGC_S_USER, DisabledKind); } #if PG_VERSION_NUM >= 90100 +static bool +checkOnlyIndexes(char **newval, void **extra, GucSource source) +{ + char *val; + + val = (char*)indexesAssign(*newval, false, source, OnlyKind); + + if (val) + { + *newval = val; + return true; + } + + return false; +} + static bool checkDisabledIndexes(char **newval, void **extra, GucSource source) { char *val; - val = (char*)indexesAssign(*newval, false, source, true); + val = (char*)indexesAssign(*newval, false, source, DisabledKind); if (val) { @@ -184,7 +310,7 @@ checkEnabledIndexes(char **newval, void **extra, GucSource source) { char *val; - val = (char*)indexesAssign(*newval, false, source, false); + val = (char*)indexesAssign(*newval, false, source, EnabledKind); if (val) { @@ -207,6 +333,12 @@ assignEnabledIndexesNew(const char *newval, void *extra) assignEnabledIndexes(newval, true, PGC_S_USER /* doesn't matter */); } +static void +assignOnlyIndexesNew(const char *newval, void *extra) +{ + assignOnlyIndexes(newval, true, PGC_S_USER /* doesn't matter */); +} + #endif static void @@ -215,7 +347,33 @@ indexFilter(PlannerInfo *root, Oid relationObjectId, bool inhparent, { int i; - for(i=0;i 0) + { + ListCell *l; + +restart1: + foreach(l, rel->indexlist) + { + IndexOptInfo *info = (IndexOptInfo*)lfirst(l); + bool remove = true; + + for(i=0; remove && iindexoid) + remove = false; + + if (remove) + { + rel->indexlist = list_delete_ptr(rel->indexlist, info); + goto restart1; + } + } + + return; + } + + for(i=0; ipages = 0.0; + rel->pages = 1.0; rel->tuples = 0.0; } @@ -277,6 +435,8 @@ IndexFilterShow(Oid* indexes, int nIndexes) int i, len; + lateInit(); + len = 1 /* \0 */ + nIndexes * (2 * NAMEDATALEN + 2 /* ', ' */ + 1 /* . */); ptr = val = palloc(len); @@ -311,6 +471,12 @@ enabledIndexFilterShow(void) return IndexFilterShow(enabledIndexes, nEnabledIndexes); } +static const char* +onlyIndexFilterShow(void) +{ + return IndexFilterShow(onlyIndexes, nOnlyIndexes); +} + void _PG_init(void); void _PG_init(void) @@ -366,6 +532,23 @@ _PG_init(void) enabledIndexFilterShow ); + DefineCustomStringVariable( + "plantuner.only_index", + "List of explicitly enabled indexes (overload plantuner.disable_index and plantuner.enable_index)", + "Only indexes in this list are allowed", + &onlyIndexesOutStr, + "", + PGC_USERSET, + 0, +#if PG_VERSION_NUM >= 90100 + checkOnlyIndexes, + assignOnlyIndexesNew, +#else + assignOnlyIndexes, +#endif + onlyIndexFilterShow + ); + DefineCustomBoolVariable( "plantuner.fix_empty_table", "Sets to zero estimations for empty tables",