001package gudusoft.gsqlparser.ir.semantic.catalog;
002
003/**
004 * Slice 76 — minimal column descriptor inside a {@link Catalog}.
005 *
006 * <p>Slice 173 (join-analysis S12) extends it with optional, additive
007 * metadata — declared data type, nullability, and PRIMARY KEY / UNIQUE /
008 * indexed flags — that external callers <em>may</em> supply. The parser
009 * never fetches these; they are accepted and surfaced verbatim. The
010 * one-arg constructor and all prior behaviour are unchanged: a column
011 * built with just a name reports {@code null} type, {@code null}
012 * nullability (unknown), and {@code false} key/index flags.
013 *
014 * <p>Identifier semantics (case folding, quoted vs unquoted, vendor
015 * rules) are delegated to {@code TSQLEnv} via the analyzer's internal
016 * bridge — names are stored exactly as written by the caller.
017 *
018 * <p>This class is immutable and safe to share across threads.
019 */
020public final class CatalogColumn {
021
022    private final String name;
023    private final String dataType;
024    private final Boolean nullable;
025    private final boolean primaryKey;
026    private final boolean unique;
027    private final boolean indexed;
028
029    /**
030     * @param name the column name as written by the caller; must be non-null
031     *             and non-empty.
032     * @throws IllegalArgumentException when {@code name} is {@code null} or empty.
033     */
034    public CatalogColumn(String name) {
035        this(name, null, null, false, false, false);
036    }
037
038    /**
039     * Full constructor (slice 173). All metadata is optional:
040     * {@code dataType} may be null, {@code nullable} may be null (unknown),
041     * and the key/index flags default to {@code false}.
042     */
043    public CatalogColumn(String name, String dataType, Boolean nullable,
044                         boolean primaryKey, boolean unique, boolean indexed) {
045        if (name == null) {
046            throw new IllegalArgumentException("column name must not be null");
047        }
048        if (name.isEmpty()) {
049            throw new IllegalArgumentException("column name must not be empty");
050        }
051        this.name = name;
052        this.dataType = dataType;
053        this.nullable = nullable;
054        this.primaryKey = primaryKey;
055        this.unique = unique;
056        this.indexed = indexed;
057    }
058
059    /** A fresh builder for a column with the given name. */
060    public static Builder builder(String name) {
061        return new Builder(name);
062    }
063
064    public String getName() {
065        return name;
066    }
067
068    /** Declared data type, or {@code null} when not supplied. */
069    public String getDataType() {
070        return dataType;
071    }
072
073    /** {@code TRUE}/{@code FALSE} when known, {@code null} when unknown. */
074    public Boolean getNullable() {
075        return nullable;
076    }
077
078    public boolean isPrimaryKey() {
079        return primaryKey;
080    }
081
082    public boolean isUnique() {
083        return unique;
084    }
085
086    public boolean isIndexed() {
087        return indexed;
088    }
089
090    @Override
091    public String toString() {
092        return "CatalogColumn{name=" + name
093                + (dataType != null ? ", type=" + dataType : "")
094                + (nullable != null ? ", nullable=" + nullable : "")
095                + (primaryKey ? ", pk" : "")
096                + (unique ? ", unique" : "")
097                + (indexed ? ", indexed" : "")
098                + "}";
099    }
100
101    /** Fluent builder for a {@link CatalogColumn} with optional metadata. */
102    public static final class Builder {
103        private final String name;
104        private String dataType;
105        private Boolean nullable;
106        private boolean primaryKey;
107        private boolean unique;
108        private boolean indexed;
109
110        private Builder(String name) {
111            this.name = name;
112        }
113
114        public Builder dataType(String dataType) {
115            this.dataType = dataType;
116            return this;
117        }
118
119        public Builder nullable(Boolean nullable) {
120            this.nullable = nullable;
121            return this;
122        }
123
124        public Builder primaryKey(boolean primaryKey) {
125            this.primaryKey = primaryKey;
126            return this;
127        }
128
129        public Builder unique(boolean unique) {
130            this.unique = unique;
131            return this;
132        }
133
134        public Builder indexed(boolean indexed) {
135            this.indexed = indexed;
136            return this;
137        }
138
139        public CatalogColumn build() {
140            return new CatalogColumn(name, dataType, nullable, primaryKey, unique, indexed);
141        }
142    }
143}