001package gudusoft.gsqlparser.catalog.input.model;
002
003import gudusoft.gsqlparser.EDbVendor;
004
005import java.util.Objects;
006
007/**
008 * Vendor-aware identifier folding/comparison flags.
009 *
010 * <p>Plan §9.2. Strict subset of {@code IdentifierProfile.VendorFlags} with three additions
011 * pinned by spike T0.5: {@code mssqlCollation}, {@code mysqlLowerCaseTableNames}, and the
012 * BigQuery split between {@code tableCaseSensitive} / {@code columnCaseSensitive}.</p>
013 *
014 * <p>This type is a strict data carrier; it does <em>not</em> implement folding logic.
015 * Folding goes through {@code IdentifierService} via {@code CatalogIdentifierPolicy}.</p>
016 */
017public final class IdentifierConfig {
018
019    private final EDbVendor vendor;
020    private final boolean foldUnquotedToUpper;
021    private final boolean foldUnquotedToLower;
022    private final boolean preserveQuotedCase;
023    private final Boolean tableCaseSensitive;
024    private final Boolean columnCaseSensitive;
025    private final Integer mysqlLowerCaseTableNames;
026    private final String mssqlCollation;
027    private final boolean stripQuotedDelimiters;
028
029    private IdentifierConfig(Builder b) {
030        if (b.vendor == null) {
031            throw new IllegalArgumentException("IdentifierConfig.vendor is required");
032        }
033        if (b.foldUnquotedToUpper && b.foldUnquotedToLower) {
034            throw new IllegalArgumentException(
035                "IdentifierConfig: cannot set both foldUnquotedToUpper and foldUnquotedToLower");
036        }
037        this.vendor = b.vendor;
038        this.foldUnquotedToUpper = b.foldUnquotedToUpper;
039        this.foldUnquotedToLower = b.foldUnquotedToLower;
040        this.preserveQuotedCase = b.preserveQuotedCase;
041        this.tableCaseSensitive = b.tableCaseSensitive;
042        this.columnCaseSensitive = b.columnCaseSensitive;
043        this.mysqlLowerCaseTableNames = b.mysqlLowerCaseTableNames;
044        this.mssqlCollation = b.mssqlCollation;
045        this.stripQuotedDelimiters = b.stripQuotedDelimiters;
046    }
047
048    public static Builder builder() {
049        return new Builder();
050    }
051
052    /** Sensible defaults for the supplied vendor. Mirrors the matrix in spike T0.5 §9.4. */
053    public static IdentifierConfig defaultsFor(EDbVendor vendor) {
054        Builder b = new Builder().vendor(vendor).preserveQuotedCase(true).stripQuotedDelimiters(true);
055        switch (vendor) {
056            case dbvoracle:
057            case dbvdb2:
058                return b.foldUnquotedToUpper(true).build();
059            case dbvpostgresql:
060            case dbvgreenplum:
061            case dbvredshift:
062            case dbvgaussdb:
063                return b.foldUnquotedToLower(true).build();
064            case dbvmysql:
065                return b.mysqlLowerCaseTableNames(0).build();
066            case dbvmssql:
067            case dbvazuresql:
068                return b.tableCaseSensitive(Boolean.FALSE).columnCaseSensitive(Boolean.FALSE).build();
069            case dbvbigquery:
070                return b.tableCaseSensitive(Boolean.TRUE).columnCaseSensitive(Boolean.FALSE).build();
071            default:
072                return b.build();
073        }
074    }
075
076    public EDbVendor vendor() {
077        return vendor;
078    }
079
080    public boolean foldUnquotedToUpper() {
081        return foldUnquotedToUpper;
082    }
083
084    public boolean foldUnquotedToLower() {
085        return foldUnquotedToLower;
086    }
087
088    public boolean preserveQuotedCase() {
089        return preserveQuotedCase;
090    }
091
092    public Boolean tableCaseSensitive() {
093        return tableCaseSensitive;
094    }
095
096    public Boolean columnCaseSensitive() {
097        return columnCaseSensitive;
098    }
099
100    public Integer mysqlLowerCaseTableNames() {
101        return mysqlLowerCaseTableNames;
102    }
103
104    public String mssqlCollation() {
105        return mssqlCollation;
106    }
107
108    public boolean stripQuotedDelimiters() {
109        return stripQuotedDelimiters;
110    }
111
112    @Override
113    public boolean equals(Object o) {
114        if (this == o) return true;
115        if (!(o instanceof IdentifierConfig)) return false;
116        IdentifierConfig that = (IdentifierConfig) o;
117        return foldUnquotedToUpper == that.foldUnquotedToUpper
118            && foldUnquotedToLower == that.foldUnquotedToLower
119            && preserveQuotedCase == that.preserveQuotedCase
120            && stripQuotedDelimiters == that.stripQuotedDelimiters
121            && vendor == that.vendor
122            && Objects.equals(tableCaseSensitive, that.tableCaseSensitive)
123            && Objects.equals(columnCaseSensitive, that.columnCaseSensitive)
124            && Objects.equals(mysqlLowerCaseTableNames, that.mysqlLowerCaseTableNames)
125            && Objects.equals(mssqlCollation, that.mssqlCollation);
126    }
127
128    @Override
129    public int hashCode() {
130        return Objects.hash(vendor, foldUnquotedToUpper, foldUnquotedToLower, preserveQuotedCase,
131            tableCaseSensitive, columnCaseSensitive, mysqlLowerCaseTableNames, mssqlCollation,
132            stripQuotedDelimiters);
133    }
134
135    @Override
136    public String toString() {
137        return "IdentifierConfig{vendor=" + vendor
138            + ", foldU=" + foldUnquotedToUpper
139            + ", foldL=" + foldUnquotedToLower
140            + ", preserveQuoted=" + preserveQuotedCase
141            + ", tableCS=" + tableCaseSensitive
142            + ", columnCS=" + columnCaseSensitive
143            + ", mysqlLctn=" + mysqlLowerCaseTableNames
144            + ", mssqlCol=" + mssqlCollation
145            + ", stripDelim=" + stripQuotedDelimiters + '}';
146    }
147
148    public static final class Builder {
149
150        private EDbVendor vendor;
151        private boolean foldUnquotedToUpper;
152        private boolean foldUnquotedToLower;
153        private boolean preserveQuotedCase = true;
154        private Boolean tableCaseSensitive;
155        private Boolean columnCaseSensitive;
156        private Integer mysqlLowerCaseTableNames;
157        private String mssqlCollation;
158        private boolean stripQuotedDelimiters = true;
159
160        private Builder() {
161        }
162
163        public Builder vendor(EDbVendor v) {
164            this.vendor = v;
165            return this;
166        }
167
168        public Builder foldUnquotedToUpper(boolean v) {
169            this.foldUnquotedToUpper = v;
170            return this;
171        }
172
173        public Builder foldUnquotedToLower(boolean v) {
174            this.foldUnquotedToLower = v;
175            return this;
176        }
177
178        public Builder preserveQuotedCase(boolean v) {
179            this.preserveQuotedCase = v;
180            return this;
181        }
182
183        public Builder tableCaseSensitive(Boolean v) {
184            this.tableCaseSensitive = v;
185            return this;
186        }
187
188        public Builder columnCaseSensitive(Boolean v) {
189            this.columnCaseSensitive = v;
190            return this;
191        }
192
193        public Builder mysqlLowerCaseTableNames(Integer v) {
194            if (v != null && (v < 0 || v > 2)) {
195                throw new IllegalArgumentException(
196                    "mysqlLowerCaseTableNames must be 0, 1, or 2 (got " + v + ")");
197            }
198            this.mysqlLowerCaseTableNames = v;
199            return this;
200        }
201
202        public Builder mssqlCollation(String v) {
203            this.mssqlCollation = v;
204            return this;
205        }
206
207        public Builder stripQuotedDelimiters(boolean v) {
208            this.stripQuotedDelimiters = v;
209            return this;
210        }
211
212        public IdentifierConfig build() {
213            return new IdentifierConfig(this);
214        }
215    }
216}