timing.diff
text/plain
Filename: timing.diff
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/commands/trigger.c | 38 | 19 |
| src/backend/executor/spi.c | 17 | 12 |
| src/backend/utils/adt/ri_triggers.c | 2 | 3 |
| src/include/executor/spi.h | 1 | 1 |
| src/test/regress/expected/foreign_key.out | 14 | 1 |
| src/test/regress/sql/foreign_key.sql | 17 | 0 |
Index: src/backend/commands/trigger.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/trigger.c,v
retrieving revision 1.193
diff -c -r1.193 trigger.c
*** src/backend/commands/trigger.c 23 Aug 2005 22:40:08 -0000 1.193
--- src/backend/commands/trigger.c 24 Aug 2005 03:24:48 -0000
***************
*** 2281,2286 ****
--- 2280,2286 ----
TriggerDesc *trigdesc = NULL;
FmgrInfo *finfo = NULL;
Instrumentation *instr = NULL;
+ bool last_relation_loaded = false;
/* Make a per-tuple memory context for trigger function calls */
per_tuple_context =
***************
*** 2309,2314 ****
--- 2309,2328 ----
*/
if (rel == NULL || rel->rd_id != event->ate_relid)
{
+ bool found_relation_in_estate = false;
+ if (last_relation_loaded) {
+ if (rel)
+ heap_close(rel, NoLock);
+ if (trigdesc)
+ FreeTriggerDesc(trigdesc);
+ if (finfo)
+ pfree(finfo);
+ Assert(instr == NULL); /* never used in this case */
+ rel = NULL;
+ trigdesc = NULL;
+ finfo = NULL;
+ }
+
if (estate)
{
/* Find target relation among estate's result rels */
***************
*** 2324,2348 ****
rInfo++;
nr--;
}
! if (nr <= 0) /* should not happen */
! elog(ERROR, "could not find relation %u among query result relations",
! event->ate_relid);
! rel = rInfo->ri_RelationDesc;
! trigdesc = rInfo->ri_TrigDesc;
! finfo = rInfo->ri_TrigFunctions;
! instr = rInfo->ri_TrigInstrument;
}
- else
- {
- /* Hard way: we manage the resources for ourselves */
- if (rel)
- heap_close(rel, NoLock);
- if (trigdesc)
- FreeTriggerDesc(trigdesc);
- if (finfo)
- pfree(finfo);
- Assert(instr == NULL); /* never used in this case */
/*
* We assume that an appropriate lock is still held by
* the executor, so grab no new lock here.
--- 2338,2355 ----
rInfo++;
nr--;
}
! if (nr > 0)
! {
! rel = rInfo->ri_RelationDesc;
! trigdesc = rInfo->ri_TrigDesc;
! finfo = rInfo->ri_TrigFunctions;
! instr = rInfo->ri_TrigInstrument;
! found_relation_in_estate = true;
! }
}
+ if (!found_relation_in_estate)
+ {
/*
* We assume that an appropriate lock is still held by
* the executor, so grab no new lock here.
***************
*** 2367,2372 ****
--- 2374,2386 ----
palloc0(trigdesc->numtriggers * sizeof(FmgrInfo));
/* Never any EXPLAIN info in this case */
+ instr = NULL;
+
+ last_relation_loaded = true;
+ }
+ else
+ {
+ last_relation_loaded = false;
}
}
***************
*** 2417,2423 ****
events->tail = prev_event;
/* Release working resources */
! if (!estate)
{
if (rel)
heap_close(rel, NoLock);
--- 2431,2437 ----
events->tail = prev_event;
/* Release working resources */
! if (last_relation_loaded)
{
if (rel)
heap_close(rel, NoLock);
***************
*** 2543,2551 ****
* will be available for it to fire.
*
* If we find no firable events, we don't have to increment firing_counter.
*/
events = &afterTriggers->query_stack[afterTriggers->query_depth];
! if (afterTriggerMarkEvents(events, &afterTriggers->events, true))
{
CommandId firing_id = afterTriggers->firing_counter++;
--- 2557,2569 ----
* will be available for it to fire.
*
* If we find no firable events, we don't have to increment firing_counter.
+ *
+ * If we do find events, we continue to mark events and invoking them
+ * until there are no events remaining because a referential action may
+ * be adding not yet marked events to the end of our queue.
*/
events = &afterTriggers->query_stack[afterTriggers->query_depth];
! while (afterTriggerMarkEvents(events, &afterTriggers->events, true))
{
CommandId firing_id = afterTriggers->firing_counter++;
Index: src/backend/executor/spi.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/executor/spi.c,v
retrieving revision 1.141
diff -c -r1.141 spi.c
*** src/backend/executor/spi.c 9 Jun 2005 21:25:22 -0000 1.141
--- src/backend/executor/spi.c 24 Aug 2005 03:24:50 -0000
***************
*** 40,48 ****
static int _SPI_execute_plan(_SPI_plan *plan,
Datum *Values, const char *Nulls,
Snapshot snapshot, Snapshot crosscheck_snapshot,
! bool read_only, long tcount);
! static int _SPI_pquery(QueryDesc *queryDesc, long tcount);
static void _SPI_error_callback(void *arg);
--- 40,48 ----
static int _SPI_execute_plan(_SPI_plan *plan,
Datum *Values, const char *Nulls,
Snapshot snapshot, Snapshot crosscheck_snapshot,
! bool read_only, long tcount, bool nest_triggers);
! static int _SPI_pquery(QueryDesc *queryDesc, long tcount, bool nest_triggers);
static void _SPI_error_callback(void *arg);
***************
*** 302,308 ****
res = _SPI_execute_plan(&plan, NULL, NULL,
InvalidSnapshot, InvalidSnapshot,
! read_only, tcount);
_SPI_end_call(true);
return res;
--- 302,308 ----
res = _SPI_execute_plan(&plan, NULL, NULL,
InvalidSnapshot, InvalidSnapshot,
! read_only, tcount, true);
_SPI_end_call(true);
return res;
***************
*** 335,341 ****
res = _SPI_execute_plan((_SPI_plan *) plan,
Values, Nulls,
InvalidSnapshot, InvalidSnapshot,
! read_only, tcount);
_SPI_end_call(true);
return res;
--- 335,341 ----
res = _SPI_execute_plan((_SPI_plan *) plan,
Values, Nulls,
InvalidSnapshot, InvalidSnapshot,
! read_only, tcount, true);
_SPI_end_call(true);
return res;
***************
*** 361,367 ****
SPI_execute_snapshot(void *plan,
Datum *Values, const char *Nulls,
Snapshot snapshot, Snapshot crosscheck_snapshot,
! bool read_only, long tcount)
{
int res;
--- 361,367 ----
SPI_execute_snapshot(void *plan,
Datum *Values, const char *Nulls,
Snapshot snapshot, Snapshot crosscheck_snapshot,
! bool read_only, long tcount, bool nest_triggers)
{
int res;
***************
*** 378,384 ****
res = _SPI_execute_plan((_SPI_plan *) plan,
Values, Nulls,
snapshot, crosscheck_snapshot,
! read_only, tcount);
_SPI_end_call(true);
return res;
--- 378,384 ----
res = _SPI_execute_plan((_SPI_plan *) plan,
Values, Nulls,
snapshot, crosscheck_snapshot,
! read_only, tcount, nest_triggers);
_SPI_end_call(true);
return res;
***************
*** 1306,1316 ****
* crosscheck_snapshot: for RI use, all others pass InvalidSnapshot
* read_only: TRUE for read-only execution (no CommandCounterIncrement)
* tcount: execution tuple-count limit, or 0 for none
*/
static int
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
Snapshot snapshot, Snapshot crosscheck_snapshot,
! bool read_only, long tcount)
{
volatile int res = 0;
Snapshot saveActiveSnapshot;
--- 1306,1319 ----
* crosscheck_snapshot: for RI use, all others pass InvalidSnapshot
* read_only: TRUE for read-only execution (no CommandCounterIncrement)
* tcount: execution tuple-count limit, or 0 for none
+ * nest_triggers: TRUE to treat as a separate query for after triggers,
+ * FALSE to place after triggers on the outer statement's
+ * queue.
*/
static int
_SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
Snapshot snapshot, Snapshot crosscheck_snapshot,
! bool read_only, long tcount, bool nest_triggers)
{
volatile int res = 0;
Snapshot saveActiveSnapshot;
***************
*** 1462,1468 ****
dest,
paramLI, false);
res = _SPI_pquery(qdesc,
! queryTree->canSetTag ? tcount : 0);
FreeQueryDesc(qdesc);
}
FreeSnapshot(ActiveSnapshot);
--- 1465,1471 ----
dest,
paramLI, false);
res = _SPI_pquery(qdesc,
! queryTree->canSetTag ? tcount : 0, nest_triggers);
FreeQueryDesc(qdesc);
}
FreeSnapshot(ActiveSnapshot);
***************
*** 1494,1500 ****
}
static int
! _SPI_pquery(QueryDesc *queryDesc, long tcount)
{
int operation = queryDesc->operation;
CommandDest origDest = queryDesc->dest->mydest;
--- 1497,1503 ----
}
static int
! _SPI_pquery(QueryDesc *queryDesc, long tcount, bool nest_triggers)
{
int operation = queryDesc->operation;
CommandDest origDest = queryDesc->dest->mydest;
***************
*** 1529,1535 ****
ResetUsage();
#endif
! AfterTriggerBeginQuery();
ExecutorStart(queryDesc, false);
--- 1532,1539 ----
ResetUsage();
#endif
! if (nest_triggers)
! AfterTriggerBeginQuery();
ExecutorStart(queryDesc, false);
***************
*** 1544,1551 ****
elog(ERROR, "consistency check on SPI tuple count failed");
}
! /* Take care of any queued AFTER triggers */
! AfterTriggerEndQuery(queryDesc->estate);
ExecutorEnd(queryDesc);
--- 1548,1556 ----
elog(ERROR, "consistency check on SPI tuple count failed");
}
! /* Take care of any queued AFTER triggers if we are nesting triggers */
! if (nest_triggers)
! AfterTriggerEndQuery(queryDesc->estate);
ExecutorEnd(queryDesc);
Index: src/backend/utils/adt/ri_triggers.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v
retrieving revision 1.80
diff -c -r1.80 ri_triggers.c
*** src/backend/utils/adt/ri_triggers.c 28 Jun 2005 05:09:00 -0000 1.80
--- src/backend/utils/adt/ri_triggers.c 24 Aug 2005 03:24:56 -0000
***************
*** 2383,2389 ****
qkey.keypair[i][RI_KEYPAIR_PK_IDX]);
}
strcat(querystr, qualstr);
-
/* Prepare the plan, don't save it */
qplan = ri_PlanCheck(querystr, qkey.nkeypairs, queryoids,
&qkey, fk_rel, pk_rel, false);
--- 2383,2388 ----
***************
*** 2745,2751 ****
NULL, NULL,
CopySnapshot(GetLatestSnapshot()),
InvalidSnapshot,
! true, 1);
/* Check result */
if (spi_result != SPI_OK_SELECT)
--- 2744,2750 ----
NULL, NULL,
CopySnapshot(GetLatestSnapshot()),
InvalidSnapshot,
! true, 1, false);
/* Check result */
if (spi_result != SPI_OK_SELECT)
***************
*** 3175,3181 ****
spi_result = SPI_execute_snapshot(qplan,
vals, nulls,
test_snapshot, crosscheck_snapshot,
! false, limit);
/* Restore UID */
SetUserId(save_uid);
--- 3174,3180 ----
spi_result = SPI_execute_snapshot(qplan,
vals, nulls,
test_snapshot, crosscheck_snapshot,
! false, limit, false);
/* Restore UID */
SetUserId(save_uid);
Index: src/include/executor/spi.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/executor/spi.h,v
retrieving revision 1.52
diff -c -r1.52 spi.h
*** src/include/executor/spi.h 2 May 2005 00:37:06 -0000 1.52
--- src/include/executor/spi.h 24 Aug 2005 03:24:58 -0000
***************
*** 92,98 ****
Datum *Values, const char *Nulls,
Snapshot snapshot,
Snapshot crosscheck_snapshot,
! bool read_only, long tcount);
extern void *SPI_prepare(const char *src, int nargs, Oid *argtypes);
extern void *SPI_saveplan(void *plan);
extern int SPI_freeplan(void *plan);
--- 92,98 ----
Datum *Values, const char *Nulls,
Snapshot snapshot,
Snapshot crosscheck_snapshot,
! bool read_only, long tcount, bool nest_triggers);
extern void *SPI_prepare(const char *src, int nargs, Oid *argtypes);
extern void *SPI_saveplan(void *plan);
extern int SPI_freeplan(void *plan);
Index: src/test/regress/expected/foreign_key.out
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/expected/foreign_key.out,v
retrieving revision 1.39
diff -c -r1.39 foreign_key.out
*** src/test/regress/expected/foreign_key.out 30 May 2005 07:20:59 -0000 1.39
--- src/test/regress/expected/foreign_key.out 24 Aug 2005 03:25:03 -0000
***************
*** 646,652 ****
UPDATE PKTABLE set ptest2=5 where ptest2=2;
ERROR: insert or update on table "fktable" violates foreign key constraint "constrname3"
DETAIL: Key (ftest1,ftest2,ftest3)=(1,-1,3) is not present in table "pktable".
- CONTEXT: SQL statement "UPDATE ONLY "public"."fktable" SET "ftest2" = DEFAULT WHERE "ftest1" = $1 AND "ftest2" = $2 AND "ftest3" = $3"
-- Try to update something that will set default
UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2;
UPDATE PKTABLE set ptest2=10 where ptest2=4;
--- 646,651 ----
***************
*** 1172,1174 ****
--- 1171,1187 ----
COMMIT;
ERROR: insert or update on table "fktable" violates foreign key constraint "fktable_fk_fkey"
DETAIL: Key (fk)=(20) is not present in table "pktable".
+ -- Check to make sure that forcing checks like the above doesn't allow
+ -- us to see intermediate states caused by multiple referential actions
+ -- on the same row.
+ DROP TABLE pktable, fktable CASCADE;
+ NOTICE: drop cascades to constraint fktable_fk_fkey on table fktable
+ CREATE TEMP TABLE pktable(id int PRIMARY KEY);
+ NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable_pkey" for table "pktable"
+ CREATE TEMP TABLE fktable(id1 int REFERENCES pktable ON UPDATE CASCADE,
+ id2 int REFERENCES pktable ON UPDATE CASCADE,
+ id3 int REFERENCES pktable ON UPDATE CASCADE);
+ INSERT INTO pktable VALUES (1);
+ INSERT INTO fktable VALUES (1,1,1);
+ -- This should succeed
+ UPDATE pktable SET id = 2;
Index: src/test/regress/sql/foreign_key.sql
===================================================================
RCS file: /projects/cvsroot/pgsql/src/test/regress/sql/foreign_key.sql,v
retrieving revision 1.16
diff -c -r1.16 foreign_key.sql
*** src/test/regress/sql/foreign_key.sql 30 May 2005 07:20:59 -0000 1.16
--- src/test/regress/sql/foreign_key.sql 24 Aug 2005 03:25:04 -0000
***************
*** 808,810 ****
--- 808,827 ----
-- should catch error from initial INSERT
COMMIT;
+
+
+ -- Check to make sure that forcing checks like the above doesn't allow
+ -- us to see intermediate states caused by multiple referential actions
+ -- on the same row if we update it a bunch of times in a single statement.
+ DROP TABLE pktable, fktable CASCADE;
+ CREATE TEMP TABLE pktable(id int PRIMARY KEY);
+ CREATE TEMP TABLE fktable(id1 int REFERENCES pktable ON UPDATE CASCADE,
+ id2 int REFERENCES pktable ON UPDATE CASCADE,
+ id3 int REFERENCES pktable ON UPDATE CASCADE);
+
+ INSERT INTO pktable VALUES (1);
+ INSERT INTO fktable VALUES (1,1,1);
+
+ -- This should succeed
+ UPDATE pktable SET id = 2;
+