Replace BackendIds with 0-based ProcNumbers Marina Polyakova <m.polyakova@postgrespro.ru>
[plantuner.git] / plantuner.c
index afec4bf..e454698 100644 (file)
@@ -35,6 +35,9 @@
 #include <access/xact.h>
 #include <catalog/namespace.h>
 #include <catalog/pg_class.h>
+#if PG_VERSION_NUM >= 160000
+#include <nodes/miscnodes.h>
+#endif
 #include <nodes/pg_list.h>
 #include <optimizer/plancat.h>
 #include <storage/bufmgr.h>
 
 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 = "";
@@ -57,14 +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;
@@ -82,14 +102,29 @@ indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable)
         * follow work could be done only in normal processing because of
         * accsess to system catalog
         */
-       if (MyBackendId == InvalidBackendId || !IsUnderPostmaster ||
-               !IsNormalProcessingMode() || !IsTransactionState())
+#if PG_VERSION_NUM >= 170000
+       if (MyProcNumber == INVALID_PROC_NUMBER ||
+#else
+       if (MyBackendId == InvalidBackendId ||
+#endif
+               !IsUnderPostmaster ||
+               !IsTransactionState())
        {
                /* reset init state */
-               if (isDisable)
-                       plantuner_disable_inited = false;
-               else
-                       plantuner_enable_inited = false;
+               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;
        }
@@ -103,18 +138,42 @@ indexesAssign(const char * newval, bool doit, GucSource source, bool isDisable)
                                 (int)(sizeof(Oid) * (nOids+1)));
        }
 
-       if (isDisable)
-               plantuner_disable_inited = true;
-       else
-               plantuner_enable_inited = true;
+       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)),
@@ -145,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");
                }
        }
 
@@ -177,32 +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, false);
+               indexesAssign(enableIndexesOutStr, true, PGC_S_USER, EnabledKind);
        if (!plantuner_disable_inited)
-               indexesAssign(disableIndexesOutStr, true, PGC_S_USER, true);
+               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)
        {
@@ -218,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)
        {
@@ -241,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
@@ -251,7 +349,31 @@ indexFilter(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 
        lateInit();
 
-       for(i=0;i<nDisabledIndexes;i++)
+       if (nOnlyIndexes > 0)
+       {
+               ListCell        *l;
+
+restart1:
+               foreach(l, rel->indexlist)
+               {
+                       IndexOptInfo    *info = (IndexOptInfo*)lfirst(l);
+                       bool                    remove = true;
+
+                       for(i=0; remove && i<nOnlyIndexes; i++)
+                               if (onlyIndexes[i] == info->indexoid)
+                                       remove = false;
+
+                       if (remove)
+                       {
+                               rel->indexlist = list_delete_ptr(rel->indexlist, info);
+                               goto restart1;
+                       }
+               }
+
+               return;
+       }
+
+       for(i=0; i<nDisabledIndexes; i++)
        {
                ListCell   *l;
 
@@ -291,7 +413,7 @@ execPlantuner(PlannerInfo *root, Oid relationObjectId, bool inhparent,
                         * estimate_rel_size() could be too pessimistic for particular
                         * workload
                         */
-                       rel->pages = 0.0;
+                       rel->pages = 1.0;
                        rel->tuples = 0.0;
                }
 
@@ -349,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)
@@ -404,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",