001package io.ebeaninternal.dbmigration.ddlgeneration.platform; 002 003import io.ebean.config.dbplatform.DatabasePlatform; 004import io.ebean.util.StringHelper; 005import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer; 006import io.ebeaninternal.dbmigration.migration.AlterColumn; 007import io.ebeaninternal.dbmigration.migration.Column; 008 009import java.io.IOException; 010import java.util.Collection; 011 012/** 013 * MySql specific DDL. 014 */ 015public class MySqlDdl extends PlatformDdl { 016 017 // check constraint support is disabled by default. See https://groups.google.com/forum/#!topic/ebean/luFN-2xBkUw 018 // this flag is for compatibility. Use it with care. 019 private static final boolean USE_CHECK_CONSTRAINT = Boolean.getBoolean("ebean.mysql.useCheckConstraint"); 020 021 public MySqlDdl(DatabasePlatform platform) { 022 super(platform); 023 this.alterColumn = "modify"; 024 this.dropUniqueConstraint = "drop index"; 025 this.historyDdl = new MySqlHistoryDdl(); 026 this.inlineComments = true; 027 } 028 029 /** 030 * Return the drop index statement. 031 */ 032 @Override 033 public String dropIndex(String indexName, String tableName, boolean concurrent) { 034 return "drop index " + maxConstraintName(indexName) + " on " + tableName; 035 } 036 037 /** 038 * Return the drop foreign key clause. 039 */ 040 @Override 041 public String alterTableDropForeignKey(String tableName, String fkName) { 042 return "alter table " + tableName + " drop foreign key " + maxConstraintName(fkName); 043 } 044 045 @Override 046 public String createCheckConstraint(String ckName, String checkConstraint) { 047 if (USE_CHECK_CONSTRAINT) { 048 return super.createCheckConstraint(ckName, checkConstraint); 049 } else { 050 return null; 051 } 052 } 053 054 @Override 055 public String alterTableAddCheckConstraint(String tableName, String checkConstraintName, String checkConstraint) { 056 if (USE_CHECK_CONSTRAINT) { 057 return super.alterTableAddCheckConstraint(tableName, checkConstraintName, checkConstraint); 058 } else { 059 return null; 060 } 061 } 062 063 @Override 064 public String alterTableDropConstraint(String tableName, String constraintName) { 065 // drop constraint not supported in MySQL 5.7 and 8.0 but starting with MariaDB 066 // 10.2.1 CHECK is evaluated 067 if (USE_CHECK_CONSTRAINT) { 068 StringBuilder sb = new StringBuilder(); 069 // statement for MySQL >= 8.0.16 070 sb.append("/*!80016 alter table ").append(tableName); 071 sb.append(" drop check ").append(constraintName).append(" */;\n"); 072 // statement for MariaDB >= 10.2.1 073 sb.append("/*M!100201 "); 074 sb.append(super.alterTableDropConstraint(tableName, constraintName)); 075 sb.append(" */"); 076 return sb.toString(); 077 } else { 078 return null; 079 } 080 } 081 082 @Override 083 public String alterColumnType(String tableName, String columnName, String type) { 084 // can't alter itself - done in alterColumnBaseAttributes() 085 return null; 086 } 087 088 @Override 089 public String alterColumnNotnull(String tableName, String columnName, boolean notnull) { 090 // can't alter itself - done in alterColumnBaseAttributes() 091 return null; 092 } 093 094 @Override 095 public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) { 096 String suffix = DdlHelp.isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + convertDefaultValue(defaultValue); 097 return "alter table " + tableName + " alter " + columnName + " " + suffix; 098 } 099 100 @Override 101 public String alterColumnBaseAttributes(AlterColumn alter) { 102 if (alter.getType() == null && alter.isNotnull() == null) { 103 // No type change or notNull change 104 // defaultValue change already handled in alterColumnDefaultValue 105 return null; 106 } 107 String tableName = alter.getTableName(); 108 String columnName = alter.getColumnName(); 109 String type = alter.getType() != null ? alter.getType() : alter.getCurrentType(); 110 type = convert(type); 111 boolean notnull = (alter.isNotnull() != null) ? alter.isNotnull() : Boolean.TRUE.equals(alter.isCurrentNotnull()); 112 String notnullClause = notnull ? " not null" : ""; 113 114 return "alter table " + tableName + " modify " + columnName + " " + type + notnullClause; 115 } 116 117 @Override 118 protected void writeColumnDefinition(DdlBuffer buffer, Column column, DdlIdentity identity) throws IOException { 119 super.writeColumnDefinition(buffer, column, identity); 120 String comment = column.getComment(); 121 if (!StringHelper.isNull(comment)) { 122 // in mysql 5.5 column comment save in information_schema.COLUMNS.COLUMN_COMMENT(VARCHAR 1024) 123 if (comment.length() > 500) { 124 comment = comment.substring(0, 500); 125 } 126 buffer.append(String.format(" comment '%s'", comment)); 127 } 128 } 129 130 @Override 131 public void inlineTableComment(DdlBuffer apply, String tableComment) throws IOException { 132 if (tableComment.length() > 1000) { 133 tableComment = tableComment.substring(0, 1000); 134 } 135 apply.append(" comment='").append(tableComment).append("'"); 136 } 137 138 /** 139 * Add table comment as a separate statement (from the create table statement). 140 */ 141 @Override 142 public void addTableComment(DdlBuffer apply, String tableName, String tableComment) throws IOException { 143 if (DdlHelp.isDropComment(tableComment)) { 144 tableComment = ""; 145 } 146 apply.append(String.format("alter table %s comment = '%s'", tableName, tableComment)).endOfStatement(); 147 } 148 149 @Override 150 public void addColumnComment(DdlBuffer apply, String table, String column, String comment) { 151 // alter comment currently not supported as it requires to repeat whole column definition 152 } 153 154 155 /** 156 * Locks all tables for triggers that have to be updated. 157 */ 158 @Override 159 public void lockTables(DdlBuffer buffer, Collection<String> tables) throws IOException { 160 if (!tables.isEmpty()) { 161 buffer.append("lock tables "); 162 int i = 0; 163 for (String table : tables) { 164 if (i > 0) { 165 buffer.append(", "); 166 } 167 buffer.append(table).append(" write"); 168 i++; 169 } 170 buffer.endOfStatement(); 171 } 172 } 173 174 /** 175 * Unlocks all tables for triggers that have to be updated. 176 */ 177 @Override 178 public void unlockTables(DdlBuffer buffer, Collection<String> tables) throws IOException { 179 buffer.append("unlock tables").endOfStatement(); 180 } 181 182}