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: