package com.github.coolcooldee.sloth.source.db.mysql;
import com.github.coolcooldee.sloth.parameter.DBSourceParameters;
import com.github.coolcooldee.sloth.target.JavaType;
import com.github.coolcooldee.sloth.utils.PinYinUtil;
import com.github.coolcooldee.sloth.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import java.sql.*;
import java.util.*;
/**
* Created by sloth on 16/6/17.
*/
@SuppressWarnings("unchecked")
public abstract class TableUtil {
public static final List<String> getTableNames(Connection conn, String... tableNames) throws SQLException {
DatabaseMetaData dme = conn.getMetaData();
List<String> tableNanes = new ArrayList<String>();
List<ResultSet> sets = new ArrayList<ResultSet>();
if (tableNames != null && tableNames.length != 0) {
for (String tableName : tableNames) {
ResultSet rs = dme.getTables("", "", tableName, new String[]{"TABLE"});
sets.add(rs);
}
} else {
ResultSet rs = dme.getTables("", "", "", new String[]{"TABLE"});
sets.add(rs);
}
List<Map> list = resToList(sets);
for (Map map : list) {
String tableName = map.get("TABLE_NAME").toString();
tableNanes.add(tableName);
}
return tableNanes;
}
public static final List<Map<String, Object>> getCarrays(Connection conn, String tableName) throws Exception {
String sql = String.format("SELECT * FROM `%s` LIMIT 1", tableName);
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
List<Map<String, Object>> list = getColumns(rs);
return list;
}
public static final String getRemark(Connection conn, String tableName, String columnName) throws Exception {
String sql = String.format("SELECT " + "COLUMN_NAME, DATA_TYPE, "
+ "COLUMN_COMMENT FROM information_schema.columns " + "WHERE table_name =? and COLUMN_NAME =? ");
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, tableName);
stmt.setString(2, columnName);
ResultSet rs = stmt.executeQuery();
String remark = null;
while (rs.next()) {
remark = rs.getString("COLUMN_COMMENT");
}
return remark;
}
public static final List<Map> getIndexs(Connection conn, String tableName, boolean unique) throws SQLException {
DatabaseMetaData dmd = conn.getMetaData();
ResultSet rs = dmd.getIndexInfo(null, null, tableName, unique, true);
return resToList(rs);
}
public static final Map getBinds(Connection conn, String tableName) throws Exception {
DatabaseMetaData dmd = conn.getMetaData();
Map map = new HashMap();
ResultSet rs = null;
rs = dmd.getExportedKeys("", "", tableName);
map.put("ExportedKeys", resToList(rs));
rs = dmd.getImportedKeys("", "", tableName);
map.put("ImportedKeys", resToList(rs));
return map;
}
public static final List<Map> resToList(ResultSet resultSets) throws SQLException {
List<Map> list = new ArrayList<Map>();
while (resultSets.next()) {
list.add(resToMap(resultSets));
}
return list;
}
public static final List<Map> resToList(List<ResultSet> resultSets) throws SQLException {
List<Map> list = new ArrayList<Map>();
for (int i = 0; i < resultSets.size(); i++) {
while (resultSets.get(i).next()) {
list.add(resToMap(resultSets.get(i)));
}
}
return list;
}
private static final Map resToMap(ResultSet rs) throws SQLException {
Map map = new HashMap();
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
for (int i = 1; i <= cols; i++)
map.put(rsmd.getColumnName(i), rs.getObject(i));
return map;
}
public static final List<Map<String, Object>> getColumns(ResultSet rs) throws Exception {
List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
for (int i = 1; i <= count; i++) {
String columnName = rsmd.getColumnName(i);
int columnType = rsmd.getColumnType(i);
String columnLabel = rsmd.getColumnLabel(i);
String columnTypeName = rsmd.getColumnTypeName(i);
String catalogName = rsmd.getCatalogName(i);
String columnClassName = rsmd.getColumnClassName(i);
int precision = rsmd.getPrecision(i);
int scale = rsmd.getScale(i);
String schemaName = rsmd.getSchemaName(i);
String tableName = rsmd.getTableName(i);
int columnDisplaySize = rsmd.getColumnDisplaySize(i);
boolean isAutoIncrement = rsmd.isAutoIncrement(i);
boolean isCaseSensitive = rsmd.isCaseSensitive(i);
boolean isCurrency = rsmd.isCurrency(i);
boolean isDefinitelyWritable = rsmd.isDefinitelyWritable(i);
int isNullable = rsmd.isNullable(i);
boolean isReadOnly = rsmd.isReadOnly(i);
boolean isSearchable = rsmd.isSearchable(i);
boolean isSigned = rsmd.isSigned(i);
boolean isWritable = rsmd.isWritable(i);
@SuppressWarnings("rawtypes")
Map e = new HashMap();
e.put("i", i);
e.put("columnName", columnName);
e.put("columnType", columnType);
e.put("columnLabel", columnLabel);
e.put("columnTypeName", columnTypeName);
e.put("catalogName", catalogName);
e.put("columnClassName", columnClassName);
e.put("precision", precision);
e.put("scale", scale);
e.put("schemaName", schemaName);
e.put("tableName", tableName);
e.put("columnDisplaySize", columnDisplaySize);
e.put("isAutoIncrement", isAutoIncrement);
e.put("isCaseSensitive", isCaseSensitive);
e.put("isCurrency", isCurrency);
e.put("isDefinitelyWritable", isDefinitelyWritable);
e.put("isNullable", isNullable);
e.put("isReadOnly", isReadOnly);
e.put("isSearchable", isSearchable);
e.put("isSigned", isSigned);
e.put("isWritable", isWritable);
e.put("javaForType", JavaType.getBasicType(JavaType.getType(rsmd, columnLabel)));
ret.add(e);
}
return ret;
}
public static final List<Table> getTables(Connection conn, String packageName, String[] tableNames)
throws Exception {
List<Table> tables = new ArrayList<Table>();
Table table = null;
List<String> tabelNames = getTableNames(conn, tableNames);
StringBuilder tableNamesStr = new StringBuilder();
for(int i=0;i<tabelNames.size(); i++){
if(i>0){
tableNamesStr.append(",");
}
tableNamesStr.append(tabelNames.get(i));
}
for (String tableName : tabelNames) {
String className_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(StringUtil.newTableName(tableName)));
String className_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(StringUtil.newTableName(tableName)));
List<TableIndex> tableIndexs = getTableIndexs(conn, tableName);
List<TableBind> tableBinds = getTableBinds(conn, tableName);
Set<String> upperTableNames = new HashSet<String>();
upperTableNames.add(className_d);
for (TableBind tableBind : tableBinds) {
upperTableNames.add(tableBind.getTableName_d());
}
String stringCarrayNames1 = "";
String stringCarrayNames2 = "";
String stringCarrayNames3 = "";
String stringCarrayNames4 = "";
String stringCarrayNames5 = "";
String stringCarrayNames6 = "";
String stringCarrayNames7 = "";
List<Column> columns = getTableCarrays(conn, tableName);
for (Column column : columns) {
String remark = getRemark(conn, tableName, column.getName());
column.setRemark(remark);
if (!"".endsWith(stringCarrayNames1)) {
stringCarrayNames1 += ", ";
}
if (!"".endsWith(stringCarrayNames2)) {
stringCarrayNames2 += ", ";
}
if (!"".endsWith(stringCarrayNames3)) {
stringCarrayNames3 += ", ";
}
if (!"".endsWith(stringCarrayNames4)) {
stringCarrayNames4 += ", ";
}
if (!"".endsWith(stringCarrayNames5)) {
stringCarrayNames5 += ", ";
}
//
stringCarrayNames1 += column.getLowerFirstLetterName();
stringCarrayNames2 += column.getType() + " " + column.getLowerFirstLetterName();
if(!column.isAutoIncrement()) { //如果是主键,不需要在 insert 语句中 (Mabatis)
stringCarrayNames3 += column.getName();
}
if(!column.isAutoIncrement()) { //如果是主键,不需要在 insert 语句中 (Mabatis)
stringCarrayNames4 += String.format("#{%s}", column.getLowerFirstLetterName());
}
if(!column.isAutoIncrement()) { //如果是主键,不需要在 insert 语句中 (Mabatis)
stringCarrayNames5 += String.format("%s=#{%s}", column.getName(),
column.getName());
}
if (!column.getName().equals("ID") && !column.getName().equals("id")) {
if (!"".endsWith(stringCarrayNames6)) {
stringCarrayNames6 += ", ";
}
if (!"".endsWith(stringCarrayNames7)) {
stringCarrayNames7 += ", ";
}
stringCarrayNames6 += column.getName();
stringCarrayNames7 += String.format("#{%s}", column.getLowerFirstLetterName());
}
}
table = new Table(tableName, className_d, className_x, packageName, columns, tableIndexs, tableBinds,
upperTableNames, stringCarrayNames1, stringCarrayNames2, stringCarrayNames3, stringCarrayNames4,
stringCarrayNames5, stringCarrayNames6, stringCarrayNames7);
String stringCarrayNames8 = "";
table.setUpperName(tableName.toUpperCase());
table.setAllTablesName(tableNamesStr.toString());
table.setSourceDbSchema(DBSourceParameters.getSourceDbSchema());
if (table.getPrimaryKey() == null) {
//ResultSet trs = conn.getMetaData().getColumns(null, "%", tableName,"%");
ResultSet rs = conn.getMetaData().getPrimaryKeys(null, "%", tableName);
while (rs.next()) {
String primaryKey = rs.getString("COLUMN_NAME");
String primaryKeyType = "";
for(Column column :columns){
if(primaryKey.equals(column.getName()))
primaryKeyType = column.getType();
}
table.setPrimaryKey(primaryKey);
table.setPrimaryKeyType(primaryKeyType);
table.setLowerFirstLetterPrimaryKey(StringUtil.lowerFirst(StringUtil.newTableName(primaryKey)));
table.setUpperFirstLetterPrimaryKey(StringUtil.upperFirst(StringUtil.newTableName(primaryKey)));
stringCarrayNames8 += String.format("%s=#{%s}", primaryKey, table.getLowerFirstLetterPrimaryKey());
}
if(StringUtils.isBlank(table.getPrimaryKey())){
throw new NullPointerException("table '"+tableName + "' without primary key, please setting the " +
"primary key.");
}
}
if (!stringCarrayNames8.equals("")) {
table.setStringCarrayNames8(stringCarrayNames8);
}
tables.add(table);
}
return tables;
}
/**
* @param conn
* @param tableName
* @return
* @throws Exception
*/
public static final List<Column> getTableCarrays(Connection conn, String tableName) throws Exception {
List<Column> columns = new ArrayList<Column>();
Column tabelCarray = null;
List<Map<String, Object>> carrays = getCarrays(conn, tableName);
for (Map<String, Object> map : carrays) {
String columnLabel = map.get("columnLabel").toString();
String carrayName_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(StringUtil.newTableName(columnLabel)));
String carrayName_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(StringUtil.newTableName(columnLabel)));
boolean autoIncrement = "true".equals(map.get("isAutoIncrement").toString());
String carrayType = map.get("javaForType").toString();
if (carrayType.equals("int")) {
carrayType = "Integer";
} else if (carrayType.equals("short")) {
carrayType = "Short";
} else if (carrayType.equals("java.utils.Date")) {
carrayType = "String";
} else if (carrayType.equals("java.sql.Time")) {
carrayType = "String";
} else if (carrayType.equals("boolean")) {
carrayType = "Integer";
} else if (carrayType.equals("double")) {
carrayType = "Double";
} else if (carrayType.equals("long")) {
carrayType = "Long";
}
tabelCarray = new Column(columnLabel, carrayName_d, carrayName_x, carrayType, "", autoIncrement);
columns.add(tabelCarray);
}
return columns;
}
public static final List<TableIndex> getTableIndexs(Connection conn, String tableName) throws Exception {
List<Map> indexs = getIndexs(conn, tableName, false);
Map<String, String> carrayTypes = getTableCarrayTypes(conn, tableName);
Map<String, List<Map>> _index = new HashMap<String, List<Map>>();
for (Map map : indexs) {
String indexName = map.get("INDEX_NAME").toString();
List<Map> list = _index.remove(indexName);
if (list == null) {
list = new ArrayList<Map>();
}
list.add(map);
_index.put(indexName, list);
}
List<TableIndex> tableIndexs = new ArrayList<TableIndex>();
TableIndex tabelIndex = null;
Iterator it = _index.entrySet().iterator();
while (it.hasNext()) {
Map.Entry e = (Map.Entry) it.next();
String indexName = e.getKey().toString();
boolean unique = false;
List<String> carrayNames = new ArrayList<String>();
List<String> carrayNames_d = new ArrayList<String>();
List<String> carrayNames_x = new ArrayList<String>();
List<Map<String, String>> carrayNameMaps = new ArrayList<Map<String, String>>();
String stringCarrayNames1 = "";
String stringCarrayNames2 = "";
String stringCarrayNames3 = "";
String stringCarrayNames4 = "";
String stringCarrayNames5 = "";
List<Map> vals = (List<Map>) e.getValue();
for (Map map : vals) {
String carrayName = map.get("COLUMN_NAME").toString();
unique = "false".equals(map.get("NON_UNIQUE").toString());
String carrayName_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(StringUtil
.newTableName(carrayName)));
String carrayName_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(StringUtil
.newTableName(carrayName)));
carrayNames.add(carrayName);
carrayNames_d.add(carrayName_d);
carrayNames_x.add(carrayName_x);
Map<String, String> carrayNameMap = new HashMap<String, String>();
carrayNameMap.put("carrayName", carrayName);
carrayNameMap.put("carrayName_x", carrayName_x);
carrayNameMaps.add(carrayNameMap);
stringCarrayNames1 += carrayName_d;
if (!"".equals(stringCarrayNames2)) {
stringCarrayNames2 += ", ";
}
if (!"".equals(stringCarrayNames3)) {
stringCarrayNames3 += ", ";
}
if (!"".equals(stringCarrayNames4)) {
stringCarrayNames4 += ", ";
}
if (!"".equals(stringCarrayNames5)) {
stringCarrayNames5 += ", ";
}
stringCarrayNames2 += carrayName;
stringCarrayNames3 += carrayTypes.get(carrayName_d) + " " + carrayName_x;
stringCarrayNames4 += carrayName_x;
stringCarrayNames5 += String.format("%s=#{%s}", carrayName, carrayName_x);
}
tabelIndex = new TableIndex(indexName, carrayNames, carrayNames_d, carrayNames_x, carrayNameMaps,
stringCarrayNames1, stringCarrayNames2, stringCarrayNames3, stringCarrayNames4, stringCarrayNames5,
unique);
tableIndexs.add(tabelIndex);
}
return tableIndexs;
}
public static final Map<String, String> getTableCarrayTypes(Connection conn, String tableName) throws Exception {
Map<String, String> tableCarrayTypes = new HashMap<String, String>();
List<Map<String, Object>> carrays = getCarrays(conn, tableName);
for (Map<String, Object> map : carrays) {
String columnLabel = map.get("columnLabel").toString();
String carrayName_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(columnLabel));
String carrayType = map.get("javaForType").toString();
tableCarrayTypes.put(carrayName_d, carrayType);
}
return tableCarrayTypes;
}
public static final List<TableBind> getTableBinds(Connection conn, String tableName) throws Exception {
List<TableBind> tableBinds = new ArrayList<TableBind>();
TableBind tableBind = null;
Map map = getBinds(conn, tableName);
String keyName = "";
String keyType = "";
String carrayName = "";
String table_Name = "";
String carrayName_d = "";
String carrayName_x = "";
String table_Name_d = "";
String table_Name_x = "";
List<Map> exportedKeys = (List<Map>) map.get("ExportedKeys");
for (Map exportedKey : exportedKeys) {
keyName = exportedKey.get("FK_NAME").toString();
keyType = "exportedKey";
carrayName = exportedKey.get("FKCOLUMN_NAME").toString();
table_Name = exportedKey.get("FKTABLE_NAME").toString();
carrayName_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(carrayName));
carrayName_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(carrayName));
table_Name_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(table_Name));
table_Name_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(table_Name));
tableBind = new TableBind(keyName, keyType, table_Name_d, table_Name_x, carrayName_d, carrayName_x);
tableBinds.add(tableBind);
}
List<Map> importedKeys = (List<Map>) map.get("ImportedKeys");
for (Map importedKey : importedKeys) {
keyName = importedKey.get("FK_NAME").toString();
keyType = "importedKey";
carrayName = importedKey.get("FKCOLUMN_NAME").toString();
table_Name = importedKey.get("PKTABLE_NAME").toString();
carrayName_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(carrayName));
carrayName_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(carrayName));
table_Name_d = StringUtil.upperFirst(PinYinUtil.getFirstSpell(table_Name));
table_Name_x = StringUtil.lowerFirst(PinYinUtil.getFirstSpell(table_Name));
tableBind = new TableBind(keyName, keyType, table_Name_d, table_Name_x, carrayName_d, carrayName_x);
tableBinds.add(tableBind);
}
return tableBinds;
}
}