001package gudusoft.gsqlparser.ir.semantic;
002
003import gudusoft.gsqlparser.ir.semantic.binding.RelationBinding;
004
005import java.util.ArrayList;
006import java.util.Collections;
007import java.util.List;
008
009/**
010 * Slice 78 — write-side target of an {@code INSERT INTO target SELECT ...}
011 * statement. Carries the target table's binding plus the verbatim column
012 * spellings the SQL author wrote in the INSERT column list (e.g.
013 * {@code INSERT INTO target (a, b) ...} → {@code ["a", "b"]}).
014 *
015 * <p>Empty {@link #columns} means the surface SQL omitted the column list
016 * (e.g. {@code INSERT INTO target SELECT ...}). The IR does NOT
017 * positionally expand the catalog's columns into this list — the source
018 * SELECT's output names are the lineage endpoints, and consumers that
019 * want catalog-mapped target column names can join with the supplied
020 * {@link gudusoft.gsqlparser.ir.semantic.catalog.Catalog}.
021 *
022 * <p>This type is intentionally a 2-field value object so the IR's
023 * navigation stays simple ({@link StatementGraph#getTarget()} is null or
024 * a struct). Other INSERT facets (OUTPUT clause, RETURNING, ON CONFLICT,
025 * partition spec) are out of slice-78 scope and stay rejected via
026 * existing diagnostics.
027 */
028public final class TargetRelation {
029
030    private final RelationBinding binding;
031    private final List<String> columns;
032
033    public TargetRelation(RelationBinding binding, List<String> columns) {
034        if (binding == null) {
035            throw new IllegalArgumentException("binding must not be null");
036        }
037        if (binding.getKind() != RelationKind.TABLE) {
038            throw new IllegalArgumentException(
039                    "TargetRelation binding kind must be TABLE; got " + binding.getKind());
040        }
041        if (columns == null) {
042            throw new IllegalArgumentException("columns must not be null (use empty list)");
043        }
044        this.binding = binding;
045        this.columns = Collections.unmodifiableList(new ArrayList<>(columns));
046    }
047
048    public RelationBinding getBinding() {
049        return binding;
050    }
051
052    /**
053     * @return verbatim SQL spellings of the INSERT column list. Empty when
054     *         the SQL author omitted the column list — in that case the
055     *         source SELECT's output names are the lineage endpoints.
056     */
057    public List<String> getColumns() {
058        return columns;
059    }
060}