diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 447af02d6..3f7a8d536 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -6992,6 +6992,7 @@ ColDataType DataType(): Token prefix = null; Token tk = null; Token tk2 = null; + JdbcParameter jdbc = null; String schema; String type=""; List argumentsStringList = new ArrayList(); @@ -7026,12 +7027,29 @@ ColDataType DataType(): | tk= | tk= | tk= ) { type += " " + tk.image; } )+ ] [ - LOOKAHEAD(2) "(" ( tk= { precision = Integer.valueOf(tk.image); } | tk= { precision = Integer.MAX_VALUE; } ) - [ "," tk = { scale = Integer.valueOf(tk.image); } ] + LOOKAHEAD(2) "(" + ( + // Handle precision: S_LONG, K_MAX, or JDBC Parameter + tk= { precision = Integer.valueOf(tk.image); } + | tk= { precision = Integer.MAX_VALUE; } + | jdbc = JdbcParameter() { precision = -1; argumentsStringList.add("?"); } + ) + [ + "," + ( + tk = { scale = Integer.valueOf(tk.image); } + | jdbc = JdbcParameter() { scale = -1; argumentsStringList.add("?"); } + ) + ] ")" ] { - colDataType = new ColDataType(type, precision, scale); + // If JDBC parameters were used, construct with string arguments + if (!argumentsStringList.isEmpty()) { + colDataType = new ColDataType(type + "(" + String.join(", ", argumentsStringList) + ")"); + } else { + colDataType = new ColDataType(type, precision, scale); + } } ) ) diff --git a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java index 5213a43ae..f51ec89b0 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -5343,6 +5343,37 @@ public void testMissingBracketsNestedInIssue() throws JSQLParserException { true); } + @Test + public void testJdbcParameterInColDataTypePrecision() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT price::VARCHAR(?) FROM products WHERE quantity = 50;", + true); + } + + @Test + public void testJdbcParameterInColDataTypePrecisionAndScale() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT price::DECIMAL(?, ?) FROM products WHERE quantity = 50;", + true); + } + + @Test + public void testPrecisionJdbcParameterWithWhitespaces() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed( + "SELECT price :: numeric(?) FROM products WHERE quantity = 50;", + true); + } + + @Test + public void testCastWithPrecisionJdbcParameter() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("SELECT (CAST(? AS VARCHAR(?))) FROM products;"); + } + + @Test + public void testCastFunctionOutputWithPrecisionJdbcParameter() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("SELECT AVG(Measurement)::numeric(?);"); + } + @Test public void testAnyComparisionExpressionValuesList1232() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("select * from foo where id != ALL(VALUES 1,2,3)", true);