Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/main/java/net/sf/jsqlparser/statement/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package net.sf.jsqlparser.statement;

import java.util.function.Consumer;

public class Block implements Statement {
private boolean hasSemicolonAfterEnd = false;

Expand Down Expand Up @@ -36,9 +38,13 @@ public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
}

public StringBuilder appendTo(StringBuilder builder) {
return appendTo(builder, builder::append);
}

public StringBuilder appendTo(StringBuilder builder, Consumer<Statements> statementsPrinter) {
builder.append("BEGIN\n");
if (statements != null) {
builder.append(statements);
statementsPrinter.accept(statements);
}
builder.append("END");
if (hasSemicolonAfterEnd) {
Expand Down
18 changes: 14 additions & 4 deletions src/main/java/net/sf/jsqlparser/statement/IfElseStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package net.sf.jsqlparser.statement;

import java.util.Objects;
import java.util.function.Consumer;

import net.sf.jsqlparser.expression.Expression;

Expand Down Expand Up @@ -65,12 +66,21 @@ public void setUsingSemicolonForIfStatement(boolean usingSemicolonForIfStatement
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("IF ").append(condition).append(" ").append(ifStatement)
.append(usingSemicolonForIfStatement ? ";" : "");
return appendTo(builder, builder::append, builder::append);
}

public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionPrinter,
Consumer<Statement> statementPrinter) {
builder.append("IF ");
expressionPrinter.accept(condition);
builder.append(' ');
statementPrinter.accept(ifStatement);
builder.append(usingSemicolonForIfStatement ? ";" : "");

if (elseStatement != null) {
builder.append(" ELSE ").append(elseStatement)
.append(usingSemicolonForElseStatement ? ";" : "");
builder.append(" ELSE ");
statementPrinter.accept(elseStatement);
builder.append(usingSemicolonForElseStatement ? ";" : "");
}
return builder;
}
Expand Down
30 changes: 22 additions & 8 deletions src/main/java/net/sf/jsqlparser/statement/Statements.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class Statements extends ArrayList<Statement> implements Serializable {

Expand All @@ -34,17 +35,30 @@ public <E extends Statement> E get(Class<E> type, int index) {
return type.cast(get(index));
}

@Override
public String toString() {
StringBuilder b = new StringBuilder();
/**
* Appends each statement using the supplied renderer and the list's separators. Blocks and
* IF/ELSE statements retain their own semicolon settings. Null entries produced by error
* recovery retain the legacy "null;" placeholder without invoking the renderer.
*/
public StringBuilder appendTo(StringBuilder builder, Consumer<Statement> statementPrinter) {
for (Statement stmt : this) {
// IfElseStatements and Blocks control the Semicolons by themselves
if (stmt instanceof IfElseStatement || stmt instanceof Block) {
b.append(stmt).append("\n");
if (stmt == null) {
builder.append("null");
} else {
b.append(stmt).append(";\n");
statementPrinter.accept(stmt);
}
// IfElseStatements and Blocks control the Semicolons by themselves
if (!(stmt instanceof IfElseStatement || stmt instanceof Block)) {
builder.append(';');
}
builder.append('\n');
}
return b.toString();
return builder;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -344,8 +344,7 @@ public <S> StringBuilder visit(AlterEvent alterEvent, S context) {

@Override
public <S> StringBuilder visit(Statements statements, S context) {
statements.accept(this, context);
return builder;
return statements.appendTo(builder, statement -> statement.accept(this, context));
}

@Override
Expand Down Expand Up @@ -435,18 +434,7 @@ public <S> StringBuilder visit(ShowTablesStatement showTables, S context) {

@Override
public <S> StringBuilder visit(Block block, S context) {
builder.append("BEGIN\n");
if (block.getStatements() != null) {
for (Statement stmt : block.getStatements()) {
stmt.accept(this, context);
builder.append(";\n");
}
}
builder.append("END");
if (block.hasSemicolonAfterEnd()) {
builder.append(";");
}
return builder;
return block.appendTo(builder, statements -> statements.accept(this, context));
}

@Override
Expand Down Expand Up @@ -563,8 +551,9 @@ public <S> StringBuilder visit(AlterSession alterSession, S context) {

@Override
public <S> StringBuilder visit(IfElseStatement ifElseStatement, S context) {
ifElseStatement.appendTo(builder);
return builder;
return ifElseStatement.appendTo(builder,
expression -> expression.accept(expressionDeParser, context),
statement -> statement.accept(this, context));
}

@Override
Expand Down
14 changes: 14 additions & 0 deletions src/site/sphinx/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,20 @@ The object model works in both directions. Build the tree from Java and print it

Assertions.assertEquals(expectedSQLStr, builder.toString());

The same visitor can render an entire statement list:

.. code-block:: java

Statements statements = CCJSqlParserUtil.parseStatements("SELECT 1; SELECT 2;");
StringBuilder script = new StringBuilder();
statements.accept(new StatementDeParser(script), null);
Assertions.assertEquals("SELECT 1;\nSELECT 2;\n", script.toString());

Statement lists and nested blocks share the separator policy used by
``Statements.toString()``. Blocks and ``IF/ELSE`` statements retain their own
semicolon settings. Custom deparsers receive each child statement and the
``IF/ELSE`` condition through the visitor API, with the supplied context.


ODBC timestamp intervals
==============================
Expand Down
Loading
Loading