Skip to content
Open
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
18 changes: 8 additions & 10 deletions src/main/java/net/sf/jsqlparser/expression/JsonFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -436,12 +436,11 @@ public StringBuilder appendObject(StringBuilder builder) {
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
public StringBuilder appendObject(StringBuilder builder,
Consumer<Expression> expressionPrinter) {
builder.append("JSON_OBJECT( ");
builder.append("JSON_OBJECT(");
int start = builder.length();
int i = 0;
for (JsonKeyValuePair keyValuePair : keyValuePairs) {
if (i > 0) {
builder.append(", ");
}
builder.append(i > 0 ? ", " : " ");
keyValuePair.appendTo(builder, expressionPrinter);
i++;
}
Expand All @@ -453,7 +452,8 @@ public StringBuilder appendObject(StringBuilder builder,
appendUniqueKeys(builder);
appendReturningClause(builder, true);

builder.append(" ) ");
// An empty argument list renders as JSON_OBJECT()
builder.append(builder.length() > start ? " )" : ")");

return builder;
}
Expand Down Expand Up @@ -495,20 +495,18 @@ public StringBuilder appendArray(StringBuilder builder) {
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"})
public StringBuilder appendArray(StringBuilder builder,
Consumer<Expression> expressionPrinter) {
builder.append("JSON_ARRAY( ");
builder.append("JSON_ARRAY(");
int i = 0;

for (JsonFunctionExpression expr : expressions) {
if (i > 0) {
builder.append(", ");
}
builder.append(i > 0 ? ", " : " ");
expr.appendTo(builder, expressionPrinter);
i++;
}

appendOnNullType(builder);
appendReturningClause(builder, true);
builder.append(") ");
builder.append(')');

return builder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1304,8 +1304,7 @@ protected void toStringConstraintAlter(StringBuilder b) {
}
} else {
b.append("ADD CONSTRAINT ").append(getConstraintType()).append(" ")
.append(getConstraintSymbol())
.append(" ");
.append(getConstraintSymbol());
if (constraint instanceof KeyConstraint) {
b.append(" ")
.append(PlainSelect.getStringList(
Expand Down Expand Up @@ -1519,9 +1518,9 @@ protected void toStringPartition(StringBuilder b) {
b.append(partitions.get(0)).append(" WITH TABLE ")
.append(exchangePartitionTableName);
if (exchangePartitionWithValidation) {
b.append(" WITH VALIDATION ");
b.append(" WITH VALIDATION");
} else if (exchangePartitionWithoutValidation) {
b.append(" WITHOUT VALIDATION ");
b.append(" WITHOUT VALIDATION");
}
break;
case ANALYZE_PARTITION:
Expand Down Expand Up @@ -1575,18 +1574,20 @@ public void appendColumnDefinitionsTo(StringBuilder b, Consumer<Expression> expr
"PMD.ExcessiveMethodLength"})
private void toStringGeneral(StringBuilder b, Consumer<ColumnDataType> columnPrinter) {
if (operation == AlterOperation.COMMENT_WITH_EQUAL_SIGN) {
b.append("COMMENT =").append(" ");
b.append("COMMENT =");
} else if (operation == AlterOperation.ENABLE_ROW_LEVEL_SECURITY) {
b.append("ENABLE ROW LEVEL SECURITY").append(" ");
b.append("ENABLE ROW LEVEL SECURITY");
} else if (operation == AlterOperation.DISABLE_ROW_LEVEL_SECURITY) {
b.append("DISABLE ROW LEVEL SECURITY").append(" ");
b.append("DISABLE ROW LEVEL SECURITY");
} else if (operation == AlterOperation.FORCE_ROW_LEVEL_SECURITY) {
b.append("FORCE ROW LEVEL SECURITY").append(" ");
b.append("FORCE ROW LEVEL SECURITY");
} else if (operation == AlterOperation.NO_FORCE_ROW_LEVEL_SECURITY) {
b.append("NO FORCE ROW LEVEL SECURITY").append(" ");
b.append("NO FORCE ROW LEVEL SECURITY");
} else {
b.append(operation).append(" ");
b.append(operation);
}
int keywordEnd = b.length();
b.append(' ');
if (commentText != null) {
if (columnName != null) {
b.append(columnName).append(" COMMENT ");
Expand Down Expand Up @@ -1624,7 +1625,7 @@ private void toStringGeneral(StringBuilder b, Consumer<ColumnDataType> columnPri
}
}
if (useBrackets && colDataTypeList.size() == 1) {
b.append(" ( ");
b.append('(');
}
for (int i = 0; i < colDataTypeList.size(); i++) {
if (i > 0) {
Expand All @@ -1633,7 +1634,7 @@ private void toStringGeneral(StringBuilder b, Consumer<ColumnDataType> columnPri
columnPrinter.accept(colDataTypeList.get(i));
}
if (useBrackets && colDataTypeList.size() == 1) {
b.append(" ) ");
b.append(')');
}
if (colDataTypeList.size() > 1) {
b.append(")");
Expand All @@ -1658,6 +1659,10 @@ private void toStringGeneral(StringBuilder b, Consumer<ColumnDataType> columnPri
} else if (index != null) {
b.append(index);
}
if (b.length() == keywordEnd + 1) {
// a keyword without payload, such as FORCE, ends without a separator
b.setLength(keywordEnd);
}

if (getConstraints() != null && !getConstraints().isEmpty()) {
b.append(' ').append(PlainSelect.getStringList(constraints, false, false));
Expand Down Expand Up @@ -2125,7 +2130,7 @@ public boolean isVisible() {

@Override
public String toString() {
return columnName + " SET " + (visible ? " VISIBLE" : " INVISIBLE");
return columnName + " SET " + (visible ? "VISIBLE" : "INVISIBLE");
}
}

Expand Down
27 changes: 15 additions & 12 deletions src/main/java/net/sf/jsqlparser/statement/create/table/Index.java
Original file line number Diff line number Diff line change
Expand Up @@ -211,16 +211,16 @@ public String toString() {
}

public void appendTo(StringBuilder sql, Consumer<Expression> expressionPrinter) {
appendDeclarationTo(sql);
appendColumnsAndSpecTo(sql, expressionPrinter);
int start = sql.length();
appendDeclarationTo(sql, start);
appendColumnsAndSpecTo(sql, start, expressionPrinter);
appendIndexOptionsTo(sql, expressionPrinter);
if (tailParameters != null && !tailParameters.isEmpty()) {
sql.append(' ').append(PlainSelect.getStringList(tailParameters, false, false));
}
}

private void appendDeclarationTo(StringBuilder sql) {
int start = sql.length();
private void appendDeclarationTo(StringBuilder sql, int start) {
if (type != null) {
sql.append(type);
}
Expand All @@ -237,24 +237,27 @@ private void appendDeclarationTo(StringBuilder sql) {
sql.append(nullsDistinctClause()).append(clusteringClause());
}

/** Separates {@code word} from earlier declaration words, without a leading space. */
/** Separates {@code word} from earlier index words, without a leading space. */
private static void appendWord(StringBuilder sql, int start, String word) {
appendSeparator(sql, start);
sql.append(word);
}

private static void appendSeparator(StringBuilder sql, int start) {
if (sql.length() > start) {
sql.append(' ');
}
sql.append(word);
}

private void appendColumnsAndSpecTo(StringBuilder sql,
private void appendColumnsAndSpecTo(StringBuilder sql, int start,
Consumer<Expression> expressionPrinter) {
String spec = PlainSelect.getStringList(getIndexSpec(), false, false);
boolean hasColumns = columns != null && !columns.isEmpty();
if (hasColumns) {
sql.append(' ');
if (columns != null && !columns.isEmpty()) {
appendSeparator(sql, start);
appendColumnsTo(sql, expressionPrinter);
}
String spec = PlainSelect.getStringList(getIndexSpec(), false, false);
if (!spec.isEmpty()) {
sql.append(hasColumns ? " " : " ").append(spec);
appendWord(sql, start, spec);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
package net.sf.jsqlparser.statement.alter;

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

import java.util.List;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.create.index.CreateIndex;
import net.sf.jsqlparser.statement.create.table.Index;
import net.sf.jsqlparser.util.deparser.StatementDeParser;
import org.junit.jupiter.params.ParameterizedTest;
Expand All @@ -34,15 +37,97 @@ class DeparseWhitespaceTest {
"RENAME a TO b",
"ALTER TABLE t ADD INDEX i (body (10))",
"ALTER TABLE t ADD KEY k (a, b)",
"CREATE TABLE t (a INT, INDEX i (a))"})
"CREATE TABLE t (a INT, INDEX i (a))",
"ALTER TABLE t ALTER COLUMN c SET INVISIBLE",
"ALTER TABLE t ALTER COLUMN c SET VISIBLE",
"ALTER TABLE t ALTER c SET INVISIBLE",
"ALTER TABLE t ALTER INDEX i INVISIBLE",
"ALTER TABLE t ALTER INDEX i VISIBLE",
"ALTER TABLE t ALTER COLUMN c SET VISIBLE, ALTER INDEX i VISIBLE",
"ALTER TABLE t FORCE",
"ALTER TABLE t FORCE, ALGORITHM = INPLACE",
"CREATE TABLE t (a JSON DEFAULT (JSON_ARRAY()))",
"ALTER TABLE t ADD COLUMN j JSON DEFAULT (JSON_OBJECT())"})
void rendersSingleSpaces(String sql) throws JSQLParserException {
Statement statement =
CCJSqlParserUtil.parse(sql, parser -> parser.withDialect(Dialect.MYSQL));
assertRendersExactly(sql, Dialect.MYSQL);
}

@ParameterizedTest
@ValueSource(strings = {"ALTER TABLE t ENABLE ROW LEVEL SECURITY",
"ALTER TABLE t DISABLE ROW LEVEL SECURITY",
"ALTER TABLE t FORCE ROW LEVEL SECURITY",
"ALTER TABLE t NO FORCE ROW LEVEL SECURITY",
"ALTER TABLE t ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY",
"CREATE INDEX ON t (a)"})
void rendersSingleSpacesForPostgreSql(String sql) throws JSQLParserException {
assertRendersExactly(sql, Dialect.POSTGRESQL);
}

@ParameterizedTest
@ValueSource(strings = {"ALTER TABLE t FORCE",
"ALTER TABLE t MODIFY (c INT)",
"ALTER TABLE t MODIFY COLUMN (c INT NOT NULL)",
"ALTER TABLE t ADD (c INT), ADD d INT",
"ALTER TABLE t ADD CONSTRAINT UNIQUE KEY uk (a)",
"SELECT JSON_ARRAY() FROM t",
"SELECT JSON_OBJECT() FROM t"})
void rendersSingleSpacesWithoutDialect(String sql) throws JSQLParserException {
assertRendersExactly(sql, null);
}

@ParameterizedTest
@ValueSource(strings = {"SELECT JSON_ARRAY(1, 2) AS a FROM t",
"SELECT JSON_ARRAY(NULL ON NULL) AS a FROM t",
"SELECT JSON_OBJECT(KEY 'a' VALUE 1) AS o FROM t",
"SELECT JSON_OBJECT(ABSENT ON NULL) AS o FROM t"})
void jsonConstructorsAddNoDoubleOrTrailingSpace(String sql) throws JSQLParserException {
Statement statement = CCJSqlParserUtil.parse(sql);
String rendered = statement.toString();
assertFalse(rendered.contains(" "), rendered);
assertEquals(rendered, deparse(statement));
}

@Test
void columnVisibilityHasSingleSpaces() {
assertEquals("c SET INVISIBLE",
new AlterExpression.ColumnSetVisibility("c", false).toString());
assertEquals("c SET VISIBLE",
new AlterExpression.ColumnSetVisibility("c", true).toString());
}

@Test
void exchangePartitionHasNoTrailingSpace() {
AlterExpression expression = new AlterExpression()
.withOperation(AlterOperation.EXCHANGE_PARTITION);
expression.setPartitions(List.of("p0"));
expression.setExchangePartitionTableName("t2");
expression.setExchangePartitionWithValidation(true);
assertEquals("EXCHANGE PARTITION p0 WITH TABLE t2 WITH VALIDATION",
expression.toString());
}

@Test
void indexWithoutDeclarationHasNoLeadingSpace() throws JSQLParserException {
CreateIndex createIndex = (CreateIndex) CCJSqlParserUtil.parse("CREATE INDEX ON t (a)",
parser -> parser.withDialect(Dialect.POSTGRESQL));
assertEquals("(a)", createIndex.getIndex().toString());
assertEquals("(a)", new Index().withColumnsNames(List.of("a")).toString());
assertEquals("INDEX i INVISIBLE", new Index().withIndexKeyword("INDEX").withName("i")
.withIndexSpec(List.of("INVISIBLE")).toString());
}

private static void assertRendersExactly(String sql, Dialect dialect)
throws JSQLParserException {
Statement statement = dialect == null ? CCJSqlParserUtil.parse(sql)
: CCJSqlParserUtil.parse(sql, parser -> parser.withDialect(dialect));
assertEquals(sql, statement.toString());
assertEquals(sql, deparse(statement));
}

private static String deparse(Statement statement) {
StringBuilder deparsed = new StringBuilder();
statement.accept(new StatementDeParser(deparsed));
assertEquals(sql, deparsed.toString());
return deparsed.toString();
}

@Test
Expand Down
Loading