From d1197681435af261b924e5c82fd4c52f01e70773 Mon Sep 17 00:00:00 2001 From: Rob Audenaerde Date: Wed, 6 Jul 2022 10:22:29 +0200 Subject: [PATCH 1/3] Closes #1583 --- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 10 +++++++++- .../statement/truncate/TruncateTest.java | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 839b946c6..234865801 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -5451,7 +5451,15 @@ Truncate Truncate(): Table table; } { - +/** +* TRUNCATE can be followed directly by the table name in Postgresql +* See: https://www.postgresql.org/docs/current/sql-truncate.html +* +* TRUNCATE [ TABLE ] [ ONLY ] name [ * ] [, ... ] +* [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ] +* +*/ + [] [] table=Table() { truncate.setTable(table); truncate.setCascade(false); } [ {truncate.setCascade(true);} ] { return truncate; diff --git a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java index c4c780b9c..0b6e94c7e 100644 --- a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java @@ -41,6 +41,24 @@ public void testTruncate() throws Exception { assertEquals(statement, truncate.toString()); } + @Test + public void testTruncatePostgresqlWithoutTableName() throws Exception { + String statement = "TRUncATE myschema.mytab"; + Truncate truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("myschema", truncate.getTable().getSchemaName()); + assertEquals("myschema.mytab", truncate.getTable().getFullyQualifiedName()); + assertEquals("TRUNCATE TABLE MYSCHEMA.MYTAB", truncate.toString().toUpperCase()); + + statement = "TRUncATE mytab"; + String toStringStatement = "TRUncATE mytab"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("mytab", truncate.getTable().getName()); + assertEquals("TRUNCATE TABLE MYTAB", truncate.toString().toUpperCase()); + + statement = "TRUNCATE mytab CASCADE"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("TRUNCATE TABLE MYTAB CASCADE", truncate.toString().toUpperCase()); + } @Test public void testTruncateDeparse() throws JSQLParserException { String statement = "TRUNCATE TABLE foo"; From bb78fd8a9a5e7f4e769ba07776200c79aedb08a9 Mon Sep 17 00:00:00 2001 From: Rob Audenaerde Date: Thu, 7 Jul 2022 09:04:17 +0200 Subject: [PATCH 2/3] Closes #1583, removed unnecessary local variable. --- .../java/net/sf/jsqlparser/statement/truncate/TruncateTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java index 0b6e94c7e..c250d586a 100644 --- a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java @@ -50,7 +50,6 @@ public void testTruncatePostgresqlWithoutTableName() throws Exception { assertEquals("TRUNCATE TABLE MYSCHEMA.MYTAB", truncate.toString().toUpperCase()); statement = "TRUncATE mytab"; - String toStringStatement = "TRUncATE mytab"; truncate = (Truncate) parserManager.parse(new StringReader(statement)); assertEquals("mytab", truncate.getTable().getName()); assertEquals("TRUNCATE TABLE MYTAB", truncate.toString().toUpperCase()); From 4258702cec5921c0b8661b7577642971f962a457 Mon Sep 17 00:00:00 2001 From: Rob Audenaerde Date: Fri, 8 Jul 2022 10:09:49 +0200 Subject: [PATCH 3/3] Closes #1583, proper support for deparsing. --- .../statement/truncate/Truncate.java | 44 ++++++++++++++++++- .../util/deparser/StatementDeParser.java | 13 +++++- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 2 +- .../statement/truncate/TruncateTest.java | 33 +++++++++++--- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java b/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java index 67d064249..9848c7799 100644 --- a/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java +++ b/src/main/java/net/sf/jsqlparser/statement/truncate/Truncate.java @@ -18,6 +18,9 @@ public class Truncate implements Statement { private Table table; boolean cascade; // to support TRUNCATE TABLE ... CASCADE + boolean tableToken; // to support TRUNCATE without TABLE + boolean only; // to support TRUNCATE with ONLY + @Override public void accept(StatementVisitor statementVisitor) { statementVisitor.visit(this); @@ -41,10 +44,42 @@ public void setCascade(boolean c) { @Override public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("TRUNCATE"); + if (tableToken) { + sb.append(" TABLE"); + } + if (only) { + sb.append(" ONLY"); + } + sb.append(" "); + sb.append(table); + if (cascade) { - return "TRUNCATE TABLE " + table + " CASCADE"; + sb.append( " CASCADE"); } - return "TRUNCATE TABLE " + table; + return sb.toString(); + } + + public boolean isTableToken() { + return tableToken; + } + + public void setTableToken(boolean hasTable) { + this.tableToken = hasTable; + } + + public boolean isOnly() { + return only; + } + + public void setOnly(boolean only) { + this.only = only; + } + + public Truncate withTableToken(boolean hasTableToken){ + this.setTableToken(hasTableToken); + return this; } public Truncate withTable(Table table) { @@ -56,4 +91,9 @@ public Truncate withCascade(boolean cascade) { this.setCascade(cascade); return this; } + public Truncate withOnly(boolean only) { + this.setOnly(only); + return this; + } } + diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java index 5e904dd0b..3cadd6ccb 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/StatementDeParser.java @@ -164,11 +164,20 @@ public void visit(Select select) { @Override public void visit(Truncate truncate) { - buffer.append("TRUNCATE TABLE "); + buffer.append("TRUNCATE"); + if (truncate.isTableToken()) { + buffer.append(" TABLE"); + } + if (truncate.isOnly()) { + buffer.append(" ONLY"); + } + buffer.append(" "); buffer.append(truncate.getTable()); + if (truncate.getCascade()) { - buffer.append(" CASCADE"); + buffer.append( " CASCADE"); } + } @Override diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 234865801..82c7f70cb 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -5459,7 +5459,7 @@ Truncate Truncate(): * [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ] * */ - [] [] + [ {truncate.setTableToken(true);}] [ {truncate.setOnly(true);}] table=Table() { truncate.setTable(table); truncate.setCascade(false); } [ {truncate.setCascade(true);} ] { return truncate; diff --git a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java index c250d586a..036aa64ad 100644 --- a/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/truncate/TruncateTest.java @@ -10,12 +10,15 @@ package net.sf.jsqlparser.statement.truncate; import java.io.StringReader; + import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.parser.CCJSqlParserManager; import net.sf.jsqlparser.schema.Table; + import static net.sf.jsqlparser.test.TestUtils.assertDeparse; import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed; import static org.junit.jupiter.api.Assertions.assertEquals; + import org.junit.jupiter.api.Test; public class TruncateTest { @@ -39,6 +42,10 @@ public void testTruncate() throws Exception { statement = "TRUNCATE TABLE mytab CASCADE"; truncate = (Truncate) parserManager.parse(new StringReader(statement)); assertEquals(statement, truncate.toString()); + + statement = "TRUNCATE TABLE ONLY mytab CASCADE"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals(statement, truncate.toString()); } @Test @@ -47,29 +54,45 @@ public void testTruncatePostgresqlWithoutTableName() throws Exception { Truncate truncate = (Truncate) parserManager.parse(new StringReader(statement)); assertEquals("myschema", truncate.getTable().getSchemaName()); assertEquals("myschema.mytab", truncate.getTable().getFullyQualifiedName()); - assertEquals("TRUNCATE TABLE MYSCHEMA.MYTAB", truncate.toString().toUpperCase()); + assertEquals("TRUNCATE MYSCHEMA.MYTAB", truncate.toString().toUpperCase()); statement = "TRUncATE mytab"; truncate = (Truncate) parserManager.parse(new StringReader(statement)); assertEquals("mytab", truncate.getTable().getName()); - assertEquals("TRUNCATE TABLE MYTAB", truncate.toString().toUpperCase()); + assertEquals("TRUNCATE MYTAB", truncate.toString().toUpperCase()); statement = "TRUNCATE mytab CASCADE"; truncate = (Truncate) parserManager.parse(new StringReader(statement)); - assertEquals("TRUNCATE TABLE MYTAB CASCADE", truncate.toString().toUpperCase()); + assertEquals("TRUNCATE MYTAB CASCADE", truncate.toString().toUpperCase()); } + @Test public void testTruncateDeparse() throws JSQLParserException { String statement = "TRUNCATE TABLE foo"; assertSqlCanBeParsedAndDeparsed(statement); - assertDeparse(new Truncate().withTable(new Table("foo")), statement); + assertDeparse(new Truncate() + .withTable(new Table("foo")) + .withTableToken(true), statement); } @Test public void testTruncateCascadeDeparse() throws JSQLParserException { String statement = "TRUNCATE TABLE foo CASCADE"; assertSqlCanBeParsedAndDeparsed(statement); - assertDeparse(new Truncate().withTable(new Table("foo")).withCascade(true), statement); + assertDeparse(new Truncate() + .withTable(new Table("foo")) + .withTableToken(true) + .withCascade(true), statement); } + @Test + public void testTruncateOnlyDeparse() throws JSQLParserException { + String statement = "TRUNCATE TABLE ONLY foo CASCADE"; + assertSqlCanBeParsedAndDeparsed(statement); + assertDeparse(new Truncate() + .withTable(new Table("foo")) + .withCascade(true) + .withTableToken(true) + .withOnly(true), statement); + } }