Thread
-
Re: COPY ON_CONFLICT TABLE; save duplicated record to another table.
jian he <jian.universality@gmail.com> — 2026-05-12T08:15:19Z
On Tue, May 12, 2026 at 4:40 AM Zsolt Parragi <zsolt.parragi@percona.com> wrote: > > Hello! > > > One other thing I just noticed in BINARY mode. I believe we're missing a > > check in ProcessCopyOptions() with ON_CONFLICT TABLE to show a proper > > error message, e.g. > > It is possible to crash the current patch with binary mode, that check > is definitely needed. > binary mode lacks the concept of a line number or the whole line string. Since cstate->line_buf is null in binary mode, it will segfault in ```CStringGetTextDatum(cstate->line_buf.data);``` Supporting ON_CONFLICT in binary mode is not trivial. Since ON_ERROR IGNORE also cannot be used in binary mode, not supporting ON_CONFLICT in binary mode should be fine, IMHO. > > + MakeTransitionCaptureState(cstate->conflictRel->trigdesc, > + RelationGetRelid(cstate->conflictRel), > + CMD_INSERT); > > Shouldn't this update mtstate->mt_transition_capture? > Attached v3 fix this issue. > + if (cstate->opts.on_conflict == ONCONFLICT_TABLE) > ... > + if (conflict_mstate->fireBSTriggers) > + { > + ExecBSInsertTriggers(conflict_mstate->ps.state, > conflict_mstate->rootResultRelInfo); > + > + conflict_mstate->fireBSTriggers = false; > + } > + > > and > > + if (cstate->num_conflicts > 0) > + { > ... > + /* Execute AFTER STATEMENT insertion triggers */ > + ExecASInsertTriggers(cstate->mtcontext->estate, > + on_conflict_mtstate->rootResultRelInfo, > + on_conflict_mtstate->mt_transition_capture); > > > * Doesn't statements typically fire triggers unconditionally? INSERT > ON CONFLICT DO NOTHING; fires BS+AS triggers even if it doesn't insert > any rows. > * Isn't firing a before statement trigger after some before/after row > triggers were already fired (for non conflicting rows) strange? > Ok. I changed to Statement-level triggers on the CONFLICT_TABLE are fired unconditionally, regardless of whether an error occurred or not. Each row inserted into the CONFLICT_TABLE will fire both the BEFORE INSERT FOR EACH ROW and AFTER INSERT FOR EACH ROW triggers. > + if (valid_col_count != 4) > + errdetail_msg = _("The conflict_table is incomplete; exactly four > columns are required."); > > if valid_col_count > 4, is it still incomplete, shouldn't the error > message change in that case? With v3, whether there are more or fewer columns on the conflict_table, the error message is now the same: +ERROR: cannot use relation "err_tbl1" for COPY on_conflict error saving +DETAIL: The conflict_table should only have four columns +HINT: The conflict_table must contain exactly four columns with data types, in order: OID, TEXT, BIGINT, TEXT Regression tests for permission checks have also been added. -- jian https://www.enterprisedb.com/