mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
Fix bogus coding of SET DEFAULT ri triggers ... or at least make it less
bogus than it was. Per bug report from Adrian Pop.
This commit is contained in:
parent
15b9e2c5ff
commit
1bd159e4e9
@ -17,7 +17,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.47 2003/03/15 21:19:40 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.48 2003/03/27 19:25:40 tgl Exp $
|
||||||
*
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -37,6 +37,7 @@
|
|||||||
#include "executor/spi_priv.h"
|
#include "executor/spi_priv.h"
|
||||||
#include "optimizer/planmain.h"
|
#include "optimizer/planmain.h"
|
||||||
#include "parser/parse_oper.h"
|
#include "parser/parse_oper.h"
|
||||||
|
#include "rewrite/rewriteHandler.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
|
|
||||||
@ -2315,10 +2316,8 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
|
|||||||
const char *qualsep;
|
const char *qualsep;
|
||||||
Oid queryoids[RI_MAX_NUMKEYS];
|
Oid queryoids[RI_MAX_NUMKEYS];
|
||||||
Plan *spi_plan;
|
Plan *spi_plan;
|
||||||
AttrDefault *defval;
|
int i;
|
||||||
TargetEntry *spi_qptle;
|
List *l;
|
||||||
int i,
|
|
||||||
j;
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* The query string built is
|
* The query string built is
|
||||||
@ -2355,45 +2354,31 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);
|
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);
|
||||||
|
|
||||||
/* ----------
|
/*
|
||||||
* Here now follows very ugly code depending on internals
|
* Scan the plan's targetlist and replace the NULLs by
|
||||||
* of the SPI manager.
|
* appropriate column defaults, if any (if not, they stay
|
||||||
|
* NULL).
|
||||||
*
|
*
|
||||||
* EVIL EVIL EVIL (but must be - Jan)
|
* XXX This is really ugly; it'd be better to use "UPDATE
|
||||||
*
|
* SET foo = DEFAULT", if we had it.
|
||||||
* We replace the CONST NULL targetlist expressions
|
|
||||||
* in the generated plan by (any) default values found
|
|
||||||
* in the tuple constructor.
|
|
||||||
* ----------
|
|
||||||
*/
|
*/
|
||||||
spi_plan = (Plan *) lfirst(((_SPI_plan *) qplan)->ptlist);
|
spi_plan = (Plan *) lfirst(((_SPI_plan *) qplan)->ptlist);
|
||||||
if (fk_rel->rd_att->constr != NULL)
|
foreach(l, spi_plan->targetlist)
|
||||||
defval = fk_rel->rd_att->constr->defval;
|
|
||||||
else
|
|
||||||
defval = NULL;
|
|
||||||
for (i = 0; i < qkey.nkeypairs && defval != NULL; i++)
|
|
||||||
{
|
{
|
||||||
/*
|
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||||
* For each key attribute lookup the tuple constructor
|
Node *dfl;
|
||||||
* for a corresponding default value
|
|
||||||
*/
|
|
||||||
for (j = 0; j < fk_rel->rd_att->constr->num_defval; j++)
|
|
||||||
{
|
|
||||||
if (defval[j].adnum ==
|
|
||||||
qkey.keypair[i][RI_KEYPAIR_FK_IDX])
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* That's the one - push the expression from
|
|
||||||
* defval.adbin into the plan's targetlist
|
|
||||||
*/
|
|
||||||
spi_qptle = (TargetEntry *)
|
|
||||||
nth(defval[j].adnum - 1,
|
|
||||||
spi_plan->targetlist);
|
|
||||||
spi_qptle->expr = stringToNode(defval[j].adbin);
|
|
||||||
fix_opfuncids((Node *) spi_qptle->expr);
|
|
||||||
|
|
||||||
break;
|
/* Ignore any junk columns or Var=Var columns */
|
||||||
}
|
if (tle->resdom->resjunk)
|
||||||
|
continue;
|
||||||
|
if (IsA(tle->expr, Var))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dfl = build_column_default(fk_rel, tle->resdom->resno);
|
||||||
|
if (dfl)
|
||||||
|
{
|
||||||
|
fix_opfuncids(dfl);
|
||||||
|
tle->expr = (Expr *) dfl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2559,10 +2544,8 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
|
|||||||
const char *qualsep;
|
const char *qualsep;
|
||||||
Oid queryoids[RI_MAX_NUMKEYS];
|
Oid queryoids[RI_MAX_NUMKEYS];
|
||||||
Plan *spi_plan;
|
Plan *spi_plan;
|
||||||
AttrDefault *defval;
|
int i;
|
||||||
TargetEntry *spi_qptle;
|
List *l;
|
||||||
int i,
|
|
||||||
j;
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* The query string built is
|
* The query string built is
|
||||||
@ -2610,50 +2593,30 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
|
|||||||
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);
|
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now replace the CONST NULL targetlist expressions in
|
* Scan the plan's targetlist and replace the NULLs by
|
||||||
* the generated plan by (any) default values found in the
|
* appropriate column defaults, if any (if not, they stay
|
||||||
* tuple constructor.
|
* NULL).
|
||||||
|
*
|
||||||
|
* XXX This is really ugly; it'd be better to use "UPDATE
|
||||||
|
* SET foo = DEFAULT", if we had it.
|
||||||
*/
|
*/
|
||||||
spi_plan = (Plan *) lfirst(((_SPI_plan *) qplan)->ptlist);
|
spi_plan = (Plan *) lfirst(((_SPI_plan *) qplan)->ptlist);
|
||||||
if (fk_rel->rd_att->constr != NULL)
|
foreach(l, spi_plan->targetlist)
|
||||||
defval = fk_rel->rd_att->constr->defval;
|
|
||||||
else
|
|
||||||
defval = NULL;
|
|
||||||
for (i = 0; i < qkey.nkeypairs && defval != NULL; i++)
|
|
||||||
{
|
{
|
||||||
/*
|
TargetEntry *tle = (TargetEntry *) lfirst(l);
|
||||||
* MATCH <unspecified> - only change columns
|
Node *dfl;
|
||||||
* corresponding to changed columns in pk_rel's key.
|
|
||||||
* This conditional must match the one in the loop
|
|
||||||
* above that built the SET attrn=NULL list.
|
|
||||||
*/
|
|
||||||
if (match_type == RI_MATCH_TYPE_FULL ||
|
|
||||||
!ri_OneKeyEqual(pk_rel, i, old_row,
|
|
||||||
new_row, &qkey, RI_KEYPAIR_PK_IDX))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* For each key attribute lookup the tuple
|
|
||||||
* constructor for a corresponding default value
|
|
||||||
*/
|
|
||||||
for (j = 0; j < fk_rel->rd_att->constr->num_defval; j++)
|
|
||||||
{
|
|
||||||
if (defval[j].adnum ==
|
|
||||||
qkey.keypair[i][RI_KEYPAIR_FK_IDX])
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* That's the one - push the expression
|
|
||||||
* from defval.adbin into the plan's
|
|
||||||
* targetlist
|
|
||||||
*/
|
|
||||||
spi_qptle = (TargetEntry *)
|
|
||||||
nth(defval[j].adnum - 1,
|
|
||||||
spi_plan->targetlist);
|
|
||||||
spi_qptle->expr = stringToNode(defval[j].adbin);
|
|
||||||
fix_opfuncids((Node *) spi_qptle->expr);
|
|
||||||
|
|
||||||
break;
|
/* Ignore any junk columns or Var=Var columns */
|
||||||
}
|
if (tle->resdom->resjunk)
|
||||||
}
|
continue;
|
||||||
|
if (IsA(tle->expr, Var))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dfl = build_column_default(fk_rel, tle->resdom->resno);
|
||||||
|
if (dfl)
|
||||||
|
{
|
||||||
|
fix_opfuncids(dfl);
|
||||||
|
tle->expr = (Expr *) dfl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user