Skip to content

Commit ccb82d1

Browse files
committed
fix: parse INTERVAL column type with time-unit qualifier
Consume the optional <unit> [TO <unit>] qualifier after an INTERVAL column type (e.g. `interval hour to minute`), attaching it to the ColDataType so PostgreSQL/Oracle CREATE TABLE statements parse and round-trip correctly. Fixes #1728 Signed-off-by: 付典 <fudianchn@gmail.com>
1 parent 18b12f1 commit ccb82d1

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10705,6 +10705,8 @@ ColDataType ColDataType():
1070510705
Token prefix = null;
1070610706
Token tk = null;
1070710707
Token tk2 = null;
10708+
Token intervalUnit = null;
10709+
Token intervalTo = null;
1070810710
String schema;
1070910711
String type="";
1071010712
List<String> argumentsStringList = new ArrayList<String>();
@@ -10753,6 +10755,9 @@ ColDataType ColDataType():
1075310755
| tk=<K_NAME>
1075410756
) { schema = tk.image; }
1075510757

10758+
// INTERVAL qualifier such as `interval hour to minute` or `interval year` (PG/Oracle column type)
10759+
[ LOOKAHEAD({ tk.kind == K_INTERVAL && getToken(1).kind == K_DATE_LITERAL }) intervalUnit=<K_DATE_LITERAL> { schema += " " + intervalUnit.image; }
10760+
[ intervalTo=<K_TO> intervalUnit=<K_DATE_LITERAL> { schema += " " + intervalTo.image + " " + intervalUnit.image; } ] ]
1075610761
[ LOOKAHEAD(2) "." arrayType = ColDataType() { schema += "." + arrayType.toString(); } ]
1075710762
{ colDataType.setDataType(schema); }
1075810763
)

src/test/java/net/sf/jsqlparser/statement/create/table/ColDataTypeTest.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.junit.jupiter.api.Test;
1515

1616
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
17+
import static org.junit.jupiter.api.Assertions.assertEquals;
1718

1819
class ColDataTypeTest {
1920
@Test
@@ -57,4 +58,26 @@ void testStruct() throws JSQLParserException {
5758
" );\n";
5859
assertSqlCanBeParsedAndDeparsed(sqlStr, true);
5960
}
61+
62+
// PG/Oracle allow an INTERVAL column type carrying a time-unit qualifier,
63+
// e.g. `interval hour to minute`. Previously the qualifier was not consumed
64+
// as part of the data type, so parsing failed with "Encountered ... <K_DATE_LITERAL>".
65+
@Test
66+
void testIntervalQualifierIssue1728() throws JSQLParserException {
67+
String sqlStr = "CREATE TABLE films (code char(5), len interval hour to minute)";
68+
CreateTable create = (CreateTable) assertSqlCanBeParsedAndDeparsed(sqlStr, true);
69+
70+
// The qualifier must be attached to the column's data type, not parsed as an
71+
// alias or left unconsumed.
72+
ColumnDefinition len = create.getColumnDefinitions().stream()
73+
.filter(c -> c.getColumnName().equalsIgnoreCase("len"))
74+
.findFirst()
75+
.orElseThrow();
76+
assertEquals("interval hour to minute", len.getColDataType().getDataType());
77+
}
78+
79+
@Test
80+
void testIntervalQualifierYearToMonthIssue1728() throws JSQLParserException {
81+
assertSqlCanBeParsedAndDeparsed("CREATE TABLE t (a interval year to month)", true);
82+
}
6083
}

0 commit comments

Comments
 (0)