Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
f14fdad8
Commit
f14fdad8
authored
Nov 12, 2001
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make ALTER TABLE RENAME update foreign-key trigger arguments correctly.
Brent Verner, with review and kibitzing from Tom Lane.
parent
8bfc4373
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
304 additions
and
13 deletions
+304
-13
src/backend/commands/rename.c
src/backend/commands/rename.c
+283
-1
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ri_triggers.c
+1
-11
src/include/commands/trigger.h
src/include/commands/trigger.h
+20
-1
No files found.
src/backend/commands/rename.c
View file @
f14fdad8
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.6
1 2001/11/05 17:46:24 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.6
2 2001/11/12 00:46:36 tgl
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -16,25 +16,43 @@
...
@@ -16,25 +16,43 @@
#include <errno.h>
#include <errno.h>
#include "access/genam.h"
#include "access/heapam.h"
#include "access/heapam.h"
#include "access/itup.h"
#include "catalog/catname.h"
#include "catalog/catname.h"
#include "catalog/pg_index.h"
#include "catalog/pg_index.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
#include "catalog/pg_type.h"
#include "catalog/heap.h"
#include "catalog/heap.h"
#include "catalog/indexing.h"
#include "catalog/indexing.h"
#include "catalog/catalog.h"
#include "catalog/catalog.h"
#include "commands/rename.h"
#include "commands/rename.h"
#include "commands/trigger.h"
#include "miscadmin.h"
#include "miscadmin.h"
#include "storage/smgr.h"
#include "storage/smgr.h"
#include "optimizer/prep.h"
#include "optimizer/prep.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteDefine.h"
#include "rewrite/rewriteSupport.h"
#include "rewrite/rewriteSupport.h"
#include "utils/acl.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/relcache.h"
#include "utils/relcache.h"
#include "utils/syscache.h"
#include "utils/syscache.h"
#include "utils/temprel.h"
#include "utils/temprel.h"
#define RI_TRIGGER_PK 1
/* is a trigger on the PK relation */
#define RI_TRIGGER_FK 2
/* is a trigger on the FK relation */
#define RI_TRIGGER_NONE 0
/* is not an RI trigger function */
static
int
ri_trigger_type
(
Oid
tgfoid
);
static
void
update_ri_trigger_args
(
Oid
relid
,
const
char
*
oldname
,
const
char
*
newname
,
bool
fk_scan
,
bool
update_relname
);
/*
/*
* renameatt - changes the name of a attribute in a relation
* renameatt - changes the name of a attribute in a relation
*
*
...
@@ -226,6 +244,22 @@ renameatt(char *relname,
...
@@ -226,6 +244,22 @@ renameatt(char *relname,
freeList
(
indexoidlist
);
freeList
(
indexoidlist
);
heap_close
(
attrelation
,
RowExclusiveLock
);
heap_close
(
attrelation
,
RowExclusiveLock
);
/*
* Update att name in any RI triggers associated with the relation.
*/
if
(
targetrelation
->
rd_rel
->
reltriggers
>
0
)
{
/* update tgargs column reference where att is primary key */
update_ri_trigger_args
(
RelationGetRelid
(
targetrelation
),
oldattname
,
newattname
,
false
,
false
);
/* update tgargs column reference where att is foreign key */
update_ri_trigger_args
(
RelationGetRelid
(
targetrelation
),
oldattname
,
newattname
,
true
,
false
);
}
heap_close
(
targetrelation
,
NoLock
);
/* close rel but keep lock! */
heap_close
(
targetrelation
,
NoLock
);
/* close rel but keep lock! */
}
}
...
@@ -240,6 +274,7 @@ renamerel(const char *oldrelname, const char *newrelname)
...
@@ -240,6 +274,7 @@ renamerel(const char *oldrelname, const char *newrelname)
HeapTuple
reltup
;
HeapTuple
reltup
;
Oid
reloid
;
Oid
reloid
;
char
relkind
;
char
relkind
;
bool
relhastriggers
;
Relation
irelations
[
Num_pg_class_indices
];
Relation
irelations
[
Num_pg_class_indices
];
if
(
!
allowSystemTableMods
&&
IsSystemRelationName
(
oldrelname
))
if
(
!
allowSystemTableMods
&&
IsSystemRelationName
(
oldrelname
))
...
@@ -265,6 +300,7 @@ renamerel(const char *oldrelname, const char *newrelname)
...
@@ -265,6 +300,7 @@ renamerel(const char *oldrelname, const char *newrelname)
reloid
=
RelationGetRelid
(
targetrelation
);
reloid
=
RelationGetRelid
(
targetrelation
);
relkind
=
targetrelation
->
rd_rel
->
relkind
;
relkind
=
targetrelation
->
rd_rel
->
relkind
;
relhastriggers
=
(
targetrelation
->
rd_rel
->
reltriggers
>
0
);
/*
/*
* Close rel, but keep exclusive lock!
* Close rel, but keep exclusive lock!
...
@@ -331,4 +367,250 @@ renamerel(const char *oldrelname, const char *newrelname)
...
@@ -331,4 +367,250 @@ renamerel(const char *oldrelname, const char *newrelname)
newrulename
=
MakeRetrieveViewRuleName
(
newrelname
);
newrulename
=
MakeRetrieveViewRuleName
(
newrelname
);
RenameRewriteRule
(
oldrulename
,
newrulename
);
RenameRewriteRule
(
oldrulename
,
newrulename
);
}
}
/*
* Update rel name in any RI triggers associated with the relation.
*/
if
(
relhastriggers
)
{
/* update tgargs where relname is primary key */
update_ri_trigger_args
(
reloid
,
oldrelname
,
newrelname
,
false
,
true
);
/* update tgargs where relname is foreign key */
update_ri_trigger_args
(
reloid
,
oldrelname
,
newrelname
,
true
,
true
);
}
}
/*
* Given a trigger function OID, determine whether it is an RI trigger,
* and if so whether it is attached to PK or FK relation.
*
* XXX this probably doesn't belong here; should be exported by
* ri_triggers.c
*/
static
int
ri_trigger_type
(
Oid
tgfoid
)
{
switch
(
tgfoid
)
{
case
F_RI_FKEY_CASCADE_DEL
:
case
F_RI_FKEY_CASCADE_UPD
:
case
F_RI_FKEY_RESTRICT_DEL
:
case
F_RI_FKEY_RESTRICT_UPD
:
case
F_RI_FKEY_SETNULL_DEL
:
case
F_RI_FKEY_SETNULL_UPD
:
case
F_RI_FKEY_SETDEFAULT_DEL
:
case
F_RI_FKEY_SETDEFAULT_UPD
:
case
F_RI_FKEY_NOACTION_DEL
:
case
F_RI_FKEY_NOACTION_UPD
:
return
RI_TRIGGER_PK
;
case
F_RI_FKEY_CHECK_INS
:
case
F_RI_FKEY_CHECK_UPD
:
return
RI_TRIGGER_FK
;
}
return
RI_TRIGGER_NONE
;
}
/*
* Scan pg_trigger for RI triggers that are on the specified relation
* (if fk_scan is false) or have it as the tgconstrrel (if fk_scan
* is true). Update RI trigger args fields matching oldname to contain
* newname instead. If update_relname is true, examine the relname
* fields; otherwise examine the attname fields.
*/
static
void
update_ri_trigger_args
(
Oid
relid
,
const
char
*
oldname
,
const
char
*
newname
,
bool
fk_scan
,
bool
update_relname
)
{
Relation
tgrel
;
Relation
irel
;
ScanKeyData
skey
[
1
];
IndexScanDesc
idxtgscan
;
RetrieveIndexResult
idxres
;
Datum
values
[
Natts_pg_trigger
];
char
nulls
[
Natts_pg_trigger
];
char
replaces
[
Natts_pg_trigger
];
tgrel
=
heap_openr
(
TriggerRelationName
,
RowExclusiveLock
);
if
(
fk_scan
)
irel
=
index_openr
(
TriggerConstrRelidIndex
);
else
irel
=
index_openr
(
TriggerRelidIndex
);
ScanKeyEntryInitialize
(
&
skey
[
0
],
0x0
,
1
,
/* always column 1 of index */
F_OIDEQ
,
ObjectIdGetDatum
(
relid
));
idxtgscan
=
index_beginscan
(
irel
,
false
,
1
,
skey
);
while
((
idxres
=
index_getnext
(
idxtgscan
,
ForwardScanDirection
))
!=
NULL
)
{
HeapTupleData
tupledata
;
Buffer
buffer
;
HeapTuple
tuple
;
Form_pg_trigger
pg_trigger
;
bytea
*
val
;
bytea
*
newtgargs
;
bool
isnull
;
int
tg_type
;
bool
examine_pk
;
bool
changed
;
int
tgnargs
;
int
i
;
int
newlen
;
const
char
*
arga
[
RI_MAX_ARGUMENTS
];
const
char
*
argp
;
tupledata
.
t_self
=
idxres
->
heap_iptr
;
heap_fetch
(
tgrel
,
SnapshotNow
,
&
tupledata
,
&
buffer
,
idxtgscan
);
pfree
(
idxres
);
if
(
!
tupledata
.
t_data
)
continue
;
tuple
=
&
tupledata
;
pg_trigger
=
(
Form_pg_trigger
)
GETSTRUCT
(
tuple
);
tg_type
=
ri_trigger_type
(
pg_trigger
->
tgfoid
);
if
(
tg_type
==
RI_TRIGGER_NONE
)
{
/* Not an RI trigger, forget it */
ReleaseBuffer
(
buffer
);
continue
;
}
/*
* It is an RI trigger, so parse the tgargs bytea.
*
* NB: we assume the field will never be compressed or moved
* out of line; so does trigger.c ...
*/
tgnargs
=
pg_trigger
->
tgnargs
;
val
=
(
bytea
*
)
fastgetattr
(
tuple
,
Anum_pg_trigger_tgargs
,
tgrel
->
rd_att
,
&
isnull
);
if
(
isnull
||
tgnargs
<
RI_FIRST_ATTNAME_ARGNO
||
tgnargs
>
RI_MAX_ARGUMENTS
)
{
/* This probably shouldn't happen, but ignore busted triggers */
ReleaseBuffer
(
buffer
);
continue
;
}
argp
=
(
const
char
*
)
VARDATA
(
val
);
for
(
i
=
0
;
i
<
tgnargs
;
i
++
)
{
arga
[
i
]
=
argp
;
argp
+=
strlen
(
argp
)
+
1
;
}
/*
* Figure out which item(s) to look at. If the trigger is
* primary-key type and attached to my rel, I should look at
* the PK fields; if it is foreign-key type and attached to my
* rel, I should look at the FK fields. But the opposite rule
* holds when examining triggers found by tgconstrrel search.
*/
examine_pk
=
(
tg_type
==
RI_TRIGGER_PK
)
==
(
!
fk_scan
);
changed
=
false
;
if
(
update_relname
)
{
/* Change the relname if needed */
i
=
examine_pk
?
RI_PK_RELNAME_ARGNO
:
RI_FK_RELNAME_ARGNO
;
if
(
strcmp
(
arga
[
i
],
oldname
)
==
0
)
{
arga
[
i
]
=
newname
;
changed
=
true
;
}
}
else
{
/* Change attname(s) if needed */
i
=
examine_pk
?
RI_FIRST_ATTNAME_ARGNO
+
RI_KEYPAIR_PK_IDX
:
RI_FIRST_ATTNAME_ARGNO
+
RI_KEYPAIR_FK_IDX
;
for
(;
i
<
tgnargs
;
i
+=
2
)
{
if
(
strcmp
(
arga
[
i
],
oldname
)
==
0
)
{
arga
[
i
]
=
newname
;
changed
=
true
;
}
}
}
if
(
!
changed
)
{
/* Don't need to update this tuple */
ReleaseBuffer
(
buffer
);
continue
;
}
/*
* Construct modified tgargs bytea.
*/
newlen
=
VARHDRSZ
;
for
(
i
=
0
;
i
<
tgnargs
;
i
++
)
newlen
+=
strlen
(
arga
[
i
])
+
1
;
newtgargs
=
(
bytea
*
)
palloc
(
newlen
);
VARATT_SIZEP
(
newtgargs
)
=
newlen
;
newlen
=
VARHDRSZ
;
for
(
i
=
0
;
i
<
tgnargs
;
i
++
)
{
strcpy
(((
char
*
)
newtgargs
)
+
newlen
,
arga
[
i
]);
newlen
+=
strlen
(
arga
[
i
])
+
1
;
}
/*
* Build modified tuple.
*/
for
(
i
=
0
;
i
<
Natts_pg_trigger
;
i
++
)
{
values
[
i
]
=
(
Datum
)
0
;
replaces
[
i
]
=
' '
;
nulls
[
i
]
=
' '
;
}
values
[
Anum_pg_trigger_tgargs
-
1
]
=
PointerGetDatum
(
newtgargs
);
replaces
[
Anum_pg_trigger_tgargs
-
1
]
=
'r'
;
tuple
=
heap_modifytuple
(
tuple
,
tgrel
,
values
,
nulls
,
replaces
);
/*
* Now we can release hold on original tuple.
*/
ReleaseBuffer
(
buffer
);
/*
* Update pg_trigger and its indexes
*/
simple_heap_update
(
tgrel
,
&
tuple
->
t_self
,
tuple
);
{
Relation
irelations
[
Num_pg_attr_indices
];
CatalogOpenIndices
(
Num_pg_trigger_indices
,
Name_pg_trigger_indices
,
irelations
);
CatalogIndexInsert
(
irelations
,
Num_pg_trigger_indices
,
tgrel
,
tuple
);
CatalogCloseIndices
(
Num_pg_trigger_indices
,
irelations
);
}
/* free up our scratch memory */
pfree
(
newtgargs
);
heap_freetuple
(
tuple
);
}
index_endscan
(
idxtgscan
);
index_close
(
irel
);
heap_close
(
tgrel
,
RowExclusiveLock
);
/*
* Increment cmd counter to make updates visible; this is needed
* in case the same tuple has to be updated again by next pass
* (can happen in case of a self-referential FK relationship).
*/
CommandCounterIncrement
();
}
}
src/backend/utils/adt/ri_triggers.c
View file @
f14fdad8
...
@@ -18,7 +18,7 @@
...
@@ -18,7 +18,7 @@
* Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
* Copyright 1999 Jan Wieck
* Copyright 1999 Jan Wieck
*
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.
29 2001/10/25 05:49:45 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.
30 2001/11/12 00:46:36 tgl
Exp $
*
*
* ----------
* ----------
*/
*/
...
@@ -43,16 +43,6 @@
...
@@ -43,16 +43,6 @@
* Local definitions
* Local definitions
* ----------
* ----------
*/
*/
#define RI_CONSTRAINT_NAME_ARGNO 0
#define RI_FK_RELNAME_ARGNO 1
#define RI_PK_RELNAME_ARGNO 2
#define RI_MATCH_TYPE_ARGNO 3
#define RI_FIRST_ATTNAME_ARGNO 4
#define RI_MAX_NUMKEYS 16
#define RI_MAX_ARGUMENTS (RI_FIRST_ATTNAME_ARGNO + (RI_MAX_NUMKEYS * 2))
#define RI_KEYPAIR_FK_IDX 0
#define RI_KEYPAIR_PK_IDX 1
#define RI_INIT_QUERYHASHSIZE 128
#define RI_INIT_QUERYHASHSIZE 128
#define RI_INIT_OPREQHASHSIZE 128
#define RI_INIT_OPREQHASHSIZE 128
...
...
src/include/commands/trigger.h
View file @
f14fdad8
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* $Id: trigger.h,v 1.3
0 2001/11/05 17:46:33 momjian
Exp $
* $Id: trigger.h,v 1.3
1 2001/11/12 00:46:36 tgl
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -78,6 +78,25 @@ typedef struct TriggerData
...
@@ -78,6 +78,25 @@ typedef struct TriggerData
#define TRIGGER_FIRED_AFTER(event) \
#define TRIGGER_FIRED_AFTER(event) \
(!TRIGGER_FIRED_BEFORE (event))
(!TRIGGER_FIRED_BEFORE (event))
/*
* RI trigger function arguments are stored in pg_trigger.tgargs bytea
*
* constrname\0fkrel\0pkrel\0matchtype\0fkatt\0pkatt\0fkatt\0pkatt\0...
*
* There are one or more pairs of fkatt/pkatt names.
*/
#define RI_CONSTRAINT_NAME_ARGNO 0
#define RI_FK_RELNAME_ARGNO 1
#define RI_PK_RELNAME_ARGNO 2
#define RI_MATCH_TYPE_ARGNO 3
#define RI_FIRST_ATTNAME_ARGNO 4
/* first attname pair starts here */
#define RI_KEYPAIR_FK_IDX 0
#define RI_KEYPAIR_PK_IDX 1
#define RI_MAX_NUMKEYS INDEX_MAX_KEYS
#define RI_MAX_ARGUMENTS (RI_FIRST_ATTNAME_ARGNO + (RI_MAX_NUMKEYS * 2))
extern
void
CreateTrigger
(
CreateTrigStmt
*
stmt
);
extern
void
CreateTrigger
(
CreateTrigStmt
*
stmt
);
extern
void
DropTrigger
(
DropTrigStmt
*
stmt
);
extern
void
DropTrigger
(
DropTrigStmt
*
stmt
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment