Skip to content

Commit 5ea41f4

Browse files
committed
fix(parser): model MySQL column type modifiers
1 parent 8397d3a commit 5ea41f4

3 files changed

Lines changed: 71 additions & 4 deletions

File tree

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,17 @@
2424

2525
public class ColDataType implements Serializable {
2626

27+
public enum Signedness {
28+
SIGNED, UNSIGNED
29+
}
30+
2731
private String dataType;
2832
private List<String> argumentsStringList;
2933
private String characterSet;
3034
private IntervalQualifier intervalQualifier;
3135
private List<Integer> arrayData = new ArrayList<Integer>();
36+
private Signedness signedness;
37+
private boolean zerofill;
3238

3339
public ColDataType() {
3440
// empty constructor
@@ -94,6 +100,22 @@ public void setArrayData(List<Integer> arrayData) {
94100
this.arrayData = arrayData;
95101
}
96102

103+
public Signedness getSignedness() {
104+
return signedness;
105+
}
106+
107+
public void setSignedness(Signedness signedness) {
108+
this.signedness = signedness;
109+
}
110+
111+
public boolean isZerofill() {
112+
return zerofill;
113+
}
114+
115+
public void setZerofill(boolean zerofill) {
116+
this.zerofill = zerofill;
117+
}
118+
97119
@Override
98120
public String toString() {
99121
StringBuilder arraySpec = new StringBuilder();
@@ -109,6 +131,8 @@ public String toString() {
109131
+ (argumentsStringList != null
110132
? " " + PlainSelect.getStringList(argumentsStringList, true, true)
111133
: "")
134+
+ (signedness != null ? " " + signedness : "")
135+
+ (zerofill ? " ZEROFILL" : "")
112136
+ arraySpec.toString()
113137
+ (characterSet != null ? " CHARACTER SET " + characterSet : "");
114138
}
@@ -138,6 +162,16 @@ public ColDataType withArrayData(List<Integer> arrayData) {
138162
return this;
139163
}
140164

165+
public ColDataType withSignedness(Signedness signedness) {
166+
setSignedness(signedness);
167+
return this;
168+
}
169+
170+
public ColDataType withZerofill(boolean zerofill) {
171+
setZerofill(zerofill);
172+
return this;
173+
}
174+
141175
public ColDataType addArgumentsStringList(String... argumentsStringList) {
142176
List<String> collection =
143177
Optional.ofNullable(getArgumentsStringList()).orElseGet(ArrayList::new);
@@ -178,7 +212,9 @@ public final boolean equals(Object o) {
178212
&& Objects.equals(argumentsStringList, that.argumentsStringList)
179213
&& Objects.equals(characterSet, that.characterSet)
180214
&& Objects.equals(intervalQualifier, that.intervalQualifier)
181-
&& Objects.equals(arrayData, that.arrayData);
215+
&& Objects.equals(arrayData, that.arrayData)
216+
&& signedness == that.signedness
217+
&& zerofill == that.zerofill;
182218
}
183219

184220
@Override
@@ -188,6 +224,8 @@ public int hashCode() {
188224
result = 31 * result + Objects.hashCode(characterSet);
189225
result = 31 * result + Objects.hashCode(intervalQualifier);
190226
result = 31 * result + Objects.hashCode(arrayData);
227+
result = 31 * result + Objects.hashCode(signedness);
228+
result = 31 * result + Boolean.hashCode(zerofill);
191229
return result;
192230
}
193231
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,7 @@ String NonReservedWord() :
18151815
| tk=<K_XSINIL:"XSINIL">
18161816
| tk=<K_YAML:"YAML">
18171817
| tk=<K_YES:"YES">
1818+
| tk=<K_ZEROFILL:"ZEROFILL">
18181819
| tk=<K_ZONE:"ZONE">
18191820
)
18201821
{ return tk.image; }
@@ -11683,10 +11684,10 @@ ColDataType DataType():
1168311684
| tk=<K_CHARACTER> | tk=<K_BIT> | tk=<K_BYTES> | tk=<K_BINARY> | tk=<K_BOOLEAN>
1168411685
| tk=<K_CHAR> | tk=<K_JSON> | tk=<K_STRING> ) { type = tk.image; }
1168511686
(
11686-
// MySQL seems to allow: INT UNSIGNED. Do not consume CHARACTER when it starts
11687-
// the trailing CHARACTER SET clause of a character type.
11687+
// Signedness is parsed by ColDataType after optional precision/scale. Do not
11688+
// consume CHARACTER when it starts the trailing CHARACTER SET clause.
1168811689
LOOKAHEAD(2, { getToken(1).kind != K_CHARACTER || getToken(2).kind != K_SET })
11689-
( tk = <DATA_TYPE> | tk = <K_SIGNED> | tk = <K_UNSIGNED>
11690+
( tk = <DATA_TYPE>
1169011691
| tk=<K_CHARACTER> | tk=<K_BIT> | tk=<K_BYTES> | tk=<K_BINARY> | tk=<K_BOOLEAN>
1169111692
| tk=<K_CHAR> | tk=<K_JSON> | tk=<K_STRING> ) { type += " " + tk.image; }
1169211693
)*
@@ -11806,6 +11807,11 @@ ColDataType ColDataType():
1180611807
)*
1180711808
")"
1180811809
]
11810+
[ LOOKAHEAD(2)
11811+
( tk=<K_SIGNED> { colDataType.setSignedness(ColDataType.Signedness.SIGNED); }
11812+
| tk=<K_UNSIGNED> { colDataType.setSignedness(ColDataType.Signedness.UNSIGNED); } )
11813+
]
11814+
[ LOOKAHEAD(2) <K_ZEROFILL> { colDataType.setZerofill(true); } ]
1180911815
[ LOOKAHEAD(2) ( LOOKAHEAD(2) "[" {tk=null;} [ tk=<S_LONG> ] { array.add(tk!=null?Integer.valueOf(tk.image):null); } "]" )+ { colDataType.setArrayData(array); } ]
1181011816
[ LOOKAHEAD(2) <K_CHARACTER> <K_SET> (tk=<S_IDENTIFIER> | tk=<K_BINARY>) { colDataType.setCharacterSet(tk.image); } ]
1181111817

src/test/java/net/sf/jsqlparser/statement/create/CreateTableTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import net.sf.jsqlparser.schema.Column;
3333
import net.sf.jsqlparser.schema.Table;
3434
import net.sf.jsqlparser.statement.create.table.ColDataType;
35+
import net.sf.jsqlparser.statement.create.table.ColDataType.Signedness;
3536
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
3637
import net.sf.jsqlparser.statement.create.table.CreateTable;
3738
import net.sf.jsqlparser.statement.create.table.ExcludeConstraint;
@@ -1247,4 +1248,26 @@ void testUniqueIndexIssue1893() throws JSQLParserException {
12471248
// A plain INDEX must still parse unchanged.
12481249
assertSqlCanBeParsedAndDeparsed("CREATE TABLE t (a int, INDEX idx (a))", true);
12491250
}
1251+
1252+
@Test
1253+
void testMySqlColumnTypeModifiers() throws JSQLParserException {
1254+
String sql = "CREATE TABLE t (a INT UNSIGNED, b INT (11) UNSIGNED ZEROFILL, "
1255+
+ "c DECIMAL (10, 2) SIGNED NOT NULL)";
1256+
CreateTable createTable =
1257+
(CreateTable) assertSqlCanBeParsedAndDeparsed(sql, true);
1258+
1259+
ColDataType first = createTable.getColumnDefinitions().get(0).getColDataType();
1260+
assertEquals("INT", first.getDataType());
1261+
assertEquals(Signedness.UNSIGNED, first.getSignedness());
1262+
assertFalse(first.isZerofill());
1263+
1264+
ColDataType second = createTable.getColumnDefinitions().get(1).getColDataType();
1265+
assertEquals(Signedness.UNSIGNED, second.getSignedness());
1266+
assertTrue(second.isZerofill());
1267+
1268+
ColDataType third = createTable.getColumnDefinitions().get(2).getColDataType();
1269+
assertEquals(Signedness.SIGNED, third.getSignedness());
1270+
assertEquals(List.of("NOT", "NULL"),
1271+
createTable.getColumnDefinitions().get(2).getColumnSpecs());
1272+
}
12501273
}

0 commit comments

Comments
 (0)