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
13 changes: 11 additions & 2 deletions src/main/java/net/sf/jsqlparser/statement/AssertStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;

import java.util.function.Consumer;

/**
* BigQuery's {@code ASSERT expression [AS description]}, which fails the script when the expression
* does not evaluate to {@code TRUE}.
Expand Down Expand Up @@ -62,9 +64,16 @@ public AssertStatement withDescription(StringValue description) {
}

public StringBuilder appendTo(StringBuilder builder) {
builder.append("ASSERT ").append(expression);
return appendTo(builder, builder::append);
}

/** Shares statement syntax with deparsers while visiting both expression and description. */
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionRenderer) {
builder.append("ASSERT ");
expressionRenderer.accept(expression);
if (description != null) {
builder.append(" AS ").append(description);
builder.append(" AS ");
expressionRenderer.accept(description);
}
return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import java.io.Serializable;
import java.util.List;
import java.util.function.Consumer;

/**
* DuckDB's {@code CREATE [OR REPLACE] [TEMPORARY] MACRO name (parameters) AS [TABLE] body}, a named
Expand Down Expand Up @@ -115,6 +116,12 @@ public boolean isTable() {
}

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

/** Shares punctuation while exposing parameter defaults and both kinds of macro body. */
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionRenderer,
Consumer<Select> selectRenderer) {
builder.append("CREATE ");
if (orReplace) {
builder.append("OR REPLACE ");
Expand All @@ -127,13 +134,14 @@ public StringBuilder appendTo(StringBuilder builder) {
if (i > 0) {
builder.append(", ");
}
builder.append(parameters.get(i));
parameters.get(i).appendTo(builder, expressionRenderer);
}
builder.append(") AS ");
if (select != null) {
builder.append("TABLE ").append(select);
builder.append("TABLE ");
selectRenderer.accept(select);
} else {
builder.append(expression);
expressionRenderer.accept(expression);
}
return builder;
}
Expand Down Expand Up @@ -172,7 +180,18 @@ public Expression getDefaultValue() {

@Override
public String toString() {
return defaultValue == null ? name : name + " := " + defaultValue;
StringBuilder builder = new StringBuilder();
return appendTo(builder, builder::append).toString();
}

private StringBuilder appendTo(StringBuilder builder,
Consumer<Expression> expressionRenderer) {
builder.append(name);
if (defaultValue != null) {
builder.append(" := ");
expressionRenderer.accept(defaultValue);
}
return builder;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import net.sf.jsqlparser.statement.StatementVisitor;
import net.sf.jsqlparser.statement.select.Select;

import java.util.function.Consumer;

/**
* BigQuery's {@code EXPORT DATA [WITH CONNECTION connection] OPTIONS (option_list) AS query}.
*
Expand Down Expand Up @@ -67,14 +69,28 @@ public ExportDataStatement withSelect(Select select) {
}

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

/** Renders options and the query through the caller's expression and select visitors. */
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionRenderer,
Consumer<Select> selectRenderer) {
builder.append("EXPORT DATA");
if (connectionName != null) {
builder.append(" WITH CONNECTION ").append(connectionName);
}
if (options != null) {
builder.append(" OPTIONS (").append(options).append(")");
builder.append(" OPTIONS (");
for (int i = 0; i < options.size(); i++) {
if (i > 0) {
builder.append(", ");
}
expressionRenderer.accept(options.get(i));
}
builder.append(")");
}
builder.append(" AS ").append(select);
builder.append(" AS ");
selectRenderer.accept(select);
return builder;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,8 @@ public <S> StringBuilder visit(PragmaStatement pragmaStatement, S context) {

@Override
public <S> StringBuilder visit(AssertStatement assertStatement, S context) {
assertStatement.appendTo(builder);
assertStatement.appendTo(builder,
expression -> expression.accept(expressionDeParser, context));
return builder;
}

Expand All @@ -582,7 +583,9 @@ public <S> StringBuilder visit(ExtensionStatement extensionStatement, S context)

@Override
public <S> StringBuilder visit(ExportDataStatement exportDataStatement, S context) {
exportDataStatement.appendTo(builder);
exportDataStatement.appendTo(builder,
expression -> expression.accept(expressionDeParser, context),
select -> select.accept((SelectVisitor<?>) selectDeParser, context));
return builder;
}

Expand Down Expand Up @@ -630,7 +633,9 @@ public <S> StringBuilder visit(CopyStatement copyStatement, S context) {

@Override
public <S> StringBuilder visit(CreateMacro createMacro, S context) {
createMacro.appendTo(builder);
createMacro.appendTo(builder,
expression -> expression.accept(expressionDeParser, context),
select -> select.accept((SelectVisitor<?>) selectDeParser, context));
return builder;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.util.deparser;

import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

class StructuredStatementVisitorTest {
@ParameterizedTest
@ValueSource(strings = {
"CREATE MACRO m(x, y := 7) AS x + y + 8",
"CREATE MACRO m() AS TABLE WITH c AS (SELECT 7 AS id) SELECT id FROM c UNION ALL SELECT 8",
"ASSERT (1 = 1) AS 'expected'",
"ASSERT EXISTS (SELECT 7 FROM users WHERE id = 8)",
"EXPORT DATA OPTIONS(uri='gs://example/*.csv',format='CSV') AS SELECT 7 FROM users",
"EXPORT DATA OPTIONS(uri='gs://example/*.csv',format='CSV') AS WITH c AS (SELECT 7 AS id) SELECT id FROM c UNION ALL SELECT 8"
})
void defaultDeparserMatchesStatementOutput(String sql) throws Exception {
Statement statement = CCJSqlParserUtil.parse(sql);
StringBuilder output = new StringBuilder();
statement.accept(new StatementDeParser(output), null);
assertEquals(statement.toString(), output.toString());
assertEquals(output.toString(), CCJSqlParserUtil.parse(output.toString()).toString());
}

@Test
void visitsMacroDefaultsAndScalarBody() throws Exception {
assertVisited("CREATE MACRO m(x, y := 7) AS x + y + 8", List.of("7", "8"),
"CREATE MACRO m (x, y := 107) AS x + y + 108");
}

@Test
void visitsMacroQueriesAndCtes() throws Exception {
assertVisited(
"CREATE MACRO m() AS TABLE WITH c AS (SELECT 7 AS id) SELECT id FROM c UNION ALL SELECT 8",
List.of("7", "8"),
"CREATE MACRO m () AS TABLE WITH c AS (SELECT 107 AS id) SELECT id FROM c UNION ALL SELECT 108");
}

@Test
void visitsAssertionAndDescription() throws Exception {
assertVisited("ASSERT (1 = 1) AS 'expected'", List.of("1", "1", "expected"),
"ASSERT (101 = 101) AS 'changed'");
}

@Test
void visitsExportOptionsAndQuery() throws Exception {
assertVisited(
"EXPORT DATA OPTIONS(uri='gs://example/*.csv',format='CSV') AS SELECT 7 FROM users WHERE id = 8",
List.of("gs://example/*.csv", "CSV", "7", "8"),
"EXPORT DATA OPTIONS (uri = 'changed', format = 'changed') AS SELECT 107 FROM users WHERE id = 108");
}

private void assertVisited(String sql, List<String> expectedVisits, String expectedOutput)
throws Exception {
List<String> visited = new ArrayList<>();
ExpressionDeParser expressions = new ExpressionDeParser() {
@Override
public <S> StringBuilder visit(LongValue value, S context) {
visited.add(value.getStringValue());
return getBuilder().append(value.getValue() + 100);
}

@Override
public <S> StringBuilder visit(StringValue value, S context) {
visited.add(value.getValue());
return getBuilder().append("'changed'");
}
};
StringBuilder output = new StringBuilder();
Statement statement = CCJSqlParserUtil.parse(sql);
statement.accept(new StatementDeParser(expressions, new SelectDeParser(), output),
"context");
assertEquals(expectedVisits, visited);
assertEquals(expectedOutput, output.toString());
assertEquals(expectedOutput, CCJSqlParserUtil.parse(output.toString()).toString());
}
}
Loading