From 0433af2bbeb1a5319d5668a602bc34222a938188 Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Fri, 15 Dec 2023 22:16:52 +0800 Subject: [PATCH 1/2] feat: Support `RENAME INDEX` for MySQL, `RENAME CONSTRAINT` for PostgreSQL --- .../statement/alter/AlterExpression.java | 1404 +++++++++-------- .../statement/alter/AlterOperation.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 15 +- .../jsqlparser/statement/alter/AlterTest.java | 10 + 4 files changed, 739 insertions(+), 692 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 2902c0833..45b33cd3f 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -12,14 +12,12 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; - import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; - import net.sf.jsqlparser.statement.ReferentialAction; import net.sf.jsqlparser.statement.ReferentialAction.Action; import net.sf.jsqlparser.statement.ReferentialAction.Type; @@ -31,743 +29,771 @@ @SuppressWarnings({"PMD.CyclomaticComplexity"}) public class AlterExpression implements Serializable { - private AlterOperation operation; - private String optionalSpecifier; - private String newTableName; - private String columnName; - private String columnOldName; - // private ColDataType dataType; + private AlterOperation operation; + private String optionalSpecifier; + private String newTableName; + private String columnName; + private String columnOldName; + // private ColDataType dataType; - private List colDataTypeList; - private List columnDropNotNullList; + private List colDataTypeList; + private List columnDropNotNullList; - private List columnDropDefaultList; - - private List pkColumns; - private List ukColumns; - private String ukName; - private Index index = null; - private String constraintName; - private boolean usingIfExists; - - private Set referentialActions = new LinkedHashSet<>(2); - - private List fkColumns; - private String fkSourceSchema; - - private String fkSourceTable; - private List fkSourceColumns; - private boolean uk; - private boolean useEqual; - - private List constraints; - private List parameters; - private String commentText; - - private boolean hasColumn = false; - - - private boolean useBrackets=false; - - public boolean hasColumn() { - return hasColumn; - } - - public boolean useBrackets() { - return useBrackets; - } - - public void useBrackets(boolean useBrackets) { - this.useBrackets = useBrackets; - } - - public void hasColumn(boolean hasColumn) { - this.hasColumn = hasColumn; - } - - public String getFkSourceSchema() { - return fkSourceSchema; - } - - public void setFkSourceSchema(String fkSourceSchema) { - this.fkSourceSchema = fkSourceSchema; - } - - public String getCommentText() { - return commentText; - } - - public void setCommentText(String commentText) { - this.commentText = commentText; - } - - public AlterOperation getOperation() { - return operation; - } - - public void setOperation(AlterOperation operation) { - this.operation = operation; - } - - public String getOptionalSpecifier() { - return optionalSpecifier; - } - - public void setOptionalSpecifier(String optionalSpecifier) { - this.optionalSpecifier = optionalSpecifier; - } - - /** - * @param type - * @param action - */ - public void setReferentialAction(Type type, Action action) { - setReferentialAction(type, action, true); - } - - public AlterExpression withReferentialAction(Type type, Action action) { - setReferentialAction(type, action); - return this; - } - - /** @param type */ - public void removeReferentialAction(Type type) { - setReferentialAction(type, null, false); - } - - /** - * @param type - * @return - */ - public ReferentialAction getReferentialAction(Type type) { - return referentialActions.stream() - .filter(ra -> type.equals(ra.getType())) - .findFirst() - .orElse(null); - } - - private void setReferentialAction(Type type, Action action, boolean set) { - ReferentialAction found = getReferentialAction(type); - if (set) { - if (found == null) { - referentialActions.add(new ReferentialAction(type, action)); - } else { - found.setAction(action); - } - } else if (found != null) { - referentialActions.remove(found); - } - } - /** - * @return - * @deprecated use {@link #getReferentialAction(ReferentialAction.Type)} - */ - @Deprecated - public boolean isOnDeleteCascade() { - ReferentialAction found = getReferentialAction(Type.DELETE); - return found != null && Action.CASCADE.equals(found.getAction()); - } - - /** - * @param onDeleteCascade - * @deprecated use {@link #setReferentialAction(ReferentialAction.Type, ReferentialAction.Action, boolean)} - */ - @Deprecated - public void setOnDeleteCascade(boolean onDeleteCascade) { - setReferentialAction(Type.DELETE, Action.CASCADE, onDeleteCascade); - } - - /** - * @return - * @deprecated use {@link #getReferentialAction(ReferentialAction.Type)} - */ - @Deprecated - public boolean isOnDeleteRestrict() { - ReferentialAction found = getReferentialAction(Type.DELETE); - return found != null && Action.RESTRICT.equals(found.getAction()); - } - - /** - * @param onDeleteRestrict - * @deprecated use {@link #setReferentialAction(ReferentialAction.Type, ReferentialAction.Action, boolean)} - */ - @Deprecated - public void setOnDeleteRestrict(boolean onDeleteRestrict) { - setReferentialAction(Type.DELETE, Action.RESTRICT, onDeleteRestrict); - } - - /** - * @return - * @deprecated use {@link #getReferentialAction(ReferentialAction.Type)} - */ - @Deprecated - public boolean isOnDeleteSetNull() { - ReferentialAction found = getReferentialAction(Type.DELETE); - return found != null && Action.SET_NULL.equals(found.getAction()); - } - - /** - * @param onDeleteSetNull - * @deprecated use {@link #setReferentialAction(ReferentialAction.Type, ReferentialAction.Action, boolean)} - */ - @Deprecated - public void setOnDeleteSetNull(boolean onDeleteSetNull) { - setReferentialAction(Type.DELETE, Action.SET_NULL, onDeleteSetNull); - } - - public List getFkColumns() { - return fkColumns; - } - - public void setFkColumns(List fkColumns) { - this.fkColumns = fkColumns; - } - - public String getFkSourceTable() { - return fkSourceTable; - } - - public void setFkSourceTable(String fkSourceTable) { - this.fkSourceTable = fkSourceTable; - } - - public List getColDataTypeList() { - return colDataTypeList; - } - - public void addColDataType(String columnName, ColDataType colDataType) { - addColDataType(new ColumnDataType(columnName, false, colDataType, null)); - } - - public void addColDataType(ColumnDataType columnDataType) { - if (colDataTypeList == null) { - colDataTypeList = new ArrayList<>(); - } - colDataTypeList.add(columnDataType); - } - - public void addColDropNotNull(ColumnDropNotNull columnDropNotNull) { - if (columnDropNotNullList == null) { - columnDropNotNullList = new ArrayList<>(); - } - columnDropNotNullList.add(columnDropNotNull); - } - - public void addColDropDefault(ColumnDropDefault columnDropDefault) { - if (columnDropDefaultList == null) { - columnDropDefaultList = new ArrayList<>(); - } - columnDropDefaultList.add(columnDropDefault); - } - - public List getFkSourceColumns() { - return fkSourceColumns; - } - - public void setFkSourceColumns(List fkSourceColumns) { - this.fkSourceColumns = fkSourceColumns; - } - - public String getNewTableName() { - return newTableName; - } - - public void setNewTableName(String newTableName) { - this.newTableName = newTableName; - } - - public String getColumnName() { - return columnName; - } - - public void setColumnName(String columnName) { - this.columnName = columnName; - } - - @Deprecated - public String getColOldName() { - return getColumnOldName(); - } - - @Deprecated - public void setColOldName(String columnOldName) { - setColumnOldName(columnOldName); - } - - public String getColumnOldName() { - return columnOldName; - } - - public void setColumnOldName(String columnOldName) { - this.columnOldName = columnOldName; - } + private List columnDropDefaultList; - public String getConstraintName() { - return this.constraintName; - } + private List pkColumns; + private List ukColumns; + private String ukName; + private Index index = null; + private Index oldIndex = null; + private String constraintName; + private boolean usingIfExists; - public void setConstraintName(final String constraintName) { - this.constraintName = constraintName; - } + private Set referentialActions = new LinkedHashSet<>(2); - public boolean isUsingIfExists() { - return usingIfExists; - } + private List fkColumns; + private String fkSourceSchema; - public void setUsingIfExists(boolean usingIfExists) { - this.usingIfExists = usingIfExists; - } + private String fkSourceTable; + private List fkSourceColumns; + private boolean uk; + private boolean useEqual; - public List getPkColumns() { - return pkColumns; - } + private List constraints; + private List parameters; + private String commentText; - public void setPkColumns(List pkColumns) { - this.pkColumns = pkColumns; - } - - public List getUkColumns() { - return ukColumns; - } - - public void setUkColumns(List ukColumns) { - this.ukColumns = ukColumns; - } - - public String getUkName() { - return ukName; - } - - public void setUkName(String ukName) { - this.ukName = ukName; - } - - public Index getIndex() { - return index; - } - - public void setIndex(Index index) { - this.index = index; - } - - public List getConstraints() { - return constraints; - } - - public void setConstraints(List constraints) { - this.constraints = constraints; - } - - public List getColumnDropNotNullList() { - return columnDropNotNullList; - } - - public void addParameters(String... params) { - if (parameters == null) { - parameters = new ArrayList<>(); - } - parameters.addAll(Arrays.asList(params)); - } - - public List getParameters() { - return parameters; - } - - public boolean getUseEqual() { - return useEqual; - } - - public void setUseEqual(boolean useEqual) { - this.useEqual = useEqual; - } - - public boolean getUk() { - return uk; - } - - public void setUk(boolean uk) { - this.uk = uk; - } - - @Override - @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.ExcessiveMethodLength"}) - public String toString() { - - StringBuilder b = new StringBuilder(); - - if (operation== AlterOperation.UNSPECIFIC) { - b.append(optionalSpecifier); - } else if (operation== AlterOperation.RENAME_TABLE) { - - b.append("RENAME TO ").append(newTableName); - } else if (operation== AlterOperation.DROP_PRIMARY_KEY) { - - b.append("DROP PRIMARY KEY "); - } else if (operation== AlterOperation.DROP_UNIQUE) { - - b.append("DROP UNIQUE (").append(PlainSelect.getStringList(pkColumns)).append(')'); - } else if (operation== AlterOperation.DROP_FOREIGN_KEY) { - - b.append("DROP FOREIGN KEY (").append(PlainSelect.getStringList(pkColumns)).append(')'); - } else if (operation== AlterOperation.DROP && columnName==null && pkColumns!=null && pkColumns.size()>0) { - // Oracle Multi Column Drop - b.append("DROP (").append(PlainSelect.getStringList(pkColumns)).append(')'); - } else { - b.append(operation).append(" "); - - if (commentText != null) { - if (columnName != null) { - b.append(columnName).append(" COMMENT "); - } - b.append(commentText); - } else if (columnName != null) { - if (hasColumn) { - b.append("COLUMN "); - } - if (usingIfExists) { - b.append("IF EXISTS "); - } - if (operation == AlterOperation.RENAME) { - b.append(columnOldName).append(" TO "); - } - b.append(columnName); - } else if (getColDataTypeList() != null) { - if (operation == AlterOperation.CHANGE) { - if (optionalSpecifier != null) { - b.append(optionalSpecifier).append(" "); - } - b.append(columnOldName).append(" "); - } else if (colDataTypeList.size() > 1) { - b.append("("); - } else { - if (hasColumn) { - b.append("COLUMN "); - } - } - if (useBrackets && colDataTypeList.size() == 1){ - b.append(" ( "); - } - b.append(PlainSelect.getStringList(colDataTypeList)); - if (useBrackets && colDataTypeList.size() == 1 ){ - b.append(" ) "); - } - if (colDataTypeList.size() > 1) { - b.append(")"); - } - } else if (getColumnDropNotNullList() != null) { - b.append("COLUMN "); - b.append(PlainSelect.getStringList(columnDropNotNullList)); - } else if ( columnDropDefaultList != null && !columnDropDefaultList.isEmpty() ) { - b.append("COLUMN "); - b.append(PlainSelect.getStringList(columnDropDefaultList)); - } else if (constraintName != null) { - b.append("CONSTRAINT "); - if (usingIfExists) { - b.append("IF EXISTS "); - } - b.append(constraintName); - } else if (pkColumns != null) { - b.append("PRIMARY KEY (").append(PlainSelect.getStringList(pkColumns)).append(')'); - } else if (ukColumns != null) { - b.append("UNIQUE"); - if (ukName != null) { - if (getUk()) { - b.append(" KEY "); + private boolean hasColumn = false; + + + private boolean useBrackets = false; + + public Index getOldIndex() { + return oldIndex; + } + + public void setOldIndex(Index oldIndex) { + this.oldIndex = oldIndex; + } + + public boolean hasColumn() { + return hasColumn; + } + + public boolean useBrackets() { + return useBrackets; + } + + public void useBrackets(boolean useBrackets) { + this.useBrackets = useBrackets; + } + + public void hasColumn(boolean hasColumn) { + this.hasColumn = hasColumn; + } + + public String getFkSourceSchema() { + return fkSourceSchema; + } + + public void setFkSourceSchema(String fkSourceSchema) { + this.fkSourceSchema = fkSourceSchema; + } + + public String getCommentText() { + return commentText; + } + + public void setCommentText(String commentText) { + this.commentText = commentText; + } + + public AlterOperation getOperation() { + return operation; + } + + public void setOperation(AlterOperation operation) { + this.operation = operation; + } + + public String getOptionalSpecifier() { + return optionalSpecifier; + } + + public void setOptionalSpecifier(String optionalSpecifier) { + this.optionalSpecifier = optionalSpecifier; + } + + /** + * @param type + * @param action + */ + public void setReferentialAction(Type type, Action action) { + setReferentialAction(type, action, true); + } + + public AlterExpression withReferentialAction(Type type, Action action) { + setReferentialAction(type, action); + return this; + } + + /** + * @param type + */ + public void removeReferentialAction(Type type) { + setReferentialAction(type, null, false); + } + + /** + * @param type + * @return + */ + public ReferentialAction getReferentialAction(Type type) { + return referentialActions.stream() + .filter(ra -> type.equals(ra.getType())) + .findFirst() + .orElse(null); + } + + private void setReferentialAction(Type type, Action action, boolean set) { + ReferentialAction found = getReferentialAction(type); + if (set) { + if (found == null) { + referentialActions.add(new ReferentialAction(type, action)); } else { - b.append(" INDEX "); + found.setAction(action); } - b.append(ukName); - } - b.append(" (").append(PlainSelect.getStringList(ukColumns)).append(")"); - } else if (fkColumns != null) { - b.append("FOREIGN KEY (") - .append(PlainSelect.getStringList(fkColumns)) - .append(") REFERENCES ") - .append( - fkSourceSchema != null && fkSourceSchema.trim().length() > 0 - ? fkSourceSchema + "." - : "") - .append(fkSourceTable) - .append(" (") - .append(PlainSelect.getStringList(fkSourceColumns)) - .append(")"); - referentialActions.forEach(b::append); - } else if (index != null) { - b.append(index); + } else if (found != null) { + referentialActions.remove(found); } + } + /** + * @return + * @deprecated use {@link #getReferentialAction(ReferentialAction.Type)} + */ + @Deprecated + public boolean isOnDeleteCascade() { + ReferentialAction found = getReferentialAction(Type.DELETE); + return found != null && Action.CASCADE.equals(found.getAction()); + } + + /** + * @param onDeleteCascade + * @deprecated use + * {@link #setReferentialAction(ReferentialAction.Type, ReferentialAction.Action, boolean)} + */ + @Deprecated + public void setOnDeleteCascade(boolean onDeleteCascade) { + setReferentialAction(Type.DELETE, Action.CASCADE, onDeleteCascade); + } + + /** + * @return + * @deprecated use {@link #getReferentialAction(ReferentialAction.Type)} + */ + @Deprecated + public boolean isOnDeleteRestrict() { + ReferentialAction found = getReferentialAction(Type.DELETE); + return found != null && Action.RESTRICT.equals(found.getAction()); + } + + /** + * @param onDeleteRestrict + * @deprecated use + * {@link #setReferentialAction(ReferentialAction.Type, ReferentialAction.Action, boolean)} + */ + @Deprecated + public void setOnDeleteRestrict(boolean onDeleteRestrict) { + setReferentialAction(Type.DELETE, Action.RESTRICT, onDeleteRestrict); + } - if (getConstraints() != null && !getConstraints().isEmpty()) { - b.append(' ').append(PlainSelect.getStringList(constraints, false, false)); + /** + * @return + * @deprecated use {@link #getReferentialAction(ReferentialAction.Type)} + */ + @Deprecated + public boolean isOnDeleteSetNull() { + ReferentialAction found = getReferentialAction(Type.DELETE); + return found != null && Action.SET_NULL.equals(found.getAction()); + } + + /** + * @param onDeleteSetNull + * @deprecated use + * {@link #setReferentialAction(ReferentialAction.Type, ReferentialAction.Action, boolean)} + */ + @Deprecated + public void setOnDeleteSetNull(boolean onDeleteSetNull) { + setReferentialAction(Type.DELETE, Action.SET_NULL, onDeleteSetNull); + } + + public List getFkColumns() { + return fkColumns; + } + + public void setFkColumns(List fkColumns) { + this.fkColumns = fkColumns; + } + + public String getFkSourceTable() { + return fkSourceTable; + } + + public void setFkSourceTable(String fkSourceTable) { + this.fkSourceTable = fkSourceTable; + } + + public List getColDataTypeList() { + return colDataTypeList; + } + + public void addColDataType(String columnName, ColDataType colDataType) { + addColDataType(new ColumnDataType(columnName, false, colDataType, null)); + } + + public void addColDataType(ColumnDataType columnDataType) { + if (colDataTypeList == null) { + colDataTypeList = new ArrayList<>(); } - if (getUseEqual()) { - b.append('='); + colDataTypeList.add(columnDataType); + } + + public void addColDropNotNull(ColumnDropNotNull columnDropNotNull) { + if (columnDropNotNullList == null) { + columnDropNotNullList = new ArrayList<>(); } + columnDropNotNullList.add(columnDropNotNull); } - if (parameters != null && !parameters.isEmpty()) { - b.append(' ').append(PlainSelect.getStringList(parameters, false, false)); - } - - return b.toString(); - } - - public AlterExpression withOperation(AlterOperation operation) { - this.setOperation(operation); - return this; - } - - public AlterExpression withOptionalSpecifier(String optionalSpecifier) { - this.setOptionalSpecifier(optionalSpecifier); - return this; - } - - public AlterExpression withColumnName(String columnName) { - this.setColumnName(columnName); - return this; - } - - public AlterExpression withPkColumns(List pkColumns) { - this.setPkColumns(pkColumns); - return this; - } - - public AlterExpression withUkColumns(List ukColumns) { - this.setUkColumns(ukColumns); - return this; - } - - public AlterExpression withUkName(String ukName) { - this.setUkName(ukName); - return this; - } - - public AlterExpression withIndex(Index index) { - this.setIndex(index); - return this; - } - - public AlterExpression withConstraintName(String constraintName) { - this.setConstraintName(constraintName); - return this; - } - - public AlterExpression withUsingIfExists(boolean usingIfExists) { - this.setUsingIfExists(usingIfExists); - return this; - } - - public AlterExpression withOnDeleteRestrict(boolean onDeleteRestrict) { - this.setOnDeleteRestrict(onDeleteRestrict); - return this; - } - - public AlterExpression withOnDeleteSetNull(boolean onDeleteSetNull) { - this.setOnDeleteSetNull(onDeleteSetNull); - return this; - } - - public AlterExpression withOnDeleteCascade(boolean onDeleteCascade) { - this.setOnDeleteCascade(onDeleteCascade); - return this; - } - - public AlterExpression withFkColumns(List fkColumns) { - this.setFkColumns(fkColumns); - return this; - } - - public AlterExpression withFkSourceSchema(String fkSourceSchema) { - this.setFkSourceTable(fkSourceSchema); - return this; - } - - public AlterExpression withFkSourceTable(String fkSourceTable) { - this.setFkSourceTable(fkSourceTable); - return this; - } - - public AlterExpression withFkSourceColumns(List fkSourceColumns) { - this.setFkSourceColumns(fkSourceColumns); - return this; - } - - public AlterExpression withUk(boolean uk) { - this.setUk(uk); - return this; - } - - public AlterExpression withUseEqual(boolean useEqual) { - this.setUseEqual(useEqual); - return this; - } - - public AlterExpression withConstraints(List constraints) { - this.setConstraints(constraints); - return this; - } - - public AlterExpression withCommentText(String commentText) { - this.setCommentText(commentText); - return this; - } - - public AlterExpression withColumnOldName(String columnOldName) { - setColumnOldName(columnOldName); - return this; - } - - public AlterExpression addPkColumns(String... pkColumns) { - List collection = Optional.ofNullable(getPkColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, pkColumns); - return this.withPkColumns(collection); - } - - public AlterExpression addPkColumns(Collection pkColumns) { - List collection = Optional.ofNullable(getPkColumns()).orElseGet(ArrayList::new); - collection.addAll(pkColumns); - return this.withPkColumns(collection); - } - - public AlterExpression addUkColumns(String... ukColumns) { - List collection = Optional.ofNullable(getUkColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, ukColumns); - return this.withUkColumns(collection); - } - - public AlterExpression addUkColumns(Collection ukColumns) { - List collection = Optional.ofNullable(getUkColumns()).orElseGet(ArrayList::new); - collection.addAll(ukColumns); - return this.withUkColumns(collection); - } - - public AlterExpression addFkColumns(String... fkColumns) { - List collection = Optional.ofNullable(getFkColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, fkColumns); - return this.withFkColumns(collection); - } - - public AlterExpression addFkColumns(Collection fkColumns) { - List collection = Optional.ofNullable(getFkColumns()).orElseGet(ArrayList::new); - collection.addAll(fkColumns); - return this.withFkColumns(collection); - } - - public AlterExpression addFkSourceColumns(String... fkSourceColumns) { - List collection = Optional.ofNullable(getFkSourceColumns()).orElseGet(ArrayList::new); - Collections.addAll(collection, fkSourceColumns); - return this.withFkSourceColumns(collection); - } - - public AlterExpression addFkSourceColumns(Collection fkSourceColumns) { - List collection = Optional.ofNullable(getFkSourceColumns()).orElseGet(ArrayList::new); - collection.addAll(fkSourceColumns); - return this.withFkSourceColumns(collection); - } - - public AlterExpression addConstraints(ConstraintState... constraints) { - List collection = - Optional.ofNullable(getConstraints()).orElseGet(ArrayList::new); - Collections.addAll(collection, constraints); - return this.withConstraints(collection); - } - - public AlterExpression addConstraints(Collection constraints) { - List collection = - Optional.ofNullable(getConstraints()).orElseGet(ArrayList::new); - collection.addAll(constraints); - return this.withConstraints(collection); - } - - public static final class ColumnDataType extends ColumnDefinition { - - private final boolean withType; - - public ColumnDataType(boolean withType) { - super(); - this.withType = withType; - } - - public ColumnDataType( - String columnName, boolean withType, ColDataType colDataType, List columnSpecs) { - super(columnName, colDataType, columnSpecs); - this.withType = withType; + public void addColDropDefault(ColumnDropDefault columnDropDefault) { + if (columnDropDefaultList == null) { + columnDropDefaultList = new ArrayList<>(); + } + columnDropDefaultList.add(columnDropDefault); } - @Override - public String toString() { - return getColumnName() + (withType ? " TYPE " : " ") + toStringDataTypeAndSpec(); + public List getFkSourceColumns() { + return fkSourceColumns; } - @Override - public ColumnDataType withColDataType(ColDataType colDataType) { - return (ColumnDataType) super.withColDataType(colDataType); + public void setFkSourceColumns(List fkSourceColumns) { + this.fkSourceColumns = fkSourceColumns; } - @Override - public ColumnDataType withColumnName(String columnName) { - return (ColumnDataType) super.withColumnName(columnName); + public String getNewTableName() { + return newTableName; } - @Override - public ColumnDataType addColumnSpecs(String... columnSpecs) { - return (ColumnDataType) super.addColumnSpecs(columnSpecs); + public void setNewTableName(String newTableName) { + this.newTableName = newTableName; } - @Override - public ColumnDataType addColumnSpecs(Collection columnSpecs) { - return (ColumnDataType) super.addColumnSpecs(columnSpecs); + public String getColumnName() { + return columnName; } - @Override - public ColumnDataType withColumnSpecs(List columnSpecs) { - return (ColumnDataType) super.withColumnSpecs(columnSpecs); + public void setColumnName(String columnName) { + this.columnName = columnName; } - } - public static final class ColumnDropNotNull implements Serializable { + @Deprecated + public String getColOldName() { + return getColumnOldName(); + } - private final String columnName; - private final boolean withNot; + @Deprecated + public void setColOldName(String columnOldName) { + setColumnOldName(columnOldName); + } - public ColumnDropNotNull(String columnName) { - this(columnName, false); + public String getColumnOldName() { + return columnOldName; } - public ColumnDropNotNull(String columnName, boolean withNot) { - this.columnName = columnName; - this.withNot = withNot; + public void setColumnOldName(String columnOldName) { + this.columnOldName = columnOldName; } - public String getColumnName() { - return columnName; + public String getConstraintName() { + return this.constraintName; } - public boolean isWithNot() { - return withNot; + public void setConstraintName(final String constraintName) { + this.constraintName = constraintName; } - @Override - public String toString() { - return columnName + " DROP" + (withNot ? " NOT " : " ") + "NULL"; + public boolean isUsingIfExists() { + return usingIfExists; } - } - public static final class ColumnDropDefault implements Serializable { + public void setUsingIfExists(boolean usingIfExists) { + this.usingIfExists = usingIfExists; + } - private final String columnName; + public List getPkColumns() { + return pkColumns; + } - public ColumnDropDefault(String columnName) { - this.columnName = columnName; + public void setPkColumns(List pkColumns) { + this.pkColumns = pkColumns; } - public String getColumnName() { - return columnName; + public List getUkColumns() { + return ukColumns; + } + + public void setUkColumns(List ukColumns) { + this.ukColumns = ukColumns; + } + + public String getUkName() { + return ukName; + } + + public void setUkName(String ukName) { + this.ukName = ukName; + } + + public Index getIndex() { + return index; + } + + public void setIndex(Index index) { + this.index = index; + } + + public List getConstraints() { + return constraints; + } + + public void setConstraints(List constraints) { + this.constraints = constraints; + } + + public List getColumnDropNotNullList() { + return columnDropNotNullList; + } + + public void addParameters(String... params) { + if (parameters == null) { + parameters = new ArrayList<>(); + } + parameters.addAll(Arrays.asList(params)); + } + + public List getParameters() { + return parameters; + } + + public boolean getUseEqual() { + return useEqual; + } + + public void setUseEqual(boolean useEqual) { + this.useEqual = useEqual; + } + + public boolean getUk() { + return uk; + } + + public void setUk(boolean uk) { + this.uk = uk; } @Override + @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", + "PMD.ExcessiveMethodLength"}) public String toString() { - return columnName + " DROP DEFAULT"; + + StringBuilder b = new StringBuilder(); + + if (operation == AlterOperation.UNSPECIFIC) { + b.append(optionalSpecifier); + } else if (getOldIndex() != null) { + b.append("RENAME"); + if (operation == AlterOperation.RENAME_INDEX) { + b.append(" INDEX "); + } else if (operation == AlterOperation.RENAME_CONSTRAINT) { + b.append(" CONSTRAINT "); + } + b.append(getOldIndex().getName()).append(" TO ").append(getIndex().getName()); + } else if (operation == AlterOperation.RENAME_TABLE) { + + b.append("RENAME TO ").append(newTableName); + } else if (operation == AlterOperation.DROP_PRIMARY_KEY) { + + b.append("DROP PRIMARY KEY "); + } else if (operation == AlterOperation.DROP_UNIQUE) { + + b.append("DROP UNIQUE (").append(PlainSelect.getStringList(pkColumns)).append(')'); + } else if (operation == AlterOperation.DROP_FOREIGN_KEY) { + + b.append("DROP FOREIGN KEY (").append(PlainSelect.getStringList(pkColumns)).append(')'); + } else if (operation == AlterOperation.DROP && columnName == null && pkColumns != null + && !pkColumns.isEmpty()) { + // Oracle Multi Column Drop + b.append("DROP (").append(PlainSelect.getStringList(pkColumns)).append(')'); + } else { + b.append(operation).append(" "); + + if (commentText != null) { + if (columnName != null) { + b.append(columnName).append(" COMMENT "); + } + b.append(commentText); + } else if (columnName != null) { + if (hasColumn) { + b.append("COLUMN "); + } + if (usingIfExists) { + b.append("IF EXISTS "); + } + if (operation == AlterOperation.RENAME) { + b.append(columnOldName).append(" TO "); + } + b.append(columnName); + } else if (getColDataTypeList() != null) { + if (operation == AlterOperation.CHANGE) { + if (optionalSpecifier != null) { + b.append(optionalSpecifier).append(" "); + } + b.append(columnOldName).append(" "); + } else if (colDataTypeList.size() > 1) { + b.append("("); + } else { + if (hasColumn) { + b.append("COLUMN "); + } + } + if (useBrackets && colDataTypeList.size() == 1) { + b.append(" ( "); + } + b.append(PlainSelect.getStringList(colDataTypeList)); + if (useBrackets && colDataTypeList.size() == 1) { + b.append(" ) "); + } + if (colDataTypeList.size() > 1) { + b.append(")"); + } + } else if (getColumnDropNotNullList() != null) { + b.append("COLUMN "); + b.append(PlainSelect.getStringList(columnDropNotNullList)); + } else if (columnDropDefaultList != null && !columnDropDefaultList.isEmpty()) { + b.append("COLUMN "); + b.append(PlainSelect.getStringList(columnDropDefaultList)); + } else if (constraintName != null) { + b.append("CONSTRAINT "); + if (usingIfExists) { + b.append("IF EXISTS "); + } + b.append(constraintName); + } else if (pkColumns != null) { + b.append("PRIMARY KEY (").append(PlainSelect.getStringList(pkColumns)).append(')'); + } else if (ukColumns != null) { + b.append("UNIQUE"); + if (ukName != null) { + if (getUk()) { + b.append(" KEY "); + } else { + b.append(" INDEX "); + } + b.append(ukName); + } + b.append(" (").append(PlainSelect.getStringList(ukColumns)).append(")"); + } else if (fkColumns != null) { + b.append("FOREIGN KEY (") + .append(PlainSelect.getStringList(fkColumns)) + .append(") REFERENCES ") + .append( + fkSourceSchema != null && fkSourceSchema.trim().length() > 0 + ? fkSourceSchema + "." + : "") + .append(fkSourceTable) + .append(" (") + .append(PlainSelect.getStringList(fkSourceColumns)) + .append(")"); + referentialActions.forEach(b::append); + } else if (index != null) { + b.append(index); + } + + + if (getConstraints() != null && !getConstraints().isEmpty()) { + b.append(' ').append(PlainSelect.getStringList(constraints, false, false)); + } + if (getUseEqual()) { + b.append('='); + } + } + + if (parameters != null && !parameters.isEmpty()) { + b.append(' ').append(PlainSelect.getStringList(parameters, false, false)); + } + + return b.toString(); + } + + public AlterExpression withOperation(AlterOperation operation) { + this.setOperation(operation); + return this; + } + + public AlterExpression withOptionalSpecifier(String optionalSpecifier) { + this.setOptionalSpecifier(optionalSpecifier); + return this; + } + + public AlterExpression withColumnName(String columnName) { + this.setColumnName(columnName); + return this; + } + + public AlterExpression withPkColumns(List pkColumns) { + this.setPkColumns(pkColumns); + return this; + } + + public AlterExpression withUkColumns(List ukColumns) { + this.setUkColumns(ukColumns); + return this; + } + + public AlterExpression withUkName(String ukName) { + this.setUkName(ukName); + return this; + } + + public AlterExpression withIndex(Index index) { + this.setIndex(index); + return this; + } + + public AlterExpression withConstraintName(String constraintName) { + this.setConstraintName(constraintName); + return this; + } + + public AlterExpression withUsingIfExists(boolean usingIfExists) { + this.setUsingIfExists(usingIfExists); + return this; + } + + public AlterExpression withOnDeleteRestrict(boolean onDeleteRestrict) { + this.setOnDeleteRestrict(onDeleteRestrict); + return this; + } + + public AlterExpression withOnDeleteSetNull(boolean onDeleteSetNull) { + this.setOnDeleteSetNull(onDeleteSetNull); + return this; + } + + public AlterExpression withOnDeleteCascade(boolean onDeleteCascade) { + this.setOnDeleteCascade(onDeleteCascade); + return this; + } + + public AlterExpression withFkColumns(List fkColumns) { + this.setFkColumns(fkColumns); + return this; + } + + public AlterExpression withFkSourceSchema(String fkSourceSchema) { + this.setFkSourceTable(fkSourceSchema); + return this; + } + + public AlterExpression withFkSourceTable(String fkSourceTable) { + this.setFkSourceTable(fkSourceTable); + return this; + } + + public AlterExpression withFkSourceColumns(List fkSourceColumns) { + this.setFkSourceColumns(fkSourceColumns); + return this; + } + + public AlterExpression withUk(boolean uk) { + this.setUk(uk); + return this; + } + + public AlterExpression withUseEqual(boolean useEqual) { + this.setUseEqual(useEqual); + return this; + } + + public AlterExpression withConstraints(List constraints) { + this.setConstraints(constraints); + return this; + } + + public AlterExpression withCommentText(String commentText) { + this.setCommentText(commentText); + return this; + } + + public AlterExpression withColumnOldName(String columnOldName) { + setColumnOldName(columnOldName); + return this; + } + + public AlterExpression addPkColumns(String... pkColumns) { + List collection = Optional.ofNullable(getPkColumns()).orElseGet(ArrayList::new); + Collections.addAll(collection, pkColumns); + return this.withPkColumns(collection); + } + + public AlterExpression addPkColumns(Collection pkColumns) { + List collection = Optional.ofNullable(getPkColumns()).orElseGet(ArrayList::new); + collection.addAll(pkColumns); + return this.withPkColumns(collection); + } + + public AlterExpression addUkColumns(String... ukColumns) { + List collection = Optional.ofNullable(getUkColumns()).orElseGet(ArrayList::new); + Collections.addAll(collection, ukColumns); + return this.withUkColumns(collection); + } + + public AlterExpression addUkColumns(Collection ukColumns) { + List collection = Optional.ofNullable(getUkColumns()).orElseGet(ArrayList::new); + collection.addAll(ukColumns); + return this.withUkColumns(collection); + } + + public AlterExpression addFkColumns(String... fkColumns) { + List collection = Optional.ofNullable(getFkColumns()).orElseGet(ArrayList::new); + Collections.addAll(collection, fkColumns); + return this.withFkColumns(collection); + } + + public AlterExpression addFkColumns(Collection fkColumns) { + List collection = Optional.ofNullable(getFkColumns()).orElseGet(ArrayList::new); + collection.addAll(fkColumns); + return this.withFkColumns(collection); + } + + public AlterExpression addFkSourceColumns(String... fkSourceColumns) { + List collection = + Optional.ofNullable(getFkSourceColumns()).orElseGet(ArrayList::new); + Collections.addAll(collection, fkSourceColumns); + return this.withFkSourceColumns(collection); + } + + public AlterExpression addFkSourceColumns(Collection fkSourceColumns) { + List collection = + Optional.ofNullable(getFkSourceColumns()).orElseGet(ArrayList::new); + collection.addAll(fkSourceColumns); + return this.withFkSourceColumns(collection); + } + + public AlterExpression addConstraints(ConstraintState... constraints) { + List collection = + Optional.ofNullable(getConstraints()).orElseGet(ArrayList::new); + Collections.addAll(collection, constraints); + return this.withConstraints(collection); + } + + public AlterExpression addConstraints(Collection constraints) { + List collection = + Optional.ofNullable(getConstraints()).orElseGet(ArrayList::new); + collection.addAll(constraints); + return this.withConstraints(collection); + } + + public static final class ColumnDataType extends ColumnDefinition { + + private final boolean withType; + + public ColumnDataType(boolean withType) { + super(); + this.withType = withType; + } + + public ColumnDataType( + String columnName, boolean withType, ColDataType colDataType, + List columnSpecs) { + super(columnName, colDataType, columnSpecs); + this.withType = withType; + } + + @Override + public String toString() { + return getColumnName() + (withType ? " TYPE " : " ") + toStringDataTypeAndSpec(); + } + + @Override + public ColumnDataType withColDataType(ColDataType colDataType) { + return (ColumnDataType) super.withColDataType(colDataType); + } + + @Override + public ColumnDataType withColumnName(String columnName) { + return (ColumnDataType) super.withColumnName(columnName); + } + + @Override + public ColumnDataType addColumnSpecs(String... columnSpecs) { + return (ColumnDataType) super.addColumnSpecs(columnSpecs); + } + + @Override + public ColumnDataType addColumnSpecs(Collection columnSpecs) { + return (ColumnDataType) super.addColumnSpecs(columnSpecs); + } + + @Override + public ColumnDataType withColumnSpecs(List columnSpecs) { + return (ColumnDataType) super.withColumnSpecs(columnSpecs); + } + } + + public static final class ColumnDropNotNull implements Serializable { + + private final String columnName; + private final boolean withNot; + + public ColumnDropNotNull(String columnName) { + this(columnName, false); + } + + public ColumnDropNotNull(String columnName, boolean withNot) { + this.columnName = columnName; + this.withNot = withNot; + } + + public String getColumnName() { + return columnName; + } + + public boolean isWithNot() { + return withNot; + } + + @Override + public String toString() { + return columnName + " DROP" + (withNot ? " NOT " : " ") + "NULL"; + } + } + + public static final class ColumnDropDefault implements Serializable { + + private final String columnName; + + public ColumnDropDefault(String columnName) { + this.columnName = columnName; + } + + public String getColumnName() { + return columnName; + } + + @Override + public String toString() { + return columnName + " DROP DEFAULT"; + } } - } } diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index bb13956f4..bd41ff401 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, COMMENT, UNSPECIFIC; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_CONSTRAINT, COMMENT, UNSPECIFIC; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index a8cda9de0..26dcb6d46 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -6460,15 +6460,26 @@ AlterExpression AlterExpression(): (tk2= | tk2=) { alterExp.setColumnName(tk2.image); } | - ( + LOOKAHEAD(2)( {alterExp.setOperation(AlterOperation.RENAME_TABLE);} - (tk2= | tk2=) { alterExp.setNewTableName(tk2.image);} + (tk2= | tk2=) { alterExp.setNewTableName(tk2.image);} ) | ( {alterExp.setOperation(AlterOperation.COMMENT);} tk= { alterExp.setCommentText(tk.image); } ) | + LOOKAHEAD(2)( (( | ) { alterExp.setOperation(AlterOperation.RENAME_INDEX); } | { alterExp.setOperation(AlterOperation.RENAME_CONSTRAINT); }) + (tk= | tk=){ + alterExp.setOldIndex(new Index().withName(tk.image)); + } + + (tk2= | tk2=){ + index = new Index().withName(tk2.image); + alterExp.setIndex(index); + } + ) + | tokens = captureRest() { alterExp.setOperation(AlterOperation.UNSPECIFIC); StringBuilder optionalSpecifier = new StringBuilder(); diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 881af7c2e..6a1e482bf 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -83,6 +83,16 @@ public void testAlterTableBackBrackets() throws JSQLParserException { } + @Test + public void testAlterTableIssue1815() throws JSQLParserException { + // MySQL: see https://dev.mysql.com/doc/refman/8.0/en/alter-table.html + assertSqlCanBeParsedAndDeparsed( + "ALTER TABLE cers_record_10 RENAME INDEX idx_cers_record_1_gmtcreate TO idx_cers_record_10_gmtcreate"); + // PostgreSQL: see https://www.postgresql.org/docs/current/sql-altertable.html + assertSqlCanBeParsedAndDeparsed( + "ALTER TABLE cers_record_10 RENAME CONSTRAINT cst_cers_record_1_gmtcreate TO cst_cers_record_10_gmtcreate"); + } + @Test public void testAlterTablePrimaryKey() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed("ALTER TABLE animals ADD PRIMARY KEY (id)"); From a88a351c6b26af959a2472e9a122c268ea15faaf Mon Sep 17 00:00:00 2001 From: jxnu-liguobin Date: Fri, 15 Dec 2023 22:24:12 +0800 Subject: [PATCH 2/2] Fix --- .../statement/alter/AlterExpression.java | 16 +++++++++++----- .../statement/alter/AlterOperation.java | 2 +- .../net/sf/jsqlparser/parser/JSqlParserCC.jjt | 6 +++++- .../sf/jsqlparser/statement/alter/AlterTest.java | 2 ++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index 45b33cd3f..084749e42 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -404,7 +404,7 @@ public void setUk(boolean uk) { @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity", - "PMD.ExcessiveMethodLength"}) + "PMD.ExcessiveMethodLength", "PMD.SwitchStmtsShouldHaveDefault"}) public String toString() { StringBuilder b = new StringBuilder(); @@ -413,10 +413,16 @@ public String toString() { b.append(optionalSpecifier); } else if (getOldIndex() != null) { b.append("RENAME"); - if (operation == AlterOperation.RENAME_INDEX) { - b.append(" INDEX "); - } else if (operation == AlterOperation.RENAME_CONSTRAINT) { - b.append(" CONSTRAINT "); + switch (operation) { + case RENAME_KEY: + b.append(" KEY "); + break; + case RENAME_INDEX: + b.append(" INDEX "); + break; + case RENAME_CONSTRAINT: + b.append(" CONSTRAINT "); + break; } b.append(getOldIndex().getName()).append(" TO ").append(getIndex().getName()); } else if (operation == AlterOperation.RENAME_TABLE) { diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index bd41ff401..d1791cc8b 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_CONSTRAINT, COMMENT, UNSPECIFIC; + ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, UNSPECIFIC; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 26dcb6d46..6e6cce16b 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -6469,7 +6469,11 @@ AlterExpression AlterExpression(): tk= { alterExp.setCommentText(tk.image); } ) | - LOOKAHEAD(2)( (( | ) { alterExp.setOperation(AlterOperation.RENAME_INDEX); } | { alterExp.setOperation(AlterOperation.RENAME_CONSTRAINT); }) + LOOKAHEAD(2) + ( (( {alterExp.setOperation(AlterOperation.RENAME_INDEX);} + | {alterExp.setOperation(AlterOperation.RENAME_KEY);}) + | { alterExp.setOperation(AlterOperation.RENAME_CONSTRAINT); } + ) (tk= | tk=){ alterExp.setOldIndex(new Index().withName(tk.image)); } diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 6a1e482bf..0821224f8 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -88,6 +88,8 @@ public void testAlterTableIssue1815() throws JSQLParserException { // MySQL: see https://dev.mysql.com/doc/refman/8.0/en/alter-table.html assertSqlCanBeParsedAndDeparsed( "ALTER TABLE cers_record_10 RENAME INDEX idx_cers_record_1_gmtcreate TO idx_cers_record_10_gmtcreate"); + assertSqlCanBeParsedAndDeparsed( + "ALTER TABLE cers_record_10 RENAME KEY k_cers_record_1_gmtcreate TO k_cers_record_10_gmtcreate"); // PostgreSQL: see https://www.postgresql.org/docs/current/sql-altertable.html assertSqlCanBeParsedAndDeparsed( "ALTER TABLE cers_record_10 RENAME CONSTRAINT cst_cers_record_1_gmtcreate TO cst_cers_record_10_gmtcreate");