]> granicus.if.org Git - postgresql/commitdiff
Fix problems in pg_autovacuum:
authorBruce Momjian <bruce@momjian.us>
Wed, 26 May 2004 18:48:25 +0000 (18:48 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 26 May 2004 18:48:25 +0000 (18:48 +0000)
1) temp table crash

2) Check send_query() function call return value.

Backpatch to 7.4.X.

contrib/pg_autovacuum/pg_autovacuum.c
contrib/pg_autovacuum/pg_autovacuum.h

index d0e2108563bb4957822b69027b27d4e4c68e665a..191b91ba384e72d42877ca82c7ec6360ba3df275 100644 (file)
@@ -225,70 +225,73 @@ update_table_list(db_info * dbi)
                 * tables to the list that are new
                 */
                res = send_query((char *) TABLE_STATS_QUERY, dbi);
-               t = PQntuples(res);
-
-               /*
-                * First: use the tbl_list as the outer loop and the result set as
-                * the inner loop, this will determine what tables should be
-                * removed
-                */
-               while (tbl_elem != NULL)
-               {
-                       tbl = ((tbl_info *) DLE_VAL(tbl_elem));
-                       found_match = 0;
-
-                       for (i = 0; i < t; i++)
-                       {                                       /* loop through result set looking for a
-                                                                * match */
-                               if (tbl->relid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
-                               {
-                                       found_match = 1;
-                                       break;
-                               }
-                       }
-                       if (found_match == 0)
-                       {                                       /* then we didn't find this tbl_elem in
-                                                                * the result set */
-                               Dlelem     *elem_to_remove = tbl_elem;
-
-                               tbl_elem = DLGetSucc(tbl_elem);
-                               remove_table_from_list(elem_to_remove);
-                       }
-                       else
-                               tbl_elem = DLGetSucc(tbl_elem);
-               }                                               /* Done removing dropped tables from the
-                                                                * table_list */
-
-               /*
-                * Then loop use result set as outer loop and tbl_list as the
-                * inner loop to determine what tables are new
-                */
-               for (i = 0; i < t; i++)
+               if (res != NULL)
                {
-                       tbl_elem = DLGetHead(dbi->table_list);
-                       found_match = 0;
+                       t = PQntuples(res);
+                       
+                       /*
+                       * First: use the tbl_list as the outer loop and the result set as
+                       * the inner loop, this will determine what tables should be
+                       * removed
+                       */
                        while (tbl_elem != NULL)
                        {
                                tbl = ((tbl_info *) DLE_VAL(tbl_elem));
-                               if (tbl->relid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
-                               {
-                                       found_match = 1;
-                                       break;
+                               found_match = 0;
+                               
+                               for (i = 0; i < t; i++)
+                               {                                       /* loop through result set looking for a
+                                                                       * match */
+                                       if (tbl->relid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
+                                       {
+                                               found_match = 1;
+                                               break;
+                                       }
                                }
-                               tbl_elem = DLGetSucc(tbl_elem);
-                       }
-                       if (found_match == 0)           /* then we didn't find this result
-                                                                                * now in the tbl_list */
+                               if (found_match == 0)
+                               {                                       /* then we didn't find this tbl_elem in
+                                                                       * the result set */
+                                       Dlelem     *elem_to_remove = tbl_elem;
+                                       
+                                       tbl_elem = DLGetSucc(tbl_elem);
+                                       remove_table_from_list(elem_to_remove);
+                               }
+                               else
+                                       tbl_elem = DLGetSucc(tbl_elem);
+                       }                                               /* Done removing dropped tables from the
+                                                                       * table_list */
+                       
+                       /*
+                       * Then loop use result set as outer loop and tbl_list as the
+                       * inner loop to determine what tables are new
+                       */
+                       for (i = 0; i < t; i++)
                        {
-                               DLAddTail(dbi->table_list, DLNewElem(init_table_info(res, i, dbi)));
-                               if (args->debug >= 1)
+                               tbl_elem = DLGetHead(dbi->table_list);
+                               found_match = 0;
+                               while (tbl_elem != NULL)
                                {
-                                       sprintf(logbuffer, "added table: %s.%s", dbi->dbname,
-                                                       ((tbl_info *) DLE_VAL(DLGetTail(dbi->table_list)))->table_name);
-                                       log_entry(logbuffer);
+                                       tbl = ((tbl_info *) DLE_VAL(tbl_elem));
+                                       if (tbl->relid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
+                                       {
+                                               found_match = 1;
+                                               break;
+                                       }
+                                       tbl_elem = DLGetSucc(tbl_elem);
                                }
-                       }
-               }                                               /* end of for loop that adds tables */
+                               if (found_match == 0)           /* then we didn't find this result
+                                                                                       * now in the tbl_list */
+                               {
+                                       DLAddTail(dbi->table_list, DLNewElem(init_table_info(res, i, dbi)));
+                                       if (args->debug >= 1)
+                                       {
+                                               sprintf(logbuffer, "added table: %s.%s", dbi->dbname,
+                                                               ((tbl_info *) DLE_VAL(DLGetTail(dbi->table_list)))->table_name);
+                                               log_entry(logbuffer);
+                                       }
+                               }
+                       }                                               /* end of for loop that adds tables */
+               }
                fflush(LOGOUTPUT);
                PQclear(res);
                res = NULL;
@@ -410,13 +413,18 @@ init_db_list()
        if (dbs->conn != NULL)
        {
                res = send_query(FROZENOID_QUERY, dbs);
-               dbs->oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
-               dbs->age = atol(PQgetvalue(res, 0, PQfnumber(res, "age")));
-               if (res)
-                       PQclear(res);
-
-               if (args->debug >= 2)
-                       print_db_list(db_list, 0);
+               if (res != NULL)
+               {
+                       dbs->oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "oid")));
+                       dbs->age = atol(PQgetvalue(res, 0, PQfnumber(res, "age")));
+                       if (res)
+                               PQclear(res);
+       
+                       if (args->debug >= 2)
+                               print_db_list(db_list, 0);
+               }
+               else
+                       return NULL;
        }
        return db_list;
 }
@@ -488,78 +496,81 @@ update_db_list(Dllist *db_list)
                 * add databases to the list that are new
                 */
                res = send_query(FROZENOID_QUERY2, dbi_template1);
-               t = PQntuples(res);
-
-               /*
-                * First: use the db_list as the outer loop and the result set as
-                * the inner loop, this will determine what databases should be
-                * removed
-                */
-               while (db_elem != NULL)
-               {
-                       dbi = ((db_info *) DLE_VAL(db_elem));
-                       found_match = 0;
-
-                       for (i = 0; i < t; i++)
-                       {                                       /* loop through result set looking for a
-                                                                * match */
-                               if (dbi->oid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
-                               {
-                                       found_match = 1;
-
-                                       /*
-                                        * update the dbi->age so that we ensure
-                                        * xid_wraparound won't happen
-                                        */
-                                       dbi->age = atol(PQgetvalue(res, i, PQfnumber(res, "age")));
-                                       break;
-                               }
-                       }
-                       if (found_match == 0)
-                       {                                       /* then we didn't find this db_elem in the
-                                                                * result set */
-                               Dlelem     *elem_to_remove = db_elem;
-
-                               db_elem = DLGetSucc(db_elem);
-                               remove_db_from_list(elem_to_remove);
-                       }
-                       else
-                               db_elem = DLGetSucc(db_elem);
-               }                                               /* Done removing dropped databases from
-                                                                * the table_list */
-
-               /*
-                * Then loop use result set as outer loop and db_list as the inner
-                * loop to determine what databases are new
-                */
-               for (i = 0; i < t; i++)
+               if (res != NULL)
                {
-                       db_elem = DLGetHead(db_list);
-                       found_match = 0;
+                       t = PQntuples(res);
+       
+                       /*
+                       * First: use the db_list as the outer loop and the result set as
+                       * the inner loop, this will determine what databases should be
+                       * removed
+                       */
                        while (db_elem != NULL)
                        {
                                dbi = ((db_info *) DLE_VAL(db_elem));
-                               if (dbi->oid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
-                               {
-                                       found_match = 1;
-                                       break;
+                               found_match = 0;
+       
+                               for (i = 0; i < t; i++)
+                               {                                       /* loop through result set looking for a
+                                                                       * match */
+                                       if (dbi->oid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
+                                       {
+                                               found_match = 1;
+       
+                                               /*
+                                               * update the dbi->age so that we ensure
+                                               * xid_wraparound won't happen
+                                               */
+                                               dbi->age = atol(PQgetvalue(res, i, PQfnumber(res, "age")));
+                                               break;
+                                       }
                                }
-                               db_elem = DLGetSucc(db_elem);
-                       }
-                       if (found_match == 0)           /* then we didn't find this result
-                                                                                * now in the tbl_list */
+                               if (found_match == 0)
+                               {                                       /* then we didn't find this db_elem in the
+                                                                       * result set */
+                                       Dlelem     *elem_to_remove = db_elem;
+       
+                                       db_elem = DLGetSucc(db_elem);
+                                       remove_db_from_list(elem_to_remove);
+                               }
+                               else
+                                       db_elem = DLGetSucc(db_elem);
+                       }                                               /* Done removing dropped databases from
+                                                                       * the table_list */
+       
+                       /*
+                       * Then loop use result set as outer loop and db_list as the inner
+                       * loop to determine what databases are new
+                       */
+                       for (i = 0; i < t; i++)
                        {
-                               DLAddTail(db_list, DLNewElem(init_dbinfo
-                                                 (PQgetvalue(res, i, PQfnumber(res, "datname")),
-                                                atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))),
-                                         atol(PQgetvalue(res, i, PQfnumber(res, "age"))))));
-                               if (args->debug >= 1)
+                               db_elem = DLGetHead(db_list);
+                               found_match = 0;
+                               while (db_elem != NULL)
                                {
-                                       sprintf(logbuffer, "added database: %s", ((db_info *) DLE_VAL(DLGetTail(db_list)))->dbname);
-                                       log_entry(logbuffer);
+                                       dbi = ((db_info *) DLE_VAL(db_elem));
+                                       if (dbi->oid == atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))))
+                                       {
+                                               found_match = 1;
+                                               break;
+                                       }
+                                       db_elem = DLGetSucc(db_elem);
                                }
-                       }
-               }                                               /* end of for loop that adds tables */
+                               if (found_match == 0)           /* then we didn't find this result
+                                                                                       * now in the tbl_list */
+                               {
+                                       DLAddTail(db_list, DLNewElem(init_dbinfo
+                                                       (PQgetvalue(res, i, PQfnumber(res, "datname")),
+                                                       atooid(PQgetvalue(res, i, PQfnumber(res, "oid"))),
+                                               atol(PQgetvalue(res, i, PQfnumber(res, "age"))))));
+                                       if (args->debug >= 1)
+                                       {
+                                               sprintf(logbuffer, "added database: %s", ((db_info *) DLE_VAL(DLGetTail(db_list)))->dbname);
+                                               log_entry(logbuffer);
+                                       }
+                               }
+                       }                                               /* end of for loop that adds tables */
+               }
                fflush(LOGOUTPUT);
                PQclear(res);
                res = NULL;
@@ -599,7 +610,10 @@ xid_wraparound_check(db_info * dbi)
 
                res = send_query("VACUUM", dbi);
                /* FIXME: Perhaps should add a check for PQ_COMMAND_OK */
-               PQclear(res);
+               if (res != NULL)
+               {
+                       PQclear(res);
+               }
                return 1;
        }
        return 0;
@@ -750,7 +764,7 @@ check_stats_enabled(db_info * dbi)
        int                     ret = 0;
 
        res = send_query("SHOW stats_row_level", dbi);
-       if (res)
+       if (res != NULL)
        {
                ret = strcmp("on", PQgetvalue(res, 0, PQfnumber(res, "stats_row_level")));
                PQclear(res);
@@ -1079,81 +1093,84 @@ main(int argc, char *argv[])
                                        res = send_query(TABLE_STATS_QUERY, dbs);       /* Get an updated
                                                                                                                                 * snapshot of this dbs
                                                                                                                                 * table stats */
-                                       for (j = 0; j < PQntuples(res); j++)
-                                       {                       /* loop through result set */
-                                               tbl_elem = DLGetHead(dbs->table_list);  /* Reset tbl_elem to top
-                                                                                                                                * of dbs->table_list */
-                                               while (tbl_elem != NULL)
-                                               {               /* Loop through tables in list */
-                                                       tbl = ((tbl_info *) DLE_VAL(tbl_elem));         /* set tbl_info =
-                                                                                                                                                * current_table */
-                                                       if (tbl->relid == atooid(PQgetvalue(res, j, PQfnumber(res, "oid"))))
-                                                       {
-                                                               tbl->curr_analyze_count =
-                                                                       (atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_ins"))) +
-                                                                        atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))) +
-                                                                        atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))));
-                                                               tbl->curr_vacuum_count =
-                                                                       (atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))) +
-                                                                        atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))));
-
-                                                               /*
-                                                                * Check numDeletes to see if we need to
-                                                                * vacuum, if so: Run vacuum analyze
-                                                                * (adding analyze is small so we might as
-                                                                * well) Update table thresholds and
-                                                                * related information if numDeletes is
-                                                                * not big enough for vacuum then check
-                                                                * numInserts for analyze
-                                                                */
-                                                               if (tbl->curr_vacuum_count - tbl->CountAtLastVacuum >= tbl->vacuum_threshold)
+                                       if (res != NULL)
+                                       {
+                                               for (j = 0; j < PQntuples(res); j++)
+                                               {                       /* loop through result set */
+                                                       tbl_elem = DLGetHead(dbs->table_list);  /* Reset tbl_elem to top
+                                                                                                                                       * of dbs->table_list */
+                                                       while (tbl_elem != NULL)
+                                                       {               /* Loop through tables in list */
+                                                               tbl = ((tbl_info *) DLE_VAL(tbl_elem));         /* set tbl_info =
+                                                                                                                                                       * current_table */
+                                                               if (tbl->relid == atooid(PQgetvalue(res, j, PQfnumber(res, "oid"))))
                                                                {
+                                                                       tbl->curr_analyze_count =
+                                                                               (atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_ins"))) +
+                                                                               atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))) +
+                                                                               atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))));
+                                                                       tbl->curr_vacuum_count =
+                                                                               (atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_del"))) +
+                                                                               atol(PQgetvalue(res, j, PQfnumber(res, "n_tup_upd"))));
+       
                                                                        /*
-                                                                        * if relisshared = t and database !=
-                                                                        * template1 then only do an analyze
-                                                                        */
-                                                                       if (tbl->relisshared > 0 && strcmp("template1", dbs->dbname))
-                                                                               snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
-                                                                       else
-                                                                               snprintf(buf, sizeof(buf), "VACUUM ANALYZE %s", tbl->table_name);
-                                                                       if (args->debug >= 1)
+                                                                       * Check numDeletes to see if we need to
+                                                                       * vacuum, if so: Run vacuum analyze
+                                                                       * (adding analyze is small so we might as
+                                                                       * well) Update table thresholds and
+                                                                       * related information if numDeletes is
+                                                                       * not big enough for vacuum then check
+                                                                       * numInserts for analyze
+                                                                       */
+                                                                       if (tbl->curr_vacuum_count - tbl->CountAtLastVacuum >= tbl->vacuum_threshold)
                                                                        {
-                                                                               sprintf(logbuffer, "Performing: %s", buf);
-                                                                               log_entry(logbuffer);
-                                                                               fflush(LOGOUTPUT);
+                                                                               /*
+                                                                               * if relisshared = t and database !=
+                                                                               * template1 then only do an analyze
+                                                                               */
+                                                                               if (tbl->relisshared > 0 && strcmp("template1", dbs->dbname))
+                                                                                       snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
+                                                                               else
+                                                                                       snprintf(buf, sizeof(buf), "VACUUM ANALYZE %s", tbl->table_name);
+                                                                               if (args->debug >= 1)
+                                                                               {
+                                                                                       sprintf(logbuffer, "Performing: %s", buf);
+                                                                                       log_entry(logbuffer);
+                                                                                       fflush(LOGOUTPUT);
+                                                                               }
+                                                                               send_query(buf, dbs);
+                                                                               update_table_thresholds(dbs, tbl, VACUUM_ANALYZE);
+                                                                               if (args->debug >= 2)
+                                                                                       print_table_info(tbl);
                                                                        }
-                                                                       send_query(buf, dbs);
-                                                                       update_table_thresholds(dbs, tbl, VACUUM_ANALYZE);
-                                                                       if (args->debug >= 2)
-                                                                               print_table_info(tbl);
-                                                               }
-                                                               else if (tbl->curr_analyze_count - tbl->CountAtLastAnalyze >= tbl->analyze_threshold)
-                                                               {
-                                                                       snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
-                                                                       if (args->debug >= 1)
+                                                                       else if (tbl->curr_analyze_count - tbl->CountAtLastAnalyze >= tbl->analyze_threshold)
                                                                        {
-                                                                               sprintf(logbuffer, "Performing: %s", buf);
-                                                                               log_entry(logbuffer);
-                                                                               fflush(LOGOUTPUT);
+                                                                               snprintf(buf, sizeof(buf), "ANALYZE %s", tbl->table_name);
+                                                                               if (args->debug >= 1)
+                                                                               {
+                                                                                       sprintf(logbuffer, "Performing: %s", buf);
+                                                                                       log_entry(logbuffer);
+                                                                                       fflush(LOGOUTPUT);
+                                                                               }
+                                                                               send_query(buf, dbs);
+                                                                               update_table_thresholds(dbs, tbl, ANALYZE_ONLY);
+                                                                               if (args->debug >= 2)
+                                                                                       print_table_info(tbl);
                                                                        }
-                                                                       send_query(buf, dbs);
-                                                                       update_table_thresholds(dbs, tbl, ANALYZE_ONLY);
-                                                                       if (args->debug >= 2)
-                                                                               print_table_info(tbl);
+                                                                       
+                                                                       break;  /* once we have found a match, no
+                                                                                       * need to keep checking. */
                                                                }
-
-                                                               break;  /* once we have found a match, no
-                                                                                * need to keep checking. */
-                                                       }
-
-                                                       /*
-                                                        * Advance the table pointers for the next
-                                                        * loop
-                                                        */
-                                                       tbl_elem = DLGetSucc(tbl_elem);
-
-                                               }               /* end for table while loop */
-                                       }                       /* end for j loop (tuples in PGresult) */
+                                                               
+                                                               /*
+                                                               * Advance the table pointers for the next
+                                                               * loop
+                                                               */
+                                                               tbl_elem = DLGetSucc(tbl_elem);
+                                                               
+                                                       }               /* end for table while loop */
+                                               }                       /* end for j loop (tuples in PGresult) */
+                                       }                       /* end if (res != NULL) */
                                }                               /* close of if(xid_wraparound_check()) */
                                /* Done working on this db, Clean up, then advance cur_db */
                                PQclear(res);
index 86cd64b2d7deca21babdcafbe2f69544e75d6d7f..7152a2a5592841c155c61c27b1589d3a5377a122 100644 (file)
@@ -34,7 +34,7 @@
 #define VACUUM_ANALYZE         0
 #define ANALYZE_ONLY           1
 
-#define TABLE_STATS_QUERY      "select a.oid,a.relname,a.relnamespace,a.relpages,a.relisshared,a.reltuples,b.schemaname,b.n_tup_ins,b.n_tup_upd,b.n_tup_del from pg_class a, pg_stat_all_tables b where a.oid=b.relid and a.relkind = 'r'"
+#define TABLE_STATS_QUERY      "select a.oid,a.relname,a.relnamespace,a.relpages,a.relisshared,a.reltuples,b.schemaname,b.n_tup_ins,b.n_tup_upd,b.n_tup_del from pg_class a, pg_stat_all_tables b where a.oid=b.relid and a.relkind = 'r' and schemaname not like 'pg_temp_%'"
 
 #define FRONTEND
 #define PAGES_QUERY "select oid,reltuples,relpages from pg_class where oid=%u"