diff --git a/README.md b/README.md index 1effe613d..db50e7a00 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ Additionally, we have fixed many errors and improved the code quality and the te * support table option **character set** and **index** options * support Postgresql optional **TABLE** in **TRUNCATE** * support for `ANALYZE mytable` +* extended support Postgres' `Extract( field FROM source)` where `field` is a String instead of a Keyword ## Building from the sources diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index bba0b815c..bc5b5cebd 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -4410,13 +4410,14 @@ WindowOffset WindowOffset(): ExtractExpression ExtractExpression() : { ExtractExpression retval = new ExtractExpression(); - String token = null; + String fieldName = null; + Token token = null; Expression expr = null; } { "(" - token=RelObjectName() { retval.setName(token); } + ( fieldName=RelObjectName() { retval.setName(fieldName); } | token= { retval.setName(token.image); } ) expr=SimpleExpression() { retval.setExpression(expr); } ")" diff --git a/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java new file mode 100644 index 000000000..53f043f6f --- /dev/null +++ b/src/test/java/net/sf/jsqlparser/statement/select/PostgresTest.java @@ -0,0 +1,35 @@ +package net.sf.jsqlparser.statement.select; + +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.test.TestUtils; +import org.junit.jupiter.api.Test; + +public class PostgresTest { + @Test + public void testExtractFunction() throws JSQLParserException { + String sqlStr = "SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40')"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT EXTRACT('HOUR' FROM TIMESTAMP '2001-02-16 20:38:40')"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + + sqlStr = "SELECT EXTRACT('HOURS' FROM TIMESTAMP '2001-02-16 20:38:40')"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } + + @Test + public void testExtractFunctionIssue1582() throws JSQLParserException { + String sqlStr = "" + + "select\n" + + " t0.operatienr\n" + + " , case\n" + + " when\n" + + " case when (t0.vc_begintijd_operatie is null or lpad((extract('hours' from t0.vc_begintijd_operatie::timestamp))::text,2,'0') ||':'|| lpad(extract('minutes' from t0.vc_begintijd_operatie::timestamp)::text,2,'0') = '00:00') then null\n" + + " else (greatest(((extract('hours' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp))*60 + extract('minutes' from (t0.vc_eindtijd_operatie::timestamp-t0.vc_begintijd_operatie::timestamp)))/60)::numeric(12,2),0))*60\n" + + " end = 0 then null\n" + + " else '25. Meer dan 4 uur'\n" + + " end \n" + + " as snijtijd_interval"; + TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true); + } +}