Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb813554

Browse files
committed
Improve documentation of trigger firing queue handling, cleanup.
Neil Conway
1 parent2132ac8 commitb813554

File tree

5 files changed

+307
-169
lines changed

5 files changed

+307
-169
lines changed

‎doc/src/sgml/ref/set_constraints.sgml‎

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_constraints.sgml,v 1.4 2002/06/03 01:10:38 momjian Exp $ -->
1+
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_constraints.sgml,v 1.5 2002/08/17 12:15:48 momjian Exp $ -->
22
<refentry id="SQL-SET-CONSTRAINTS">
33
<refmeta>
44
<refentrytitle id="SQL-SET-CONSTRAINTS-title">SET CONSTRAINTS</refentrytitle>
@@ -22,10 +22,32 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">constraint</replaceable>
2222

2323
<para>
2424
<command>SET CONSTRAINTS</command> sets the behavior of constraint
25-
evaluation in the current transaction. In
26-
<option>IMMEDIATE</option> mode, constraints are checked at the end
27-
of each statement. In <option>DEFERRED</option> mode, constraints
28-
are not checked until transaction commit.
25+
evaluation in the current transaction. In <option>IMMEDIATE
26+
</option> mode, constraints are checked at the end of each
27+
statement. In <option>DEFERRED</option> mode, constraints are not
28+
checked until transaction commit.
29+
</para>
30+
31+
<note>
32+
<para>
33+
This command only alters the behavior of constraints within the
34+
current transaction. Thus, if you execute this command outside
35+
of an explicit transaction block (such as one started with
36+
<command>BEGIN</command>), it will not appear to have any effect.
37+
If you wish to change the behavior of a constraint without needing
38+
to issue a <command>SET CONSTRAINTS</command> command in every
39+
transaction, specify <option>INITIALLY DEFERRED</option> or
40+
<option>INITIALLY IMMEDIATE</option> when you create the constraint.
41+
</para>
42+
</note>
43+
44+
<para>
45+
When you change the mode of a constraint to be <option>IMMEDIATE
46+
</option>, the new constraint mode takes effect retroactively:
47+
any outstanding data modifications that would have been checked
48+
at the end of the transaction (when using
49+
<option>DEFERRED</option>) are instead checked during the
50+
execution of the <command>SET CONSTRAINTS</command> command.
2951
</para>
3052

3153
<para>
@@ -52,7 +74,11 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">constraint</replaceable>
5274

5375
<para>
5476
<command>SET CONSTRAINTS</command> is defined in
55-
<acronym>SQL92</acronym> and <acronym>SQL99</acronym>.
77+
<acronym>SQL92</acronym> and <acronym>SQL99</acronym>. The
78+
implementation in <productname>PostgreSQL</productname> complies
79+
with the behavior defined in the standard, except for the
80+
<productname>PostgreSQL</productname> limitation that <command>SET
81+
CONSTRAINTS</command> cannot be applied to check or unique constraints.
5682
</para>
5783
</refsect2>
5884
</refsect1>

‎src/backend/commands/trigger.c‎

Lines changed: 104 additions & 159 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.125 2002/08/13 17:22:08 petere Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.126 2002/08/17 12:15:48 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1266,12 +1266,10 @@ static MemoryContext deftrig_cxt = NULL;
12661266
* state IMMEDIATE or DEFERRED.
12671267
* ----------
12681268
*/
1269-
staticbooldeftrig_dfl_all_isset= false;
1270-
staticbooldeftrig_dfl_all_isdeferred= false;
12711269
staticList*deftrig_dfl_trigstates=NIL;
12721270

1273-
staticbooldeftrig_all_isset;
1274-
staticbooldeftrig_all_isdeferred;
1271+
staticbooldeftrig_all_isset= false;
1272+
staticbooldeftrig_all_isdeferred= false;
12751273
staticList*deftrig_trigstates;
12761274

12771275
/* ----------
@@ -1702,8 +1700,11 @@ DeferredTriggerBeginXact(void)
17021700
ALLOCSET_DEFAULT_MAXSIZE);
17031701
oldcxt=MemoryContextSwitchTo(deftrig_cxt);
17041702

1705-
deftrig_all_isset=deftrig_dfl_all_isset;
1706-
deftrig_all_isdeferred=deftrig_dfl_all_isdeferred;
1703+
deftrig_all_isset= false;
1704+
/*
1705+
* If unspecified, constraints default to IMMEDIATE, per SQL
1706+
*/
1707+
deftrig_all_isdeferred= false;
17071708

17081709
deftrig_trigstates=NIL;
17091710
foreach(l,deftrig_dfl_trigstates)
@@ -1793,189 +1794,125 @@ DeferredTriggerAbortXact(void)
17931794
/* ----------
17941795
* DeferredTriggerSetState()
17951796
*
1796-
*Called for theusersSET CONSTRAINTS ... utility command.
1797+
*Called for the SET CONSTRAINTS ... utility command.
17971798
* ----------
17981799
*/
17991800
void
18001801
DeferredTriggerSetState(ConstraintsSetStmt*stmt)
18011802
{
1802-
Relationtgrel;
18031803
List*l;
1804-
List*ls;
1805-
List*loid=NIL;
1806-
MemoryContextoldcxt;
1807-
boolfound;
1808-
DeferredTriggerStatusstate;
1804+
1805+
/*
1806+
* If called outside a transaction block, we can safely return: this
1807+
* command cannot effect any subsequent transactions, and there
1808+
* are no "session-level" trigger settings.
1809+
*/
1810+
if (!IsTransactionBlock())
1811+
return;
18091812

18101813
/*
18111814
* Handle SET CONSTRAINTS ALL ...
18121815
*/
18131816
if (stmt->constraints==NIL)
18141817
{
1815-
if (!IsTransactionBlock())
1816-
{
1817-
/*
1818-
* ... outside of a transaction block
1819-
*
1820-
* Drop all information about individual trigger states per
1821-
* session.
1822-
*/
1823-
l=deftrig_dfl_trigstates;
1824-
while (l!=NIL)
1825-
{
1826-
List*next=lnext(l);
1827-
1828-
pfree(lfirst(l));
1829-
pfree(l);
1830-
l=next;
1831-
}
1832-
deftrig_dfl_trigstates=NIL;
1833-
1834-
/*
1835-
* Set the session ALL state to known.
1836-
*/
1837-
deftrig_dfl_all_isset= true;
1838-
deftrig_dfl_all_isdeferred=stmt->deferred;
1839-
1840-
return;
1841-
}
1842-
else
1818+
/*
1819+
* Drop all per-transaction information about individual trigger
1820+
* states.
1821+
*/
1822+
l=deftrig_trigstates;
1823+
while (l!=NIL)
18431824
{
1844-
/*
1845-
* ... inside of a transaction block
1846-
*
1847-
* Drop all information about individual trigger states per
1848-
* transaction.
1849-
*/
1850-
l=deftrig_trigstates;
1851-
while (l!=NIL)
1852-
{
1853-
List*next=lnext(l);
1854-
1855-
pfree(lfirst(l));
1856-
pfree(l);
1857-
l=next;
1858-
}
1859-
deftrig_trigstates=NIL;
1860-
1861-
/*
1862-
* Set the per transaction ALL state to known.
1863-
*/
1864-
deftrig_all_isset= true;
1865-
deftrig_all_isdeferred=stmt->deferred;
1825+
List*next=lnext(l);
18661826

1867-
return;
1827+
pfree(lfirst(l));
1828+
pfree(l);
1829+
l=next;
18681830
}
1869-
}
1870-
1871-
/* ----------
1872-
* Handle SET CONSTRAINTS constraint-name [, ...]
1873-
* First lookup all trigger Oid's for the constraint names.
1874-
* ----------
1875-
*/
1876-
tgrel=heap_openr(TriggerRelationName,AccessShareLock);
1877-
1878-
foreach(l,stmt->constraints)
1879-
{
1880-
char*cname=strVal(lfirst(l));
1881-
ScanKeyDataskey;
1882-
SysScanDesctgscan;
1883-
HeapTuplehtup;
1884-
1885-
/*
1886-
* Check that only named constraints are set explicitly
1887-
*/
1888-
if (strlen(cname)==0)
1889-
elog(ERROR,"unnamed constraints cannot be set explicitly");
1831+
deftrig_trigstates=NIL;
18901832

18911833
/*
1892-
*Setup to scan pg_trigger by tgconstrname ...
1834+
*Set the per-transaction ALL state to known.
18931835
*/
1894-
ScanKeyEntryInitialize(&skey,
1895-
(bits16)0x0,
1896-
(AttrNumber)Anum_pg_trigger_tgconstrname,
1897-
(RegProcedure)F_NAMEEQ,
1898-
PointerGetDatum(cname));
1899-
1900-
tgscan=systable_beginscan(tgrel,TriggerConstrNameIndex, true,
1901-
SnapshotNow,1,&skey);
1902-
1903-
/*
1904-
* ... and search for the constraint trigger row
1836+
deftrig_all_isset= true;
1837+
deftrig_all_isdeferred=stmt->deferred;
1838+
}
1839+
else
1840+
{
1841+
Relationtgrel;
1842+
MemoryContextoldcxt;
1843+
boolfound;
1844+
DeferredTriggerStatusstate;
1845+
List*ls;
1846+
List*loid=NIL;
1847+
1848+
/* ----------
1849+
* Handle SET CONSTRAINTS constraint-name [, ...]
1850+
* First lookup all trigger Oid's for the constraint names.
1851+
* ----------
19051852
*/
1906-
found=false;
1853+
tgrel=heap_openr(TriggerRelationName,AccessShareLock);
19071854

1908-
while (HeapTupleIsValid(htup=systable_getnext(tgscan)))
1855+
foreach(l,stmt->constraints)
19091856
{
1910-
Form_pg_triggerpg_trigger= (Form_pg_trigger)GETSTRUCT(htup);
1911-
Oidconstr_oid;
1857+
char*cname=strVal(lfirst(l));
1858+
ScanKeyDataskey;
1859+
SysScanDesctgscan;
1860+
HeapTuplehtup;
19121861

19131862
/*
1914-
* If we found some, check that they fit the deferrability but
1915-
* skip ON <event> RESTRICT ones, since they are silently
1916-
* never deferrable.
1863+
* Check that only named constraints are set explicitly
19171864
*/
1918-
if (stmt->deferred&& !pg_trigger->tgdeferrable&&
1919-
pg_trigger->tgfoid!=F_RI_FKEY_RESTRICT_UPD&&
1920-
pg_trigger->tgfoid!=F_RI_FKEY_RESTRICT_DEL)
1921-
elog(ERROR,"Constraint '%s' is not deferrable",
1922-
cname);
1923-
1924-
AssertTupleDescHasOid(tgrel->rd_att);
1925-
constr_oid=HeapTupleGetOid(htup);
1926-
loid=lappendi(loid,constr_oid);
1927-
found= true;
1928-
}
1929-
1930-
systable_endscan(tgscan);
1865+
if (strlen(cname)==0)
1866+
elog(ERROR,"unnamed constraints cannot be set explicitly");
19311867

1932-
/*
1933-
*Not found ?
1934-
*/
1935-
if (!found)
1936-
elog(ERROR,"Constraint '%s' does not exist",cname);
1937-
}
1938-
heap_close(tgrel,AccessShareLock);
1868+
/*
1869+
*Setup to scan pg_trigger by tgconstrname ...
1870+
*/
1871+
ScanKeyEntryInitialize(&skey, (bits16)0x0,
1872+
(AttrNumber)Anum_pg_trigger_tgconstrname,
1873+
(RegProcedure)F_NAMEEQ,
1874+
PointerGetDatum(cname));
19391875

1940-
if (!IsTransactionBlock())
1941-
{
1942-
/*
1943-
* Outside of a transaction block set the trigger states of
1944-
* individual triggers on session level.
1945-
*/
1946-
oldcxt=MemoryContextSwitchTo(deftrig_gcxt);
1876+
tgscan=systable_beginscan(tgrel,TriggerConstrNameIndex, true,
1877+
SnapshotNow,1,&skey);
19471878

1948-
foreach(l,loid)
1949-
{
1879+
/*
1880+
* ... and search for the constraint trigger row
1881+
*/
19501882
found= false;
1951-
foreach(ls,deftrig_dfl_trigstates)
1952-
{
1953-
state= (DeferredTriggerStatus)lfirst(ls);
1954-
if (state->dts_tgoid== (Oid)lfirsti(l))
1955-
{
1956-
state->dts_tgisdeferred=stmt->deferred;
1957-
found= true;
1958-
break;
1959-
}
1960-
}
1961-
if (!found)
1883+
1884+
while (HeapTupleIsValid(htup=systable_getnext(tgscan)))
19621885
{
1963-
state= (DeferredTriggerStatus)
1964-
palloc(sizeof(DeferredTriggerStatusData));
1965-
state->dts_tgoid= (Oid)lfirsti(l);
1966-
state->dts_tgisdeferred=stmt->deferred;
1886+
Form_pg_triggerpg_trigger= (Form_pg_trigger)GETSTRUCT(htup);
1887+
Oidconstr_oid;
19671888

1968-
deftrig_dfl_trigstates=
1969-
lappend(deftrig_dfl_trigstates,state);
1889+
/*
1890+
* If we found some, check that they fit the deferrability but
1891+
* skip ON <event> RESTRICT ones, since they are silently
1892+
* never deferrable.
1893+
*/
1894+
if (stmt->deferred&& !pg_trigger->tgdeferrable&&
1895+
pg_trigger->tgfoid!=F_RI_FKEY_RESTRICT_UPD&&
1896+
pg_trigger->tgfoid!=F_RI_FKEY_RESTRICT_DEL)
1897+
elog(ERROR,"Constraint '%s' is not deferrable",
1898+
cname);
1899+
1900+
AssertTupleDescHasOid(tgrel->rd_att);
1901+
constr_oid=HeapTupleGetOid(htup);
1902+
loid=lappendi(loid,constr_oid);
1903+
found= true;
19701904
}
1971-
}
19721905

1973-
MemoryContextSwitchTo(oldcxt);
1906+
systable_endscan(tgscan);
1907+
1908+
/*
1909+
* Not found ?
1910+
*/
1911+
if (!found)
1912+
elog(ERROR,"Constraint '%s' does not exist",cname);
1913+
}
1914+
heap_close(tgrel,AccessShareLock);
19741915

1975-
return;
1976-
}
1977-
else
1978-
{
19791916
/*
19801917
* Inside of a transaction block set the trigger states of
19811918
* individual triggers on transaction level.
@@ -2008,9 +1945,17 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
20081945
}
20091946

20101947
MemoryContextSwitchTo(oldcxt);
2011-
2012-
return;
20131948
}
1949+
1950+
/*
1951+
* SQL99 requires that when a constraint is set to IMMEDIATE, any
1952+
* deferred checks against that constraint must be made when the
1953+
* SET CONSTRAINTS command is executed -- i.e. the effects of the
1954+
* SET CONSTRAINTS command applies retroactively. This happens "for
1955+
* free" since we have already made the necessary modifications to
1956+
* the constraints, and deferredTriggerEndQuery() is called by
1957+
* finish_xact_command().
1958+
*/
20141959
}
20151960

20161961

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp