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
4 changes: 3 additions & 1 deletion src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -3066,6 +3066,7 @@ Token KeywordOrIdentifier():
| tk = <K_DATA>
| tk = <K_TYPE>
| tk = <K_VERSION>
| tk = <K_COMMENT>
)
{ return tk; }
}
Expand Down Expand Up @@ -17262,7 +17263,8 @@ AlterExpression AlterExpressionAddAlterModify():
constraints=AlterExpressionConstraintState() { alterExp.setConstraints(constraints); }
[ AlterExpressionUsingIndex(alterExp) ]
|
LOOKAHEAD(2) (
// Include the literal: COLUMN comment is a column definition, not a COMMENT clause.
LOOKAHEAD(RelObjectName() <K_COMMENT> <S_CHAR_LITERAL>) (
sk3=RelObjectName() <K_COMMENT> tk=<S_CHAR_LITERAL> { alterExp.withColumnName(sk3).withCommentText(tk.image); }
)
|
Expand Down
19 changes: 19 additions & 0 deletions src/site/sphinx/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,25 @@ One grammar covers every supported RDBMS, but a few pieces of syntax mean differ

Features set explicitly *after* the preset win over it.

ALTER column names
~~~~~~~~~~~~~~~~~~

Non-reserved names such as ``comment`` work unquoted in ``ADD``, ``MODIFY``,
``CHANGE``, ``DROP`` and ``RENAME`` column actions. The ``COLUMN`` keyword does
not change how the name is interpreted. Column definitions remain editable:

.. code-block:: java

Alter alter = (Alter) CCJSqlParserUtil.parse(
"ALTER TABLE t MODIFY COLUMN comment TEXT",
parser -> parser.withDialect(Dialect.MYSQL));
AlterExpression.ColumnDataType column = alter.getAlterExpressions().get(0)
.getColDataTypeList().get(0);
column.setColumnName("notes");
column.getColDataType().setDataType("LONGTEXT");
// ALTER TABLE t MODIFY COLUMN notes LONGTEXT
String sql = alter.toString();

PostgreSQL names and literals
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*-
* #%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.statement.alter;

import static org.junit.jupiter.api.Assertions.*;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.util.deparser.StatementDeParser;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class AlterCommentColumnTest {
@ParameterizedTest
@ValueSource(strings = {
"ADD COLUMN comment TEXT", "ADD comment TEXT", "MODIFY COLUMN comment TEXT",
"MODIFY comment TEXT", "MODIFY COLUMN `comment` TEXT",
"MODIFY COLUMN comment TEXT COMMENT 'note' AFTER id",
"CHANGE COLUMN comment comment2 TEXT", "CHANGE COLUMN old_name comment TEXT",
"DROP COLUMN comment", "DROP comment", "RENAME COLUMN comment TO comment2",
"RENAME COLUMN old_name TO comment"
})
void roundTripsUnquotedCommentColumn(String action) throws JSQLParserException {
for (Dialect dialect : new Dialect[] {null, Dialect.MYSQL}) {
Alter alter = parse("ALTER TABLE t " + action, dialect);
assertEquals(1, alter.getAlterExpressions().size());
assertRoundTrip(alter, dialect);
}
}

@Test
void exposesEditableColumnDefinitionInsteadOfColumnComment() throws JSQLParserException {
Alter alter = parse("ALTER TABLE t MODIFY COLUMN comment TEXT", Dialect.MYSQL);
AlterExpression action = alter.getAlterExpressions().get(0);
assertEquals(AlterOperation.MODIFY, action.getOperation());
assertNull(action.getCommentText());
AlterExpression.ColumnDataType column = action.getColDataTypeList().get(0);
assertEquals("comment", column.getColumnName());
assertEquals("TEXT", column.getColDataType().getDataType());
column.setColumnName("notes");
column.getColDataType().setDataType("LONGTEXT");
assertEquals("ALTER TABLE t MODIFY COLUMN notes LONGTEXT", alter.toString());
assertRoundTrip(alter, Dialect.MYSQL);
}

@Test
void exposesBothNamesInRenameAndChange() throws JSQLParserException {
Alter rename = parse("ALTER TABLE t RENAME COLUMN comment TO notes", Dialect.MYSQL);
AlterExpression action = rename.getAlterExpressions().get(0);
assertEquals("comment", action.getColumnOldName());
assertEquals("notes", action.getColumnName());
action.setColumnName("remarks");
assertEquals("ALTER TABLE t RENAME COLUMN comment TO remarks", rename.toString());
assertRoundTrip(rename, Dialect.MYSQL);
Alter change = parse("ALTER TABLE t CHANGE COLUMN comment notes TEXT", Dialect.MYSQL);
assertEquals("comment", change.getAlterExpressions().get(0).getColumnOldName());
assertEquals("notes",
change.getAlterExpressions().get(0).getColDataTypeList().get(0).getColumnName());
}

@ParameterizedTest
@ValueSource(strings = {"ALTER c COMMENT 'description'", "COMMENT = 'table description'",
"DROP COLUMN type", "DROP INDEX idx", "DROP CONSTRAINT ck", "RENAME TO other",
"RENAME INDEX idx TO other_idx", "RENAME CONSTRAINT ck TO other_ck"})
void preservesOtherAlterBranches(String action) throws JSQLParserException {
assertRoundTrip(parse("ALTER TABLE t " + action, null), null);
}

private static Alter parse(String sql, Dialect dialect) throws JSQLParserException {
return (Alter) CCJSqlParserUtil.parse(sql, p -> {
if (dialect != null) {
p.withDialect(dialect);
}
});
}

private static void assertRoundTrip(Alter alter, Dialect dialect) throws JSQLParserException {
StringBuilder buffer = new StringBuilder();
alter.accept(new StatementDeParser(buffer), null);
assertEquals(alter.toString(), buffer.toString());
assertEquals(alter.toString(), parse(buffer.toString(), dialect).toString());
}
}
Loading