diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 0070f0f33a..5fff558e4d 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -1077,6 +1077,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, { Node *parsetree = pstmt->utilityStmt; uint64 saved_queryId = pstmt->queryId; + int saved_stmt_location = pstmt->stmt_location; + int saved_stmt_len = pstmt->stmt_len; /* * Force utility statements to get queryId zero. We do this even in cases @@ -1142,6 +1144,16 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, } PG_END_TRY(); + /* + * CAUTION: do not access the *pstmt data structure again below here. + * If it was a ROLLBACK or similar, that data structure may have been + * freed. We must copy everything we still need into local variables, + * which we did above. + * + * For the same reason, we can't risk restoring pstmt->queryId to its + * former value, which'd otherwise be a good idea. + */ + INSTR_TIME_SET_CURRENT(duration); INSTR_TIME_SUBTRACT(duration, start); @@ -1166,8 +1178,8 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString, pgss_store(queryString, saved_queryId, - pstmt->stmt_location, - pstmt->stmt_len, + saved_stmt_location, + saved_stmt_len, PGSS_EXEC, INSTR_TIME_GET_MILLISEC(duration), rows,