| 1 | |
package liquibase.snapshot.jvm; |
| 2 | |
|
| 3 | |
import liquibase.database.Database; |
| 4 | |
import liquibase.database.jvm.JdbcConnection; |
| 5 | |
import liquibase.database.structure.ForeignKeyInfo; |
| 6 | |
import liquibase.database.typeconversion.TypeConverterFactory; |
| 7 | |
import liquibase.database.core.MySQLDatabase; |
| 8 | |
import liquibase.database.structure.Column; |
| 9 | |
import liquibase.exception.DatabaseException; |
| 10 | |
|
| 11 | |
import java.sql.ResultSet; |
| 12 | |
import java.sql.SQLException; |
| 13 | |
import java.sql.Statement; |
| 14 | |
import java.text.ParseException; |
| 15 | |
import java.util.ArrayList; |
| 16 | |
import java.util.HashMap; |
| 17 | |
import java.util.List; |
| 18 | |
import java.util.Map; |
| 19 | |
|
| 20 | 0 | public class MySQLDatabaseSnapshotGenerator extends JdbcDatabaseSnapshotGenerator { |
| 21 | |
|
| 22 | |
|
| 23 | |
|
| 24 | |
|
| 25 | 0 | private static Map<String, Map<String, List<String>>> schemaCache = new HashMap<String, Map<String, List<String>>>(); |
| 26 | |
|
| 27 | |
public int getPriority(Database database) { |
| 28 | 0 | return PRIORITY_DATABASE; |
| 29 | |
} |
| 30 | |
|
| 31 | |
public boolean supports(Database database) { |
| 32 | 0 | return database instanceof MySQLDatabase; |
| 33 | |
} |
| 34 | |
|
| 35 | |
|
| 36 | |
|
| 37 | |
|
| 38 | |
@Override |
| 39 | |
protected void getColumnTypeAndDefValue(Column columnInfo, ResultSet rs, Database database) throws SQLException, |
| 40 | |
DatabaseException { |
| 41 | |
|
| 42 | 0 | String columnTypeName = rs.getString("TYPE_NAME"); |
| 43 | 0 | String columnName = rs.getString("COLUMN_NAME"); |
| 44 | 0 | String tableName = rs.getString("TABLE_NAME"); |
| 45 | 0 | String schemaName = rs.getString("TABLE_CAT"); |
| 46 | |
|
| 47 | 0 | Map<String, List<String>> tableSchema = new HashMap<String, List<String>>(); |
| 48 | |
|
| 49 | 0 | if (!schemaCache.containsKey(tableName)) { |
| 50 | |
|
| 51 | 0 | Statement selectStatement = null; |
| 52 | 0 | ResultSet rsColumnType = null; |
| 53 | |
try { |
| 54 | 0 | selectStatement = ((JdbcConnection) database.getConnection()).getUnderlyingConnection() |
| 55 | |
.createStatement(); |
| 56 | 0 | rsColumnType = selectStatement.executeQuery("DESC " + database.escapeTableName(schemaName, tableName)); |
| 57 | |
|
| 58 | 0 | while (rsColumnType.next()) { |
| 59 | 0 | List<String> colSchema = new ArrayList<String>(); |
| 60 | 0 | colSchema.add(rsColumnType.getString("Type")); |
| 61 | 0 | colSchema.add(rsColumnType.getString("Default")); |
| 62 | 0 | tableSchema.put(rsColumnType.getString("Field"), colSchema); |
| 63 | 0 | } |
| 64 | |
} finally { |
| 65 | 0 | if (rsColumnType != null) { |
| 66 | |
try { |
| 67 | 0 | rsColumnType.close(); |
| 68 | 0 | } catch (SQLException ignore) { |
| 69 | 0 | } |
| 70 | |
} |
| 71 | 0 | if (selectStatement != null) { |
| 72 | |
try { |
| 73 | 0 | selectStatement.close(); |
| 74 | 0 | } catch (SQLException ignore) { |
| 75 | 0 | } |
| 76 | |
} |
| 77 | |
} |
| 78 | |
|
| 79 | 0 | schemaCache.put(tableName, tableSchema); |
| 80 | |
|
| 81 | |
} |
| 82 | |
|
| 83 | 0 | tableSchema = schemaCache.get(tableName); |
| 84 | |
|
| 85 | |
|
| 86 | 0 | if (columnTypeName.toLowerCase().startsWith("enum") || columnTypeName.toLowerCase().startsWith("set")) { |
| 87 | |
|
| 88 | 0 | columnInfo.setTypeName(tableSchema.get(columnName).get(0)); |
| 89 | |
try { |
| 90 | 0 | String tmpDefaultValue = (String) TypeConverterFactory |
| 91 | |
.getInstance() |
| 92 | |
.findTypeConverter(database) |
| 93 | |
.convertDatabaseValueToObject(tableSchema.get(columnName).get(1), columnInfo.getDataType(), |
| 94 | |
columnInfo.getColumnSize(), columnInfo.getDecimalDigits(), database); |
| 95 | 0 | if ("".equals(tmpDefaultValue)) { |
| 96 | 0 | columnInfo.setDefaultValue(null); |
| 97 | |
} else { |
| 98 | 0 | columnInfo.setDefaultValue(tmpDefaultValue); |
| 99 | |
} |
| 100 | 0 | } catch (ParseException e) { |
| 101 | 0 | throw new DatabaseException(e); |
| 102 | 0 | } |
| 103 | |
|
| 104 | |
|
| 105 | 0 | } else if (columnTypeName.toLowerCase().equals("text") || columnTypeName.toLowerCase().equals("blob")) { |
| 106 | 0 | columnInfo.setTypeName(columnTypeName); |
| 107 | 0 | columnInfo.setDefaultValue(null); |
| 108 | |
|
| 109 | |
|
| 110 | |
|
| 111 | 0 | } else if (columnTypeName.toLowerCase().equals("timestamp") |
| 112 | |
&& !"CURRENT_TIMESTAMP".equals(tableSchema.get(columnName).get(1))) { |
| 113 | 0 | columnInfo.setTypeName(columnTypeName); |
| 114 | 0 | columnInfo.setDefaultValue(tableSchema.get(columnName).get(1)); |
| 115 | |
} else { |
| 116 | 0 | super.getColumnTypeAndDefValue(columnInfo, rs, database); |
| 117 | |
} |
| 118 | 0 | } |
| 119 | |
|
| 120 | |
@Override |
| 121 | |
protected String convertPrimaryKeyName(String pkName) throws SQLException { |
| 122 | 0 | if (pkName.equals("PRIMARY")) { |
| 123 | 0 | return null; |
| 124 | |
} else { |
| 125 | 0 | return pkName; |
| 126 | |
} |
| 127 | |
} |
| 128 | |
|
| 129 | |
@Override |
| 130 | |
protected ForeignKeyInfo fillForeignKeyInfo(ResultSet rs) throws DatabaseException, SQLException { |
| 131 | 0 | ForeignKeyInfo fkinfo = super.fillForeignKeyInfo(rs); |
| 132 | |
|
| 133 | 0 | fkinfo.setPkTableSchema(convertFromDatabaseName(rs.getString("PKTABLE_CAT"))); |
| 134 | 0 | fkinfo.setFkSchema(convertFromDatabaseName(rs.getString("FKTABLE_CAT"))); |
| 135 | 0 | return fkinfo; |
| 136 | |
} |
| 137 | |
|
| 138 | |
} |