88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.586 2010/01/2316:37:12 sriggs Exp $
11+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.587 2010/01/2317:04:05 sriggs Exp $
1212 *
1313 * NOTES
1414 * this is the "main" module of the postgres backend and
@@ -172,8 +172,9 @@ static intUseNewLine = 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 cancelledduring recovery by conflictprocessing or not */
175+ /* whetheror not, and why, we were cancelled by conflictwith 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)
22542256return 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*/
27172752if (!proc_exit_inprogress )
27182753{
2754+ RecoveryConflictReason = reason ;
27192755switch (reason )
27202756{
27212757case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN :
@@ -2835,7 +2871,8 @@ ProcessInterrupts(void)
28352871else if (RecoveryConflictPending )
28362872ereport (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 ()));
28392876else
28402877ereport (FATAL ,
28412878(errcode (ERRCODE_ADMIN_SHUTDOWN ),
@@ -2883,11 +2920,15 @@ ProcessInterrupts(void)
28832920if (DoingCommandRead )
28842921ereport (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." )));
28872927else
28882928ereport (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/*