All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sagacity.sqltoy.plugins.ddl.DDLUtils Maven / Gradle / Ivy

There is a newer version: 5.6.31.jre8
Show newest version
/**
 * 
 */
package org.sagacity.sqltoy.plugins.ddl;

import java.sql.Types;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.sagacity.sqltoy.config.model.EntityMeta;
import org.sagacity.sqltoy.config.model.FieldMeta;
import org.sagacity.sqltoy.config.model.ForeignModel;
import org.sagacity.sqltoy.config.model.IndexModel;
import org.sagacity.sqltoy.model.ColumnMeta;
import org.sagacity.sqltoy.model.TableMeta;
import org.sagacity.sqltoy.utils.DataSourceUtils.DBType;
import org.sagacity.sqltoy.utils.StringUtil;

/**
 * @project sagacity-sqltoy
 * @description 创建表语句的工具类,用于将EntityMeta依旧外键关系排序,转化封装为TableModel
 * @author zhongxuchen
 * @version v1.0, Date:2023年12月17日
 * @modify 2023年12月17日,修改说明
 */
public class DDLUtils {
	public static String NEWLINE = "\r\n";
	public static String TAB = "   ";

	/**
	 * @TODO 因为存在外键关系,首先需要对表进行排序,被依赖的优先创建
	 * @param entitysMetaMap
	 * @return
	 */
	public static List sortTables(ConcurrentHashMap entitysMetaMap) {
		// 构建一个暂时存放
		LinkedHashMap tmpEntityMeta = new LinkedHashMap();
		EntityMeta entityMeta;
		String tableName;
		for (Map.Entry entry : entitysMetaMap.entrySet()) {
			entityMeta = entry.getValue();
			tableName = entityMeta.getSchemaTable(null, null);
			tmpEntityMeta.put(tableName, entityMeta);
		}

		// 组织排序
		LinkedHashMap sortTables = new LinkedHashMap();
		LinkedHashMap swotTables = new LinkedHashMap();
		for (Map.Entry entry : entitysMetaMap.entrySet()) {
			entityMeta = entry.getValue();
			tableName = entityMeta.getSchemaTable(null, null);
			// 有外键依赖的表放在前面
			if (entityMeta.getForeignFields() != null) {
				String foreignTable;
				for (Map.Entry iter : entityMeta.getForeignFields().entrySet()) {
					foreignTable = iter.getValue().getForeignTable();
					if (entityMeta.getSchema() != null
							&& !foreignTable.startsWith(entityMeta.getSchema().concat("."))) {
						foreignTable = entityMeta.getSchema().concat(".").concat(foreignTable);
					}
					if (!sortTables.containsKey(foreignTable)) {
						sortTables.put(foreignTable, tmpEntityMeta.get(foreignTable));
					} // 外表和当前表都已经在排序队列中
					else if (sortTables.containsKey(tableName) && !isBefore(sortTables, foreignTable, tableName)) {
						swotTables.clear();
						// 将外键关联的表放第一位置
						swotTables.put(foreignTable, tmpEntityMeta.get(foreignTable));
						// 先移除外键关联表
						sortTables.remove(foreignTable);
						swotTables.putAll(sortTables);
						sortTables.clear();
						// 完成关联表放首位的调整
						sortTables.putAll(swotTables);
					}
				}
			}
			// 未被依赖过
			if (!sortTables.containsKey(tableName)) {
				sortTables.put(tableName, entityMeta);
			}
		}
		return new ArrayList(sortTables.values());
	}

	/**
	 * @TODO 判断外键关联表位置是否在当前表的前面
	 * @param sortTables
	 * @param foreignTable
	 * @param nowTable
	 * @return
	 */
	public static boolean isBefore(LinkedHashMap sortTables, String foreignTable, String nowTable) {
		int foreignTableIndex = 0;
		int nowTableIndex = 0;
		String tableName;
		int index = 0;
		for (Map.Entry entry : sortTables.entrySet()) {
			tableName = entry.getKey();
			if (foreignTable.equals(tableName)) {
				foreignTableIndex = index;
			} else if (nowTable.equals(tableName)) {
				nowTableIndex = index;
			}
			index++;
		}
		if (foreignTableIndex < nowTableIndex) {
			return true;
		}
		return false;
	}

	/**
	 * @TODO 将EntityMeta转化为TableMeta 便于输出表结构
	 * @param entityMeta
	 * @return
	 */
	public static TableMeta wrapTableMeta(EntityMeta entityMeta) {
		TableMeta tableMeta = new TableMeta();
		tableMeta.setTableName(entityMeta.getTableName());
		tableMeta.setRemarks(translateSpecialSymbols(entityMeta.getTableComment()));
		tableMeta.setSchema(entityMeta.getSchema());
		tableMeta.setPkConstraint(entityMeta.getPkConstraint());
		// 索引信息
		if (entityMeta.getIndexModels() != null) {
			List indexModels = new ArrayList<>();
			for (IndexModel indexModel : entityMeta.getIndexModels()) {
				indexModels.add(indexModel);
			}
			tableMeta.setIndexes(indexModels);
		}
		// 外键信息
		if (entityMeta.getForeignFields() != null) {
			List foreignModels = new ArrayList<>();
			for (Map.Entry entry : entityMeta.getForeignFields().entrySet()) {
				foreignModels.add(entry.getValue());
			}
			tableMeta.setForeigns(foreignModels);
		}
		// 列信息
		Map fieldMetaMap = entityMeta.getFieldsMeta();
		FieldMeta fieldMeta;
		List columns = new ArrayList<>();
		for (Map.Entry entry : fieldMetaMap.entrySet()) {
			fieldMeta = entry.getValue();
			ColumnMeta columnMeta = new ColumnMeta();
			columnMeta.setColName(fieldMeta.getColumnName());
			columnMeta.setComments(translateSpecialSymbols(fieldMeta.getComments()));
			columnMeta.setAutoIncrement(fieldMeta.isAutoIncrement());
			columnMeta.setColumnSize(fieldMeta.getLength());
			columnMeta.setPartitionKey(fieldMeta.isPartitionKey());
			columnMeta.setDefaultValue(fieldMeta.getDefaultValue());
			columnMeta.setNullable(fieldMeta.isNullable());
			columnMeta.setDataType(fieldMeta.getType());
			columnMeta.setTypeName(fieldMeta.getFieldType());
			columnMeta.setPK(fieldMeta.isPK());
			columnMeta.setDecimalDigits(fieldMeta.getPrecision());
			columnMeta.setNumPrecRadix(fieldMeta.getScale());
			columnMeta.setNativeType(fieldMeta.getNativeType());
			columns.add(columnMeta);
		}
		tableMeta.setColumns(columns);
		return tableMeta;
	}

	/**
	 * @TODO 设置类型
	 * @param colMeta
	 * @param dbType
	 * @return
	 */
	public static String convertType(ColumnMeta colMeta, int dbType) {
		if (colMeta.getNativeType() != null) {
			if (colMeta.getNativeType().equalsIgnoreCase("JSON")) {
				return "JSON";
			} else if (colMeta.getNativeType().equalsIgnoreCase("BSON")) {
				if (dbType == DBType.POSTGRESQL || dbType == DBType.POSTGRESQL15 || dbType == DBType.GAUSSDB
						|| dbType == DBType.OPENGAUSS || dbType == DBType.MOGDB || dbType == DBType.STARDB
						|| dbType == DBType.OSCAR || dbType == DBType.VASTBASE) {
					return "BSON";
				} else {
					return "JSON";
				}
			}
		}
		boolean isBytes = false;
		String typeName = "VARCHAR";
		switch (colMeta.getDataType()) {
		case java.sql.Types.BIGINT:
			if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "NUMBER";
				typeName = setLength(typeName, true, colMeta);
			} else {
				typeName = "BIGINT";
			}
			break;
		case java.sql.Types.INTEGER:
			typeName = "INTEGER";
			break;
		case java.sql.Types.TINYINT:
			if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "INTEGER";
			} else {
				typeName = "TINYINT";
				typeName = setLength(typeName, true, colMeta);
			}
			break;
		case java.sql.Types.SMALLINT:
			typeName = "SMALLINT";
			break;
		case java.sql.Types.CHAR:
		case java.sql.Types.NCHAR:
			typeName = "CHAR";
			typeName = setLength(typeName, false, colMeta);
			break;
		case java.sql.Types.VARCHAR:
		case java.sql.Types.NVARCHAR:
			typeName = "VARCHAR";
			typeName = setLength(typeName, false, colMeta);
			break;
		case java.sql.Types.LONGNVARCHAR:
			if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "CLOB";
			} else {
				typeName = "TEXT";
			}
			break;
		case java.sql.Types.BLOB:
			if (dbType == DBType.POSTGRESQL || dbType == DBType.POSTGRESQL15 || dbType == DBType.GAUSSDB
					|| dbType == DBType.OPENGAUSS || dbType == DBType.MOGDB || dbType == DBType.STARDB
					|| dbType == DBType.OSCAR || dbType == DBType.VASTBASE) {
				typeName = "bytea";
			} else if (dbType == DBType.SQLSERVER) {
				typeName = "IMAGE";
			} else {
				typeName = "BLOB";
			}
			isBytes = true;
			break;
		case java.sql.Types.BINARY:
			if (dbType == DBType.POSTGRESQL || dbType == DBType.POSTGRESQL15 || dbType == DBType.GAUSSDB
					|| dbType == DBType.OPENGAUSS || dbType == DBType.STARDB || dbType == DBType.OSCAR
					|| dbType == DBType.MOGDB || dbType == DBType.VASTBASE) {
				typeName = "bytea";
			} else if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "BLOB";
			} else if (dbType == DBType.SQLSERVER) {
				typeName = "IMAGE";
			} else {
				typeName = "BINARY";
				typeName = setLength(typeName, false, colMeta);
			}
			isBytes = true;
			break;
		case java.sql.Types.VARBINARY:
		case java.sql.Types.LONGVARBINARY:
			if (dbType == DBType.POSTGRESQL || dbType == DBType.POSTGRESQL15 || dbType == DBType.GAUSSDB
					|| dbType == DBType.OPENGAUSS || dbType == DBType.STARDB || dbType == DBType.OSCAR
					|| dbType == DBType.MOGDB || dbType == DBType.VASTBASE) {
				typeName = "bytea";
			} else if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "BLOB";
			} else if (dbType == DBType.SQLSERVER) {
				typeName = "IMAGE";
			} else {
				typeName = "VARBINARY";
				typeName = setLength(typeName, false, colMeta);
			}
			isBytes = true;
			break;
		case java.sql.Types.CLOB:
		case java.sql.Types.NCLOB:
			if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "CLOB";
			} else {
				typeName = "TEXT";
			}
			break;
		case java.sql.Types.TIME:
			typeName = "TIME";
			break;
		case java.sql.Types.TIMESTAMP:
			typeName = "TIMESTAMP";
			break;
		case java.sql.Types.DATE:
			if (dbType == DBType.MYSQL || dbType == DBType.MYSQL57 || dbType == DBType.SQLSERVER) {
				typeName = "DATETIME";
			} else {
				typeName = "DATE";
			}
			break;
		case java.sql.Types.BOOLEAN:
			if (colMeta.getTypeName().equals("string")) {
				if (colMeta.getColumnSize() > 0) {
					typeName = "VARCHAR";
					typeName = setLength(typeName, false, colMeta);
				} else {
					typeName = "CHAR(1)";
				}
			} else if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "INTEGER";
			} else {
				typeName = "TINYINT(1)";
			}
			break;
		case java.sql.Types.FLOAT:
			typeName = "FLOAT";
			break;
		case java.sql.Types.DOUBLE:
			typeName = "DOUBLE";
			break;
		case java.sql.Types.DECIMAL:
		case java.sql.Types.NUMERIC:
			if (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM) {
				typeName = "NUMBER";
			} else if (dbType == DBType.POSTGRESQL || dbType == DBType.POSTGRESQL15) {
				typeName = "NUMERIC";
			} else {
				typeName = "DECIMAL";
			}
			typeName = setLength(typeName, true, colMeta);
			break;
		default: {
			if (colMeta.getNativeType() != null) {
				typeName = colMeta.getNativeType();
			} else {
				typeName = "VARCHAR";
				typeName = setLength(typeName, false, colMeta);
			}
		}
		}
		// 数组类型
		if ((dbType == DBType.POSTGRESQL || dbType == DBType.POSTGRESQL15 || dbType == DBType.GAUSSDB
				|| dbType == DBType.OPENGAUSS || dbType == DBType.MOGDB || dbType == DBType.STARDB
				|| dbType == DBType.OSCAR || dbType == DBType.VASTBASE) && colMeta.getTypeName().endsWith("[]")
				&& !isBytes && !typeName.startsWith("_")) {
			return "_".concat(typeName);
		}
		return typeName;
	}

	/**
	 * @TODO 设置类型长度
	 * @param typeName
	 * @param isNumber
	 * @param colMeta
	 * @return
	 */
	public static String setLength(String typeName, boolean isNumber, ColumnMeta colMeta) {
		if (isNumber) {
			if (colMeta.getNumPrecRadix() > 0) {
				return typeName + "(" + colMeta.getColumnSize() + "," + colMeta.getNumPrecRadix() + ")";
			}
		}
		if (colMeta.getColumnSize() > 0) {
			if (typeName.equals("CHAR") || typeName.equals("VARCHAR")) {
				return typeName + "(" + (colMeta.getColumnSize() > 10485760 ? 10485760 : colMeta.getColumnSize()) + ")";
			}
			return typeName + "(" + colMeta.getColumnSize() + ")";
		}
		return typeName;
	}

	/**
	 * @TODO 包装主键信息
	 * @param tableMeta
	 * @param dbType
	 * @param tableSql
	 */
	public static void wrapTablePrimaryKeys(TableMeta tableMeta, int dbType, StringBuilder tableSql) {
		String primaryKeys = "";
		for (ColumnMeta colMeta : tableMeta.getColumns()) {
			if (colMeta.isPK()) {
				if (primaryKeys.equals("")) {
					primaryKeys = colMeta.getColName();
				} else {
					primaryKeys = primaryKeys + "," + colMeta.getColName();
				}
			}
		}
		// 主键
		if (!primaryKeys.equals("")) {
			tableSql.append(",").append(NEWLINE);
			tableSql.append(TAB);
			tableSql.append("primary key (").append(primaryKeys).append(")");
		}
	}

	/**
	 * @TODO 组织索引信息
	 * @param tableMeta
	 * @param dbType
	 * @param tableSql
	 * @param outerTable create table () 括号外还是内部
	 */
	public static void wrapTableIndexes(TableMeta tableMeta, int dbType, StringBuilder tableSql, boolean outerTable) {
		if (tableMeta.getIndexes() == null || tableMeta.getIndexes().isEmpty()) {
			return;
		}
		String splitSign = ";";
		// 索引
		for (IndexModel indexModel : tableMeta.getIndexes()) {
			if (outerTable) {
				tableSql.append(splitSign).append(NEWLINE);
				tableSql.append("create ");
				if (indexModel.isUnique()) {
					tableSql.append("UNIQUE ");
				}
				tableSql.append("index ").append(indexModel.getName());
				tableSql.append(" on ").append(tableMeta.getTableName());
			} else {
				tableSql.append(",").append(NEWLINE);
				tableSql.append(TAB);
				if (indexModel.isUnique()) {
					tableSql.append("UNIQUE ");
				}
				tableSql.append("KEY ").append(indexModel.getName());
			}
			tableSql.append(" (");
			int meter = 0;
			String[] sortTypes = indexModel.getSortTypes();
			int typeLen = (sortTypes == null) ? 0 : sortTypes.length;
			for (String col : indexModel.getColumns()) {
				if (meter > 0) {
					tableSql.append(",");
				}
				tableSql.append(col);
				if (meter < typeLen && StringUtil.isNotBlank(sortTypes[meter])) {
					tableSql.append(" ").append(sortTypes[meter]);
				}
				meter++;
			}
			tableSql.append(")");
		}
	}

	/**
	 * @TODO 组织外键信息
	 * @param tableMeta
	 * @param dbType
	 * @param tableSql
	 * @param outerTable create table () 括号外还是内部
	 */
	public static void wrapForeignKeys(TableMeta tableMeta, int dbType, StringBuilder tableSql, boolean outerTable) {
		if (tableMeta.getForeigns() == null || tableMeta.getForeigns().isEmpty()) {
			return;
		}
		boolean isOracle = false;
		String splitSign = ";";
		for (ForeignModel foreign : tableMeta.getForeigns()) {
			isOracle = (dbType == DBType.ORACLE || dbType == DBType.ORACLE11 || dbType == DBType.DM);
			if (outerTable) {
				tableSql.append(splitSign).append(NEWLINE);
				tableSql.append("alter table ").append(tableMeta.getTableName());
				tableSql.append(" add ");
			} else {
				tableSql.append(",").append(NEWLINE);
				tableSql.append(TAB);
			}
			tableSql.append(" CONSTRAINT ").append(foreign.getConstraintName());
			tableSql.append(" FOREIGN KEY (").append(StringUtil.linkAry(",", true, foreign.getColumns())).append(")");
			tableSql.append(" REFERENCES ").append(foreign.getForeignTable()).append("(");
			tableSql.append(StringUtil.linkAry(",", true, foreign.getForeignColumns()));
			tableSql.append(")");
			if (foreign.getDeleteRestict() == 1) {
				if (!isOracle) {
					tableSql.append(" ON DELETE RESTRICT");
				}
			} else if (foreign.getDeleteRestict() == 0) {
				tableSql.append(" ON DELETE CASCADE");
			} else if (foreign.getDeleteRestict() == 2) {
				tableSql.append(" ON DELETE SET NULL");
			} else if (foreign.getDeleteRestict() == 3) {
				tableSql.append(" ON DELETE NO ACTION");
			} else if (foreign.getDeleteRestict() == 4) {
				tableSql.append(" ON DELETE SET DEFAULT");
			}
			if (!isOracle) {
				if (foreign.getUpdateRestict() == 1) {
					tableSql.append(" ON UPDATE RESTRICT");
				} else if (foreign.getUpdateRestict() == 0) {
					tableSql.append(" ON UPDATE CASCADE");
				} else if (foreign.getUpdateRestict() == 2) {
					tableSql.append(" ON UPDATE SET NULL");
				} else if (foreign.getUpdateRestict() == 3) {
					tableSql.append(" ON UPDATE NO ACTION");
				} else if (foreign.getUpdateRestict() == 4) {
					tableSql.append(" ON UPDATE SET DEFAULT");
				}
			}
		}
	}

	/**
	 * @TODO 统一处理表和字段的备注
	 * @param tableMeta
	 * @param dbType
	 * @param tableSql
	 */
	public static void wrapTableAndColumnsComment(TableMeta tableMeta, int dbType, StringBuilder tableSql) {
		String splitSign = ";";
		// 表注释
		if (StringUtil.isNotBlank(tableMeta.getRemarks())) {
			tableSql.append(splitSign);
			tableSql.append(NEWLINE);
			tableSql.append("COMMENT ON TABLE ").append(tableMeta.getTableName()).append(" IS '")
					.append(tableMeta.getRemarks()).append("'");
		}
		// 字段注释
		for (ColumnMeta colMeta : tableMeta.getColumns()) {
			if (StringUtil.isNotBlank(colMeta.getComments())) {
				tableSql.append(splitSign);
				tableSql.append(NEWLINE);
				tableSql.append("COMMENT ON COLUMN ").append(tableMeta.getTableName()).append(".")
						.append(colMeta.getColName()).append(" IS '").append(colMeta.getComments()).append("'");
			}
		}
	}

	/**
	 * @TODO 判断类型默认值是否需要加单引号
	 * @param dataType
	 * @return
	 */
	public static boolean isNotChar(int dataType) {
		if (dataType == Types.BIGINT || dataType == Types.INTEGER || dataType == Types.BOOLEAN
				|| dataType == Types.DECIMAL || dataType == Types.DOUBLE || dataType == Types.NUMERIC
				|| dataType == Types.FLOAT || dataType == Types.REAL || dataType == Types.SMALLINT
				|| dataType == Types.TINYINT || dataType == Types.BIT) {
			return true;
		}
		return false;
	}

	/**
	 * @TODO 转化单引号、双引号
	 * @param str
	 * @return
	 */
	private static String translateSpecialSymbols(String str) {
		if (str == null) {
			return str;
		}
		return str.replaceAll("\'", "\\\\\'").replaceAll("\"", "\\\\\"");
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy