/*-------------------------------------------------------------------------
 * conflict.h
 *	   Exports for conflicts logging.
 *
 * Copyright (c) 2024-2026, PostgreSQL Global Development Group
 *
 *-------------------------------------------------------------------------
 */
#ifndef CONFLICT_H
#define CONFLICT_H

#include "access/xlogdefs.h"
#include "datatype/timestamp.h"
#include "nodes/pg_list.h"

/* Avoid including execnodes.h here */
typedef struct EState EState;
typedef struct ResultRelInfo ResultRelInfo;
typedef struct TupleTableSlot TupleTableSlot;


/*
 * Conflict types that could occur while applying remote changes.
 *
 * This enum is used in statistics collection (see
 * PgStat_StatSubEntry::conflict_count and
 * PgStat_BackendSubEntry::conflict_count) as well, therefore, when adding new
 * values or reordering existing ones, ensure to review and potentially adjust
 * the corresponding statistics collection codes.
 */
typedef enum
{
	/* The row to be inserted violates unique constraint */
	CT_INSERT_EXISTS,

	/* The row to be updated was modified by a different origin */
	CT_UPDATE_ORIGIN_DIFFERS,

	/* The updated row value violates unique constraint */
	CT_UPDATE_EXISTS,

	/* The row to be updated was concurrently deleted by a different origin */
	CT_UPDATE_DELETED,

	/* The row to be updated is missing */
	CT_UPDATE_MISSING,

	/* The row to be deleted was modified by a different origin */
	CT_DELETE_ORIGIN_DIFFERS,

	/* The row to be deleted is missing */
	CT_DELETE_MISSING,

	/* The row to be inserted/updated violates multiple unique constraint */
	CT_MULTIPLE_UNIQUE_CONFLICTS,

	/*
	 * Other conflicts, such as exclusion constraint violations, involve more
	 * complex rules than simple equality checks. These conflicts are left for
	 * future improvements.
	 */
} ConflictType;

#define CONFLICT_NUM_TYPES (CT_MULTIPLE_UNIQUE_CONFLICTS + 1)

/*
 * Information for the local row that caused the conflict.
 */
typedef struct ConflictTupleInfo
{
	TupleTableSlot *slot;		/* tuple slot holding the conflicting local
								 * tuple */
	Oid			indexoid;		/* OID of the index where the conflict
								 * occurred */
	TransactionId xmin;			/* transaction ID of the modification causing
								 * the conflict */
	ReplOriginId origin;		/* origin identifier of the modification */
	TimestampTz ts;				/* timestamp of when the modification on the
								 * conflicting local row occurred */
} ConflictTupleInfo;

extern bool GetTupleTransactionInfo(TupleTableSlot *localslot,
									TransactionId *xmin,
									ReplOriginId *localorigin,
									TimestampTz *localts);
extern void ReportApplyConflict(EState *estate, ResultRelInfo *relinfo,
								int elevel, ConflictType type,
								TupleTableSlot *searchslot,
								TupleTableSlot *remoteslot,
								List *conflicttuples);
extern void InitConflictIndexes(ResultRelInfo *relInfo);
#endif
