Index: src/backend/access/nbtree/nbtinsert.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v retrieving revision 1.131 diff -c -r1.131 nbtinsert.c *** src/backend/access/nbtree/nbtinsert.c 17 Jan 2006 00:09:00 -0000 1.131 --- src/backend/access/nbtree/nbtinsert.c 2 Feb 2006 20:05:47 -0000 *************** *** 121,127 **** { TransactionId xwait; ! xwait = _bt_check_unique(rel, btitem, heapRel, buf, itup_scankey); if (TransactionIdIsValid(xwait)) { --- 121,139 ---- { TransactionId xwait; ! PG_TRY(); ! { ! xwait = _bt_check_unique(rel, btitem, heapRel, buf, itup_scankey); ! } ! PG_CATCH(); ! { ! _bt_freestack(stack); ! _bt_freeskey(itup_scankey); ! HOLD_INTERRUPTS(); ! _bt_wrtbuf(rel, buf); ! PG_RE_THROW(); ! } ! PG_END_TRY(); if (TransactionIdIsValid(xwait)) { *************** *** 240,245 **** --- 252,259 ---- return xwait; } + if (nbuf != InvalidBuffer) + ReleaseBuffer(nbuf); /* * Otherwise we have a definite conflict. */ Index: src/backend/commands/copy.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/commands/copy.c,v retrieving revision 1.257 diff -c -r1.257 copy.c *** src/backend/commands/copy.c 28 Dec 2005 03:25:32 -0000 1.257 --- src/backend/commands/copy.c 2 Feb 2006 20:05:47 -0000 *************** *** 1968,1973 **** --- 1968,1975 ---- if (!skip_tuple) { + bool trapped = false; + /* Place tuple in tuple slot */ ExecStoreTuple(tuple, slot, InvalidBuffer, false); *************** *** 1979,1988 **** simple_heap_insert(cstate->rel, tuple); if (resultRelInfo->ri_NumIndices > 0) ! ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); /* AFTER ROW INSERT Triggers */ ! ExecARInsertTriggers(estate, resultRelInfo, tuple); } } --- 1981,2022 ---- simple_heap_insert(cstate->rel, tuple); if (resultRelInfo->ri_NumIndices > 0) ! { ! MemoryContext curr = CurrentMemoryContext; ! PG_TRY(); ! { ! ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); ! } ! PG_CATCH(); ! { ! trapped = true; ! MemoryContextSwitchTo(curr); ! } ! PG_END_TRY(); ! ! if (trapped) ! { ! ErrorData *ed; ! TransactionId xid; ! ItemPointerData tid; ! ! ed = CopyErrorData(); ! FlushErrorState(); ! if (ed->sqlerrcode != ERRCODE_UNIQUE_VIOLATION) ! ReThrowError(ed); ! ! FreeErrorData(ed); ! heap_delete(cstate->rel, ! &(tuple->t_self), &tid, &xid, ! GetCurrentCommandId() + 1, ! InvalidSnapshot, ! true); ! } ! } /* AFTER ROW INSERT Triggers */ ! if (!trapped) ! ExecARInsertTriggers(estate, resultRelInfo, tuple); } } Index: src/backend/executor/execMain.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/executor/execMain.c,v retrieving revision 1.265 diff -c -r1.265 execMain.c *** src/backend/executor/execMain.c 12 Jan 2006 21:48:53 -0000 1.265 --- src/backend/executor/execMain.c 2 Feb 2006 20:05:47 -0000 *************** *** 1444,1453 **** * insert index entries for tuple */ if (resultRelInfo->ri_NumIndices > 0) ! ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); ! /* AFTER ROW INSERT Triggers */ ! ExecARInsertTriggers(estate, resultRelInfo, tuple); } /* ---------------------------------------------------------------- --- 1444,1494 ---- * insert index entries for tuple */ if (resultRelInfo->ri_NumIndices > 0) ! { ! bool trapped_tuple = false; ! MemoryContext curr = CurrentMemoryContext; ! ! PG_TRY(); ! { ! ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); ! } ! PG_CATCH(); ! { ! trapped_tuple = true; ! MemoryContextSwitchTo(curr); ! } ! PG_END_TRY(); ! ! if (trapped_tuple) ! { ! ErrorData *ed; ! TransactionId xid; ! ItemPointerData tid = {{0, 0}, 0}; ! ! ed = CopyErrorData(); ! FlushErrorState(); ! if (ed->sqlerrcode != ERRCODE_UNIQUE_VIOLATION) ! ReThrowError(ed); ! ! FreeErrorData(ed); ! (estate->es_processed)--; ! estate->es_lastoid = InvalidOid; ! setLastTid(&tid); ! ! heap_delete(resultRelationDesc, ! &(tuple->t_self), &tid, &xid, ! estate->es_snapshot->curcid + 1, ! estate->es_crosscheck_snapshot, ! true); ! CommandCounterIncrement(); ! } ! if (!trapped_tuple) ! { ! /* AFTER ROW INSERT Triggers */ ! ExecARInsertTriggers(estate, resultRelInfo, tuple); ! } ! } } /* ---------------------------------------------------------------- Index: src/backend/parser/gram.y =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v retrieving revision 2.521 diff -c -r2.521 gram.y *** src/backend/parser/gram.y 29 Dec 2005 04:53:18 -0000 2.521 --- src/backend/parser/gram.y 2 Feb 2006 20:05:48 -0000 *************** *** 230,235 **** --- 230,237 ---- prep_type_clause prep_type_list execute_param_clause using_clause + %type insert_unless insert_unless_constraints + %type into_clause OptTempTableName %type createfunc_opt_item common_func_opt_item *************** *** 406,415 **** TRUNCATE TRUSTED TYPE_P UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL ! UPDATE USER USING VACUUM VALID VALIDATOR VALUES VARCHAR VARYING ! VERBOSE VIEW VOLATILE WHEN WHERE WITH WITHOUT WORK WRITE --- 408,417 ---- TRUNCATE TRUSTED TYPE_P UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL ! UNLESS UPDATE USER USING VACUUM VALID VALIDATOR VALUES VARCHAR VARYING ! VERBOSE VIEW VIOLATION VOLATILE WHEN WHERE WITH WITHOUT WORK WRITE *************** *** 5071,5080 **** *****************************************************************************/ InsertStmt: ! INSERT INTO qualified_name insert_rest { ! $4->relation = $3; ! $$ = (Node *) $4; } ; --- 5073,5099 ---- *****************************************************************************/ InsertStmt: ! INSERT INTO qualified_name insert_unless insert_rest ! { ! $5->relation = $3; ! $5->unless = $4; ! $$ = (Node *) $5; ! } ! ; ! ! insert_unless: ! UNLESS CONSTRAINT VIOLATION ON insert_unless_constraints { ! $$ = $5; ! } ! | /* empty */ ! { $$ = NIL; } ! ; ! ! insert_unless_constraints: ! '(' constraints_set_list ')' ! { ! $$ = $2; } ; *************** *** 8315,8320 **** --- 8334,8340 ---- | UNCOMMITTED | UNENCRYPTED | UNKNOWN + | UNLESS | UNLISTEN | UNTIL | UPDATE *************** *** 8324,8329 **** --- 8344,8350 ---- | VALUES | VARYING | VIEW + | VIOLATION | VOLATILE | WITH | WITHOUT Index: src/backend/parser/keywords.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v retrieving revision 1.170 diff -c -r1.170 keywords.c *** src/backend/parser/keywords.c 27 Dec 2005 04:00:07 -0000 1.170 --- src/backend/parser/keywords.c 2 Feb 2006 20:05:48 -0000 *************** *** 345,350 **** --- 345,351 ---- {"union", UNION}, {"unique", UNIQUE}, {"unknown", UNKNOWN}, + {"unless", UNLESS}, {"unlisten", UNLISTEN}, {"until", UNTIL}, {"update", UPDATE}, *************** *** 358,363 **** --- 359,365 ---- {"varying", VARYING}, {"verbose", VERBOSE}, {"view", VIEW}, + {"violation", VIOLATION}, {"volatile", VOLATILE}, {"when", WHEN}, {"where", WHERE}, Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.298 diff -c -r1.298 parsenodes.h *** src/include/nodes/parsenodes.h 7 Dec 2005 15:20:55 -0000 1.298 --- src/include/nodes/parsenodes.h 2 Feb 2006 20:05:48 -0000 *************** *** 602,607 **** --- 602,608 ---- NodeTag type; RangeVar *relation; /* relation to insert into */ List *cols; /* optional: names of the target columns */ + List *unless; /* optional: names of indexes to avoid */ /* * An INSERT statement has *either* VALUES or SELECT, never both. If