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
2eb53e68
Commit
2eb53e68
authored
Dec 06, 1999
by
Jan Wieck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added ON DELETE/UPDATE SET NULL
Jan
parent
b8ef7e7f
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
411 additions
and
18 deletions
+411
-18
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/ri_triggers.c
+411
-18
No files found.
src/backend/utils/adt/ri_triggers.c
View file @
2eb53e68
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* 1999 Jan Wieck
* 1999 Jan Wieck
*
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.
4 1999/12/06 18:02:44
wieck Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.
5 1999/12/06 19:50:49
wieck Exp $
*
*
* ----------
* ----------
*/
*/
...
@@ -72,6 +72,8 @@
...
@@ -72,6 +72,8 @@
#define RI_PLAN_CASCADE_UPD_DOUPDATE 1
#define RI_PLAN_CASCADE_UPD_DOUPDATE 1
#define RI_PLAN_RESTRICT_DEL_CHECKREF 1
#define RI_PLAN_RESTRICT_DEL_CHECKREF 1
#define RI_PLAN_RESTRICT_UPD_CHECKREF 1
#define RI_PLAN_RESTRICT_UPD_CHECKREF 1
#define RI_PLAN_SETNULL_DEL_DOUPDATE 1
#define RI_PLAN_SETNULL_UPD_DOUPDATE 1
/* ----------
/* ----------
...
@@ -210,6 +212,10 @@ RI_FKey_check (FmgrInfo *proinfo)
...
@@ -210,6 +212,10 @@ RI_FKey_check (FmgrInfo *proinfo)
* Gereral rules 2) a):
* Gereral rules 2) a):
* If Rf and Rt are empty (no columns to compare given)
* If Rf and Rt are empty (no columns to compare given)
* constraint is true if 0 < (SELECT COUNT(*) FROM T)
* constraint is true if 0 < (SELECT COUNT(*) FROM T)
*
* Note: The special case that no columns are given cannot
* occur up to now in Postgres, it's just there for
* future enhancements.
* ----------
* ----------
*/
*/
if
(
tgnargs
==
4
)
{
if
(
tgnargs
==
4
)
{
...
@@ -562,7 +568,7 @@ RI_FKey_cascade_del (FmgrInfo *proinfo)
...
@@ -562,7 +568,7 @@ RI_FKey_cascade_del (FmgrInfo *proinfo)
heap_close
(
fk_rel
,
NoLock
);
heap_close
(
fk_rel
,
NoLock
);
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_c
heck
()"
);
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_c
ascade_del
()"
);
/* ----------
/* ----------
* Fetch or prepare a saved plan for the cascaded delete
* Fetch or prepare a saved plan for the cascaded delete
...
@@ -714,7 +720,7 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
...
@@ -714,7 +720,7 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
/* ----------
/* ----------
* Get the relation descriptors of the FK and PK tables and
* Get the relation descriptors of the FK and PK tables and
* the old tuple.
* the
new and
old tuple.
* ----------
* ----------
*/
*/
fk_rel
=
heap_openr
(
tgargs
[
RI_FK_RELNAME_ARGNO
],
NoLock
);
fk_rel
=
heap_openr
(
tgargs
[
RI_FK_RELNAME_ARGNO
],
NoLock
);
...
@@ -768,11 +774,11 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
...
@@ -768,11 +774,11 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
return
NULL
;
return
NULL
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_
restrict
_upd()"
);
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_
cascade
_upd()"
);
/* ----------
/* ----------
* Fetch or prepare a saved plan for the
restrict dele
te
* Fetch or prepare a saved plan for the
cascaded upda
te
*
lookup for
foreign references
*
of
foreign references
* ----------
* ----------
*/
*/
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
...
@@ -864,7 +870,7 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
...
@@ -864,7 +870,7 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
return
NULL
;
return
NULL
;
/* ----------
/* ----------
* Handle MATCH PARTIAL
restrict
update.
* Handle MATCH PARTIAL
cascade
update.
* ----------
* ----------
*/
*/
case
RI_MATCH_TYPE_PARTIAL
:
case
RI_MATCH_TYPE_PARTIAL
:
...
@@ -876,7 +882,7 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
...
@@ -876,7 +882,7 @@ RI_FKey_cascade_upd (FmgrInfo *proinfo)
* Never reached
* Never reached
* ----------
* ----------
*/
*/
elog
(
ERROR
,
"internal error #
4
in ri_triggers.c"
);
elog
(
ERROR
,
"internal error #
3
in ri_triggers.c"
);
return
NULL
;
return
NULL
;
}
}
...
@@ -988,7 +994,7 @@ RI_FKey_restrict_del (FmgrInfo *proinfo)
...
@@ -988,7 +994,7 @@ RI_FKey_restrict_del (FmgrInfo *proinfo)
/* ----------
/* ----------
* Fetch or prepare a saved plan for the restrict delete
* Fetch or prepare a saved plan for the restrict delete
* lookup
for foreign references
* lookup
if foreign references exist
* ----------
* ----------
*/
*/
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
...
@@ -1079,7 +1085,7 @@ RI_FKey_restrict_del (FmgrInfo *proinfo)
...
@@ -1079,7 +1085,7 @@ RI_FKey_restrict_del (FmgrInfo *proinfo)
* Never reached
* Never reached
* ----------
* ----------
*/
*/
elog
(
ERROR
,
"internal error #
3
in ri_triggers.c"
);
elog
(
ERROR
,
"internal error #
4
in ri_triggers.c"
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1143,7 +1149,7 @@ RI_FKey_restrict_upd (FmgrInfo *proinfo)
...
@@ -1143,7 +1149,7 @@ RI_FKey_restrict_upd (FmgrInfo *proinfo)
/* ----------
/* ----------
* Get the relation descriptors of the FK and PK tables and
* Get the relation descriptors of the FK and PK tables and
* the old tuple.
* the
new and
old tuple.
* ----------
* ----------
*/
*/
fk_rel
=
heap_openr
(
tgargs
[
RI_FK_RELNAME_ARGNO
],
NoLock
);
fk_rel
=
heap_openr
(
tgargs
[
RI_FK_RELNAME_ARGNO
],
NoLock
);
...
@@ -1200,8 +1206,8 @@ RI_FKey_restrict_upd (FmgrInfo *proinfo)
...
@@ -1200,8 +1206,8 @@ RI_FKey_restrict_upd (FmgrInfo *proinfo)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_restrict_upd()"
);
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_restrict_upd()"
);
/* ----------
/* ----------
* Fetch or prepare a saved plan for the restrict
dele
te
* Fetch or prepare a saved plan for the restrict
upda
te
* lookup
for foreign references
* lookup
if foreign references exist
* ----------
* ----------
*/
*/
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
...
@@ -1292,7 +1298,7 @@ RI_FKey_restrict_upd (FmgrInfo *proinfo)
...
@@ -1292,7 +1298,7 @@ RI_FKey_restrict_upd (FmgrInfo *proinfo)
* Never reached
* Never reached
* ----------
* ----------
*/
*/
elog
(
ERROR
,
"internal error #
4
in ri_triggers.c"
);
elog
(
ERROR
,
"internal error #
5
in ri_triggers.c"
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1307,11 +1313,198 @@ HeapTuple
...
@@ -1307,11 +1313,198 @@ HeapTuple
RI_FKey_setnull_del
(
FmgrInfo
*
proinfo
)
RI_FKey_setnull_del
(
FmgrInfo
*
proinfo
)
{
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
Relation
pk_rel
;
HeapTuple
old_row
;
RI_QueryKey
qkey
;
void
*
qplan
;
Datum
upd_values
[
RI_MAX_NUMKEYS
];
char
upd_nulls
[
RI_MAX_NUMKEYS
+
1
];
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
CurrentTriggerData
=
NULL
;
elog
(
ERROR
,
"RI_FKey_setnull_del() called
\n
"
);
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
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
))
elog
(
ERROR
,
"RI_FKey_setnull_del() must be fired AFTER ROW"
);
if
(
!
TRIGGER_FIRED_BY_DELETE
(
trigdata
->
tg_event
))
elog
(
ERROR
,
"RI_FKey_setnull_del() must be fired for DELETE"
);
/* ----------
* Check for the correct # of call arguments
* ----------
*/
tgnargs
=
trigdata
->
tg_trigger
->
tgnargs
;
tgargs
=
trigdata
->
tg_trigger
->
tgargs
;
if
(
tgnargs
<
4
||
(
tgnargs
%
2
)
!=
0
)
elog
(
ERROR
,
"wrong # of arguments in call to RI_FKey_setnull_del()"
);
if
(
tgnargs
>
RI_MAX_ARGUMENTS
)
elog
(
ERROR
,
"too many keys (%d max) in call to RI_FKey_setnull_del()"
,
RI_MAX_NUMKEYS
);
/* ----------
* Nothing to do if no column names to compare given
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
* the old tuple.
* ----------
*/
fk_rel
=
heap_openr
(
tgargs
[
RI_FK_RELNAME_ARGNO
],
NoLock
);
pk_rel
=
trigdata
->
tg_relation
;
old_row
=
trigdata
->
tg_trigtuple
;
switch
(
ri_DetermineMatchType
(
tgargs
[
RI_MATCH_TYPE_ARGNO
]))
{
/* ----------
* SQL3 11.9 <referential constraint definition>
* Gereral rules 6) a) ii):
* MATCH <UNSPECIFIED> or MATCH FULL
* ... ON DELETE SET NULL
* ----------
*/
case
RI_MATCH_TYPE_UNSPECIFIED
:
case
RI_MATCH_TYPE_FULL
:
ri_BuildQueryKeyFull
(
&
qkey
,
trigdata
->
tg_trigger
->
tgoid
,
RI_PLAN_SETNULL_DEL_DOUPDATE
,
fk_rel
,
pk_rel
,
tgnargs
,
tgargs
);
switch
(
ri_NullCheck
(
pk_rel
,
old_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
{
case
RI_KEYS_ALL_NULL
:
case
RI_KEYS_SOME_NULL
:
/* ----------
* No update - MATCH FULL means there cannot be any
* reference to old key if it contains NULL
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
case
RI_KEYS_NONE_NULL
:
/* ----------
* Have a full qualified key - continue below
* ----------
*/
break
;
}
heap_close
(
fk_rel
,
NoLock
);
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_setnull_del()"
);
/* ----------
* Fetch or prepare a saved plan for the set null delete
* operation
* ----------
*/
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
{
char
buf
[
256
];
char
querystr
[
8192
];
char
qualstr
[
8192
];
char
*
querysep
;
char
*
qualsep
;
Oid
queryoids
[
RI_MAX_NUMKEYS
];
/* ----------
* The query string built is
* UPDATE <fktable> SET fkatt1 = NULL [, ...]
* WHERE fkatt1 = $1 [AND ...]
* The type id's for the $ parameters are those of the
* corresponding PK attributes. Thus, SPI_prepare could
* eventually fail if the parser cannot identify some way
* how to compare these two types by '='.
* ----------
*/
sprintf
(
querystr
,
"UPDATE
\"
%s
\"
SET"
,
tgargs
[
RI_FK_RELNAME_ARGNO
]);
qualstr
[
0
]
=
'\0'
;
querysep
=
""
;
qualsep
=
"WHERE"
;
for
(
i
=
0
;
i
<
qkey
.
nkeypairs
;
i
++
)
{
sprintf
(
buf
,
"%s
\"
%s
\"
= NULL"
,
querysep
,
tgargs
[
4
+
i
*
2
]);
strcat
(
querystr
,
buf
);
sprintf
(
buf
,
" %s
\"
%s
\"
= $%d"
,
qualsep
,
tgargs
[
4
+
i
*
2
],
i
+
1
);
strcat
(
qualstr
,
buf
);
querysep
=
","
;
qualsep
=
"AND"
;
queryoids
[
i
]
=
SPI_gettypeid
(
pk_rel
->
rd_att
,
qkey
.
keypair
[
i
][
RI_KEYPAIR_PK_IDX
]);
}
strcat
(
querystr
,
qualstr
);
/* ----------
* Prepare, save and remember the new plan.
* ----------
*/
qplan
=
SPI_prepare
(
querystr
,
qkey
.
nkeypairs
*
2
,
queryoids
);
qplan
=
SPI_saveplan
(
qplan
);
ri_HashPreparedPlan
(
&
qkey
,
qplan
);
}
/* ----------
* We have a plan now. Build up the arguments for SPI_execp()
* from the key values in the updated PK tuple.
* ----------
*/
for
(
i
=
0
;
i
<
qkey
.
nkeypairs
;
i
++
)
{
upd_values
[
i
]
=
SPI_getbinval
(
old_row
,
pk_rel
->
rd_att
,
qkey
.
keypair
[
i
][
RI_KEYPAIR_PK_IDX
],
&
isnull
);
if
(
isnull
)
upd_nulls
[
i
]
=
'n'
;
else
upd_nulls
[
i
]
=
' '
;
}
upd_nulls
[
i
]
=
'\0'
;
/* ----------
* Now update the existing references
* ----------
*/
if
(
SPI_execp
(
qplan
,
upd_values
,
upd_nulls
,
0
)
!=
SPI_OK_UPDATE
)
elog
(
ERROR
,
"SPI_execp() failed in RI_FKey_setnull_del()"
);
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_setnull_del()"
);
return
NULL
;
/* ----------
* Handle MATCH PARTIAL set null delete.
* ----------
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
}
/* ----------
* Never reached
* ----------
*/
elog
(
ERROR
,
"internal error #6 in ri_triggers.c"
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1326,11 +1519,211 @@ HeapTuple
...
@@ -1326,11 +1519,211 @@ HeapTuple
RI_FKey_setnull_upd
(
FmgrInfo
*
proinfo
)
RI_FKey_setnull_upd
(
FmgrInfo
*
proinfo
)
{
{
TriggerData
*
trigdata
;
TriggerData
*
trigdata
;
int
tgnargs
;
char
**
tgargs
;
Relation
fk_rel
;
Relation
pk_rel
;
HeapTuple
new_row
;
HeapTuple
old_row
;
RI_QueryKey
qkey
;
void
*
qplan
;
Datum
upd_values
[
RI_MAX_NUMKEYS
];
char
upd_nulls
[
RI_MAX_NUMKEYS
+
1
];
bool
isnull
;
int
i
;
trigdata
=
CurrentTriggerData
;
trigdata
=
CurrentTriggerData
;
CurrentTriggerData
=
NULL
;
CurrentTriggerData
=
NULL
;
elog
(
ERROR
,
"RI_FKey_setnull_upd() called
\n
"
);
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if
(
trigdata
==
NULL
)
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
))
elog
(
ERROR
,
"RI_FKey_setnull_upd() must be fired AFTER ROW"
);
if
(
!
TRIGGER_FIRED_BY_UPDATE
(
trigdata
->
tg_event
))
elog
(
ERROR
,
"RI_FKey_setnull_upd() must be fired for UPDATE"
);
/* ----------
* Check for the correct # of call arguments
* ----------
*/
tgnargs
=
trigdata
->
tg_trigger
->
tgnargs
;
tgargs
=
trigdata
->
tg_trigger
->
tgargs
;
if
(
tgnargs
<
4
||
(
tgnargs
%
2
)
!=
0
)
elog
(
ERROR
,
"wrong # of arguments in call to RI_FKey_setnull_upd()"
);
if
(
tgnargs
>
RI_MAX_ARGUMENTS
)
elog
(
ERROR
,
"too many keys (%d max) in call to RI_FKey_setnull_upd()"
,
RI_MAX_NUMKEYS
);
/* ----------
* Nothing to do if no column names to compare given
* ----------
*/
if
(
tgnargs
==
4
)
return
NULL
;
/* ----------
* Get the relation descriptors of the FK and PK tables and
* the old tuple.
* ----------
*/
fk_rel
=
heap_openr
(
tgargs
[
RI_FK_RELNAME_ARGNO
],
NoLock
);
pk_rel
=
trigdata
->
tg_relation
;
new_row
=
trigdata
->
tg_newtuple
;
old_row
=
trigdata
->
tg_trigtuple
;
switch
(
ri_DetermineMatchType
(
tgargs
[
RI_MATCH_TYPE_ARGNO
]))
{
/* ----------
* SQL3 11.9 <referential constraint definition>
* Gereral rules 7) a) ii) 2):
* MATCH FULL
* ... ON UPDATE SET NULL
* ----------
*/
case
RI_MATCH_TYPE_UNSPECIFIED
:
elog
(
ERROR
,
"MATCH UNSPECIFIED not yet supported"
);
return
NULL
;
case
RI_MATCH_TYPE_FULL
:
ri_BuildQueryKeyFull
(
&
qkey
,
trigdata
->
tg_trigger
->
tgoid
,
RI_PLAN_SETNULL_UPD_DOUPDATE
,
fk_rel
,
pk_rel
,
tgnargs
,
tgargs
);
switch
(
ri_NullCheck
(
pk_rel
,
old_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
{
case
RI_KEYS_ALL_NULL
:
case
RI_KEYS_SOME_NULL
:
/* ----------
* No update - MATCH FULL means there cannot be any
* reference to old key if it contains NULL
* ----------
*/
heap_close
(
fk_rel
,
NoLock
);
return
NULL
;
case
RI_KEYS_NONE_NULL
:
/* ----------
* Have a full qualified key - continue below
* ----------
*/
break
;
}
heap_close
(
fk_rel
,
NoLock
);
/* ----------
* No need to do anything if old and new keys are equal
* ----------
*/
if
(
ri_KeysEqual
(
pk_rel
,
old_row
,
new_row
,
&
qkey
,
RI_KEYPAIR_PK_IDX
))
return
NULL
;
if
(
SPI_connect
()
!=
SPI_OK_CONNECT
)
elog
(
NOTICE
,
"SPI_connect() failed in RI_FKey_setnull_upd()"
);
/* ----------
* Fetch or prepare a saved plan for the set null update
* operation
* ----------
*/
if
((
qplan
=
ri_FetchPreparedPlan
(
&
qkey
))
==
NULL
)
{
char
buf
[
256
];
char
querystr
[
8192
];
char
qualstr
[
8192
];
char
*
querysep
;
char
*
qualsep
;
Oid
queryoids
[
RI_MAX_NUMKEYS
];
/* ----------
* The query string built is
* UPDATE <fktable> SET fkatt1 = NULL [, ...]
* WHERE fkatt1 = $1 [AND ...]
* The type id's for the $ parameters are those of the
* corresponding PK attributes. Thus, SPI_prepare could
* eventually fail if the parser cannot identify some way
* how to compare these two types by '='.
* ----------
*/
sprintf
(
querystr
,
"UPDATE
\"
%s
\"
SET"
,
tgargs
[
RI_FK_RELNAME_ARGNO
]);
qualstr
[
0
]
=
'\0'
;
querysep
=
""
;
qualsep
=
"WHERE"
;
for
(
i
=
0
;
i
<
qkey
.
nkeypairs
;
i
++
)
{
sprintf
(
buf
,
"%s
\"
%s
\"
= NULL"
,
querysep
,
tgargs
[
4
+
i
*
2
]);
strcat
(
querystr
,
buf
);
sprintf
(
buf
,
" %s
\"
%s
\"
= $%d"
,
qualsep
,
tgargs
[
4
+
i
*
2
],
i
+
1
);
strcat
(
qualstr
,
buf
);
querysep
=
","
;
qualsep
=
"AND"
;
queryoids
[
i
]
=
SPI_gettypeid
(
pk_rel
->
rd_att
,
qkey
.
keypair
[
i
][
RI_KEYPAIR_PK_IDX
]);
}
strcat
(
querystr
,
qualstr
);
/* ----------
* Prepare, save and remember the new plan.
* ----------
*/
qplan
=
SPI_prepare
(
querystr
,
qkey
.
nkeypairs
*
2
,
queryoids
);
qplan
=
SPI_saveplan
(
qplan
);
ri_HashPreparedPlan
(
&
qkey
,
qplan
);
}
/* ----------
* We have a plan now. Build up the arguments for SPI_execp()
* from the key values in the updated PK tuple.
* ----------
*/
for
(
i
=
0
;
i
<
qkey
.
nkeypairs
;
i
++
)
{
upd_values
[
i
]
=
SPI_getbinval
(
old_row
,
pk_rel
->
rd_att
,
qkey
.
keypair
[
i
][
RI_KEYPAIR_PK_IDX
],
&
isnull
);
if
(
isnull
)
upd_nulls
[
i
]
=
'n'
;
else
upd_nulls
[
i
]
=
' '
;
}
upd_nulls
[
i
]
=
'\0'
;
/* ----------
* Now update the existing references
* ----------
*/
if
(
SPI_execp
(
qplan
,
upd_values
,
upd_nulls
,
0
)
!=
SPI_OK_UPDATE
)
elog
(
ERROR
,
"SPI_execp() failed in RI_FKey_setnull_upd()"
);
if
(
SPI_finish
()
!=
SPI_OK_FINISH
)
elog
(
NOTICE
,
"SPI_finish() failed in RI_FKey_setnull_upd()"
);
return
NULL
;
/* ----------
* Handle MATCH PARTIAL set null update.
* ----------
*/
case
RI_MATCH_TYPE_PARTIAL
:
elog
(
ERROR
,
"MATCH PARTIAL not yet supported"
);
return
NULL
;
}
/* ----------
* Never reached
* ----------
*/
elog
(
ERROR
,
"internal error #7 in ri_triggers.c"
);
return
NULL
;
return
NULL
;
}
}
...
...
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