Skip to content

Commit 2806656

Browse files
authored
feat: expose base type names and retain large numeric lengths (#2647)
1 parent 956e109 commit 2806656

4 files changed

Lines changed: 310 additions & 26 deletions

File tree

‎src/main/java/net/sf/jsqlparser/statement/create/table/ColDataType.java‎

Lines changed: 95 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import net.sf.jsqlparser.statement.select.PlainSelect;
1414

1515
import java.io.Serializable;
16+
import java.math.BigInteger;
1617
import java.util.ArrayList;
1718
import java.util.Collection;
1819
import 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
/**

‎src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15042,15 +15042,15 @@ ColDataType DataType():
1504215042
ColDataType arrayType;
1504315043
Integer zonePrecision = null;
1504415044

15045-
Integer precision = null;
15045+
String precision = null;
1504615046
Integer scale = null;
1504715047
String scaleText;
1504815048
}
1504915049
{
1505015050
(
1505115051
LOOKAHEAD(2) tk=<K_TEXT_LITERAL> {
1505215052
type = tk.image;
15053-
return ColDataType.fromNumericParameters(type, precision, scale);
15053+
return ColDataType.fromTypeParameters(type, precision, scale);
1505415054
}
1505515055
|
1505615056
LOOKAHEAD(2) tk=<K_ARRAY_LITERAL> (
@@ -15077,13 +15077,13 @@ ColDataType DataType():
1507715077
| tk=<K_CHAR> | tk=<K_JSON> | tk=<K_STRING> ) { type += " " + tk.image; }
1507815078
)*
1507915079
[
15080-
LOOKAHEAD(2) "(" ( tk=<S_LONG> { precision = Integer.valueOf(tk.image); } | tk=<K_MAX> { precision = Integer.MAX_VALUE; } )
15080+
LOOKAHEAD(2) "(" ( tk=<S_LONG> { precision = tk.image; } | tk=<K_MAX> { precision = "MAX"; } )
1508115081
[ <K_BYTE> | <K_CHAR> ]
1508215082
[ "," scaleText=SignedIntegerTypeArgument() { scale = Integer.valueOf(scaleText); } ]
1508315083
")"
1508415084
]
1508515085
{
15086-
colDataType = ColDataType.fromNumericParameters(type, precision, scale);
15086+
colDataType = ColDataType.fromTypeParameters(type, precision, scale);
1508715087
if (zonePrecision != null) {
1508815088
colDataType.setPrecision(zonePrecision);
1508915089
}
@@ -15290,10 +15290,10 @@ ColDataType ColDataType():
1529015290
colDataType.setArgumentsStringList(argumentsStringList);
1529115291
// Integer arguments expose numeric parameters, including negative scales.
1529215292
if (argumentsStringList.size() == 1 && argumentsStringList.get(0).matches("\\d+")) {
15293-
colDataType.setPrecision(Integer.valueOf(argumentsStringList.get(0)));
15293+
colDataType.setNumericPrecision(new java.math.BigInteger(argumentsStringList.get(0)));
1529415294
} else if (argumentsStringList.size() == 2 && argumentsStringList.get(0).matches("\\d+")
1529515295
&& argumentsStringList.get(1).matches("-?\\d+")) {
15296-
colDataType.setPrecision(Integer.valueOf(argumentsStringList.get(0)));
15296+
colDataType.setNumericPrecision(new java.math.BigInteger(argumentsStringList.get(0)));
1529715297
colDataType.setScale(Integer.valueOf(argumentsStringList.get(1)));
1529815298
}
1529915299
}

0 commit comments

Comments
 (0)