001package gudusoft.gsqlparser.nodes;
002
003import gudusoft.gsqlparser.ESqlClause;
004import gudusoft.gsqlparser.TCustomSqlStatement;
005
006/**
007 * Represents a PostgreSQL INSERT ... ON CONFLICT clause (UPSERT).
008 *
009 * <p>PostgreSQL syntax:
010 * <pre>
011 * INSERT INTO table_name ...
012 * ON CONFLICT [ conflict_target ] conflict_action
013 *
014 * conflict_target:
015 *   ( { index_column_name | ( index_expression ) } [, ...] ) [ WHERE index_predicate ]
016 *   | ON CONSTRAINT constraint_name
017 *
018 * conflict_action:
019 *   DO NOTHING
020 *   | DO UPDATE SET { column_name = expression } [, ...] [ WHERE condition ]
021 * </pre>
022 *
023 * @see gudusoft.gsqlparser.stmt.TInsertSqlStatement#getOnConflictClause()
024 */
025public class TOnConflictClause extends TParseTreeNode {
026
027    private EOnConflictActionType actionType;
028
029    /**
030     * Conflict target: index columns/expressions in parentheses.
031     * Each item is a TOrderByItem representing an index element.
032     * Null when ON CONSTRAINT is used or no conflict target is specified.
033     */
034    private TOrderByItemList indexColumns;
035
036    /**
037     * Conflict target: constraint name when ON CONSTRAINT syntax is used.
038     * Null when column-based conflict target or no conflict target is specified.
039     */
040    private TObjectName constraintName;
041
042    /**
043     * WHERE clause on the conflict target (partial unique index predicate).
044     * Only applicable when column-based conflict target is used.
045     */
046    private TWhereClause indexWhereClause;
047
048    /**
049     * SET clause assignments for DO UPDATE action.
050     * Null when action is DO NOTHING.
051     */
052    private TResultColumnList updateSetClause;
053
054    /**
055     * WHERE clause for DO UPDATE action.
056     * Null when action is DO NOTHING or no WHERE specified on the UPDATE.
057     */
058    private TWhereClause updateWhereClause;
059
060    /**
061     * Returns the conflict action type: DO NOTHING or DO UPDATE.
062     * @return the action type
063     */
064    public EOnConflictActionType getActionType() {
065        return actionType;
066    }
067
068    public void setActionType(EOnConflictActionType actionType) {
069        this.actionType = actionType;
070    }
071
072    /**
073     * Returns the list of index column names or expressions that form the conflict target.
074     * @return the index column list, or null if ON CONSTRAINT or no target specified
075     */
076    public TOrderByItemList getIndexColumns() {
077        return indexColumns;
078    }
079
080    public void setIndexColumns(TOrderByItemList indexColumns) {
081        this.indexColumns = indexColumns;
082    }
083
084    /**
085     * Returns the constraint name when ON CONSTRAINT syntax is used.
086     * @return the constraint name, or null
087     */
088    public TObjectName getConstraintName() {
089        return constraintName;
090    }
091
092    public void setConstraintName(TObjectName constraintName) {
093        this.constraintName = constraintName;
094    }
095
096    /**
097     * Returns the WHERE clause for the partial unique index predicate on the conflict target.
098     * @return the index WHERE clause, or null
099     */
100    public TWhereClause getIndexWhereClause() {
101        return indexWhereClause;
102    }
103
104    public void setIndexWhereClause(TWhereClause indexWhereClause) {
105        this.indexWhereClause = indexWhereClause;
106    }
107
108    /**
109     * Returns the SET clause assignments for the DO UPDATE action.
110     * @return the SET clause result column list, or null if DO NOTHING
111     */
112    public TResultColumnList getUpdateSetClause() {
113        return updateSetClause;
114    }
115
116    public void setUpdateSetClause(TResultColumnList updateSetClause) {
117        this.updateSetClause = updateSetClause;
118    }
119
120    /**
121     * Returns the WHERE clause for the DO UPDATE action.
122     * @return the update WHERE clause, or null
123     */
124    public TWhereClause getUpdateWhereClause() {
125        return updateWhereClause;
126    }
127
128    public void setUpdateWhereClause(TWhereClause updateWhereClause) {
129        this.updateWhereClause = updateWhereClause;
130    }
131
132    /**
133     * Sets the conflict target from a TDummy node produced by the grammar.
134     * The TDummy carries: list1 = index columns (TOrderByItemList),
135     * node1 = index WHERE clause (TWhereClause), node2 = constraint name (TObjectName).
136     */
137    public void setConflictTarget(TDummy dummy) {
138        if (dummy == null) return;
139        if (dummy.list1 != null) {
140            this.indexColumns = (TOrderByItemList) dummy.list1;
141        }
142        if (dummy.node1 != null) {
143            this.indexWhereClause = (TWhereClause) dummy.node1;
144        }
145        if (dummy.node2 != null) {
146            this.constraintName = (TObjectName) dummy.node2;
147        }
148    }
149
150    /**
151     * Parses the ON CONFLICT clause within the context of the parent statement.
152     */
153    public void doParse(TCustomSqlStatement psql, ESqlClause clauseType) {
154        if (indexColumns != null) {
155            indexColumns.doParse(psql, clauseType);
156        }
157        if (constraintName != null) {
158            constraintName.doParse(psql, clauseType);
159        }
160        if (indexWhereClause != null) {
161            indexWhereClause.doParse(psql, clauseType);
162        }
163        if (updateSetClause != null) {
164            updateSetClause.doParse(psql, clauseType);
165        }
166        if (updateWhereClause != null) {
167            updateWhereClause.doParse(psql, clauseType);
168        }
169    }
170
171    public void acceptChildren(TParseTreeVisitor v) {
172        if (indexColumns != null) {
173            indexColumns.acceptChildren(v);
174        }
175        if (indexWhereClause != null) {
176            indexWhereClause.acceptChildren(v);
177        }
178        if (updateSetClause != null) {
179            updateSetClause.acceptChildren(v);
180        }
181        if (updateWhereClause != null) {
182            updateWhereClause.acceptChildren(v);
183        }
184    }
185}