88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.586 2010/01/23 16:37:12 sriggs Exp $
11+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.587 2010/01/23 17:04:05 sriggs Exp $
1212 *
1313 * NOTES
1414 * this is the "main" module of the postgres backend and
@@ -172,8 +172,9 @@ static int UseNewLine = 1; /* Use newlines query delimiters (the default) */
172172static int UseNewLine = 0 ; /* Use EOF as query delimiters */
173173#endif /* TCOP_DONTUSENEWLINE */
174174
175- /* whether we were cancelled during recovery by conflict processing or not */
175+ /* whether or not, and why, we were cancelled by conflict with recovery */
176176static bool RecoveryConflictPending = false;
177+ static ProcSignalReason RecoveryConflictReason ;
177178
178179/* ----------------------------------------------------------------
179180 * decls for routines only used in this file
@@ -188,6 +189,7 @@ static bool check_log_statement(List *stmt_list);
188189static int errdetail_execute (List * raw_parsetree_list );
189190static int errdetail_params (ParamListInfo params );
190191static int errdetail_abort (void );
192+ static int errdetail_recovery_conflict (void );
191193static void start_xact_command (void );
192194static void finish_xact_command (void );
193195static bool IsTransactionExitStmt (Node * parsetree );
@@ -2254,6 +2256,39 @@ errdetail_abort(void)
22542256 return 0 ;
22552257}
22562258
2259+ /*
2260+ * errdetail_recovery_conflict
2261+ *
2262+ * Add an errdetail() line showing conflict source.
2263+ */
2264+ static int
2265+ errdetail_recovery_conflict (void )
2266+ {
2267+ switch (RecoveryConflictReason )
2268+ {
2269+ case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN :
2270+ errdetail ("User was holding shared buffer pin for too long." );
2271+ break ;
2272+ case PROCSIG_RECOVERY_CONFLICT_LOCK :
2273+ errdetail ("User was holding a relation lock for too long." );
2274+ break ;
2275+ case PROCSIG_RECOVERY_CONFLICT_TABLESPACE :
2276+ errdetail ("User was or may have been using tablespace that must be dropped." );
2277+ break ;
2278+ case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT :
2279+ errdetail ("User query might have needed to see row versions that must be removed." );
2280+ break ;
2281+ case PROCSIG_RECOVERY_CONFLICT_DATABASE :
2282+ errdetail ("User was connected to a database that must be dropped." );
2283+ break ;
2284+ default :
2285+ break ;
2286+ /* no errdetail */
2287+ }
2288+
2289+ return 0 ;
2290+ }
2291+
22572292/*
22582293 * exec_describe_statement_message
22592294 *
@@ -2716,6 +2751,7 @@ RecoveryConflictInterrupt(ProcSignalReason reason)
27162751 */
27172752 if (!proc_exit_inprogress )
27182753 {
2754+ RecoveryConflictReason = reason ;
27192755 switch (reason )
27202756 {
27212757 case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN :
@@ -2835,7 +2871,8 @@ ProcessInterrupts(void)
28352871 else if (RecoveryConflictPending )
28362872 ereport (FATAL ,
28372873 (errcode (ERRCODE_ADMIN_SHUTDOWN ),
2838- errmsg ("terminating connection due to conflict with recovery" )));
2874+ errmsg ("terminating connection due to conflict with recovery" ),
2875+ errdetail_recovery_conflict ()));
28392876 else
28402877 ereport (FATAL ,
28412878 (errcode (ERRCODE_ADMIN_SHUTDOWN ),
@@ -2883,11 +2920,15 @@ ProcessInterrupts(void)
28832920 if (DoingCommandRead )
28842921 ereport (FATAL ,
28852922 (errcode (ERRCODE_ADMIN_SHUTDOWN ),
2886- errmsg ("terminating connection due to conflict with recovery" )));
2923+ errmsg ("terminating connection due to conflict with recovery" ),
2924+ errdetail_recovery_conflict (),
2925+ errhint ("In a moment you should be able to reconnect to the"
2926+ " database and repeat your command." )));
28872927 else
28882928 ereport (ERROR ,
28892929 (errcode (ERRCODE_QUERY_CANCELED ),
2890- errmsg ("canceling statement due to conflict with recovery" )));
2930+ errmsg ("canceling statement due to conflict with recovery" ),
2931+ errdetail_recovery_conflict ()));
28912932 }
28922933
28932934 /*
0 commit comments