mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Fire non-deferred AFTER triggers immediately upon query completion,
rather than when returning to the idle loop. This makes no particular difference for interactively-issued queries, but it makes a big difference for queries issued within functions: trigger execution now occurs before the calling function is allowed to proceed. This responds to numerous complaints about nonintuitive behavior of foreign key checking, such as http://archives.postgresql.org/pgsql-bugs/2004-09/msg00020.php, and appears to be required by the SQL99 spec. Also take the opportunity to simplify the data structures used for the pending-trigger list, rename them for more clarity, and squeeze out a bit of space.
This commit is contained in:
@ -8,13 +8,14 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.85 2004/08/29 05:06:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.86 2004/09/10 18:40:00 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "commands/trigger.h"
|
||||
#include "executor/executor.h"
|
||||
#include "miscadmin.h"
|
||||
#include "tcop/tcopprot.h"
|
||||
@ -136,6 +137,11 @@ ProcessQuery(Query *parsetree,
|
||||
*/
|
||||
queryDesc = CreateQueryDesc(parsetree, plan, dest, params, false);
|
||||
|
||||
/*
|
||||
* Set up to collect AFTER triggers
|
||||
*/
|
||||
AfterTriggerBeginQuery();
|
||||
|
||||
/*
|
||||
* Call ExecStart to prepare the plan for execution
|
||||
*/
|
||||
@ -185,6 +191,9 @@ ProcessQuery(Query *parsetree,
|
||||
*/
|
||||
ExecutorEnd(queryDesc);
|
||||
|
||||
/* And take care of any queued AFTER triggers */
|
||||
AfterTriggerEndQuery();
|
||||
|
||||
FreeQueryDesc(queryDesc);
|
||||
}
|
||||
|
||||
@ -290,6 +299,13 @@ PortalStart(Portal portal, ParamListInfo params)
|
||||
params,
|
||||
false);
|
||||
|
||||
/*
|
||||
* We do *not* call AfterTriggerBeginQuery() here. We
|
||||
* assume that a SELECT cannot queue any triggers. It
|
||||
* would be messy to support triggers since the execution
|
||||
* of the portal may be interleaved with other queries.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Call ExecStart to prepare the plan for execution
|
||||
*/
|
||||
@ -1144,8 +1160,8 @@ DoPortalRunFetch(Portal portal,
|
||||
return PortalRunSelect(portal, false, 1L, dest);
|
||||
}
|
||||
else
|
||||
/* count == 0 */
|
||||
{
|
||||
/* count == 0 */
|
||||
/* Rewind to start, return zero rows */
|
||||
DoPortalRewind(portal);
|
||||
return PortalRunSelect(portal, true, 0L, dest);
|
||||
@ -1173,8 +1189,8 @@ DoPortalRunFetch(Portal portal,
|
||||
return PortalRunSelect(portal, false, 1L, dest);
|
||||
}
|
||||
else
|
||||
/* count == 0 */
|
||||
{
|
||||
/* count == 0 */
|
||||
/* Same as FETCH FORWARD 0, so fall out of switch */
|
||||
fdirection = FETCH_FORWARD;
|
||||
}
|
||||
|
Reference in New Issue
Block a user