Skip to content

Commit a0556bd

Browse files
committed
feat(parser): add column data type fragment parser
Expose strict CCJSqlParserUtil helpers for ColDataType fragments, including parser configuration and full-input validation.
1 parent 9a32ff5 commit a0556bd

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

src/main/java/net/sf/jsqlparser/parser/CCJSqlParserUtil.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import net.sf.jsqlparser.parser.feature.Feature;
3131
import net.sf.jsqlparser.statement.Statement;
3232
import net.sf.jsqlparser.statement.Statements;
33+
import net.sf.jsqlparser.statement.create.table.ColDataType;
3334

3435
/**
3536
* Toolfunctions to start and use JSqlParser.
@@ -199,6 +200,61 @@ public static Expression parseExpression(String expression, boolean allowPartial
199200
});
200201
}
201202

203+
/**
204+
* Parses a column data type fragment. The complete input must represent the data type; trailing
205+
* tokens are rejected.
206+
*
207+
* @param columnDataType the column data type fragment to parse
208+
* @return the parsed column data type, or {@code null} for a null or empty input
209+
* @throws JSQLParserException when the input cannot be parsed completely
210+
* @see #parseColDataType(String, Consumer)
211+
*/
212+
public static ColDataType parseColDataType(String columnDataType) throws JSQLParserException {
213+
return parseColDataType(columnDataType, null);
214+
}
215+
216+
/**
217+
* Parses a column data type fragment while allowing the parser to be configured. The complete
218+
* input must represent the data type; trailing tokens are rejected.
219+
*
220+
* @param columnDataType the column data type fragment to parse
221+
* @param consumer parser configuration callback, or {@code null}
222+
* @return the parsed column data type, or {@code null} for a null or empty input
223+
* @throws JSQLParserException when the input cannot be parsed completely
224+
*/
225+
public static ColDataType parseColDataType(String columnDataType,
226+
Consumer<CCJSqlParser> consumer) throws JSQLParserException {
227+
if (columnDataType == null || columnDataType.isEmpty()) {
228+
return null;
229+
}
230+
231+
try {
232+
return parseColDataType(columnDataType, false, consumer);
233+
} catch (JSQLParserException ex) {
234+
return parseColDataType(columnDataType, true, consumer);
235+
}
236+
}
237+
238+
private static ColDataType parseColDataType(String columnDataType, boolean allowComplexParsing,
239+
Consumer<CCJSqlParser> consumer) throws JSQLParserException {
240+
CCJSqlParser parser = newParser(columnDataType)
241+
.withAllowComplexParsing(allowComplexParsing);
242+
if (consumer != null) {
243+
consumer.accept(parser);
244+
}
245+
246+
try {
247+
ColDataType result = parser.ColDataType();
248+
if (parser.getNextToken().kind != CCJSqlParserTokenManager.EOF) {
249+
throw new JSQLParserException(
250+
"could only parse partial column data type " + result);
251+
}
252+
return result;
253+
} catch (ParseException ex) {
254+
throw new JSQLParserException(columnDataType, ex);
255+
}
256+
}
257+
202258
@SuppressWarnings("PMD.CyclomaticComplexity")
203259
public static Expression parseExpression(String expressionStr, boolean allowPartialParse,
204260
Consumer<CCJSqlParser> consumer) throws JSQLParserException {

src/test/java/net/sf/jsqlparser/parser/CCJSqlParserUtilTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import net.sf.jsqlparser.statement.Statement;
2121
import net.sf.jsqlparser.statement.Statements;
2222
import net.sf.jsqlparser.statement.UnsupportedStatement;
23+
import net.sf.jsqlparser.statement.create.table.ColDataType;
2324
import net.sf.jsqlparser.statement.select.PlainSelect;
2425
import net.sf.jsqlparser.statement.select.Select;
2526
import net.sf.jsqlparser.statement.select.TableStatement;
@@ -39,6 +40,7 @@
3940
import java.util.concurrent.Executors;
4041
import java.util.concurrent.TimeUnit;
4142
import java.util.concurrent.TimeoutException;
43+
import java.util.concurrent.atomic.AtomicBoolean;
4244

4345
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
4446
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -107,6 +109,34 @@ public void testParseExpression2() throws Exception {
107109
assertInstanceOf(ParenthesedExpressionList.class, mult.getRightExpression());
108110
}
109111

112+
@Test
113+
public void testParseColDataType() throws Exception {
114+
assertNull(CCJSqlParserUtil.parseColDataType(null));
115+
assertNull(CCJSqlParserUtil.parseColDataType(""));
116+
117+
ColDataType arrayType = CCJSqlParserUtil.parseColDataType("integer[][]");
118+
assertEquals("integer", arrayType.getDataType());
119+
assertEquals(2, arrayType.getArrayData().size());
120+
assertNull(arrayType.getArrayData().get(0));
121+
assertNull(arrayType.getArrayData().get(1));
122+
123+
AtomicBoolean configured = new AtomicBoolean();
124+
ColDataType enumType =
125+
CCJSqlParserUtil.parseColDataType("enum('small','medium')", parser -> {
126+
configured.set(true);
127+
parser.withDialect(AbstractJSqlParser.Dialect.MYSQL);
128+
});
129+
assertTrue(configured.get());
130+
assertEquals("enum", enumType.getDataType());
131+
assertEquals(List.of("'small'", "'medium'"), enumType.getArgumentsStringList());
132+
}
133+
134+
@Test
135+
public void testParseColDataTypeRejectsTrailingTokens() {
136+
assertThrows(JSQLParserException.class,
137+
() -> CCJSqlParserUtil.parseColDataType("varchar(255) NOT NULL"));
138+
}
139+
110140
@Test
111141
public void testParseExpressionNonPartial() throws Exception {
112142
assertThrows(JSQLParserException.class,

0 commit comments

Comments
 (0)