*** ri_triggers.msg Thu Feb 27 13:53:22 2003 --- ri_triggers.old Thu Feb 27 13:47:36 2003 *************** *** 141,163 **** static bool ri_OneKeyEqual(Relation rel, int column, HeapTuple oldtup, HeapTuple newtup, RI_QueryKey *key, int pairidx); static bool ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue); static bool ri_Check_Pk_Match(Relation pk_rel, HeapTuple old_row, Oid tgoid, int match_type, int tgnargs, char **tgargs); static void ri_InitHashTables(void); static void *ri_FetchPreparedPlan(RI_QueryKey *key); static void ri_HashPreparedPlan(RI_QueryKey *key, void *plan); - static void ri_ReportViolation (const char *constr, Relation pk_rel, - Relation fk_rel, RI_QueryKey *qkey, - HeapTuple violator); /* ---------- * RI_FKey_check - * * Check foreign key existence (combined for INSERT and UPDATE). * ---------- */ static Datum RI_FKey_check(PG_FUNCTION_ARGS) { TriggerData *trigdata = (TriggerData *) fcinfo->context; --- 141,160 ---- *************** *** 294,315 **** elog(WARNING, "SPI_connect() failed in RI_FKey_check()"); SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_check()"); SetUserId(save_uid); if (SPI_processed == 0) ! ri_ReportViolation (tgargs[RI_CONSTRAINT_NAME_ARGNO], pk_rel, fk_rel, ! &qkey, NULL); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_check()"); heap_close(pk_rel, RowShareLock); return PointerGetDatum(NULL); } --- 291,314 ---- elog(WARNING, "SPI_connect() failed in RI_FKey_check()"); SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_check()"); SetUserId(save_uid); if (SPI_processed == 0) ! elog(ERROR, "%s referential integrity violation - " ! "no rows found in %s", ! tgargs[RI_CONSTRAINT_NAME_ARGNO], ! RelationGetRelationName(pk_rel)); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_check()"); heap_close(pk_rel, RowShareLock); return PointerGetDatum(NULL); } *************** *** 476,497 **** */ SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_check()"); SetUserId(save_uid); if (SPI_processed == 0) ! ri_ReportViolation (tgargs[RI_CONSTRAINT_NAME_ARGNO], pk_rel, fk_rel, ! &qkey, new_row); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_check()"); heap_close(pk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Never reached --- 475,499 ---- */ SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_check()"); SetUserId(save_uid); if (SPI_processed == 0) ! elog(ERROR, "%s referential integrity violation - " ! "key referenced from %s not found in %s", ! tgargs[RI_CONSTRAINT_NAME_ARGNO], ! RelationGetRelationName(fk_rel), ! RelationGetRelationName(pk_rel)); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_check()"); heap_close(pk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Never reached *************** *** 871,900 **** if (isnull) del_nulls[i] = 'n'; else del_nulls[i] = ' '; } del_nulls[i] = '\0'; /* * Now check for existing references */ ! SetUserId(RelationGetForm(fk_rel)->relowner); if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_del()"); SetUserId(save_uid); if (SPI_processed > 0) ! ri_ReportViolation (tgargs[RI_CONSTRAINT_NAME_ARGNO], ! pk_rel, fk_rel, &qkey, old_row); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_noaction_del()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL restrict delete. --- 873,905 ---- if (isnull) del_nulls[i] = 'n'; else del_nulls[i] = ' '; } del_nulls[i] = '\0'; /* * Now check for existing references */ ! SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_del()"); SetUserId(save_uid); if (SPI_processed > 0) ! elog(ERROR, "%s referential integrity violation - " ! "key in %s still referenced from %s", ! tgargs[RI_CONSTRAINT_NAME_ARGNO], ! RelationGetRelationName(pk_rel), ! RelationGetRelationName(fk_rel)); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_noaction_del()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL restrict delete. *************** *** 1109,1138 **** if (isnull) upd_nulls[i] = 'n'; else upd_nulls[i] = ' '; } upd_nulls[i] = '\0'; /* * Now check for existing references */ ! SetUserId(RelationGetForm(fk_rel)->relowner); if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_upd()"); SetUserId(save_uid); if (SPI_processed > 0) ! ri_ReportViolation (tgargs[RI_CONSTRAINT_NAME_ARGNO], ! pk_rel, fk_rel, &qkey, old_row); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_noaction_upd()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL noaction update. --- 1114,1146 ---- if (isnull) upd_nulls[i] = 'n'; else upd_nulls[i] = ' '; } upd_nulls[i] = '\0'; /* * Now check for existing references */ ! SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_upd()"); SetUserId(save_uid); if (SPI_processed > 0) ! elog(ERROR, "%s referential integrity violation - " ! "key in %s still referenced from %s", ! tgargs[RI_CONSTRAINT_NAME_ARGNO], ! RelationGetRelationName(pk_rel), ! RelationGetRelationName(fk_rel)); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_noaction_upd()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL noaction update. *************** *** 1781,1802 **** */ save_uid = GetUserId(); SetUserId(fk_owner); if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_del()"); SetUserId(save_uid); if (SPI_processed > 0) ! ri_ReportViolation (tgargs[RI_CONSTRAINT_NAME_ARGNO], ! pk_rel, fk_rel, &qkey, old_row); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_restrict_del()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL restrict delete. --- 1789,1813 ---- */ save_uid = GetUserId(); SetUserId(fk_owner); if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_del()"); SetUserId(save_uid); if (SPI_processed > 0) ! elog(ERROR, "%s referential integrity violation - " ! "key in %s still referenced from %s", ! tgargs[RI_CONSTRAINT_NAME_ARGNO], ! RelationGetRelationName(pk_rel), ! RelationGetRelationName(fk_rel)); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_restrict_del()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL restrict delete. *************** *** 2014,2035 **** SetUserId(fk_owner); SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_upd()"); SetUserId(save_uid); if (SPI_processed > 0) ! ri_ReportViolation (tgargs[RI_CONSTRAINT_NAME_ARGNO], ! pk_rel, fk_rel, &qkey, old_row); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_restrict_upd()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL restrict update. --- 2025,2049 ---- SetUserId(fk_owner); SetUserId(RelationGetForm(pk_rel)->relowner); if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT) elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_upd()"); SetUserId(save_uid); if (SPI_processed > 0) ! elog(ERROR, "%s referential integrity violation - " ! "key in %s still referenced from %s", ! tgargs[RI_CONSTRAINT_NAME_ARGNO], ! RelationGetRelationName(pk_rel), ! RelationGetRelationName(fk_rel)); if (SPI_finish() != SPI_OK_FINISH) elog(WARNING, "SPI_finish() failed in RI_FKey_restrict_upd()"); heap_close(fk_rel, RowShareLock); return PointerGetDatum(NULL); /* * Handle MATCH PARTIAL restrict update. *************** *** 3289,3373 **** key->keypair[i][RI_KEYPAIR_FK_IDX] = fno; fno = SPI_fnumber(pk_rel->rd_att, argv[j + 1]); if (fno == SPI_ERROR_NOATTRIBUTE) elog(ERROR, "constraint %s: table %s does not have an attribute %s", argv[RI_CONSTRAINT_NAME_ARGNO], RelationGetRelationName(pk_rel), argv[j + 1]); key->keypair[i][RI_KEYPAIR_PK_IDX] = fno; } - } - - static void ri_ReportViolation (const char *constr, Relation pk_rel, - Relation fk_rel, RI_QueryKey *qkey, - HeapTuple violator) - { - static char *null_str = "null"; - - char key_names [512]; - char key_values [512]; - - char *name_ptr = key_names; - char *val_ptr = key_values; - int idx = 0; - - /* If the failed constraint was on insert/update to the FK table, - * we want the key names and values extracted from there, and the error - * message to look like 'key blah referenced from FK not found in PK' - * Otherwise, the attr names and values come from the PK table and the - * message looks like 'key blah in PK still referenced in FK'. - * So, rel is set to where the tuple description is coming from - * (FK in the first case, and PK in the second case), and it also is - * the first relation mentioned in the message, other_rel is respectively - * the other relation. - */ - - bool onfk = (qkey -> constr_queryno == RI_PLAN_CHECK_LOOKUPPK); - - int key_idx = onfk ? RI_KEYPAIR_FK_IDX : RI_KEYPAIR_PK_IDX; - Relation rel = onfk ? fk_rel : pk_rel; - Relation other_rel = onfk ? pk_rel : fk_rel; - - /* Special case - if there are no keys at all, this is a 'no column' - * constraint - no need to try to extract the values, and the message - * in this case looks differently - */ - if (qkey -> nkeypairs == 0) - elog(ERROR, "%s referential integrity violation - no rows found in %s", - constr, RelationGetRelationName(pk_rel)); - - for (idx = 0; idx < qkey->nkeypairs; idx++) - { - int fnum = qkey->keypair[idx][key_idx]; - char *name = SPI_fname (rel->rd_att, fnum); - char *val = SPI_getvalue (violator, rel->rd_att, fnum); - if (!val) - val = null_str; - - if (name_ptr - key_names + strlen(name) + 5 >= 512 || - val_ptr - key_values + strlen (val) + 5 >= 512) - { - sprintf (name_ptr, "..."); - sprintf (val_ptr, "..."); - break; - } - - name_ptr += sprintf (name_ptr, "%s%s", idx > 0 ? "," : "", name); - val_ptr += sprintf (val_ptr, "%s%s", idx > 0 ? "," : "", val); - } - - elog (ERROR, "%s referential integrity violation - key (%s)=(%s) " - "%s %s %s in %s", constr, key_names, key_values, - onfk ? "referenced from" : "in", RelationGetRelationName (rel), - onfk ? "not found" : "still referenced", - RelationGetRelationName (other_rel)); } /* ---------- * ri_BuildQueryKeyPkCheck - * * Build up a new hashtable key for a prepared SPI plan of a * check for PK rows in noaction triggers. * * constr_type is FULL * constr_id is the OID of the pg_trigger row that invoked us --- 3303,3322 ----