Re: Postgresql 7.3.2 Crash

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Stephan Szabo <sszabo(at)megazone23(dot)bigpanda(dot)com>
Cc: Adrian Pop <adrpo(at)ida(dot)liu(dot)se>, pgsql-bugs(at)postgresql(dot)org
Subject: Re: Postgresql 7.3.2 Crash
Date: 2003-03-27 19:27:45
Message-ID: 15479.1048793265@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Stephan Szabo <sszabo(at)megazone23(dot)bigpanda(dot)com> writes:
> That's because the set default uses a pretty ugly hack. It plans the
> query with =NULL and then replaces the NULL with the default value's
> stored plan info. My first guess is that it's something with this that's
> causing the crash.

I've applied the attached patch (for 7.3, cvs tip is a bit different)
to fix this problem.

regards, tom lane

*** src/backend/utils/adt/ri_triggers.c.orig Thu Oct 3 17:06:23 2002
--- src/backend/utils/adt/ri_triggers.c Thu Mar 27 11:28:36 2003
***************
*** 35,41 ****
--- 35,43 ----
#include "catalog/pg_operator.h"
#include "commands/trigger.h"
#include "executor/spi_priv.h"
+ #include "optimizer/planmain.h"
#include "parser/parse_oper.h"
+ #include "rewrite/rewriteHandler.h"
#include "utils/lsyscache.h"
#include "miscadmin.h"

***************
*** 2672,2681 ****
const char *qualsep;
Oid queryoids[RI_MAX_NUMKEYS];
Plan *spi_plan;
! AttrDefault *defval;
! TargetEntry *spi_qptle;
! int i,
! j;

/* ----------
* The query string built is
--- 2674,2681 ----
const char *qualsep;
Oid queryoids[RI_MAX_NUMKEYS];
Plan *spi_plan;
! int i;
! List *l;

/* ----------
* The query string built is
***************
*** 2712,2755 ****
*/
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);

! /* ----------
! * Here now follows very ugly code depending on internals
! * of the SPI manager.
! *
! * EVIL EVIL EVIL (but must be - Jan)
*
! * 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);
! if (fk_rel->rd_att->constr != NULL)
! defval = fk_rel->rd_att->constr->defval;
! else
! defval = NULL;
! for (i = 0; i < qkey.nkeypairs && defval != NULL; i++)
{
! /*
! * 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);

! break;
! }
}
}
}
--- 2712,2742 ----
*/
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);

! /*
! * Scan the plan's targetlist and replace the NULLs by
! * appropriate column defaults, if any (if not, they stay
! * 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);
! foreach(l, spi_plan->targetlist)
{
! TargetEntry *tle = (TargetEntry *) lfirst(l);
! Node *dfl;

! /* 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_opids(dfl);
! tle->expr = dfl;
}
}
}
***************
*** 2947,2956 ****
const char *qualsep;
Oid queryoids[RI_MAX_NUMKEYS];
Plan *spi_plan;
! AttrDefault *defval;
! TargetEntry *spi_qptle;
! int i,
! j;

/* ----------
* The query string built is
--- 2934,2941 ----
const char *qualsep;
Oid queryoids[RI_MAX_NUMKEYS];
Plan *spi_plan;
! int i;
! List *l;

/* ----------
* The query string built is
***************
*** 2998,3046 ****
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);

/*
! * Now 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);
! if (fk_rel->rd_att->constr != NULL)
! defval = fk_rel->rd_att->constr->defval;
! else
! defval = NULL;
! for (i = 0; i < qkey.nkeypairs && defval != NULL; i++)
{
! /*
! * MATCH <unspecified> - only change columns
! * 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);
!
! break;
! }
! }
}
}
}
--- 2983,3012 ----
qplan = SPI_prepare(querystr, qkey.nkeypairs, queryoids);

/*
! * Scan the plan's targetlist and replace the NULLs by
! * appropriate column defaults, if any (if not, they stay
! * 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);
! foreach(l, spi_plan->targetlist)
{
! TargetEntry *tle = (TargetEntry *) lfirst(l);
! Node *dfl;
!
! /* 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_opids(dfl);
! tle->expr = dfl;
}
}
}

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2003-03-27 19:38:31 Re: Solution for bug #899
Previous Message Bruce Momjian 2003-03-27 16:39:35 Re: Solution for bug #899