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 839b946c6..82c7f70cb 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 ] +* +*/ + [ {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 c4c780b9c..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,20 +42,57 @@ 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 + 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 MYSCHEMA.MYTAB", truncate.toString().toUpperCase()); + + statement = "TRUncATE mytab"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + assertEquals("mytab", truncate.getTable().getName()); + assertEquals("TRUNCATE MYTAB", truncate.toString().toUpperCase()); + + statement = "TRUNCATE mytab CASCADE"; + truncate = (Truncate) parserManager.parse(new StringReader(statement)); + 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); + } }