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}