001package gudusoft.gsqlparser.ir.semantic.catalog;
002
003import java.util.ArrayList;
004import java.util.Collections;
005import java.util.List;
006
007/**
008 * Slice 76 — minimal table descriptor inside a {@link Catalog}.
009 *
010 * <p>Carries a name (possibly qualified, e.g. {@code "schema.table"}; the
011 * exact qualifier rules are delegated to {@code TSQLEnv.addTable} via the
012 * analyzer's internal bridge) and an ordered list of
013 * {@link CatalogColumn}s.
014 *
015 * <p>This class is immutable; construct it via {@link #builder(String)}.
016 */
017public final class CatalogTable {
018
019    private final String name;
020    private final List<CatalogColumn> columns;
021
022    private CatalogTable(String name, List<CatalogColumn> columns) {
023        this.name = name;
024        this.columns = Collections.unmodifiableList(columns);
025    }
026
027    public static Builder builder(String name) {
028        return new Builder(name);
029    }
030
031    public String getName() {
032        return name;
033    }
034
035    /**
036     * @return an unmodifiable view of the columns in declaration order.
037     */
038    public List<CatalogColumn> getColumns() {
039        return columns;
040    }
041
042    /**
043     * Slice 173 (join-analysis S12) — case-insensitive lookup of a column
044     * by name, so a consumer holding a resolved {@code ColumnRef} can
045     * surface that column's catalog metadata (type / nullability / PK /
046     * unique / index). Returns {@code null} when no column matches.
047     */
048    public CatalogColumn findColumn(String columnName) {
049        if (columnName == null) return null;
050        for (CatalogColumn c : columns) {
051            if (c.getName().equalsIgnoreCase(columnName)) {
052                return c;
053            }
054        }
055        return null;
056    }
057
058    @Override
059    public String toString() {
060        return "CatalogTable{name=" + name + ", columns=" + columns + "}";
061    }
062
063    /**
064     * Mutable builder for {@link CatalogTable}. Single-use:
065     * {@link #build()} returns one {@code CatalogTable} and the builder
066     * should not be reused after that.
067     */
068    public static final class Builder {
069        private final String name;
070        private final List<CatalogColumn> columns = new ArrayList<>();
071
072        private Builder(String name) {
073            if (name == null) {
074                throw new IllegalArgumentException("table name must not be null");
075            }
076            if (name.isEmpty()) {
077                throw new IllegalArgumentException("table name must not be empty");
078            }
079            this.name = name;
080        }
081
082        /** Convenience overload — equivalent to {@code addColumn(new CatalogColumn(name))}. */
083        public Builder addColumn(String columnName) {
084            return addColumn(new CatalogColumn(columnName));
085        }
086
087        public Builder addColumn(CatalogColumn column) {
088            if (column == null) {
089                throw new IllegalArgumentException("column must not be null");
090            }
091            columns.add(column);
092            return this;
093        }
094
095        public CatalogTable build() {
096            return new CatalogTable(name, new ArrayList<>(columns));
097        }
098    }
099}