Skip to content

Commit 2c0359a

Browse files
authored
fix: render single spaces in DROP PRIMARY KEY, RENAME TABLE and indexes (#2792)
DROP PRIMARY KEY ended with a space, which doubled before CASCADE or RESTRICT. RENAME TABLE rendered two spaces before the first table, and an index without a type rendered a leading space, so ALTER TABLE ... ADD INDEX and named-only indexes came out with doubled spaces. Separate these words with exactly one space; the SQL is otherwise unchanged. Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent a5ffe5c commit 2c0359a

7 files changed

Lines changed: 83 additions & 16 deletions

File tree

‎src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1421,7 +1421,7 @@ protected void toStringRename(StringBuilder b) {
14211421
protected void toStringDropSpecial(StringBuilder b) {
14221422
switch (operation) {
14231423
case DROP_PRIMARY_KEY:
1424-
b.append("DROP PRIMARY KEY ");
1424+
b.append("DROP PRIMARY KEY");
14251425
break;
14261426
case DROP_UNIQUE:
14271427
b.append("DROP UNIQUE (").append(PlainSelect.getStringList(dropColumns))

‎src/main/java/net/sf/jsqlparser/statement/alter/RenameTableStatement.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ public StringBuilder appendTo(StringBuilder builder) {
125125
if (i == 0) {
126126
builder
127127
.append("RENAME")
128-
.append(usingTableKeyword ? " TABLE " : " ")
129-
.append(usingIfExistsKeyword ? " IF EXISTS " : " ")
128+
.append(usingTableKeyword ? " TABLE" : "")
129+
.append(usingIfExistsKeyword ? " IF EXISTS" : "")
130+
.append(' ')
130131
.append(e.getKey())
131132
.append(waitDirective != null && waitDirective.length() > 0
132133
? " " + waitDirective

‎src/main/java/net/sf/jsqlparser/statement/create/table/Index.java‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -220,21 +220,31 @@ public void appendTo(StringBuilder sql, Consumer<Expression> expressionPrinter)
220220
}
221221

222222
private void appendDeclarationTo(StringBuilder sql) {
223-
String keyword = indexKeyword != null && (type == null
224-
|| !type.toUpperCase(java.util.Locale.ROOT)
225-
.endsWith(indexKeyword.toUpperCase(java.util.Locale.ROOT)))
226-
? " " + indexKeyword
227-
: "";
228-
sql.append(type != null ? type : "").append(keyword);
223+
int start = sql.length();
224+
if (type != null) {
225+
sql.append(type);
226+
}
227+
if (indexKeyword != null && (type == null || !type.toUpperCase(java.util.Locale.ROOT)
228+
.endsWith(indexKeyword.toUpperCase(java.util.Locale.ROOT)))) {
229+
appendWord(sql, start, indexKeyword);
230+
}
229231
if (!name.isEmpty()) {
230-
sql.append(' ').append(getName());
232+
appendWord(sql, start, getName());
231233
}
232234
if (getUsing() != null) {
233-
sql.append(" USING ").append(getUsing());
235+
appendWord(sql, start, "USING " + getUsing());
234236
}
235237
sql.append(nullsDistinctClause()).append(clusteringClause());
236238
}
237239

240+
/** Separates {@code word} from earlier declaration words, without a leading space. */
241+
private static void appendWord(StringBuilder sql, int start, String word) {
242+
if (sql.length() > start) {
243+
sql.append(' ');
244+
}
245+
sql.append(word);
246+
}
247+
238248
private void appendColumnsAndSpecTo(StringBuilder sql,
239249
Consumer<Expression> expressionPrinter) {
240250
String spec = PlainSelect.getStringList(getIndexSpec(), false, false);

‎src/test/java/net/sf/jsqlparser/statement/alter/AlterConstraintSeparationTest.java‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void uniqueConstraintAndOrdinaryIndexHaveSeparateEditableDefinitions() throws Ex
5050
indexAction.getIndex().setName("new_ix");
5151
assertRoundTrip(statement,
5252
"ALTER TABLE t ADD CONSTRAINT unique_symbol UNIQUE INDEX legacy_uq (new_id), "
53-
+ "ADD INDEX new_ix (other)",
53+
+ "ADD INDEX new_ix (other)",
5454
Dialect.MYSQL);
5555
}
5656

@@ -98,7 +98,7 @@ void replacingDefinitionChangesTheRenderedActionAndItsClassification() throws Ex
9898
assertNull(action.getConstraint());
9999
action.setConstraint(null);
100100
assertEquals(ConstraintKind.OTHER, action.getConstraintKind());
101-
assertRoundTrip(statement, "ALTER TABLE t ADD INDEX ix_new (id)", Dialect.MYSQL);
101+
assertRoundTrip(statement, "ALTER TABLE t ADD INDEX ix_new (id)", Dialect.MYSQL);
102102
}
103103

104104
@ParameterizedTest
@@ -116,7 +116,7 @@ void replacingLegacyUniqueDefinitionClearsItsOldHeader(boolean replaceWithIndex)
116116
.withName("ix").withColumnsNames(List.of("id")));
117117
assertNull(action.getConstraint());
118118
assertEquals(ConstraintKind.OTHER, action.getConstraintKind());
119-
assertRoundTrip(statement, "ALTER TABLE t ADD INDEX ix (id)", Dialect.MYSQL);
119+
assertRoundTrip(statement, "ALTER TABLE t ADD INDEX ix (id)", Dialect.MYSQL);
120120
} else {
121121
action.setConstraint(new CheckConstraint()
122122
.withExpression(CCJSqlParserUtil.parseCondExpression("id > 0")));
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.alter;
11+
12+
import static org.junit.jupiter.api.Assertions.assertEquals;
13+
14+
import net.sf.jsqlparser.JSQLParserException;
15+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
16+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
17+
import net.sf.jsqlparser.statement.Statement;
18+
import net.sf.jsqlparser.statement.create.table.Index;
19+
import net.sf.jsqlparser.util.deparser.StatementDeParser;
20+
import org.junit.jupiter.params.ParameterizedTest;
21+
import org.junit.jupiter.params.provider.ValueSource;
22+
import org.junit.jupiter.api.Test;
23+
24+
/** Renderers separate words with exactly one space and add no trailing space. */
25+
class DeparseWhitespaceTest {
26+
27+
@ParameterizedTest
28+
@ValueSource(strings = {"ALTER TABLE t DROP PRIMARY KEY",
29+
"ALTER TABLE t DROP PRIMARY KEY CASCADE",
30+
"ALTER TABLE t DROP PRIMARY KEY, DROP COLUMN c",
31+
"RENAME TABLE t TO t2",
32+
"RENAME TABLE a TO b, c TO d",
33+
"RENAME TABLE IF EXISTS a TO b",
34+
"RENAME a TO b",
35+
"ALTER TABLE t ADD INDEX i (body (10))",
36+
"ALTER TABLE t ADD KEY k (a, b)",
37+
"CREATE TABLE t (a INT, INDEX i (a))"})
38+
void rendersSingleSpaces(String sql) throws JSQLParserException {
39+
Statement statement =
40+
CCJSqlParserUtil.parse(sql, parser -> parser.withDialect(Dialect.MYSQL));
41+
assertEquals(sql, statement.toString());
42+
43+
StringBuilder deparsed = new StringBuilder();
44+
statement.accept(new StatementDeParser(deparsed));
45+
assertEquals(sql, deparsed.toString());
46+
}
47+
48+
@Test
49+
void indexDeclarationHasNoLeadingSpace() {
50+
assertEquals("i2", new Index().withName("i2").toString());
51+
assertEquals("KEY k (a)", new Index().withIndexKeyword("KEY").withName("k")
52+
.withColumnsNames(java.util.List.of("a")).toString());
53+
assertEquals("UNIQUE INDEX u (a)", new Index().withType("UNIQUE").withIndexKeyword("INDEX")
54+
.withName("u").withColumnsNames(java.util.List.of("a")).toString());
55+
}
56+
}

‎src/test/java/net/sf/jsqlparser/statement/alter/IndexOptionBoundaryTest.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void tablespaceBelongsToConstraintOptions(String key) throws JSQLParserException
4747
void mysqlAddIndexAttributes(String options) throws JSQLParserException {
4848
Alter alter = (Alter) parse("ALTER TABLE t ADD INDEX ix (id) " + options, Dialect.MYSQL);
4949
assertEquals("ix", alter.getAlterExpressions().get(0).getIndex().getName());
50-
assertEquals("ALTER TABLE t ADD INDEX ix (id) " + options, alter.toString());
50+
assertEquals("ALTER TABLE t ADD INDEX ix (id) " + options, alter.toString());
5151
assertRoundTrip(alter, Dialect.MYSQL);
5252
}
5353

‎src/test/java/net/sf/jsqlparser/util/deparser/TableConstraintExpressionDeParserTest.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ void createAndAlterFunctionalIndexesUseExpressionVisitor() throws JSQLParserExce
4848
assertRewrite("CREATE TABLE t (id INT, INDEX idx ((id + 1)))",
4949
"CREATE TABLE t (id INT, INDEX idx ((mapped_id + 101)))");
5050
assertRewrite("ALTER TABLE t ADD INDEX idx ((id + 1))",
51-
"ALTER TABLE t ADD INDEX idx ((mapped_id + 101))");
51+
"ALTER TABLE t ADD INDEX idx ((mapped_id + 101))");
5252
}
5353

5454
@ParameterizedTest

0 commit comments

Comments
 (0)