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
18952f67
Commit
18952f67
authored
May 29, 2000
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Second round of fmgr changes: triggers are now invoked in new style,
CurrentTriggerData is history.
parent
147ccf5c
Changes
41
Hide whitespace changes
Inline
Side-by-side
Showing
41 changed files
with
658 additions
and
666 deletions
+658
-666
contrib/fulltextindex/README
contrib/fulltextindex/README
+2
-1
contrib/fulltextindex/fti.c
contrib/fulltextindex/fti.c
+22
-24
contrib/fulltextindex/fticopy
contrib/fulltextindex/fticopy
+1
-1
contrib/lo/lo.c
contrib/lo/lo.c
+15
-17
contrib/lo/lo.sql.in
contrib/lo/lo.sql.in
+2
-2
contrib/noupdate/noup.c
contrib/noupdate/noup.c
+20
-26
contrib/noupdate/noup.source
contrib/noupdate/noup.source
+1
-1
contrib/spi/autoinc.c
contrib/spi/autoinc.c
+15
-17
contrib/spi/autoinc.source
contrib/spi/autoinc.source
+1
-1
contrib/spi/insert_username.c
contrib/spi/insert_username.c
+15
-16
contrib/spi/insert_username.source
contrib/spi/insert_username.source
+1
-1
contrib/spi/moddatetime.c
contrib/spi/moddatetime.c
+20
-22
contrib/spi/moddatetime.source
contrib/spi/moddatetime.source
+1
-1
contrib/spi/refint.c
contrib/spi/refint.c
+36
-48
contrib/spi/refint.source
contrib/spi/refint.source
+2
-2
contrib/spi/timetravel.c
contrib/spi/timetravel.c
+30
-35
contrib/spi/timetravel.source
contrib/spi/timetravel.source
+2
-2
doc/src/sgml/ref/create_language.sgml
doc/src/sgml/ref/create_language.sgml
+58
-44
doc/src/sgml/trigger.sgml
doc/src/sgml/trigger.sgml
+59
-23
src/backend/commands/command.c
src/backend/commands/command.c
+15
-10
src/backend/commands/trigger.c
src/backend/commands/trigger.c
+78
-67
src/backend/commands/user.c
src/backend/commands/user.c
+4
-10
src/backend/executor/execMain.c
src/backend/executor/execMain.c
+2
-5
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ri_triggers.c
+130
-156
src/backend/utils/adt/tid.c
src/backend/utils/adt/tid.c
+3
-1
src/backend/utils/adt/timestamp.c
src/backend/utils/adt/timestamp.c
+6
-4
src/backend/utils/fmgr/fmgr.c
src/backend/utils/fmgr/fmgr.c
+1
-2
src/include/catalog/catversion.h
src/include/catalog/catversion.h
+2
-2
src/include/catalog/pg_proc.h
src/include/catalog/pg_proc.h
+14
-14
src/include/commands/trigger.h
src/include/commands/trigger.h
+13
-4
src/include/commands/user.h
src/include/commands/user.h
+2
-2
src/include/executor/executor.h
src/include/executor/executor.h
+3
-1
src/include/fmgr.h
src/include/fmgr.h
+3
-1
src/include/nodes/nodes.h
src/include/nodes/nodes.h
+8
-2
src/include/utils/builtins.h
src/include/utils/builtins.h
+14
-23
src/pl/plperl/plperl.c
src/pl/plperl/plperl.c
+6
-12
src/pl/plpgsql/src/pl_handler.c
src/pl/plpgsql/src/pl_handler.c
+4
-14
src/pl/tcl/pltcl.c
src/pl/tcl/pltcl.c
+5
-11
src/test/regress/input/create_function_1.source
src/test/regress/input/create_function_1.source
+5
-5
src/test/regress/output/create_function_1.source
src/test/regress/output/create_function_1.source
+5
-5
src/test/regress/regress.c
src/test/regress/regress.c
+32
-31
No files found.
contrib/fulltextindex/README
View file @
18952f67
...
...
@@ -56,7 +56,8 @@ sub-string will fit.
The create the function that contains the trigger::
create function fti() returns opaque as '/path/to/fti.so' language 'C';
create function fti() returns opaque as
'/path/to/fti.so' language 'newC';
And finally define the trigger on the 'cds' table:
...
...
contrib/fulltextindex/fti.c
View file @
18952f67
...
...
@@ -17,7 +17,7 @@
Example:
create function fti() returns opaque as
'/home/boekhold/src/postgresql-6.2/contrib/fti/fti.so' language '
c
';
'/home/boekhold/src/postgresql-6.2/contrib/fti/fti.so' language '
newC
';
create table title_fti (string varchar(25), id oid);
create index title_fti_idx on title_fti (string);
...
...
@@ -61,11 +61,11 @@ select p.* from product p, title_fti f1, title_fti f2 where
that can build the final query automatigally?
*/
HeapTuple
fti
(
void
);
char
*
breakup
(
char
*
,
char
*
);
bool
is_stopword
(
char
*
);
extern
Datum
fti
(
PG_FUNCTION_ARGS
);
static
char
*
breakup
(
char
*
,
char
*
);
static
bool
is_stopword
(
char
*
);
bool
new_tuple
=
false
;
static
bool
new_tuple
=
false
;
/* THIS LIST MUST BE IN SORTED ORDER, A BINARY SEARCH IS USED!!!! */
...
...
@@ -93,9 +93,10 @@ static int nDeletePlans = 0;
static
EPlan
*
find_plan
(
char
*
ident
,
EPlan
**
eplan
,
int
*
nplans
);
/***********************************************************************/
HeapTuple
fti
()
Datum
fti
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of arguments */
char
**
args
;
/* arguments */
...
...
@@ -119,32 +120,29 @@ fti()
* function\n"); fflush(debug);
*/
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"Full Text Indexing:
triggers are not initialized
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"Full Text Indexing:
not fired by trigger manager
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"Full Text Indexing: can't process STATEMENT events"
);
if
(
TRIGGER_FIRED_BEFORE
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BEFORE
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"Full Text Indexing: must be fired AFTER event"
);
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
isinsert
=
true
;
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
{
isdelete
=
true
;
isinsert
=
true
;
}
if
(
TRIGGER_FIRED_BY_DELETE
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_DELETE
(
trigd
ata
->
tg_event
))
isdelete
=
true
;
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
rel
=
CurrentTriggerD
ata
->
tg_relation
;
trigger
=
trigd
ata
->
tg_trigger
;
rel
=
trigd
ata
->
tg_relation
;
relname
=
SPI_getrelname
(
rel
);
rettuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
rettuple
=
trigd
ata
->
tg_trigtuple
;
if
(
isdelete
&&
isinsert
)
/* is an UPDATE */
rettuple
=
CurrentTriggerData
->
tg_newtuple
;
CurrentTriggerData
=
NULL
;
/* invalidate 'normal' calls to this
* function */
rettuple
=
trigdata
->
tg_newtuple
;
if
((
ret
=
SPI_connect
())
<
0
)
elog
(
ERROR
,
"Full Text Indexing: SPI_connect failed, returned %d
\n
"
,
ret
);
...
...
@@ -289,10 +287,10 @@ fti()
}
SPI_finish
();
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
char
*
static
char
*
breakup
(
char
*
string
,
char
*
substring
)
{
static
char
*
last_start
;
...
...
@@ -342,7 +340,7 @@ breakup(char *string, char *substring)
}
/* copied from src/backend/parser/keywords.c and adjusted for our situation*/
bool
static
bool
is_stopword
(
char
*
text
)
{
char
**
StopLow
;
/* for list of stop-words */
...
...
contrib/fulltextindex/fticopy
View file @
18952f67
...
...
@@ -29,7 +29,7 @@
#
# create function fti() returns opaque as
# '/path/to/fti/file/fti.so'
# language 'C';
# language '
new
C';
#
# create trigger my_fti_trigger after update or insert or delete
# on mytable
...
...
contrib/lo/lo.c
View file @
18952f67
/*
* PostgreSQL type definitions for managed LargeObjects.
*
* $Id: lo.c,v 1.
2 1999/05/25 16:05:45 momjian
Exp $
* $Id: lo.c,v 1.
3 2000/05/29 01:59:02 tgl
Exp $
*
*/
...
...
@@ -37,7 +37,7 @@ Blob *lo_in(char *str); /* Create from String */
char
*
lo_out
(
Blob
*
addr
);
/* Output oid as String */
Oid
lo_oid
(
Blob
*
addr
);
/* Return oid as an oid */
Blob
*
lo
(
Oid
oid
);
/* Return Blob based on oid */
HeapTuple
lo_manage
(
void
);
/* Trigger handler */
Datum
lo_manage
(
PG_FUNCTION_ARGS
);
/* Trigger handler */
/*
* This creates a large object, and set's its OID to the value in the
...
...
@@ -139,9 +139,10 @@ lo(Oid oid)
/*
* This handles the trigger that protects us from orphaned large objects
*/
HeapTuple
lo_manage
(
void
)
Datum
lo_manage
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
attnum
;
/* attribute number to monitor */
char
**
args
;
/* Args containing attr name */
TupleDesc
tupdesc
;
/* Tuple Descriptor */
...
...
@@ -150,28 +151,25 @@ lo_manage(void)
HeapTuple
newtuple
=
NULL
;
/* The new value for tuple */
HeapTuple
trigtuple
;
/* The original value of tuple */
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"lo:
triggers are not initialized
"
);
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"lo:
not fired by trigger manager
"
);
/*
* Fetch some values from
CurrentTriggerD
ata
* Fetch some values from
trigd
ata
*/
newtuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
trigtuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
tupdesc
=
CurrentTriggerD
ata
->
tg_relation
->
rd_att
;
args
=
CurrentTriggerD
ata
->
tg_trigger
->
tgargs
;
newtuple
=
trigd
ata
->
tg_newtuple
;
trigtuple
=
trigd
ata
->
tg_trigtuple
;
tupdesc
=
trigd
ata
->
tg_relation
->
rd_att
;
args
=
trigd
ata
->
tg_trigger
->
tgargs
;
/* tuple to return to Executor */
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
rettuple
=
newtuple
;
else
rettuple
=
trigtuple
;
/* Are we deleting the row? */
isdelete
=
TRIGGER_FIRED_BY_DELETE
(
CurrentTriggerData
->
tg_event
);
/* Were done with it */
CurrentTriggerData
=
NULL
;
isdelete
=
TRIGGER_FIRED_BY_DELETE
(
trigdata
->
tg_event
);
/* Get the column were interested in */
attnum
=
SPI_fnumber
(
tupdesc
,
args
[
0
]);
...
...
@@ -214,5 +212,5 @@ lo_manage(void)
}
}
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
contrib/lo/lo.sql.in
View file @
18952f67
--
-- PostgreSQL code for LargeObjects
--
-- $Id: lo.sql.in,v 1.
1 1998/06/16 07:07:11 momjian
Exp $
-- $Id: lo.sql.in,v 1.
2 2000/05/29 01:59:02 tgl
Exp $
--
load '_OBJWD_/lo_DLSUFFIX_';
...
...
@@ -47,7 +47,7 @@ create function lo(oid)
create function lo_manage()
returns opaque
as '_OBJWD_/lo_DLSUFFIX_'
language '
c
';
language '
newC
';
-- This allows us to map lo to oid
--
...
...
contrib/noupdate/noup.c
View file @
18952f67
...
...
@@ -6,7 +6,7 @@
#include "commands/trigger.h"
/* -"- and triggers */
#include <ctype.h>
/* tolower () */
HeapTuple
noup
(
void
);
extern
Datum
noup
(
PG_FUNCTION_ARGS
);
/*
* noup () -- revoke permission on column
...
...
@@ -16,9 +16,10 @@ HeapTuple noup(void);
* EXECUTE PROCEDURE noup ('col').
*/
HeapTuple
/* have to return HeapTuple to Executor */
noup
()
Datum
noup
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of args specified in CREATE TRIGGER */
char
**
args
;
/* arguments: column names and table name */
...
...
@@ -36,42 +37,35 @@ noup()
*/
/* Called by trigger manager ? */
if
(
!
C
urrentTriggerData
)
elog
(
WARN
,
"noup: triggers are not initialized
"
);
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"noup: not fired by trigger manager
"
);
/* Should be called for ROW trigger */
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
elog
(
WARN
,
"noup: can't process STATEMENT events"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"noup: can't process STATEMENT events"
);
/* Not should be called for INSERT */
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
elog
(
WARN
,
"noup: can't process INSERT events"
);
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"noup: can't process INSERT events"
);
/* Not should be called for DELETE */
else
if
(
TRIGGER_FIRED_BY_DELETE
(
CurrentTriggerD
ata
->
tg_event
))
elog
(
WARN
,
"noup: can't process DELETE events"
);
else
if
(
TRIGGER_FIRED_BY_DELETE
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"noup: can't process DELETE events"
);
/* check new Tuple */
tuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
tuple
=
trigd
ata
->
tg_newtuple
;
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
nargs
=
trigger
->
tgnargs
;
args
=
trigger
->
tgargs
;
nkeys
=
nargs
;
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
tupdesc
=
rel
->
rd_att
;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData
=
NULL
;
/* Connect to SPI manager */
if
((
ret
=
SPI_connect
())
<
0
)
elog
(
WARN
,
"noup: SPI_connect returned %d"
,
ret
);
elog
(
ERROR
,
"noup: SPI_connect returned %d"
,
ret
);
/*
* We use SPI plan preparation feature, so allocate space to place key
...
...
@@ -87,7 +81,7 @@ noup()
/* Bad guys may give us un-existing column in CREATE TRIGGER */
if
(
fnumber
<
0
)
elog
(
WARN
,
"noup: there is no attribute %s in relation %s"
,
elog
(
ERROR
,
"noup: there is no attribute %s in relation %s"
,
args
[
i
],
SPI_getrelname
(
rel
));
/* Well, get binary (in internal format) value of column */
...
...
@@ -99,13 +93,13 @@ noup()
if
(
!
isnull
)
{
elog
(
WARN
,
"%s: update not allowed"
,
args
[
i
]);
elog
(
NOTICE
,
"%s: update not allowed"
,
args
[
i
]);
SPI_finish
();
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
}
SPI_finish
();
return
(
tuple
);
return
PointerGetDatum
(
tuple
);
}
contrib/noupdate/noup.source
View file @
18952f67
...
...
@@ -3,5 +3,5 @@ DROP FUNCTION noup ();
CREATE FUNCTION noup ()
RETURNS opaque
AS '_OBJWD_/noup_DLSUFFIX_'
LANGUAGE '
c
'
LANGUAGE '
newC
'
;
contrib/spi/autoinc.c
View file @
18952f67
...
...
@@ -2,13 +2,13 @@
#include "executor/spi.h"
/* this is what you need to work with SPI */
#include "commands/trigger.h"
/* -"- and triggers */
HeapTuple
autoinc
(
void
);
extern
Datum
autoinc
(
PG_FUNCTION_ARGS
);
extern
int4
nextval
(
struct
varlena
*
seqin
);
HeapTuple
autoinc
()
Datum
autoinc
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of arguments */
int
*
chattrs
;
/* attnums of attributes to change */
...
...
@@ -22,24 +22,24 @@ autoinc()
bool
isnull
;
int
i
;
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"autoinc:
triggers are not initialized
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"autoinc:
not fired by trigger manager
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"autoinc: can't process STATEMENT events"
);
if
(
TRIGGER_FIRED_AFTER
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_AFTER
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"autoinc: must be fired before event"
);
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
rettuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
else
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
rettuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
rettuple
=
trigd
ata
->
tg_trigtuple
;
else
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
rettuple
=
trigd
ata
->
tg_newtuple
;
else
elog
(
ERROR
,
"autoinc: can't process DELETE events"
);
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
relname
=
SPI_getrelname
(
rel
);
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
nargs
=
trigger
->
tgnargs
;
if
(
nargs
<=
0
||
nargs
%
2
!=
0
)
...
...
@@ -48,8 +48,6 @@ autoinc()
args
=
trigger
->
tgargs
;
tupdesc
=
rel
->
rd_att
;
CurrentTriggerData
=
NULL
;
chattrs
=
(
int
*
)
palloc
(
nargs
/
2
*
sizeof
(
int
));
newvals
=
(
Datum
*
)
palloc
(
nargs
/
2
*
sizeof
(
Datum
));
...
...
@@ -96,5 +94,5 @@ autoinc()
pfree
(
chattrs
);
pfree
(
newvals
);
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
contrib/spi/autoinc.source
View file @
18952f67
...
...
@@ -3,4 +3,4 @@ DROP FUNCTION autoinc();
CREATE FUNCTION autoinc()
RETURNS opaque
AS '_OBJWD_/autoinc_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
contrib/spi/insert_username.c
View file @
18952f67
...
...
@@ -10,11 +10,12 @@
#include "commands/trigger.h"
/* -"- and triggers */
#include "miscadmin.h"
/* for GetPgUserName() */
HeapTuple
insert_username
(
void
);
extern
Datum
insert_username
(
PG_FUNCTION_ARGS
);
HeapTuple
insert_username
()
Datum
insert_username
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of arguments */
Datum
newval
;
/* new value of column */
...
...
@@ -26,24 +27,24 @@ insert_username()
int
attnum
;
/* sanity checks from autoinc.c */
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"insert_username:
triggers are not initialized
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"insert_username:
not fired by trigger manager
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"insert_username: can't process STATEMENT events"
);
if
(
TRIGGER_FIRED_AFTER
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_AFTER
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"insert_username: must be fired before event"
);
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
rettuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
else
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
rettuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
rettuple
=
trigd
ata
->
tg_trigtuple
;
else
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
rettuple
=
trigd
ata
->
tg_newtuple
;
else
elog
(
ERROR
,
"insert_username: can't process DELETE events"
);
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
relname
=
SPI_getrelname
(
rel
);
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
nargs
=
trigger
->
tgnargs
;
if
(
nargs
!=
1
)
...
...
@@ -52,8 +53,6 @@ insert_username()
args
=
trigger
->
tgargs
;
tupdesc
=
rel
->
rd_att
;
CurrentTriggerData
=
NULL
;
attnum
=
SPI_fnumber
(
tupdesc
,
args
[
0
]);
if
(
attnum
<
0
)
...
...
@@ -73,5 +72,5 @@ insert_username()
pfree
(
relname
);
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
contrib/spi/insert_username.source
View file @
18952f67
...
...
@@ -3,4 +3,4 @@ DROP FUNCTION insert_username();
CREATE FUNCTION insert_username()
RETURNS opaque
AS '_OBJWD_/insert_username_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
contrib/spi/moddatetime.c
View file @
18952f67
...
...
@@ -8,18 +8,19 @@ a modification datetime stamp in a record when that record is UPDATEd.
Credits
This is 95%+ based on autoinc.c, which I used as a starting point as I do
not really know what I am doing. I also had help from
Jan Wieck <jwieck@debis.com> who told me about the
datetime
_in("now") function.
Jan Wieck <jwieck@debis.com> who told me about the
timestamp
_in("now") function.
OH, me, I'm Terry Mackintosh <terry@terrym.com>
*/
#include "executor/spi.h"
/* this is what you need to work with SPI */
#include "commands/trigger.h"
/* -"- and triggers */
HeapTuple
moddatetime
(
void
);
extern
Datum
moddatetime
(
PG_FUNCTION_ARGS
);
HeapTuple
moddatetime
()
Datum
moddatetime
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of arguments */
int
attnum
;
/* positional number of field to change */
...
...
@@ -30,26 +31,26 @@ moddatetime()
HeapTuple
rettuple
=
NULL
;
TupleDesc
tupdesc
;
/* tuple description */
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"moddatetime:
triggers are not initialized
."
);
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"moddatetime:
not fired by trigger manager
."
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"moddatetime: can't process STATEMENT events."
);
if
(
TRIGGER_FIRED_AFTER
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_AFTER
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"moddatetime: must be fired before event."
);
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"moddatetime: must be fired before event."
);
else
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
rettuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
else
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
rettuple
=
trigd
ata
->
tg_newtuple
;
else
elog
(
ERROR
,
"moddatetime: can't process DELETE events."
);
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
relname
=
SPI_getrelname
(
rel
);
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
nargs
=
trigger
->
tgnargs
;
...
...
@@ -60,11 +61,8 @@ moddatetime()
/* must be the field layout? */
tupdesc
=
rel
->
rd_att
;
/* Why do this? */
CurrentTriggerData
=
NULL
;
/* Get the current datetime. */
newdt
=
datetime
_in
(
"now"
);
newdt
=
(
Datum
)
timestamp
_in
(
"now"
);
/*
* This gets the position in the turple of the field we want. args[0]
...
...
@@ -82,12 +80,12 @@ moddatetime()
args
[
0
]);
/*
* OK, this is where we make sure the
datetime
field that we are
* modifying is really a
datetime
field. Hay, error checking, what a
* OK, this is where we make sure the
timestamp
field that we are
* modifying is really a
timestamp
field. Hay, error checking, what a
* novel idea !-)
*/
if
(
SPI_gettypeid
(
tupdesc
,
attnum
)
!=
DATETIME
OID
)
elog
(
ERROR
,
"moddatetime (%s): attribute %s must be of
DATETIME
type"
,
if
(
SPI_gettypeid
(
tupdesc
,
attnum
)
!=
TIMESTAMP
OID
)
elog
(
ERROR
,
"moddatetime (%s): attribute %s must be of
TIMESTAMP
type"
,
relname
,
args
[
0
]);
/* 1 is the number of items in the arrays attnum and newdt.
...
...
@@ -106,5 +104,5 @@ moddatetime()
/* Clean up */
pfree
(
relname
);
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
contrib/spi/moddatetime.source
View file @
18952f67
...
...
@@ -3,4 +3,4 @@ DROP FUNCTION moddatetime();
CREATE FUNCTION moddatetime()
RETURNS opaque
AS '_OBJWD_/moddatetime_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
contrib/spi/refint.c
View file @
18952f67
...
...
@@ -8,10 +8,8 @@
#include <ctype.h>
/* tolower () */
HeapTuple
check_primary_key
(
void
);
HeapTuple
check_foreign_key
(
void
);
extern
Datum
check_primary_key
(
PG_FUNCTION_ARGS
);
extern
Datum
check_foreign_key
(
PG_FUNCTION_ARGS
);
typedef
struct
...
...
@@ -38,9 +36,10 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
* check_primary_key ('Fkey1', 'Fkey2', 'Ptable', 'Pkey1', 'Pkey2').
*/
HeapTuple
/* have to return HeapTuple to Executor */
check_primary_key
()
Datum
check_primary_key
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of args specified in CREATE TRIGGER */
char
**
args
;
/* arguments: column names and table name */
...
...
@@ -57,33 +56,35 @@ check_primary_key()
int
ret
;
int
i
;
/*
* Some checks first...
*/
#ifdef DEBUG_QUERY
elog
(
NOTICE
,
"Check_primary_key Enter Function"
);
#endif
/*
* Some checks first...
*/
/* Called by trigger manager ? */
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"check_primary_key:
triggers are not initialized
"
);
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"check_primary_key:
not fired by trigger manager
"
);
/* Should be called for ROW trigger */
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"check_primary_key: can't process STATEMENT events"
);
/* If INSERTion then must check Tuple to being inserted */
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
tuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
tuple
=
trigd
ata
->
tg_trigtuple
;
/* Not should be called for DELETE */
else
if
(
TRIGGER_FIRED_BY_DELETE
(
CurrentTriggerD
ata
->
tg_event
))
else
if
(
TRIGGER_FIRED_BY_DELETE
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"check_primary_key: can't process DELETE events"
);
/* If UPDATion the must check new Tuple, not old one */
else
tuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
tuple
=
trigd
ata
->
tg_newtuple
;
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
nargs
=
trigger
->
tgnargs
;
args
=
trigger
->
tgargs
;
...
...
@@ -92,16 +93,9 @@ check_primary_key()
nkeys
=
nargs
/
2
;
relname
=
args
[
nkeys
];
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
tupdesc
=
rel
->
rd_att
;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData
=
NULL
;
/* Connect to SPI manager */
if
((
ret
=
SPI_connect
())
<
0
)
elog
(
ERROR
,
"check_primary_key: SPI_connect returned %d"
,
ret
);
...
...
@@ -145,7 +139,7 @@ check_primary_key()
if
(
isnull
)
{
SPI_finish
();
return
(
tuple
);
return
PointerGetDatum
(
tuple
);
}
if
(
plan
->
nplans
<=
0
)
/* Get typeId of column */
...
...
@@ -207,7 +201,7 @@ check_primary_key()
SPI_finish
();
return
(
tuple
);
return
PointerGetDatum
(
tuple
);
}
/*
...
...
@@ -222,9 +216,10 @@ check_primary_key()
* 'Ftable1', 'Fkey11', 'Fkey12', 'Ftable2', 'Fkey21', 'Fkey22').
*/
HeapTuple
/* have to return HeapTuple to Executor */
check_foreign_key
()
Datum
check_foreign_key
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
int
nargs
;
/* # of args specified in CREATE TRIGGER */
char
**
args
;
/* arguments: as described above */
...
...
@@ -258,19 +253,19 @@ check_foreign_key()
*/
/* Called by trigger manager ? */
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"check_foreign_key:
triggers are not initialized
"
);
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"check_foreign_key:
not fired by trigger manager
"
);
/* Should be called for ROW trigger */
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"check_foreign_key: can't process STATEMENT events"
);
/* Not should be called for INSERT */
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"check_foreign_key: can't process INSERT events"
);
/* Have to check tg_trigtuple - tuple being deleted */
trigtuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
trigtuple
=
trigd
ata
->
tg_trigtuple
;
/*
* But if this is UPDATE then we have to return tg_newtuple. Also, if
...
...
@@ -278,12 +273,12 @@ check_foreign_key()
* do.
*/
is_update
=
0
;
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
{
newtuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
newtuple
=
trigd
ata
->
tg_newtuple
;
is_update
=
1
;
}
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
nargs
=
trigger
->
tgnargs
;
args
=
trigger
->
tgargs
;
...
...
@@ -304,16 +299,9 @@ check_foreign_key()
elog
(
ERROR
,
"check_foreign_key: invalid number of arguments %d for %d references"
,
nargs
+
2
,
nrefs
);
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
tupdesc
=
rel
->
rd_att
;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData
=
NULL
;
/* Connect to SPI manager */
if
((
ret
=
SPI_connect
())
<
0
)
elog
(
ERROR
,
"check_foreign_key: SPI_connect returned %d"
,
ret
);
...
...
@@ -364,7 +352,7 @@ check_foreign_key()
if
(
isnull
)
{
SPI_finish
();
return
((
newtuple
==
NULL
)
?
trigtuple
:
newtuple
);
return
PointerGetDatum
((
newtuple
==
NULL
)
?
trigtuple
:
newtuple
);
}
/*
...
...
@@ -527,7 +515,7 @@ check_foreign_key()
if
(
newtuple
!=
NULL
&&
isequal
)
{
SPI_finish
();
return
(
newtuple
);
return
PointerGetDatum
(
newtuple
);
}
/*
...
...
@@ -571,7 +559,7 @@ check_foreign_key()
SPI_finish
();
return
((
newtuple
==
NULL
)
?
trigtuple
:
newtuple
);
return
PointerGetDatum
((
newtuple
==
NULL
)
?
trigtuple
:
newtuple
);
}
static
EPlan
*
...
...
contrib/spi/refint.source
View file @
18952f67
...
...
@@ -4,11 +4,11 @@ DROP FUNCTION check_foreign_key ();
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/refint_DLSUFFIX_'
LANGUAGE '
c
'
LANGUAGE '
newC
'
;
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/refint_DLSUFFIX_'
LANGUAGE '
c
'
LANGUAGE '
newC
'
;
contrib/spi/timetravel.c
View file @
18952f67
...
...
@@ -10,8 +10,8 @@
#define ABSTIMEOID 702
/* it should be in pg_type.h */
AbsoluteTime
currabstime
(
void
);
HeapTuple
timetravel
(
void
);
int32
set_timetravel
(
Name
relname
,
int32
on
);
Datum
timetravel
(
PG_FUNCTION_ARGS
);
Datum
set_timetravel
(
PG_FUNCTION_ARGS
);
typedef
struct
{
...
...
@@ -47,9 +47,10 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
* timetravel ('date_on', 'date_off').
*/
HeapTuple
/* have to return HeapTuple to Executor */
timetravel
()
Datum
timetravel
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
char
**
args
;
/* arguments */
int
attnum
[
2
];
/* fnumbers of start/stop columns */
...
...
@@ -78,27 +79,27 @@ timetravel()
*/
/* Called by trigger manager ? */
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"timetravel:
triggers are not initialized
"
);
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"timetravel:
not fired by trigger manager
"
);
/* Should be called for ROW trigger */
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"timetravel: can't process STATEMENT events"
);
/* Should be called BEFORE */
if
(
TRIGGER_FIRED_AFTER
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_AFTER
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"timetravel: must be fired before event"
);
/* INSERT ? */
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
isinsert
=
true
;
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
newtuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
newtuple
=
trigd
ata
->
tg_newtuple
;
trigtuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
trigtuple
=
trigd
ata
->
tg_trigtuple
;
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
relname
=
SPI_getrelname
(
rel
);
/* check if TT is OFF for this relation */
...
...
@@ -108,10 +109,10 @@ timetravel()
if
(
i
<
nTTOff
)
/* OFF - nothing to do */
{
pfree
(
relname
);
return
((
newtuple
!=
NULL
)
?
newtuple
:
trigtuple
);
return
PointerGetDatum
((
newtuple
!=
NULL
)
?
newtuple
:
trigtuple
);
}
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
if
(
trigger
->
tgnargs
!=
2
)
elog
(
ERROR
,
"timetravel (%s): invalid (!= 2) number of arguments %d"
,
...
...
@@ -121,13 +122,6 @@ timetravel()
tupdesc
=
rel
->
rd_att
;
natts
=
tupdesc
->
natts
;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData
=
NULL
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
attnum
[
i
]
=
SPI_fnumber
(
tupdesc
,
args
[
i
]);
...
...
@@ -175,11 +169,11 @@ timetravel()
pfree
(
relname
);
if
(
chnattrs
<=
0
)
return
(
trigtuple
);
return
PointerGetDatum
(
trigtuple
);
rettuple
=
SPI_modifytuple
(
rel
,
trigtuple
,
chnattrs
,
chattrs
,
newvals
,
NULL
);
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
oldon
=
SPI_getbinval
(
trigtuple
,
tupdesc
,
attnum
[
0
],
&
isnull
);
...
...
@@ -210,13 +204,13 @@ timetravel()
if
(
newoff
!=
NOEND_ABSTIME
)
{
pfree
(
relname
);
/* allocated in upper executor context */
return
(
NULL
);
return
PointerGetDatum
(
NULL
);
}
}
else
if
(
oldoff
!=
NOEND_ABSTIME
)
/* DELETE */
{
pfree
(
relname
);
return
(
NULL
);
return
PointerGetDatum
(
NULL
);
}
newoff
=
GetCurrentAbsoluteTime
();
...
...
@@ -325,16 +319,18 @@ timetravel()
pfree
(
relname
);
return
(
rettuple
);
return
PointerGetDatum
(
rettuple
);
}
/*
* set_timetravel () --
* set_timetravel (
relname, on
) --
* turn timetravel for specified relation ON/OFF
*/
int32
set_timetravel
(
Name
relname
,
int32
on
)
Datum
set_timetravel
(
PG_FUNCTION_ARGS
)
{
Name
relname
=
PG_GETARG_NAME
(
0
);
int32
on
=
PG_GETARG_INT32
(
1
);
char
*
rname
;
char
*
d
;
char
*
s
;
...
...
@@ -347,7 +343,7 @@ set_timetravel(Name relname, int32 on)
if
(
i
<
nTTOff
)
/* OFF currently */
{
if
(
on
==
0
)
return
(
0
);
PG_RETURN_INT32
(
0
);
/* turn ON */
free
(
TTOff
[
i
]);
...
...
@@ -360,12 +356,12 @@ set_timetravel(Name relname, int32 on)
TTOff
=
realloc
(
TTOff
,
(
nTTOff
-
1
)
*
sizeof
(
char
*
));
}
nTTOff
--
;
return
(
0
);
PG_RETURN_INT32
(
0
);
}
/* ON currently */
if
(
on
!=
0
)
return
(
1
);
PG_RETURN_INT32
(
1
);
/* turn OFF */
if
(
nTTOff
==
0
)
...
...
@@ -380,8 +376,7 @@ set_timetravel(Name relname, int32 on)
pfree
(
rname
);
nTTOff
++
;
return
(
1
);
PG_RETURN_INT32
(
1
);
}
AbsoluteTime
...
...
contrib/spi/timetravel.source
View file @
18952f67
...
...
@@ -4,9 +4,9 @@ DROP FUNCTION set_timetravel(name, int4);
CREATE FUNCTION timetravel()
RETURNS opaque
AS '_OBJWD_/timetravel_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION set_timetravel(name, int4)
RETURNS int4
AS '_OBJWD_/timetravel_DLSUFFIX_'
LANGUAGE '
c'
;
LANGUAGE '
newC' WITH (isStrict)
;
doc/src/sgml/ref/create_language.sgml
View file @
18952f67
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.
9 2000/03/26 18:32:27 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.
10 2000/05/29 01:59:06 tgl
Exp $
Postgres documentation
-->
...
...
@@ -160,44 +160,42 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
<title>
Writing PL handlers
</title>
<note>
<para>
In <productname>Postgres</productname> 7.1 and later, call handlers
must adhere to the "new style" function manager interface.
</para>
</note>
<para>
The call handler for a procedural language must be written
in a compile
r
language such as 'C' and registered with
in a compile
d
language such as 'C' and registered with
<productname>Postgres</productname> as a function taking
no arguments and returning the
<type>opaque</type> type, a placeholder for unspecified or undefined types.
.
<type>opaque</type> type, a placeholder for unspecified or undefined types.
This prevents the call handler from being
called directly as a function from queries.
(However, arguments may be supplied in the actual call when a
PL function in the language offered by the handler is to be executed.)
</para>
<para>
However, arguments must be supplied on the actual call when a
PL function or trigger
procedure in the language offered by the handler is to be
executed.
<itemizedlist>
<listitem>
<para>
When called from the trigger manager, the only argument is
the object ID from the procedure's <filename>pg_proc</filename>
entry. All other
information from the trigger manager is found in the
global <structname>CurrentTriggerData</structname> pointer.
</para>
</listitem>
<listitem>
<para>
When called from the function manager, the arguments are
the object ID of the procedure's <filename>pg_proc</filename>
entry, the number
of arguments given to the PL function, the arguments in a
<structname>FmgrValues</structname> structure and a pointer
to a boolean where the
function tells the caller if the return value is the SQL
NULL value.
</para>
</listitem>
</itemizedlist>
The call handler is called in the same way as any other new-style
function: it receives a pointer to a FunctionCallInfoData struct
containing argument values and information about the called function,
and it is expected to return a Datum result (and possibly set the
<literal>isnull</literal> field of the FunctionCallInfoData struct,
if it wishes to return an SQL NULL result). The difference between
a call handler and an ordinary callee function is that the
<literal>flinfo->fn_oid</literal> field of the FunctionCallInfoData
struct will contain the OID of the PL function to be called, not of
the call handler itself. The call handler must use this field to
determine which function to execute. Also, the passed argument list
has been set up according to the declaration of the target PL function,
not of the call handler.
</para>
<para>
It's up to the call handler to fetch the
<filename>pg_proc</filename> entry and
...
...
@@ -212,6 +210,28 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
file or anything else that tells the call handler what to
do in detail.
</para>
<para>
Often, the same function is called many times per SQL statement.
A call handler can avoid repeated lookups of information about the
called function by using the <literal>flinfo->fn_extra</literal> field.
This will initially be NULL, but can be set by the call handler to
point at information about the PL function. On subsequent calls,
if <literal>flinfo->fn_extra</literal> is already non-NULL then it
can be used and the information lookup step skipped. The call handler
must be careful that <literal>flinfo->fn_extra</literal> is made to
point at memory that will live at least until the end of the current
query, since an FmgrInfo data structure could be kept that long.
</para>
<para>
When a PL function is invoked as a trigger, no explicit arguments
are passed, but the FunctionCallInfoData's
<literal>context</literal> field points at a TriggerData node,
rather than being NULL as it is in a plain function call.
A PL handler should provide mechanisms for PL functions to get
at the trigger information.
</para>
</refsect2>
<refsect2 id="R2-SQL-CREATELANGUAGE-4">
...
...
@@ -275,39 +295,33 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
#include "executor/spi.h"
#include "commands/trigger.h"
#include "utils/elog.h"
#include "fmgr.h"
/* for FmgrValues struct */
#include "fmgr.h"
#include "access/heapam.h"
#include "utils/syscache.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
Datum
plsample_call_handler(
Oid prooid,
int pronargs,
FmgrValues *proargs,
bool *isNull)
plsample_call_handler(PG_FUNCTION_ARGS)
{
Datum retval;
TriggerData *trigdata;
if (CurrentTriggerData == NULL) {
if (CALLED_AS_TRIGGER(fcinfo))
{
/*
* Called as a
function
* Called as a
trigger procedure
*/
TriggerData *trigdata = (TriggerData *) fcinfo->context;
retval = ...
} else {
/*
* Called as a
trigger procedure
* Called as a
function
*/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
retval = ...
}
*isNull = false;
return retval;
}
</programlisting>
...
...
@@ -325,7 +339,7 @@ plsample_call_handler(
<programlisting>
CREATE FUNCTION plsample_call_handler () RETURNS opaque
AS '/usr/local/pgsql/lib/plsample.so'
LANGUAGE 'C';
LANGUAGE '
new
C';
CREATE PROCEDURAL LANGUAGE 'plsample'
HANDLER plsample_call_handler
LANCOMPILER 'PL/Sample';
...
...
doc/src/sgml/trigger.sgml
View file @
18952f67
...
...
@@ -15,13 +15,14 @@
<para>
If a trigger event occurs, the trigger manager (called by the Executor)
initializes the global structure TriggerData *CurrentTriggerData (described
below) and calls
the trigger function to handle the event.
sets up a TriggerData information structure (described below) and calls
the trigger function to handle the event.
</para>
<para>
The trigger function must be created before the trigger is created as a
function taking no arguments and returns opaque.
function taking no arguments and returning opaque. If the function is
written in C, it must follow the "new style" function manager interface.
</para>
<para>
...
...
@@ -106,7 +107,7 @@ CREATE TRIGGER <replaceable>trigger</replaceable> [ BEFORE | AFTER ] [ INSERT |
<term><replaceable>args</replaceable></term>
<listitem>
<para>
The arguments passed to the function in the
Current
TriggerData structure.
The arguments passed to the function in the TriggerData structure.
The purpose of passing arguments to the function is to allow different
triggers with similar requirements to call the same function.
</para>
...
...
@@ -179,11 +180,35 @@ CREATE TRIGGER <replaceable>trigger</replaceable> [ BEFORE | AFTER ] [ INSERT |
<title>Interaction with the Trigger Manager</title>
<para>
As mentioned above, when function is called by the trigger manager,
structure TriggerData *CurrentTriggerData is NOT NULL and initialized. So
it is better to check CurrentTriggerData against being NULL at the start
and set it to NULL just after fetching the information to prevent calls to
a trigger function not from the trigger manager.
This section describes the low-level details of the interface to a
trigger function. This information is only needed when writing a
trigger function in C. If you are using a higher-level function
language then these details are handled for you.
</para>
<note>
<para>
The interface described here applies for
<productname>Postgres</productname> 7.1 and later.
Earlier versions passed the TriggerData pointer in a global
variable CurrentTriggerData.
</para>
</note>
<para>
When a function is called by the trigger manager, it is not passed any
normal parameters, but it is passed a "context" pointer pointing to a
TriggerData structure. C functions can check whether they were called
from the trigger manager or not by executing the macro
<literal>CALLED_AS_TRIGGER(fcinfo)</literal>, which expands to
<programlisting>
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
</programlisting>
If this returns TRUE, then it is safe to cast fcinfo->context to type
<literal>TriggerData *</literal> and make use of the pointed-to
TriggerData structure.
The function must <emphasis>not</emphasis> alter the TriggerData
structure or any of the data it points to.
</para>
<para>
...
...
@@ -192,6 +217,7 @@ CREATE TRIGGER <replaceable>trigger</replaceable> [ BEFORE | AFTER ] [ INSERT |
<programlisting>
typedef struct TriggerData
{
NodeTag type;
TriggerEvent tg_event;
Relation tg_relation;
HeapTuple tg_trigtuple;
...
...
@@ -203,6 +229,15 @@ typedef struct TriggerData
where the members are defined as follows:
<variablelist>
<varlistentry>
<term>type</term>
<listitem>
<para>
Always <literal>T_TriggerData</literal> if this is a trigger event.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>tg_event</term>
<listitem>
...
...
@@ -410,11 +445,12 @@ execution of Q) or after Q is done.
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */
HeapTuple trigf(void
);
extern Datum trigf(PG_FUNCTION_ARGS
);
HeapTuple
trigf()
Datum
trigf(
PG_FUNCTION_ARGS
)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
TupleDesc tupdesc;
HeapTuple rettuple;
char *when;
...
...
@@ -422,27 +458,27 @@ trigf()
bool isnull;
int ret, i;
if (!CurrentTriggerData)
elog(NOTICE, "trigf: triggers are not initialized");
/* Make sure trigdata is pointing at what I expect */
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "trigf: not fired by trigger manager");
/* tuple to return to Executor */
if (TRIGGER_FIRED_BY_UPDATE(
CurrentTriggerD
ata->tg_event))
rettuple =
CurrentTriggerD
ata->tg_newtuple;
if (TRIGGER_FIRED_BY_UPDATE(
trigd
ata->tg_event))
rettuple =
trigd
ata->tg_newtuple;
else
rettuple =
CurrentTriggerD
ata->tg_trigtuple;
rettuple =
trigd
ata->tg_trigtuple;
/* check for NULLs ? */
if (!TRIGGER_FIRED_BY_DELETE(
CurrentTriggerD
ata->tg_event) &&
TRIGGER_FIRED_BEFORE(
CurrentTriggerD
ata->tg_event))
if (!TRIGGER_FIRED_BY_DELETE(
trigd
ata->tg_event) &&
TRIGGER_FIRED_BEFORE(
trigd
ata->tg_event))
checknull = true;
if (TRIGGER_FIRED_BEFORE(
CurrentTriggerD
ata->tg_event))
if (TRIGGER_FIRED_BEFORE(
trigd
ata->tg_event))
when = "before";
else
when = "after ";
tupdesc = CurrentTriggerData->tg_relation->rd_att;
CurrentTriggerData = NULL;
tupdesc = trigdata->tg_relation->rd_att;
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
...
...
@@ -467,7 +503,7 @@ trigf()
rettuple = NULL;
}
return (rettuple);
return
PointerGetDatum
(rettuple);
}
</programlisting>
</para>
...
...
src/backend/commands/command.c
View file @
18952f67
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.7
2 2000/05/28 17:55:54
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.7
3 2000/05/29 01:59:06
tgl Exp $
*
* NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated
...
...
@@ -1159,19 +1159,24 @@ AlterTableAddConstraint(const char *relationName,
while
(
HeapTupleIsValid
(
tuple
=
heap_getnext
(
scan
,
0
)))
{
TriggerData
newtrigdata
;
/* Make a call to the check function */
/* No parameters are passed, but we do set a context */
FunctionCallInfoData
fcinfo
;
TriggerData
trigdata
;
newtrigdata
.
tg_event
=
TRIGGER_EVENT_INSERT
|
TRIGGER_EVENT_ROW
;
newtrigdata
.
tg_relation
=
rel
;
newtrigdata
.
tg_trigtuple
=
tuple
;
newtrigdata
.
tg_newtuple
=
NULL
;
newtrigdata
.
tg_trigger
=
&
trig
;
MemSet
(
&
fcinfo
,
0
,
sizeof
(
fcinfo
));
/* We assume RI_FKey_check_ins won't look at flinfo... */
CurrentTriggerData
=
&
newtrigdata
;
trigdata
.
type
=
T_TriggerData
;
trigdata
.
tg_event
=
TRIGGER_EVENT_INSERT
|
TRIGGER_EVENT_ROW
;
trigdata
.
tg_relation
=
rel
;
trigdata
.
tg_trigtuple
=
tuple
;
trigdata
.
tg_newtuple
=
NULL
;
trigdata
.
tg_trigger
=
&
trig
;
RI_FKey_check_ins
(
NULL
)
;
fcinfo
.
context
=
(
Node
*
)
&
trigdata
;
/* Make a call to the check function */
RI_FKey_check_ins
(
&
fcinfo
);
}
heap_endscan
(
scan
);
heap_close
(
rel
,
NoLock
);
/* close rel but keep
...
...
src/backend/commands/trigger.c
View file @
18952f67
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.6
6 2000/05/28 20:34:50
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.6
7 2000/05/29 01:59:06
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -32,14 +32,12 @@
#include "utils/syscache.h"
#include "utils/tqual.h"
DLLIMPORT
TriggerData
*
CurrentTriggerData
=
NULL
;
/* XXX no points for style */
extern
TupleTableSlot
*
EvalPlanQual
(
EState
*
estate
,
Index
rti
,
ItemPointer
tid
);
static
void
DescribeTrigger
(
TriggerDesc
*
trigdesc
,
Trigger
*
trigger
);
static
HeapTuple
GetTupleForTrigger
(
EState
*
estate
,
ItemPointer
tid
,
TupleTableSlot
**
newSlot
);
static
HeapTuple
ExecCallTriggerFunc
(
Trigger
*
trigger
,
TriggerData
*
trigdata
);
void
...
...
@@ -507,7 +505,7 @@ RelationBuildTriggers(Relation relation)
build
->
tgoid
=
htup
->
t_data
->
t_oid
;
build
->
tgname
=
nameout
(
&
pg_trigger
->
tgname
);
build
->
tgfoid
=
pg_trigger
->
tgfoid
;
build
->
tgfunc
.
fn_
addr
=
NULL
;
build
->
tgfunc
.
fn_
oid
=
InvalidOid
;
/* mark FmgrInfo as uninitialized */
build
->
tgtype
=
pg_trigger
->
tgtype
;
build
->
tgenabled
=
pg_trigger
->
tgenabled
;
build
->
tgisconstraint
=
pg_trigger
->
tgisconstraint
;
...
...
@@ -757,45 +755,66 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
return
true
;
}
static
HeapTuple
ExecCallTriggerFunc
(
Trigger
*
trigger
)
ExecCallTriggerFunc
(
Trigger
*
trigger
,
TriggerData
*
trigdata
)
{
if
(
trigger
->
tgfunc
.
fn_addr
==
NULL
)
FunctionCallInfoData
fcinfo
;
Datum
result
;
/*
* Fmgr lookup info is cached in the Trigger structure,
* so that we need not repeat the lookup on every call.
*/
if
(
trigger
->
tgfunc
.
fn_oid
==
InvalidOid
)
fmgr_info
(
trigger
->
tgfoid
,
&
trigger
->
tgfunc
);
return
(
HeapTuple
)
((
*
fmgr_faddr
(
&
trigger
->
tgfunc
))
());
/*
* Call the function, passing no arguments but setting a context.
*/
MemSet
(
&
fcinfo
,
0
,
sizeof
(
fcinfo
));
fcinfo
.
flinfo
=
&
trigger
->
tgfunc
;
fcinfo
.
context
=
(
Node
*
)
trigdata
;
result
=
FunctionCallInvoke
(
&
fcinfo
);
/*
* Trigger protocol allows function to return a null pointer,
* but NOT to set the isnull result flag.
*/
if
(
fcinfo
.
isnull
)
elog
(
ERROR
,
"ExecCallTriggerFunc: function %u returned NULL"
,
fcinfo
.
flinfo
->
fn_oid
);
return
(
HeapTuple
)
DatumGetPointer
(
result
);
}
HeapTuple
ExecBRInsertTriggers
(
Relation
rel
,
HeapTuple
trigtuple
)
{
TriggerData
*
SaveTriggerData
;
int
ntrigs
=
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_INSERT
];
Trigger
**
trigger
=
rel
->
trigdesc
->
tg_before_row
[
TRIGGER_EVENT_INSERT
];
HeapTuple
newtuple
=
trigtuple
;
HeapTuple
oldtuple
;
TriggerData
LocTriggerData
;
int
i
;
SaveTriggerData
=
(
TriggerData
*
)
palloc
(
sizeof
(
TriggerData
))
;
SaveTriggerData
->
tg_event
=
TRIGGER_EVENT_INSERT
|
TRIGGER_EVENT_ROW
|
TRIGGER_EVENT_BEFORE
;
SaveTriggerData
->
tg_relation
=
rel
;
SaveTriggerData
->
tg_newtuple
=
NULL
;
LocTriggerData
.
type
=
T_TriggerData
;
LocTriggerData
.
tg_event
=
TRIGGER_EVENT_INSERT
|
TRIGGER_EVENT_ROW
|
TRIGGER_EVENT_BEFORE
;
LocTriggerData
.
tg_relation
=
rel
;
LocTriggerData
.
tg_newtuple
=
NULL
;
for
(
i
=
0
;
i
<
ntrigs
;
i
++
)
{
if
(
!
trigger
[
i
]
->
tgenabled
)
continue
;
CurrentTriggerData
=
SaveTriggerData
;
CurrentTriggerData
->
tg_trigtuple
=
oldtuple
=
newtuple
;
CurrentTriggerData
->
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
]);
LocTriggerData
.
tg_trigtuple
=
oldtuple
=
newtuple
;
LocTriggerData
.
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
);
if
(
newtuple
==
NULL
)
break
;
else
if
(
oldtuple
!=
newtuple
&&
oldtuple
!=
trigtuple
)
heap_freetuple
(
oldtuple
);
}
CurrentTriggerData
=
NULL
;
pfree
(
SaveTriggerData
);
return
newtuple
;
}
...
...
@@ -810,9 +829,9 @@ bool
ExecBRDeleteTriggers
(
EState
*
estate
,
ItemPointer
tupleid
)
{
Relation
rel
=
estate
->
es_result_relation_info
->
ri_RelationDesc
;
TriggerData
*
SaveTriggerData
;
int
ntrigs
=
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_DELETE
];
Trigger
**
trigger
=
rel
->
trigdesc
->
tg_before_row
[
TRIGGER_EVENT_DELETE
];
TriggerData
LocTriggerData
;
HeapTuple
trigtuple
;
HeapTuple
newtuple
=
NULL
;
TupleTableSlot
*
newSlot
;
...
...
@@ -822,25 +841,22 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
if
(
trigtuple
==
NULL
)
return
false
;
SaveTriggerData
=
(
TriggerData
*
)
palloc
(
sizeof
(
TriggerData
))
;
SaveTriggerData
->
tg_event
=
TRIGGER_EVENT_DELETE
|
TRIGGER_EVENT_ROW
|
TRIGGER_EVENT_BEFORE
;
SaveTriggerData
->
tg_relation
=
rel
;
SaveTriggerData
->
tg_newtuple
=
NULL
;
LocTriggerData
.
type
=
T_TriggerData
;
LocTriggerData
.
tg_event
=
TRIGGER_EVENT_DELETE
|
TRIGGER_EVENT_ROW
|
TRIGGER_EVENT_BEFORE
;
LocTriggerData
.
tg_relation
=
rel
;
LocTriggerData
.
tg_newtuple
=
NULL
;
for
(
i
=
0
;
i
<
ntrigs
;
i
++
)
{
if
(
!
trigger
[
i
]
->
tgenabled
)
continue
;
CurrentTriggerData
=
SaveTriggerData
;
CurrentTriggerData
->
tg_trigtuple
=
trigtuple
;
CurrentTriggerData
->
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
]);
LocTriggerData
.
tg_trigtuple
=
trigtuple
;
LocTriggerData
.
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
);
if
(
newtuple
==
NULL
)
break
;
if
(
newtuple
!=
trigtuple
)
heap_freetuple
(
newtuple
);
}
CurrentTriggerData
=
NULL
;
pfree
(
SaveTriggerData
);
heap_freetuple
(
trigtuple
);
return
(
newtuple
==
NULL
)
?
false
:
true
;
...
...
@@ -860,9 +876,9 @@ HeapTuple
ExecBRUpdateTriggers
(
EState
*
estate
,
ItemPointer
tupleid
,
HeapTuple
newtuple
)
{
Relation
rel
=
estate
->
es_result_relation_info
->
ri_RelationDesc
;
TriggerData
*
SaveTriggerData
;
int
ntrigs
=
rel
->
trigdesc
->
n_before_row
[
TRIGGER_EVENT_UPDATE
];
Trigger
**
trigger
=
rel
->
trigdesc
->
tg_before_row
[
TRIGGER_EVENT_UPDATE
];
TriggerData
LocTriggerData
;
HeapTuple
trigtuple
;
HeapTuple
oldtuple
;
HeapTuple
intuple
=
newtuple
;
...
...
@@ -880,25 +896,22 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
if
(
newSlot
!=
NULL
)
intuple
=
newtuple
=
ExecRemoveJunk
(
estate
->
es_junkFilter
,
newSlot
);
SaveTriggerData
=
(
TriggerData
*
)
palloc
(
sizeof
(
TriggerData
))
;
SaveTriggerData
->
tg_event
=
TRIGGER_EVENT_UPDATE
|
TRIGGER_EVENT_ROW
|
TRIGGER_EVENT_BEFORE
;
SaveTriggerData
->
tg_relation
=
rel
;
LocTriggerData
.
type
=
T_TriggerData
;
LocTriggerData
.
tg_event
=
TRIGGER_EVENT_UPDATE
|
TRIGGER_EVENT_ROW
|
TRIGGER_EVENT_BEFORE
;
LocTriggerData
.
tg_relation
=
rel
;
for
(
i
=
0
;
i
<
ntrigs
;
i
++
)
{
if
(
!
trigger
[
i
]
->
tgenabled
)
continue
;
CurrentTriggerData
=
SaveTriggerData
;
CurrentTriggerData
->
tg_trigtuple
=
trigtuple
;
CurrentTriggerData
->
tg_newtuple
=
oldtuple
=
newtuple
;
CurrentTriggerData
->
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
]);
LocTriggerData
.
tg_trigtuple
=
trigtuple
;
LocTriggerData
.
tg_newtuple
=
oldtuple
=
newtuple
;
LocTriggerData
.
tg_trigger
=
trigger
[
i
];
newtuple
=
ExecCallTriggerFunc
(
trigger
[
i
],
&
LocTriggerData
);
if
(
newtuple
==
NULL
)
break
;
else
if
(
oldtuple
!=
newtuple
&&
oldtuple
!=
intuple
)
heap_freetuple
(
oldtuple
);
}
CurrentTriggerData
=
NULL
;
pfree
(
SaveTriggerData
);
heap_freetuple
(
trigtuple
);
return
newtuple
;
}
...
...
@@ -1167,7 +1180,7 @@ static void
deferredTriggerExecute
(
DeferredTriggerEvent
event
,
int
itemno
)
{
Relation
rel
;
TriggerData
Save
TriggerData
;
TriggerData
Loc
TriggerData
;
HeapTupleData
oldtuple
;
HeapTupleData
newtuple
;
HeapTuple
rettuple
;
...
...
@@ -1200,30 +1213,31 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
* Setup the trigger information
* ----------
*/
SaveTriggerData
.
tg_event
=
(
event
->
dte_event
&
TRIGGER_EVENT_OPMASK
)
|
LocTriggerData
.
type
=
T_TriggerData
;
LocTriggerData
.
tg_event
=
(
event
->
dte_event
&
TRIGGER_EVENT_OPMASK
)
|
TRIGGER_EVENT_ROW
;
Save
TriggerData
.
tg_relation
=
rel
;
Loc
TriggerData
.
tg_relation
=
rel
;
switch
(
event
->
dte_event
&
TRIGGER_EVENT_OPMASK
)
{
case
TRIGGER_EVENT_INSERT
:
Save
TriggerData
.
tg_trigtuple
=
&
newtuple
;
Save
TriggerData
.
tg_newtuple
=
NULL
;
Save
TriggerData
.
tg_trigger
=
Loc
TriggerData
.
tg_trigtuple
=
&
newtuple
;
Loc
TriggerData
.
tg_newtuple
=
NULL
;
Loc
TriggerData
.
tg_trigger
=
rel
->
trigdesc
->
tg_after_row
[
TRIGGER_EVENT_INSERT
][
itemno
];
break
;
case
TRIGGER_EVENT_UPDATE
:
Save
TriggerData
.
tg_trigtuple
=
&
oldtuple
;
Save
TriggerData
.
tg_newtuple
=
&
newtuple
;
Save
TriggerData
.
tg_trigger
=
Loc
TriggerData
.
tg_trigtuple
=
&
oldtuple
;
Loc
TriggerData
.
tg_newtuple
=
&
newtuple
;
Loc
TriggerData
.
tg_trigger
=
rel
->
trigdesc
->
tg_after_row
[
TRIGGER_EVENT_UPDATE
][
itemno
];
break
;
case
TRIGGER_EVENT_DELETE
:
Save
TriggerData
.
tg_trigtuple
=
&
oldtuple
;
Save
TriggerData
.
tg_newtuple
=
NULL
;
Save
TriggerData
.
tg_trigger
=
Loc
TriggerData
.
tg_trigtuple
=
&
oldtuple
;
Loc
TriggerData
.
tg_newtuple
=
NULL
;
Loc
TriggerData
.
tg_trigger
=
rel
->
trigdesc
->
tg_after_row
[
TRIGGER_EVENT_DELETE
][
itemno
];
break
;
}
...
...
@@ -1233,9 +1247,7 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
* updated tuple.
* ----------
*/
CurrentTriggerData
=
&
SaveTriggerData
;
rettuple
=
ExecCallTriggerFunc
(
SaveTriggerData
.
tg_trigger
);
CurrentTriggerData
=
NULL
;
rettuple
=
ExecCallTriggerFunc
(
LocTriggerData
.
tg_trigger
,
&
LocTriggerData
);
if
(
rettuple
!=
NULL
&&
rettuple
!=
&
oldtuple
&&
rettuple
!=
&
newtuple
)
heap_freetuple
(
rettuple
);
...
...
@@ -1778,7 +1790,7 @@ DeferredTriggerSaveEvent(Relation rel, int event,
Trigger
**
triggers
;
ItemPointerData
oldctid
;
ItemPointerData
newctid
;
TriggerData
Save
TriggerData
;
TriggerData
Loc
TriggerData
;
if
(
deftrig_cxt
==
NULL
)
elog
(
ERROR
,
...
...
@@ -1891,15 +1903,14 @@ DeferredTriggerSaveEvent(Relation rel, int event,
if
(
!
is_ri_trigger
)
continue
;
SaveTriggerData
.
tg_event
=
TRIGGER_EVENT_UPDATE
;
SaveTriggerData
.
tg_relation
=
rel
;
SaveTriggerData
.
tg_trigtuple
=
oldtup
;
SaveTriggerData
.
tg_newtuple
=
newtup
;
SaveTriggerData
.
tg_trigger
=
triggers
[
i
];
LocTriggerData
.
type
=
T_TriggerData
;
LocTriggerData
.
tg_event
=
TRIGGER_EVENT_UPDATE
;
LocTriggerData
.
tg_relation
=
rel
;
LocTriggerData
.
tg_trigtuple
=
oldtup
;
LocTriggerData
.
tg_newtuple
=
newtup
;
LocTriggerData
.
tg_trigger
=
triggers
[
i
];
CurrentTriggerData
=
&
SaveTriggerData
;
key_unchanged
=
RI_FKey_keyequal_upd
();
CurrentTriggerData
=
NULL
;
key_unchanged
=
RI_FKey_keyequal_upd
(
&
LocTriggerData
);
if
(
key_unchanged
)
{
...
...
src/backend/commands/user.c
View file @
18952f67
...
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $
Id: user.c,v 1.54 2000/05/28 17:55:55
tgl Exp $
* $
Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.55 2000/05/29 01:59:07
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -168,20 +168,14 @@ write_password_file(Relation rel)
/* This is the wrapper for triggers. */
HeapTuple
update_pg_pwd
(
void
)
Datum
update_pg_pwd
(
PG_FUNCTION_ARGS
)
{
Relation
rel
=
heap_openr
(
ShadowRelationName
,
AccessExclusiveLock
);
write_password_file
(
rel
);
heap_close
(
rel
,
AccessExclusiveLock
);
/*
* This is a trigger, so clean out the information provided by the
* trigger manager.
*/
CurrentTriggerData
=
NULL
;
return
NULL
;
return
PointerGetDatum
(
NULL
);
}
...
...
src/backend/executor/execMain.c
View file @
18952f67
...
...
@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.11
3 2000/04/12 17:15:08 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.11
4 2000/05/29 01:59:07 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -46,9 +46,6 @@
#include "utils/builtins.h"
#include "utils/syscache.h"
/* XXX no points for style */
extern
TupleTableSlot
*
EvalPlanQual
(
EState
*
estate
,
Index
rti
,
ItemPointer
tid
);
/* decls for local routines only used within this module */
static
TupleDesc
InitPlan
(
CmdType
operation
,
...
...
@@ -1974,7 +1971,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
*/
*
tid
=
tuple
.
t_self
;
return
(
EvalPlanQualNext
(
estate
)
);
return
EvalPlanQualNext
(
estate
);
}
static
TupleTableSlot
*
...
...
src/backend/utils/adt/ri_triggers.c
View file @
18952f67
...
...
@@ -6,7 +6,7 @@
*
* 1999 Jan Wieck
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.1
4 2000/04/12 17:15:51 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.1
5 2000/05/29 01:59:08 tgl
Exp $
*
* ----------
*/
...
...
@@ -20,7 +20,6 @@
*/
#include "postgres.h"
#include "fmgr.h"
#include "access/heapam.h"
#include "catalog/pg_operator.h"
...
...
@@ -28,10 +27,11 @@
#include "commands/trigger.h"
#include "executor/spi.h"
#include "executor/spi_priv.h"
#include "fmgr.h"
#include "lib/hasht.h"
#include "utils/builtins.h"
#include "utils/mcxt.h"
#include "utils/syscache.h"
#include "lib/hasht.h"
/* ----------
...
...
@@ -105,7 +105,6 @@ typedef struct RI_QueryHashEntry
typedef
struct
RI_OpreqHashEntry
{
Oid
typeid
;
Oid
oprfnid
;
FmgrInfo
oprfmgrinfo
;
}
RI_OpreqHashEntry
;
...
...
@@ -147,13 +146,13 @@ static void ri_HashPreparedPlan(RI_QueryKey *key, void *plan);
/* ----------
* RI_FKey_check -
*
* Check foreign key exist
a
nce (combined for INSERT and UPDATE).
* Check foreign key exist
e
nce (combined for INSERT and UPDATE).
* ----------
*/
static
HeapTuple
RI_FKey_check
(
FmgrInfo
*
proinfo
)
static
Datum
RI_FKey_check
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -168,15 +167,13 @@ RI_FKey_check(FmgrInfo *proinfo)
int
i
;
int
match_type
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_check() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -275,7 +272,7 @@ RI_FKey_check(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_check()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -284,7 +281,7 @@ RI_FKey_check(FmgrInfo *proinfo)
if
(
match_type
==
RI_MATCH_TYPE_PARTIAL
)
{
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
ri_BuildQueryKeyFull
(
&
qkey
,
trigdata
->
tg_trigger
->
tgoid
,
...
...
@@ -303,7 +300,7 @@ RI_FKey_check(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
pk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_SOME_NULL
:
/* ----------
...
...
@@ -324,7 +321,7 @@ RI_FKey_check(FmgrInfo *proinfo)
"and NON-NULL key values"
,
tgargs
[
RI_CONSTRAINT_NAME_ARGNO
]);
heap_close
(
pk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_MATCH_TYPE_UNSPECIFIED
:
/* ----------
...
...
@@ -333,7 +330,7 @@ RI_FKey_check(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
pk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_MATCH_TYPE_PARTIAL
:
/* ----------
...
...
@@ -345,7 +342,7 @@ RI_FKey_check(FmgrInfo *proinfo)
*/
elog
(
ERROR
,
"MATCH PARTIAL not yet implemented"
);
heap_close
(
pk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
case
RI_KEYS_NONE_NULL
:
...
...
@@ -459,40 +456,40 @@ RI_FKey_check(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_check()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Never reached
* ----------
*/
elog
(
ERROR
,
"internal error #1 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
* RI_FKey_check_ins -
*
* Check foreign key exist
a
nce at insert event on FK table.
* Check foreign key exist
e
nce at insert event on FK table.
* ----------
*/
HeapTuple
RI_FKey_check_ins
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_check_ins
(
PG_FUNCTION_ARGS
)
{
return
RI_FKey_check
(
pro
info
);
return
RI_FKey_check
(
fc
info
);
}
/* ----------
* RI_FKey_check_upd -
*
* Check foreign key exist
a
nce at update event on FK table.
* Check foreign key exist
e
nce at update event on FK table.
* ----------
*/
HeapTuple
RI_FKey_check_upd
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_check_upd
(
PG_FUNCTION_ARGS
)
{
return
RI_FKey_check
(
pro
info
);
return
RI_FKey_check
(
fc
info
);
}
...
...
@@ -504,10 +501,10 @@ RI_FKey_check_upd(FmgrInfo *proinfo)
* integrity constraint.
* ----------
*/
HeapTuple
RI_FKey_noaction_del
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_noaction_del
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -520,15 +517,13 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_noaction_del() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -553,7 +548,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -590,7 +585,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -685,7 +680,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_noaction_del()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL restrict delete.
...
...
@@ -693,7 +688,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -701,7 +696,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #2 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -713,10 +708,10 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* integrity constraint.
* ----------
*/
HeapTuple
RI_FKey_noaction_upd
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_noaction_upd
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -730,15 +725,13 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_noaction_upd() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -763,7 +756,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -801,7 +794,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -818,7 +811,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
*/
if
(
ri_KeysEqual
(
pk_rel
,
old_row
,
new_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_noaction_upd()"
);
...
...
@@ -904,7 +897,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_noaction_upd()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL noaction update.
...
...
@@ -912,7 +905,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -920,7 +913,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #3 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -930,10 +923,10 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* Cascaded delete foreign key references at delete event on PK table.
* ----------
*/
HeapTuple
RI_FKey_cascade_del
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_cascade_del
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -946,15 +939,13 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_cascade_del() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -979,7 +970,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -1016,7 +1007,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -1100,7 +1091,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_cascade_del()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL cascaded delete.
...
...
@@ -1108,7 +1099,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -1116,7 +1107,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #4 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -1126,10 +1117,10 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* Cascaded update/delete foreign key references at update event on PK table.
* ----------
*/
HeapTuple
RI_FKey_cascade_upd
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_cascade_upd
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -1144,15 +1135,13 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
int
i
;
int
j
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_cascade_upd() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -1177,7 +1166,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -1215,7 +1204,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -1232,7 +1221,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
*/
if
(
ri_KeysEqual
(
pk_rel
,
old_row
,
new_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_cascade_upd()"
);
...
...
@@ -1328,7 +1317,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_cascade_upd()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL cascade update.
...
...
@@ -1336,7 +1325,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -1344,7 +1333,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #5 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -1361,10 +1350,10 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* equivalent.
* ----------
*/
HeapTuple
RI_FKey_restrict_del
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_restrict_del
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -1377,15 +1366,13 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_restrict_del() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -1410,7 +1397,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -1447,7 +1434,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -1542,7 +1529,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_restrict_del()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL restrict delete.
...
...
@@ -1550,7 +1537,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -1558,7 +1545,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #6 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -1575,10 +1562,10 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* equivalent.
* ----------
*/
HeapTuple
RI_FKey_restrict_upd
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_restrict_upd
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -1592,15 +1579,13 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_restrict_upd() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -1625,7 +1610,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -1663,7 +1648,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -1680,7 +1665,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
*/
if
(
ri_KeysEqual
(
pk_rel
,
old_row
,
new_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_restrict_upd()"
);
...
...
@@ -1766,7 +1751,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_restrict_upd()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL restrict update.
...
...
@@ -1774,7 +1759,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -1782,7 +1767,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #7 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -1792,10 +1777,10 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* Set foreign key references to NULL values at delete event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setnull_del
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_setnull_del
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -1808,15 +1793,13 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_setnull_del() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -1841,7 +1824,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -1878,7 +1861,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -1973,7 +1956,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_setnull_del()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL set null delete.
...
...
@@ -1981,7 +1964,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -1989,7 +1972,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #8 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -1999,10 +1982,10 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* Set foreign key references to NULL at update event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setnull_upd
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_setnull_upd
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -2018,15 +2001,13 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
int
match_type
;
bool
use_cached_query
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_setnull_upd() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -2051,7 +2032,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -2090,7 +2071,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -2108,7 +2089,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
*/
if
(
ri_KeysEqual
(
pk_rel
,
old_row
,
new_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_setnull_upd()"
);
...
...
@@ -2231,7 +2212,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_setnull_upd()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL set null update.
...
...
@@ -2239,7 +2220,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -2247,7 +2228,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #9 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -2257,10 +2238,10 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* Set foreign key references to defaults at delete event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setdefault_del
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_setdefault_del
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -2273,15 +2254,13 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_setdefault_del() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -2306,7 +2285,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -2343,7 +2322,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -2485,7 +2464,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_setdefault_del()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL set null delete.
...
...
@@ -2493,7 +2472,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -2501,7 +2480,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #10 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -2511,10 +2490,10 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* Set foreign key references to defaults at update event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setdefault_upd
(
FmgrInfo
*
proinfo
)
Datum
RI_FKey_setdefault_upd
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -2529,15 +2508,13 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
int
i
;
int
match_type
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
ReferentialIntegritySnapshotOverride
=
true
;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"RI_FKey_setdefault_upd() not fired by trigger manager"
);
if
(
!
TRIGGER_FIRED_AFTER
(
trigdata
->
tg_event
)
||
!
TRIGGER_FIRED_FOR_ROW
(
trigdata
->
tg_event
))
...
...
@@ -2562,7 +2539,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
...
...
@@ -2602,7 +2579,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
case
RI_KEYS_NONE_NULL
:
/* ----------
...
...
@@ -2619,7 +2596,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
*/
if
(
ri_KeysEqual
(
pk_rel
,
old_row
,
new_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_setdefault_upd()"
);
...
...
@@ -2769,7 +2746,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_setdefault_upd()"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
/* ----------
* Handle MATCH PARTIAL set null delete.
...
...
@@ -2777,7 +2754,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
/* ----------
...
...
@@ -2785,7 +2762,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
* ----------
*/
elog
(
ERROR
,
"internal error #11 in ri_triggers.c"
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
...
...
@@ -2794,14 +2771,13 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
*
* Check if we have a key change on update.
*
* This is no real trigger procedure. It is used by the deferred
* This is no
t a
real trigger procedure. It is used by the deferred
* trigger queue manager to detect "triggered data change violation".
* ----------
*/
bool
RI_FKey_keyequal_upd
(
void
)
RI_FKey_keyequal_upd
(
TriggerData
*
trigdata
)
{
TriggerData
*
trigdata
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
...
...
@@ -2810,9 +2786,6 @@ RI_FKey_keyequal_upd(void)
HeapTuple
old_row
;
RI_QueryKey
qkey
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
/* ----------
* Check for the correct # of call arguments
* ----------
...
...
@@ -3262,8 +3235,10 @@ ri_OneKeyEqual(Relation rel, int column, HeapTuple oldtup, HeapTuple newtup,
/* ----------
* ri_AttributesEqual -
*
* Call the type specific '=' operator comparis
i
on function
* Call the type specific '=' operator comparison function
* for two values.
*
* NB: we have already checked that neither value is null.
* ----------
*/
static
bool
...
...
@@ -3271,7 +3246,6 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
{
RI_OpreqHashEntry
*
entry
;
bool
found
;
Datum
result
;
/* ----------
* On the first call initialize the hashtable
...
...
@@ -3291,6 +3265,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
/* ----------
* If not found, lookup the OPERNAME system cache for it
* to get the func OID, then do the function manager lookup,
* and remember that info.
* ----------
*/
...
...
@@ -3307,7 +3282,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
if
(
!
HeapTupleIsValid
(
opr_tup
))
elog
(
ERROR
,
"ri_AttributesEqual(): cannot find '=' operator "
"for type %
d
"
,
typeid
);
"for type %
u
"
,
typeid
);
opr_struct
=
(
Form_pg_operator
)
GETSTRUCT
(
opr_tup
);
entry
=
(
RI_OpreqHashEntry
*
)
hash_search
(
ri_opreq_cache
,
...
...
@@ -3315,15 +3290,14 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
if
(
entry
==
NULL
)
elog
(
FATAL
,
"can't insert into RI operator cache"
);
entry
->
oprfnid
=
opr_struct
->
oprcode
;
memset
(
&
(
entry
->
oprfmgrinfo
),
0
,
sizeof
(
FmgrI
nfo
));
entry
->
typeid
=
typeid
;
fmgr_info
(
opr_struct
->
oprcode
,
&
(
entry
->
oprfmgri
nfo
));
}
/* ----------
* Call the type specific '=' function
* ----------
*/
fmgr_info
(
entry
->
oprfnid
,
&
(
entry
->
oprfmgrinfo
));
result
=
(
Datum
)
(
*
fmgr_faddr
(
&
(
entry
->
oprfmgrinfo
)))
(
oldvalue
,
newvalue
);
return
(
bool
)
result
;
return
DatumGetBool
(
FunctionCall2
(
&
(
entry
->
oprfmgrinfo
),
oldvalue
,
newvalue
));
}
src/backend/utils/adt/tid.c
View file @
18952f67
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.1
6 2000/04/12 17:15:51 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.1
7 2000/05/29 01:59:08 tgl
Exp $
*
* NOTES
* input routine largely stolen from boxin().
...
...
@@ -17,6 +17,8 @@
*/
#include "postgres.h"
#include "access/heapam.h"
#include "utils/builtins.h"
#define LDELIM '('
...
...
src/backend/utils/adt/timestamp.c
View file @
18952f67
...
...
@@ -8,16 +8,17 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.2
6 2000/04/14 15:22:10 thomas
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.2
7 2000/05/29 01:59:08 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include <sys/types.h>
#include <errno.h>
#include "postgres.h"
#include <sys/types.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
...
...
@@ -28,6 +29,7 @@
#include <sys/timeb.h>
#endif
#include "access/xact.h"
#include "miscadmin.h"
#include "utils/builtins.h"
...
...
src/backend/utils/fmgr/fmgr.c
View file @
18952f67
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.4
0 2000/05/28 17:56:07
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.4
1 2000/05/29 01:59:09
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -17,7 +17,6 @@
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "commands/trigger.h"
/* TEMPORARY: for CurrentTriggerData */
#include "utils/builtins.h"
#include "utils/fmgrtab.h"
#include "utils/syscache.h"
...
...
src/include/catalog/catversion.h
View file @
18952f67
...
...
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.2
2 2000/05/28 17:56:16
tgl Exp $
* $Id: catversion.h,v 1.2
3 2000/05/29 01:59:10
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 20000528
1
#define CATALOG_VERSION_NO 20000528
2
#endif
src/include/catalog/pg_proc.h
View file @
18952f67
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.13
4 2000/05/28 17:56:16
tgl Exp $
* $Id: pg_proc.h,v 1.13
5 2000/05/29 01:59:10
tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
...
...
@@ -2103,7 +2103,7 @@ DESCR("less-than");
DATA
(
insert
OID
=
1656
(
lztext_le
PGUID
11
f
t
t
t
2
f
16
"1625 1625"
100
0
1
0
lztext_le
-
));
DESCR
(
"less-than-or-equal"
);
DATA
(
insert
OID
=
1689
(
update_pg_pwd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
update_pg_pwd
-
));
DATA
(
insert
OID
=
1689
(
update_pg_pwd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
update_pg_pwd
-
));
DESCR
(
"update pg_pwd file"
);
/* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
...
...
@@ -2163,29 +2163,29 @@ DATA(insert OID = 1643 ( pg_get_indexdef PGUID 11 f t f t 1 f 25 "26" 100 0
DESCR
(
"index description"
);
/* Generic referential integrity constraint triggers */
DATA
(
insert
OID
=
1644
(
RI_FKey_check_ins
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_check_ins
-
));
DATA
(
insert
OID
=
1644
(
RI_FKey_check_ins
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_check_ins
-
));
DESCR
(
"referential integrity FOREIGN KEY ... REFERENCES"
);
DATA
(
insert
OID
=
1645
(
RI_FKey_check_upd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_check_upd
-
));
DATA
(
insert
OID
=
1645
(
RI_FKey_check_upd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_check_upd
-
));
DESCR
(
"referential integrity FOREIGN KEY ... REFERENCES"
);
DATA
(
insert
OID
=
1646
(
RI_FKey_cascade_del
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_cascade_del
-
));
DATA
(
insert
OID
=
1646
(
RI_FKey_cascade_del
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_cascade_del
-
));
DESCR
(
"referential integrity ON DELETE CASCADE"
);
DATA
(
insert
OID
=
1647
(
RI_FKey_cascade_upd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_cascade_upd
-
));
DATA
(
insert
OID
=
1647
(
RI_FKey_cascade_upd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_cascade_upd
-
));
DESCR
(
"referential integrity ON UPDATE CASCADE"
);
DATA
(
insert
OID
=
1648
(
RI_FKey_restrict_del
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_restrict_del
-
));
DATA
(
insert
OID
=
1648
(
RI_FKey_restrict_del
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_restrict_del
-
));
DESCR
(
"referential integrity ON DELETE RESTRICT"
);
DATA
(
insert
OID
=
1649
(
RI_FKey_restrict_upd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_restrict_upd
-
));
DATA
(
insert
OID
=
1649
(
RI_FKey_restrict_upd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_restrict_upd
-
));
DESCR
(
"referential integrity ON UPDATE RESTRICT"
);
DATA
(
insert
OID
=
1650
(
RI_FKey_setnull_del
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setnull_del
-
));
DATA
(
insert
OID
=
1650
(
RI_FKey_setnull_del
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setnull_del
-
));
DESCR
(
"referential integrity ON DELETE SET NULL"
);
DATA
(
insert
OID
=
1651
(
RI_FKey_setnull_upd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setnull_upd
-
));
DATA
(
insert
OID
=
1651
(
RI_FKey_setnull_upd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setnull_upd
-
));
DESCR
(
"referential integrity ON UPDATE SET NULL"
);
DATA
(
insert
OID
=
1652
(
RI_FKey_setdefault_del
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setdefault_del
-
));
DATA
(
insert
OID
=
1652
(
RI_FKey_setdefault_del
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setdefault_del
-
));
DESCR
(
"referential integrity ON DELETE SET DEFAULT"
);
DATA
(
insert
OID
=
1653
(
RI_FKey_setdefault_upd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setdefault_upd
-
));
DATA
(
insert
OID
=
1653
(
RI_FKey_setdefault_upd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_setdefault_upd
-
));
DESCR
(
"referential integrity ON UPDATE SET DEFAULT"
);
DATA
(
insert
OID
=
1654
(
RI_FKey_noaction_del
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_noaction_del
-
));
DATA
(
insert
OID
=
1654
(
RI_FKey_noaction_del
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_noaction_del
-
));
DESCR
(
"referential integrity ON DELETE NO ACTION"
);
DATA
(
insert
OID
=
1655
(
RI_FKey_noaction_upd
PGUID
1
1
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_noaction_upd
-
));
DATA
(
insert
OID
=
1655
(
RI_FKey_noaction_upd
PGUID
1
2
f
t
f
t
0
f
0
""
100
0
0
100
RI_FKey_noaction_upd
-
));
DESCR
(
"referential integrity ON UPDATE NO ACTION"
);
DATA
(
insert
OID
=
1666
(
varbiteq
PGUID
11
f
t
t
t
2
f
16
"1562 1562"
100
0
1
0
varbiteq
-
));
...
...
src/include/commands/trigger.h
View file @
18952f67
/*-------------------------------------------------------------------------
*
* trigger.h
*
prototypes for trigger.c
.
*
Declarations for trigger handling
.
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: trigger.h,v 1.
19 2000/04/12 17:16:32 momjian
Exp $
* $Id: trigger.h,v 1.
20 2000/05/29 01:59:11 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -16,10 +16,19 @@
#include "nodes/execnodes.h"
#include "nodes/parsenodes.h"
/*
* TriggerData is the node type that is passed as fmgr "context" info
* when a function is called by the trigger manager.
*/
#define CALLED_AS_TRIGGER(fcinfo) \
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
typedef
uint32
TriggerEvent
;
typedef
struct
TriggerData
{
NodeTag
type
;
TriggerEvent
tg_event
;
Relation
tg_relation
;
HeapTuple
tg_trigtuple
;
...
...
@@ -27,7 +36,7 @@ typedef struct TriggerData
Trigger
*
tg_trigger
;
}
TriggerData
;
extern
DLLIMPORT
TriggerData
*
CurrentTriggerData
;
/* TriggerEvent bit flags */
#define TRIGGER_EVENT_INSERT 0x00000000
#define TRIGGER_EVENT_DELETE 0x00000001
...
...
@@ -136,6 +145,6 @@ extern void DeferredTriggerSaveEvent(Relation rel, int event,
* in utils/adt/ri_triggers.c
*
*/
extern
bool
RI_FKey_keyequal_upd
(
void
);
extern
bool
RI_FKey_keyequal_upd
(
TriggerData
*
trigdata
);
#endif
/* TRIGGER_H */
src/include/commands/user.h
View file @
18952f67
...
...
@@ -3,7 +3,7 @@
* user.h
*
*
*
*
$Id: user.h,v 1.12 2000/05/29 01:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -21,6 +21,6 @@ extern void CreateGroup(CreateGroupStmt *stmt);
extern
void
AlterGroup
(
AlterGroupStmt
*
stmt
,
const
char
*
tag
);
extern
void
DropGroup
(
DropGroupStmt
*
stmt
);
extern
HeapTuple
update_pg_pwd
(
void
);
extern
Datum
update_pg_pwd
(
PG_FUNCTION_ARGS
);
#endif
/* USER_H */
src/include/executor/executor.h
View file @
18952f67
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: executor.h,v 1.4
2 2000/01/26 05:58:05 momjian
Exp $
* $Id: executor.h,v 1.4
3 2000/05/29 01:59:11 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -59,6 +59,8 @@ extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
extern
void
ExecutorEnd
(
QueryDesc
*
queryDesc
,
EState
*
estate
);
extern
void
ExecConstraints
(
char
*
caller
,
Relation
rel
,
HeapTuple
tuple
,
EState
*
estate
);
extern
TupleTableSlot
*
EvalPlanQual
(
EState
*
estate
,
Index
rti
,
ItemPointer
tid
);
/*
* prototypes from functions in execProcnode.c
...
...
src/include/fmgr.h
View file @
18952f67
...
...
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: fmgr.h,v 1.
1 2000/05/28 17:56:12
tgl Exp $
* $Id: fmgr.h,v 1.
2 2000/05/29 01:59:09
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -107,6 +107,7 @@ extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
#define PG_GETARG_BOOL(n) DatumGetBool(fcinfo->arg[n])
#define PG_GETARG_OID(n) DatumGetObjectId(fcinfo->arg[n])
#define PG_GETARG_POINTER(n) DatumGetPointer(fcinfo->arg[n])
#define PG_GETARG_NAME(n) DatumGetName(fcinfo->arg[n])
/* these macros hide the pass-by-reference-ness of the datatype: */
#define PG_GETARG_FLOAT4(n) DatumGetFloat4(fcinfo->arg[n])
#define PG_GETARG_FLOAT8(n) DatumGetFloat8(fcinfo->arg[n])
...
...
@@ -133,6 +134,7 @@ extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
#define PG_RETURN_BOOL(x) return BoolGetDatum(x)
#define PG_RETURN_OID(x) return ObjectIdGetDatum(x)
#define PG_RETURN_POINTER(x) return PointerGetDatum(x)
#define PG_RETURN_NAME(x) return NameGetDatum(x)
/* these macros hide the pass-by-reference-ness of the datatype: */
#define PG_RETURN_FLOAT4(x) return Float4GetDatum(x)
#define PG_RETURN_FLOAT8(x) return Float8GetDatum(x)
...
...
src/include/nodes/nodes.h
View file @
18952f67
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodes.h,v 1.6
7 2000/04/12 17:16:40 momjian
Exp $
* $Id: nodes.h,v 1.6
8 2000/05/29 01:59:12 tgl
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -223,7 +223,13 @@ typedef enum NodeTag
T_CaseExpr
,
T_CaseWhen
,
T_RowMark
,
T_FkConstraint
T_FkConstraint
,
/*---------------------
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (cf. fmgr.h)
*---------------------
*/
T_TriggerData
=
800
/* in commands/trigger.h */
}
NodeTag
;
/*
...
...
src/include/utils/builtins.h
View file @
18952f67
...
...
@@ -7,23 +7,14 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.111 2000/04/16 04:41:03 tgl Exp $
*
* NOTES
* This should normally only be included by fmgr.h.
* Under no circumstances should it ever be included before
* including fmgr.h!
* fmgr.h does not seem to include this file, so don't know where this
* comment came from. Backend code must include this stuff explicitly
* as far as I can tell...
* - thomas 1998-06-08
* $Id: builtins.h,v 1.112 2000/05/29 01:59:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef BUILTINS_H
#define BUILTINS_H
#include "
access/heapam.h"
/* for HeapTuple */
#include "
fmgr.h"
#include "nodes/relation.h"
/* for amcostestimate parameters */
#include "storage/itemptr.h"
#include "utils/array.h"
...
...
@@ -648,17 +639,17 @@ bool lztext_lt(lztext *lz1, lztext *lz2);
bool
lztext_le
(
lztext
*
lz1
,
lztext
*
lz2
);
/* ri_triggers.c */
extern
HeapTuple
RI_FKey_check_ins
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_check_upd
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_noaction_del
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_noaction_upd
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_cascade_del
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_cascade_upd
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_restrict_del
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_restrict_upd
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_setnull_del
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_setnull_upd
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_setdefault_del
(
FmgrInfo
*
proinfo
);
extern
HeapTuple
RI_FKey_setdefault_upd
(
FmgrInfo
*
proinfo
);
extern
Datum
RI_FKey_check_ins
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_check_upd
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_noaction_del
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_noaction_upd
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_cascade_del
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_cascade_upd
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_restrict_del
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_restrict_upd
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_setnull_del
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_setnull_upd
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_setdefault_del
(
PG_FUNCTION_ARGS
);
extern
Datum
RI_FKey_setdefault_upd
(
PG_FUNCTION_ARGS
);
#endif
/* BUILTINS_H */
src/pl/plperl/plperl.c
View file @
18952f67
...
...
@@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.
7 2000/05/28 17:56:26
tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.
8 2000/05/29 01:59:13
tgl Exp $
*
**********************************************************************/
...
...
@@ -283,18 +283,18 @@ plperl_call_handler(PG_FUNCTION_ARGS)
* Determine if called as function or trigger and
* call appropriate subhandler
************************************************************/
if
(
CurrentTriggerData
==
NULL
)
retval
=
plperl_func_handler
(
fcinfo
);
else
if
(
CALLED_AS_TRIGGER
(
fcinfo
))
{
elog
(
ERROR
,
"plperl: can't use perl in triggers yet."
);
/*
* retval =
(Datum) plperl_trigger_handler(fcinfo
);
* retval =
PointerGetDatum(plperl_trigger_handler(fcinfo)
);
*/
/* make the compiler happy */
retval
=
(
Datum
)
0
;
}
else
retval
=
plperl_func_handler
(
fcinfo
);
plperl_call_level
--
;
...
...
@@ -687,7 +687,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
static
HeapTuple
plperl_trigger_handler
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
char
internal_proname
[
512
];
char
*
stroid
;
Tcl_HashEntry
*
hashent
;
...
...
@@ -710,12 +710,6 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
sigjmp_buf
save_restart
;
/************************************************************
* Save the current trigger data local
************************************************************/
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
/************************************************************
* Build our internal proc name from the functions Oid
************************************************************/
...
...
src/pl/plpgsql/src/pl_handler.c
View file @
18952f67
...
...
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.
4 2000/05/28 17:56:28
tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.
5 2000/05/29 01:59:14
tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
...
...
@@ -69,21 +69,10 @@ static PLpgSQL_function *compiled_functions = NULL;
Datum
plpgsql_call_handler
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
bool
isTrigger
;
bool
isTrigger
=
CALLED_AS_TRIGGER
(
fcinfo
);
PLpgSQL_function
*
func
;
Datum
retval
;
/* ----------
* Save the current trigger data local
*
* XXX this should go away in favor of using fcinfo->context
* ----------
*/
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
isTrigger
=
(
trigdata
!=
NULL
);
/* ----------
* Connect to SPI manager
* ----------
...
...
@@ -136,7 +125,8 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
* ----------
*/
if
(
isTrigger
)
retval
=
PointerGetDatum
(
plpgsql_exec_trigger
(
func
,
trigdata
));
retval
=
PointerGetDatum
(
plpgsql_exec_trigger
(
func
,
(
TriggerData
*
)
fcinfo
->
context
));
else
retval
=
plpgsql_exec_function
(
func
,
fcinfo
);
...
...
src/pl/tcl/pltcl.c
View file @
18952f67
...
...
@@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.2
3 2000/05/28 17:56:29
tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.2
4 2000/05/29 01:59:15
tgl Exp $
*
**********************************************************************/
...
...
@@ -390,10 +390,10 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
* Determine if called as function or trigger and
* call appropriate subhandler
************************************************************/
if
(
C
urrentTriggerData
==
NULL
)
retval
=
pltcl_func_handler
(
fcinfo
);
if
(
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
retval
=
PointerGetDatum
(
pltcl_trigger_handler
(
fcinfo
)
);
else
retval
=
(
Datum
)
pltcl_trigger
_handler
(
fcinfo
);
retval
=
pltcl_func
_handler
(
fcinfo
);
pltcl_call_level
--
;
...
...
@@ -734,7 +734,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
static
HeapTuple
pltcl_trigger_handler
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
char
internal_proname
[
512
];
char
*
stroid
;
Tcl_HashEntry
*
hashent
;
...
...
@@ -757,12 +757,6 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
sigjmp_buf
save_restart
;
/************************************************************
* Save the current trigger data local
************************************************************/
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
/************************************************************
* Build our internal proc name from the functions Oid
************************************************************/
...
...
src/test/regress/input/create_function_1.source
View file @
18952f67
...
...
@@ -15,27 +15,27 @@ CREATE FUNCTION widget_out(opaque)
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION autoinc ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/autoinc_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION funny_dup17 ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION ttdummy ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION set_ttdummy (int4)
RETURNS int4
...
...
src/test/regress/output/create_function_1.source
View file @
18952f67
...
...
@@ -13,23 +13,23 @@ CREATE FUNCTION widget_out(opaque)
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION autoinc ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/autoinc_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION funny_dup17 ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION ttdummy ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE '
c
';
LANGUAGE '
newC
';
CREATE FUNCTION set_ttdummy (int4)
RETURNS int4
AS '_OBJWD_/regress_DLSUFFIX_'
...
...
src/test/regress/regress.c
View file @
18952f67
/*
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.3
6 2000/04/12 17:17:21 momjian
Exp $
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.3
7 2000/05/29 01:59:15 tgl
Exp $
*/
#include <float.h>
/* faked on sunos */
...
...
@@ -306,11 +306,12 @@ static int fd17b_level = 0;
static
int
fd17a_level
=
0
;
static
bool
fd17b_recursion
=
true
;
static
bool
fd17a_recursion
=
true
;
HeapTuple
funny_dup17
(
void
);
extern
Datum
funny_dup17
(
PG_FUNCTION_ARGS
);
HeapTuple
/* have to return HeapTuple to Executor */
funny_dup17
()
Datum
funny_dup17
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
TransactionId
*
xid
;
int
*
level
;
bool
*
recursion
;
...
...
@@ -325,10 +326,13 @@ funny_dup17()
int
selected
=
0
;
int
ret
;
tuple
=
CurrentTriggerData
->
tg_trigtuple
;
rel
=
CurrentTriggerData
->
tg_relation
;
if
(
!
CALLED_AS_TRIGGER
(
fcinfo
))
elog
(
ERROR
,
"funny_dup17: not fired by trigger manager"
);
tuple
=
trigdata
->
tg_trigtuple
;
rel
=
trigdata
->
tg_relation
;
tupdesc
=
rel
->
rd_att
;
if
(
TRIGGER_FIRED_BEFORE
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BEFORE
(
trigd
ata
->
tg_event
))
{
xid
=
&
fd17b_xid
;
level
=
&
fd17b_level
;
...
...
@@ -343,8 +347,6 @@ funny_dup17()
when
=
"AFTER "
;
}
CurrentTriggerData
=
NULL
;
if
(
!
TransactionIdIsCurrentTransactionId
(
*
xid
))
{
*
xid
=
GetCurrentTransactionId
();
...
...
@@ -355,11 +357,11 @@ funny_dup17()
if
(
*
level
==
17
)
{
*
recursion
=
false
;
return
tuple
;
return
PointerGetDatum
(
tuple
)
;
}
if
(
!
(
*
recursion
))
return
tuple
;
return
PointerGetDatum
(
tuple
)
;
(
*
level
)
++
;
...
...
@@ -412,10 +414,10 @@ funny_dup17()
if
(
*
level
==
0
)
*
xid
=
InvalidTransactionId
;
return
tuple
;
return
PointerGetDatum
(
tuple
)
;
}
HeapTuple
ttdummy
(
void
);
extern
Datum
ttdummy
(
PG_FUNCTION_ARGS
);
int32
set_ttdummy
(
int32
on
);
extern
int4
nextval
(
struct
varlena
*
seqin
);
...
...
@@ -425,9 +427,10 @@ extern int4 nextval(struct varlena * seqin);
static
void
*
splan
=
NULL
;
static
bool
ttoff
=
false
;
HeapTuple
ttdummy
()
Datum
ttdummy
(
PG_FUNCTION_ARGS
)
{
TriggerData
*
trigdata
=
(
TriggerData
*
)
fcinfo
->
context
;
Trigger
*
trigger
;
/* to get trigger name */
char
**
args
;
/* arguments */
int
attnum
[
2
];
/* fnumbers of start/stop columns */
...
...
@@ -448,30 +451,30 @@ ttdummy()
int
ret
;
int
i
;
if
(
!
C
urrentTriggerData
)
elog
(
ERROR
,
"ttdummy:
triggers are not initialized
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
!
C
ALLED_AS_TRIGGER
(
fcinfo
)
)
elog
(
ERROR
,
"ttdummy:
not fired by trigger manager
"
);
if
(
TRIGGER_FIRED_FOR_STATEMENT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"ttdummy: can't process STATEMENT events"
);
if
(
TRIGGER_FIRED_AFTER
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_AFTER
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"ttdummy: must be fired before event"
);
if
(
TRIGGER_FIRED_BY_INSERT
(
CurrentTriggerD
ata
->
tg_event
))
if
(
TRIGGER_FIRED_BY_INSERT
(
trigd
ata
->
tg_event
))
elog
(
ERROR
,
"ttdummy: can't process INSERT event"
);
if
(
TRIGGER_FIRED_BY_UPDATE
(
CurrentTriggerD
ata
->
tg_event
))
newtuple
=
CurrentTriggerD
ata
->
tg_newtuple
;
if
(
TRIGGER_FIRED_BY_UPDATE
(
trigd
ata
->
tg_event
))
newtuple
=
trigd
ata
->
tg_newtuple
;
trigtuple
=
CurrentTriggerD
ata
->
tg_trigtuple
;
trigtuple
=
trigd
ata
->
tg_trigtuple
;
rel
=
CurrentTriggerD
ata
->
tg_relation
;
rel
=
trigd
ata
->
tg_relation
;
relname
=
SPI_getrelname
(
rel
);
/* check if TT is OFF for this relation */
if
(
ttoff
)
/* OFF - nothing to do */
{
pfree
(
relname
);
return
(
newtuple
!=
NULL
)
?
newtuple
:
trigtuple
;
return
PointerGetDatum
((
newtuple
!=
NULL
)
?
newtuple
:
trigtuple
)
;
}
trigger
=
CurrentTriggerD
ata
->
tg_trigger
;
trigger
=
trigd
ata
->
tg_trigger
;
if
(
trigger
->
tgnargs
!=
2
)
elog
(
ERROR
,
"ttdummy (%s): invalid (!= 2) number of arguments %d"
,
...
...
@@ -481,8 +484,6 @@ ttdummy()
tupdesc
=
rel
->
rd_att
;
natts
=
tupdesc
->
natts
;
CurrentTriggerData
=
NULL
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
attnum
[
i
]
=
SPI_fnumber
(
tupdesc
,
args
[
i
]);
...
...
@@ -517,13 +518,13 @@ ttdummy()
if
(
newoff
!=
TTDUMMY_INFINITY
)
{
pfree
(
relname
);
/* allocated in upper executor context */
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
}
else
if
(
oldoff
!=
TTDUMMY_INFINITY
)
/* DELETE */
{
pfree
(
relname
);
return
NULL
;
return
PointerGetDatum
(
NULL
)
;
}
{
...
...
@@ -618,7 +619,7 @@ ttdummy()
pfree
(
relname
);
return
rettuple
;
return
PointerGetDatum
(
rettuple
)
;
}
int32
...
...
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