distinguish unknown and zero number of affected rows
[online_analyze.git] / online_analyze.c
index 50ee68b..4c3e044 100644 (file)
@@ -46,6 +46,9 @@
 #include "utils/rel.h"
 #include "utils/relcache.h"
 #include "utils/timestamp.h"
+#if PG_VERSION_NUM >= 90500
+#include "nodes/makefuncs.h"
+#endif
 #endif
 
 #ifdef PG_MODULE_MAGIC
@@ -63,7 +66,7 @@ static ExecutorEnd_hook_type oldExecutorEndHook = NULL;
 static ProcessUtility_hook_type        oldProcessUtilityHook = NULL;
 #endif
 
-typedef enum 
+typedef enum
 {
        OATT_ALL                = 0x03,
        OATT_PERSISTENT = 0x01,
@@ -125,11 +128,13 @@ tableListAssign(const char * newval, bool doit, TableList *tbl)
        foreach(l, namelist)
        {
                char        *curname = (char *) lfirst(l);
-               Oid         relOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), 
 #if PG_VERSION_NUM >= 90200
-                                                                                               NoLock,
-#endif
+               Oid         relOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), 
+                                                                                               NoLock, true);
+#else
+               Oid         relOid = RangeVarGetRelid(makeRangeVarFromNameList(stringToQualifiedNameList(curname)), 
                                                                                                true);
+#endif
 
                if (relOid == InvalidOid)
                {
@@ -299,8 +304,21 @@ matchOid(TableList *tbl, Oid oid)
        return false;
 }
 
+#if PG_VERSION_NUM >= 90500
+static RangeVar*
+makeRangeVarFromOid(Oid relOid)
+{
+       return makeRangeVar(
+                               get_namespace_name(get_rel_namespace(relOid)),
+                               get_rel_name(relOid),
+                               -1
+                       );
+
+}
+#endif
+
 static void
-makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
+makeAnalyze(Oid relOid, CmdType operation, int32 naffected)
 {
        PgStat_StatTabEntry             *tabentry;
        TimestampTz                     now = GetCurrentTimestamp();
@@ -308,6 +326,16 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
        if (relOid == InvalidOid)
                return;
 
+       if (naffected == 0)
+               /* return if there is not changes */
+               return;
+       else if (naffected < 0)
+               /* number if affected rows is unknown */
+               naffected = 0;
+
+       if (get_rel_relkind(relOid) != RELKIND_RELATION)
+               return;
+
        tabentry = pgstat_fetch_stat_tabentry(relOid);
 
 #if PG_VERSION_NUM >= 90000
@@ -316,7 +344,7 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
 #define changes_since_analyze(t)       ((t)->n_live_tuples + (t)->n_dead_tuples - (t)->last_anl_tuples)
 #endif
 
-       if (    
+       if (
                tabentry == NULL /* a new table */ ||
                (
                        /* do not analyze too often, if both stamps are exceeded the go */
@@ -329,9 +357,15 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
                )
        )
        {
+#if PG_VERSION_NUM < 90500
                VacuumStmt                              vacstmt;
+#else
+               VacuumParams                    vacstmt;
+#endif
                TimestampTz                             startStamp, endStamp;
 
+               memset(&startStamp, 0, sizeof(startStamp)); /* keep compiler quiet */
+
                /*
                 * includeTables overwrites excludeTables
                 */
@@ -374,12 +408,15 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
                                break;
                }
 
-               vacstmt.type = T_VacuumStmt;
+               memset(&vacstmt, 0, sizeof(vacstmt));
+
                vacstmt.freeze_min_age = -1;
                vacstmt.freeze_table_age = -1; /* ??? */
+
+#if PG_VERSION_NUM < 90500
+               vacstmt.type = T_VacuumStmt;
                vacstmt.relation = NULL;
                vacstmt.va_cols = NIL;
-
 #if PG_VERSION_NUM >= 90000
                vacstmt.options = VACOPT_ANALYZE;
                if (online_analyze_verbose)
@@ -389,13 +426,28 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
                vacstmt.analyze = true;
                vacstmt.verbose = online_analyze_verbose;
 #endif
+#else
+               vacstmt.multixact_freeze_min_age = -1;
+               vacstmt.multixact_freeze_table_age = -1;
+               vacstmt.log_min_duration = -1;
+#endif
 
                if (online_analyze_verbose)
                        startStamp = GetCurrentTimestamp();
 
-               analyze_rel(relOid, &vacstmt, GetAccessStrategy(BAS_VACUUM)
-#if (PG_VERSION_NUM < 90004) && (PG_VERSION_NUM >= 90000)
+               analyze_rel(relOid,
+#if PG_VERSION_NUM < 90500
+                       &vacstmt
+#if PG_VERSION_NUM >= 90018
                        , true
+#endif
+                       , GetAccessStrategy(BAS_VACUUM)
+#if (PG_VERSION_NUM >= 90000) && (PG_VERSION_NUM < 90004)
+                       , true
+#endif
+#else
+                       makeRangeVarFromOid(relOid), VACOPT_ANALYZE | ((online_analyze_verbose) ? VACOPT_VERBOSE : 0),
+                       &vacstmt, NULL, true, GetAccessStrategy(BAS_VACUUM)
 #endif
                );
 
@@ -432,21 +484,19 @@ makeAnalyze(Oid relOid, CmdType operation, uint32 naffected)
 
 extern PGDLLIMPORT void onlineAnalyzeHooker(QueryDesc *queryDesc);
 void
-onlineAnalyzeHooker(QueryDesc *queryDesc) 
+onlineAnalyzeHooker(QueryDesc *queryDesc)
 {
-       uint32  naffected = 0;
+       uint32  naffected = -1;
 
        if (queryDesc->estate)
-               naffected = queryDesc->estate->es_processed;    
+               naffected = queryDesc->estate->es_processed;
 
        if (online_analyze_enable && queryDesc->plannedstmt &&
-                       (queryDesc->operation == CMD_INSERT || 
+                       (queryDesc->operation == CMD_INSERT ||
                         queryDesc->operation == CMD_UPDATE ||
-                        queryDesc->operation == CMD_DELETE ||
-#if PG_VERSION_NUM >= 90200
-                        0 /* (queryDesc->operation == CMD_SELECT && queryDesc->dest && queryDesc->dest == DestIntoRel) */
-#else
-                        (queryDesc->operation == CMD_SELECT && queryDesc->plannedstmt->intoClause)
+                        queryDesc->operation == CMD_DELETE
+#if PG_VERSION_NUM < 90200
+                        || (queryDesc->operation == CMD_SELECT && queryDesc->plannedstmt->intoClause)
 #endif
                         ))
        {
@@ -457,7 +507,7 @@ onlineAnalyzeHooker(QueryDesc *queryDesc)
 
                        makeAnalyze(relOid, queryDesc->operation, naffected);
                }
-               else 
+               else
 #endif
                if (queryDesc->plannedstmt->resultRelations &&
                                 queryDesc->plannedstmt->rtable)
@@ -468,7 +518,7 @@ onlineAnalyzeHooker(QueryDesc *queryDesc)
                        {
                                int                     n = lfirst_int(l);
                                RangeTblEntry   *rte = list_nth(queryDesc->plannedstmt->rtable, n-1);
-               
+
                                if (rte->rtekind == RTE_RELATION)
                                        makeAnalyze(rte->relid, queryDesc->operation, naffected);
                        }
@@ -483,8 +533,12 @@ onlineAnalyzeHooker(QueryDesc *queryDesc)
 
 #if PG_VERSION_NUM >= 90200
 static void
-onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString, 
+onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString,
+#if PG_VERSION_NUM >= 90300
+                                                       ProcessUtilityContext context, ParamListInfo params,
+#else
                                                        ParamListInfo params, bool isTopLevel,
+#endif
                                                        DestReceiver *dest, char *completionTag) {
        RangeVar        *tblname = NULL;
 
@@ -492,14 +546,26 @@ onlineAnalyzeHookerUtility(Node *parsetree, const char *queryString,
                tblname = (RangeVar*)copyObject(((CreateTableAsStmt*)parsetree)->into->rel);
 
        if (oldProcessUtilityHook)
-               oldProcessUtilityHook(parsetree, queryString, params, isTopLevel, dest, completionTag);
+               oldProcessUtilityHook(parsetree, queryString, 
+#if PG_VERSION_NUM >= 90300
+                                                         context, params,
+#else
+                                                         params, isTopLevel,
+#endif
+                                                         dest, completionTag);
        else
-               standard_ProcessUtility(parsetree, queryString, params, isTopLevel, dest, completionTag);
+               standard_ProcessUtility(parsetree, queryString, 
+#if PG_VERSION_NUM >= 90300
+                                                               context, params,
+#else
+                                                               params, isTopLevel,
+#endif
+                                                               dest, completionTag);
 
        if (tblname) {
                Oid     tblOid = RangeVarGetRelid(tblname, NoLock, true);
 
-               makeAnalyze(tblOid, CMD_INSERT, 0); 
+               makeAnalyze(tblOid, CMD_INSERT, -1); 
        }
 }
 #endif
@@ -603,7 +669,7 @@ _PG_init(void)
                "online_analyze.min_interval",
                "minimum time interval between analyze call (in milliseconds)",
                "minimum time interval between analyze call (in milliseconds)",
-               &online_analyze_scale_factor,
+               &online_analyze_min_interval,
 #if PG_VERSION_NUM >= 80400
                online_analyze_min_interval,
 #endif