1313import net .sf .jsqlparser .statement .select .PlainSelect ;
1414
1515import java .io .Serializable ;
16+ import java .math .BigInteger ;
1617import java .util .ArrayList ;
1718import java .util .Collection ;
1819import java .util .Collections ;
@@ -43,7 +44,8 @@ public enum NationalCharacterType {
4344 private List <Integer > arrayData = new ArrayList <Integer >();
4445 private Signedness signedness ;
4546 private boolean zerofill ;
46- private Integer precision ;
47+ private BigInteger precision ;
48+ private boolean maxPrecision ;
4749 private Integer scale ;
4850 private List <TypeModifier > typeModifiers ;
4951 private NationalCharacterType nationalCharacterType ;
@@ -55,30 +57,39 @@ public ColDataType() {
5557
5658 public ColDataType (String dataType , int precision , int scale ) {
5759 this (dataType );
58- setNumericParameters (precision < 0 ? null : Integer .valueOf (precision ),
60+ setNumericTypeParameters (precision < 0 ? null
61+ : precision == Integer .MAX_VALUE ? "MAX" : Integer .toString (precision ),
5962 scale < 0 ? null : Integer .valueOf (scale ));
6063 }
6164
6265 /**
6366 * Creates a parameterized type, using {@code null} for an omitted parameter. Unlike the legacy
64- * primitive constructor, this accepts negative scales, including {@code -1}.
67+ * primitive constructor, this accepts negative scales, including {@code -1}. The legacy
68+ * {@link Integer#MAX_VALUE} precision sentinel continues to represent MAX.
6569 */
6670 public static ColDataType fromNumericParameters (String dataType , Integer precision ,
6771 Integer scale ) {
72+ return fromTypeParameters (dataType , precision == null ? null
73+ : precision == Integer .MAX_VALUE ? "MAX" : precision .toString (), scale );
74+ }
75+
76+ /**
77+ * Creates a type from its numeric parameter spelling. Unlike the legacy primitive constructor,
78+ * a numeric 2147483647 is distinct from MAX and larger lengths are retained without narrowing.
79+ */
80+ public static ColDataType fromTypeParameters (String dataType , String precision , Integer scale ) {
6881 ColDataType type = new ColDataType (dataType );
69- type .setNumericParameters (precision , scale );
82+ type .setNumericTypeParameters (precision , scale );
7083 return type ;
7184 }
7285
73- private void setNumericParameters (Integer precision , Integer scale ) {
74- if (precision != null ) {
75- this .precision = precision ;
76- this .dataType += " (" + (precision == Integer .MAX_VALUE ? "MAX" : precision );
77- if (scale != null ) {
78- this .scale = scale ;
79- this .dataType += ", " + scale ;
80- }
81- this .dataType += ")" ;
86+ private void setNumericTypeParameters (String parameter , Integer scale ) {
87+ if (parameter != null ) {
88+ maxPrecision = "MAX" .equalsIgnoreCase (parameter );
89+ precision = maxPrecision ? null : new BigInteger (parameter );
90+ this .scale = scale ;
91+ dataType += " (" + (maxPrecision ? "MAX" : precision )
92+ + (scale != null ? ", " + scale : "" ) + ")" ;
8293 }
8394 }
8495
@@ -98,6 +109,54 @@ public String getDataType() {
98109 return dataType ;
99110 }
100111
112+ /**
113+ * Returns the type name without parenthesized parameters, retaining qualification, quoting and
114+ * multiword names such as TIMESTAMP WITH TIME ZONE. The legacy {@link #getDataType()} spelling
115+ * is unchanged. Quoted parentheses are part of an identifier and are retained.
116+ */
117+ public String getBaseTypeName () {
118+ if (dataType == null ) {
119+ return null ;
120+ }
121+ StringBuilder name = new StringBuilder ();
122+ int depth = 0 ;
123+ char quote = 0 ;
124+ for (int i = 0 ; i < dataType .length (); i ++) {
125+ char c = dataType .charAt (i );
126+ if (quote != 0 ) {
127+ if (depth == 0 ) {
128+ name .append (c );
129+ }
130+ if (c == quote ) {
131+ if (i + 1 < dataType .length () && dataType .charAt (i + 1 ) == quote ) {
132+ if (depth == 0 ) {
133+ name .append (quote );
134+ }
135+ i ++;
136+ } else {
137+ quote = 0 ;
138+ }
139+ }
140+ } else if (c == '\'' || c == '"' || c == '`' || c == '[' ) {
141+ quote = c == '[' ? ']' : c ;
142+ if (depth == 0 ) {
143+ name .append (c );
144+ }
145+ } else if (c == '(' ) {
146+ depth ++;
147+ while (name .length () > 0
148+ && Character .isWhitespace (name .charAt (name .length () - 1 ))) {
149+ name .setLength (name .length () - 1 );
150+ }
151+ } else if (c == ')' && depth > 0 ) {
152+ depth --;
153+ } else if (depth == 0 ) {
154+ name .append (c );
155+ }
156+ }
157+ return name .toString ().trim ();
158+ }
159+
101160 public void setDataType (String string ) {
102161 dataType = string ;
103162 }
@@ -215,14 +274,35 @@ public ColDataType withXmlTypeModifier(XmlTypeModifier xmlTypeModifier) {
215274 * The first numeric type parameter, e.g. {@code 255} for {@code VARCHAR(255)} or {@code 10} for
216275 * {@code DECIMAL(10, 2)}. {@code MAX} is reported as {@link Integer#MAX_VALUE}. Returns
217276 * {@code null} when the type carries no numeric parameters, e.g. {@code INT} or
218- * {@code ENUM('a', 'b')}.
277+ * {@code ENUM('a', 'b')}, or when a numeric length exceeds the integer range. Use
278+ * {@link #getNumericPrecision()} for the full range and {@link #isMaxPrecision()} to
279+ * distinguish MAX from the numeric value 2147483647.
219280 */
220281 public Integer getPrecision () {
221- return precision ;
282+ return maxPrecision ? Integer .valueOf (Integer .MAX_VALUE )
283+ : precision != null && precision .bitLength () < Integer .SIZE
284+ ? Integer .valueOf (precision .intValue ())
285+ : null ;
222286 }
223287
224288 public void setPrecision (Integer precision ) {
289+ setNumericPrecision (precision == null ? null : BigInteger .valueOf (precision ));
290+ }
291+
292+ /** Returns the exact numeric parameter, or null for an omitted parameter or MAX. */
293+ public BigInteger getNumericPrecision () {
294+ return precision ;
295+ }
296+
297+ /** Updates numeric metadata without changing the legacy rendered type spelling. */
298+ public void setNumericPrecision (BigInteger precision ) {
225299 this .precision = precision ;
300+ maxPrecision = false ;
301+ }
302+
303+ /** Distinguishes the MAX keyword from an equal numeric value in the legacy accessor. */
304+ public boolean isMaxPrecision () {
305+ return maxPrecision ;
226306 }
227307
228308 /**
0 commit comments