Re: Postgresql 7.3.2 Crash - Mailing list pgsql-bugs

From Tom Lane
Subject Re: Postgresql 7.3.2 Crash
Date
Msg-id 15479.1048793265@sss.pgh.pa.us
Whole thread Raw
In response to Re: Postgresql 7.3.2 Crash  (Stephan Szabo <sszabo@megazone23.bigpanda.com>)
List pgsql-bugs
Stephan Szabo <sszabo@megazone23.bigpanda.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;
                      }
                  }
              }

pgsql-bugs by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: Solution for bug #899
Next
From: Tom Lane
Date:
Subject: Re: Solution for bug #899