From 15bf4c582e4c60d89126d175d44c89280ba116dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Rodr=C3=ADguez?= Date: Fri, 14 Dec 2018 13:39:14 -0300 Subject: [PATCH] Added support for expressions as arguments of an IntervalExpression. Based on #414 --- .../expression/ExpressionVisitorAdapter.java | 1 + .../expression/IntervalExpression.java | 6 +++--- .../sf/jsqlparser/util/TablesNamesFinder.java | 1 + .../util/deparser/ExpressionDeParser.java | 6 +++++- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 16 +++++++++++----- .../jsqlparser/statement/select/SelectTest.java | 8 +++++++- 6 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index c5730c9a1..3b514a53d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -326,6 +326,7 @@ public void visit(ExtractExpression expr) { @Override public void visit(IntervalExpression expr) { + expr.getParameter().accept(this); } @Override diff --git a/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java b/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java index 7c0503380..2d4a6e7ea 100644 --- a/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java +++ b/src/main/java/net/sf/jsqlparser/expression/IntervalExpression.java @@ -29,14 +29,14 @@ */ public class IntervalExpression extends ASTNodeAccessImpl implements Expression { - private String parameter = null; + private Expression parameter = null; private String intervalType = null; - public String getParameter() { + public Expression getParameter() { return parameter; } - public void setParameter(String parameter) { + public void setParameter(Expression parameter) { this.parameter = parameter; } diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index debafa23e..87f3812c3 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -564,6 +564,7 @@ protected void init(boolean allowColumnProcessing) { @Override public void visit(IntervalExpression iexpr) { + iexpr.getParameter().accept(this); } @Override diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java index 9336bfa0d..5ca00dc96 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -721,7 +721,11 @@ public void visit(MultiExpressionList multiExprList) { @Override public void visit(IntervalExpression iexpr) { - buffer.append(iexpr.toString()); + buffer.append("INTERVAL "); + iexpr.getParameter().accept(this); + if(iexpr.getIntervalType() != null) { + buffer.append(" ").append(iexpr.getIntervalType()); + } } @Override diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index f63f8eee9..b68ff2576 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -2683,8 +2683,6 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(JsonExpression()) retval=JsonExpression() - | LOOKAHEAD(Function()) retval=Function() - | token= { retval = new DoubleValue(token.image); } | token= { retval = new LongValue(token.image); } @@ -2698,7 +2696,9 @@ Expression PrimaryExpression() #PrimaryExpression: | LOOKAHEAD(2) retval=DateTimeLiteralExpression() - | LOOKAHEAD(2) retval = IntervalExpression() + | LOOKAHEAD(2) retval = IntervalExpression() + + | LOOKAHEAD(Function()) retval=Function() | retval=Column() @@ -2798,12 +2798,18 @@ JsonExpression JsonExpression() : { IntervalExpression IntervalExpression() : { IntervalExpression interval = new IntervalExpression(); + Expression item; + Expression intermediate; Token token; boolean signed = false; } { - ["-" {signed=true;}] (token= | token= | token=) - { interval.setParameter((signed?"-":"") + token.image); } + + (LOOKAHEAD(ConcatExpression()) item = ConcatExpression() + |LOOKAHEAD("(" ConcatExpression() ")") "(" intermediate=ConcatExpression() ")" {item = new Parenthesis(intermediate); } + |LOOKAHEAD("(" PrimaryExpression() ")") "(" intermediate=PrimaryExpression() ")" {item = new Parenthesis(intermediate); } + | item = PrimaryExpression()) + { interval.setParameter(item); } [ LOOKAHEAD(2) token = { interval.setIntervalType(token.image); } ] { return interval; 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 bf0112fed..9bc4fe6fd 100644 --- a/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/select/SelectTest.java @@ -2103,7 +2103,7 @@ public void testInterval2() throws JSQLParserException { assertTrue(sub.getRightExpression() instanceof IntervalExpression); IntervalExpression iexpr = (IntervalExpression) sub.getRightExpression(); - assertEquals("'45 MINUTE'", iexpr.getParameter()); + assertEquals("'45 MINUTE'", iexpr.getParameter().toString()); } @Test @@ -2118,6 +2118,12 @@ public void testInterval4() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(stmt); } + @Test + public void testInterval5() throws JSQLParserException { + String stmt = "SELECT INTERVAL (UNIX_TIMESTAMP(CAST('2018-12-03 19:40:00' AS DATETIME)) / 300) * 300 SECOND"; + assertSqlCanBeParsedAndDeparsed(stmt); + } + @Test public void testInterval5_Issue228() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("SELECT ADDDATE(timeColumn1, INTERVAL 420 MINUTES) AS timeColumn1 FROM tbl");