#include "postgres.h"
#include "pgstat.h"
+#include "miscadmin.h"
#include "access/transam.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#if PG_VERSION_NUM >= 100000
#include "utils/varlena.h"
#include "utils/regproc.h"
+#if PG_VERSION_NUM >= 130000
+#include "common/hashfn.h"
+#endif
#endif
#endif
#endif
int nTables;
Oid *tables;
char *tableStr;
+ bool inited;
} TableList;
-static TableList excludeTables = {0, NULL, NULL};
-static TableList includeTables = {0, NULL, NULL};
+static TableList excludeTables = {0, NULL, NULL, false};
+static TableList includeTables = {0, NULL, NULL, false};
typedef struct OnlineAnalyzeTableStat {
Oid tableid;
bool rereadStat;
PgStat_Counter n_tuples;
- PgStat_Counter changes_since_analyze;
- TimestampTz autovac_analyze_timestamp;
- TimestampTz analyze_timestamp;
+ PgStat_Counter mod_since_analyze;
+ TimestampTz last_autoanalyze_time;
+ TimestampTz last_analyze_time;
} OnlineAnalyzeTableStat;
static MemoryContext onlineAnalyzeMemoryContext = NULL;
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())
+ {
+ includeTables.inited = false;
+ excludeTables.inited = false;
+ return newval;
+ }
+
if (doit)
{
nOids = list_length(namelist);
foreach(l, namelist)
{
char *curname = (char *) lfirst(l);
-#if PG_VERSION_NUM >= 90200
+#if PG_VERSION_NUM >= 160000
+ Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList(
+ stringToQualifiedNameList(curname, NULL)), NoLock, true);
+#elif PG_VERSION_NUM >= 90200
Oid relOid = RangeVarGetRelid(makeRangeVarFromNameList(
stringToQualifiedNameList(curname)), NoLock, true);
#else
static void
includeTablesAssign(const char *newval, void *extra)
{
- tableListAssign(newval, true, &excludeTables);
+ tableListAssign(newval, true, &includeTables);
}
#else /* PG_VERSION_NUM < 90100 */
#endif
+static void
+lateInit()
+{
+ TableList *tl[] = {&includeTables, &excludeTables};
+ int i;
+
+#if PG_VERSION_NUM >= 170000
+ if (MyProcNumber == INVALID_PROC_NUMBER ||
+#else
+ if (MyBackendId == InvalidBackendId ||
+#endif
+ !IsUnderPostmaster ||
+ !IsTransactionState())
+ return; /* we aren't in connected state */
+
+ for(i=0; i<lengthof(tl); i++)
+ {
+ TableList *tbl = tl[i];
+
+ if (tbl->inited == false)
+ tableListAssign(tbl->tableStr, true, tbl);
+ tbl->inited = true;
+ }
+}
+
static const char*
tableListShow(TableList *tbl)
{
int i,
len;
+ lateInit();
+
len = 1 /* \0 */ + tbl->nTables * (2 * NAMEDATALEN + 2 /* ', ' */ + 1 /* . */);
ptr = val = palloc(len);
*ptr ='\0';
else if (operation == CK_ANALYZE)
{
/* only analyze */
- rstat->changes_since_analyze = 0;
- rstat->analyze_timestamp = now;
+ rstat->mod_since_analyze = 0;
+ rstat->last_analyze_time = now;
if (newTable)
rstat->rereadStat = true;
return;
if (tabentry)
{
- rstat->n_tuples = tabentry->n_dead_tuples + tabentry->n_live_tuples;
- rstat->changes_since_analyze =
-#if PG_VERSION_NUM >= 90000
+ rstat->n_tuples =
+#if PG_VERSION_NUM >= 160000
+ tabentry->dead_tuples + tabentry->live_tuples;
+#else
+ tabentry->n_dead_tuples + tabentry->n_live_tuples;
+#endif
+
+ rstat->mod_since_analyze =
+#if PG_VERSION_NUM >= 160000
+ tabentry->mod_since_analyze;
+#elif PG_VERSION_NUM >= 90000
tabentry->changes_since_analyze;
#else
tabentry->n_live_tuples + tabentry->n_dead_tuples -
tabentry->last_anl_tuples;
#endif
- rstat->autovac_analyze_timestamp =
+
+ rstat->last_autoanalyze_time =
+#if PG_VERSION_NUM >= 160000
+ tabentry->last_autoanalyze_time;
+#else
tabentry->autovac_analyze_timestamp;
- rstat->analyze_timestamp = tabentry->analyze_timestamp;
+#endif
+
+ rstat->last_analyze_time =
+#if PG_VERSION_NUM >= 160000
+ tabentry->last_analyze_time;
+#else
+ tabentry->analyze_timestamp;
+#endif
}
}
/* force analyze after truncate, fasttruncate already did analyze */
operation == CK_TRUNCATE || (
/* do not analyze too often, if both stamps are exceeded the go */
- TimestampDifferenceExceeds(rstat->analyze_timestamp, now, online_analyze_min_interval) &&
- TimestampDifferenceExceeds(rstat->autovac_analyze_timestamp, now, online_analyze_min_interval) &&
+ TimestampDifferenceExceeds(rstat->last_analyze_time, now, online_analyze_min_interval) &&
+ TimestampDifferenceExceeds(rstat->last_autoanalyze_time, now, online_analyze_min_interval) &&
/* do not analyze too small tables */
- rstat->n_tuples + rstat->changes_since_analyze + naffected > online_analyze_lower_limit &&
+ rstat->n_tuples + rstat->mod_since_analyze + naffected > online_analyze_lower_limit &&
/* be in sync with relation_needs_vacanalyze */
- ((double)(rstat->changes_since_analyze + naffected)) >=
+ ((double)(rstat->mod_since_analyze + naffected)) >=
online_analyze_scale_factor * ((double)rstat->n_tuples) +
(double)online_analyze_threshold))
{
TimestampTz startStamp, endStamp;
int flags;
+#ifdef PGPRO_EE
+ /* ATX is not compatible with online_analyze */
+ if (getNestLevelATX() != 0)
+ return;
+#endif
memset(&startStamp, 0, sizeof(startStamp)); /* keep compiler quiet */
((double)secs) + ((double)microsecs)/1.0e6);
}
- rstat->autovac_analyze_timestamp = now;
- rstat->changes_since_analyze = 0;
+ rstat->last_autoanalyze_time = now;
+ rstat->mod_since_analyze = 0;
switch(operation)
{
case CK_INSERT:
case CK_UPDATE:
rstat->n_tuples += naffected;
+ /* FALLTHROUGH */
case CK_DELETE:
rstat->rereadStat = (reltype == OATT_PERSISTENT);
break;
/* update last analyze timestamp in local memory of backend */
if (tabentry)
{
+#if PG_VERSION_NUM >= 160000
+ tabentry->last_analyze_time = now;
+ tabentry->mod_since_analyze = 0;
+#else
tabentry->analyze_timestamp = now;
tabentry->changes_since_analyze = 0;
+#endif
}
#if 0
/* force reload stat for new table */
{
#if PG_VERSION_NUM >= 90000
if (tabentry)
+#if PG_VERSION_NUM >= 160000
+ tabentry->mod_since_analyze += naffected;
+#else
tabentry->changes_since_analyze += naffected;
+#endif
#endif
switch(operation)
{
case CK_CREATE:
case CK_INSERT:
- rstat->changes_since_analyze += naffected;
+ rstat->mod_since_analyze += naffected;
rstat->n_tuples += naffected;
break;
case CK_UPDATE:
- rstat->changes_since_analyze += 2 * naffected;
+ rstat->mod_since_analyze += 2 * naffected;
rstat->n_tuples += naffected;
+ break;
case CK_DELETE:
- rstat->changes_since_analyze += naffected;
+ rstat->mod_since_analyze += naffected;
break;
case CK_TRUNCATE:
case CK_FASTTRUNCATE:
- rstat->changes_since_analyze = 0;
+ rstat->mod_since_analyze = 0;
rstat->n_tuples = 0;
break;
default:
if (queryDesc->estate)
naffected = queryDesc->estate->es_processed;
+ lateInit();
+
#if PG_VERSION_NUM >= 90200
if (online_analyze_enable &&
(constval = isFastTruncateCall(queryDesc)) != NULL)
{
Datum tblnamed = constval->constvalue;
char *tblname = text_to_cstring(DatumGetTextP(tblnamed));
+#if PG_VERSION_NUM >= 160000
+ RangeVar *tblvar =
+ makeRangeVarFromNameList(stringToQualifiedNameList(tblname, NULL));
+#else
RangeVar *tblvar =
makeRangeVarFromNameList(stringToQualifiedNameList(tblname));
+#endif
makeAnalyze(RangeVarGetRelid(tblvar,
NoLock,
Node *parsetree,
#endif
const char *queryString,
+#if PG_VERSION_NUM >= 140000
+ bool readOnlyTree,
+#endif
#if PG_VERSION_NUM >= 90300
ProcessUtilityContext context, ParamListInfo params,
#if PG_VERSION_NUM >= 100000
#else
ParamListInfo params, bool isTopLevel,
#endif
- DestReceiver *dest, char *completionTag) {
+ DestReceiver *dest,
+#if PG_VERSION_NUM >= 130000
+ QueryCompletion *completionTag
+#else
+ char *completionTag
+#endif
+) {
List *tblnames = NIL;
CmdKind op = CK_INSERT;
#if PG_VERSION_NUM >= 100000
parsetree = pstmt->utilityStmt;
#endif
+ lateInit();
+
if (parsetree && online_analyze_enable)
{
if (IsA(parsetree, CreateTableAsStmt) &&
while((rstat = hash_seq_search(&hs)) != NULL)
{
- rstat->changes_since_analyze = 0;
- rstat->analyze_timestamp = now;
+ rstat->mod_since_analyze = 0;
+ rstat->last_analyze_time = now;
}
}
}
if (oldProcessUtilityHook)
oldProcessUtilityHook(parsetree, queryString,
+#if PG_VERSION_NUM >= 140000
+ readOnlyTree,
+#endif
#if PG_VERSION_NUM >= 90300
context, params,
#if PG_VERSION_NUM >= 100000
dest, completionTag);
else
standard_ProcessUtility(parsetree, queryString,
+#if PG_VERSION_NUM >= 140000
+ readOnlyTree,
+#endif
#if PG_VERSION_NUM >= 90300
context, params,
#if PG_VERSION_NUM >= 100000
RegisterXactCallback(removeTable, NULL);
}
-
-void _PG_fini(void);
-void
-_PG_fini(void)
-{
- ExecutorEnd_hook = oldExecutorEndHook;
-#if PG_VERSION_NUM >= 90200
- ProcessUtility_hook = oldProcessUtilityHook;
-#endif
-
- if (excludeTables.tables)
- free(excludeTables.tables);
- if (includeTables.tables)
- free(includeTables.tables);
-
- excludeTables.tables = includeTables.tables = NULL;
- excludeTables.nTables = includeTables.nTables = 0;
-}