*** pgsql/src/backend/utils/adt/ri_triggers_old.c Sat Nov 10 00:01:56 2001 --- pgsql/src/backend/utils/adt/ri_triggers.c Sat Nov 10 00:31:54 2001 *************** *** 218,223 **** --- 218,234 ---- new_row = trigdata->tg_trigtuple; } + /* + * We should not even consider checking the row if it is no longer + * valid since it was either deleted (doesn't matter) or updated + * (in which case it'll be checked with its final values). + */ + if (new_row) { + if (!HeapTupleSatisfiesItself(new_row->t_data)) { + return PointerGetDatum(NULL); + } + } + /* ---------- * SQL3 11.9 * Gereral rules 2) a): *************** *** 613,643 **** if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL) { char buf[256]; ! char querystr[8192]; char *querysep; Oid queryoids[RI_MAX_NUMKEYS]; /* ---------- * The query string built is * SELECT 1 FROM ONLY 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, "SELECT 1 FROM ONLY \"%s\"", tgargs[RI_FK_RELNAME_ARGNO]); querysep = "WHERE"; for (i = 0; i < qkey.nkeypairs; i++) { sprintf(buf, " %s \"%s\" = $%d", querysep, tgargs[4 + i * 2], i + 1); strcat(querystr, buf); querysep = "AND"; queryoids[i] = SPI_gettypeid(pk_rel->rd_att, qkey.keypair[i][RI_KEYPAIR_PK_IDX]); } sprintf(buf, " FOR UPDATE OF \"%s\"", tgargs[RI_FK_RELNAME_ARGNO]); strcat(querystr, buf); --- 624,668 ---- if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL) { char buf[256]; ! char querystr[16384]; ! char notexiststr[8192]; char *querysep; Oid queryoids[RI_MAX_NUMKEYS]; /* ---------- * The query string built is * SELECT 1 FROM ONLY WHERE fkatt1 = $1 [AND ...] + * AND NOT EXISTS (SELECT 1 FROM ONLY WHERE pkatt1 = $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 '='. + * 11/10/01 - The not exists clause was added to the previous + * definition to handle the case where a new row is added to the + * pktable which has the same key values (and thus the constraint + * is satisified). * ---------- */ sprintf(querystr, "SELECT 1 FROM ONLY \"%s\"", tgargs[RI_FK_RELNAME_ARGNO]); + sprintf(notexiststr, "SELECT 1 FROM ONLY \"%s\"", + tgargs[RI_PK_RELNAME_ARGNO]); querysep = "WHERE"; for (i = 0; i < qkey.nkeypairs; i++) { sprintf(buf, " %s \"%s\" = $%d", querysep, tgargs[4 + i * 2], i + 1); strcat(querystr, buf); + sprintf(buf, " %s \"%s\" = $%d", querysep, + tgargs[5 + i * 2], i + 1); + strcat(notexiststr, buf); querysep = "AND"; queryoids[i] = SPI_gettypeid(pk_rel->rd_att, qkey.keypair[i][RI_KEYPAIR_PK_IDX]); } + strcat(querystr, " AND NOT EXISTS ("); + strcat(querystr, notexiststr); + strcat(querystr, ")"); sprintf(buf, " FOR UPDATE OF \"%s\"", tgargs[RI_FK_RELNAME_ARGNO]); strcat(querystr, buf); *************** *** 827,839 **** if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL) { char buf[256]; ! char querystr[8192]; char *querysep; Oid queryoids[RI_MAX_NUMKEYS]; /* ---------- * The query string built is * SELECT 1 FROM ONLY 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 --- 852,866 ---- if ((qplan = ri_FetchPreparedPlan(&qkey)) == NULL) { char buf[256]; ! char querystr[16384]; ! char notexiststr[8192]; char *querysep; Oid queryoids[RI_MAX_NUMKEYS]; /* ---------- * The query string built is * SELECT 1 FROM ONLY WHERE fkatt1 = $1 [AND ...] + * AND NOT EXISTS (SELECT 1 FROM ONLY WHERE pkatt1 = $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 *************** *** 842,857 **** --- 869,892 ---- */ sprintf(querystr, "SELECT 1 FROM ONLY \"%s\"", tgargs[RI_FK_RELNAME_ARGNO]); + sprintf(notexiststr, "SELECT 1 FROM ONLY \"%s\"", + tgargs[RI_PK_RELNAME_ARGNO]); querysep = "WHERE"; for (i = 0; i < qkey.nkeypairs; i++) { sprintf(buf, " %s \"%s\" = $%d", querysep, tgargs[4 + i * 2], i + 1); strcat(querystr, buf); + sprintf(buf, " %s \"%s\" = $%d", querysep, + tgargs[5 + i * 2], i + 1); + strcat(notexiststr, buf); querysep = "AND"; queryoids[i] = SPI_gettypeid(pk_rel->rd_att, qkey.keypair[i][RI_KEYPAIR_PK_IDX]); } + strcat(querystr, " AND NOT EXISTS ("); + strcat(querystr, notexiststr); + strcat(querystr, ")"); sprintf(buf, " FOR UPDATE OF \"%s\"", tgargs[RI_FK_RELNAME_ARGNO]); strcat(querystr, buf);