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}