package jef.database.meta;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import jef.common.PairIS;
import jef.common.PairSS;
import jef.database.DbUtils;
import jef.database.dialect.ColumnType;
import jef.database.dialect.ColumnType.AutoIncrement;
import jef.database.dialect.ColumnType.Varchar;
import jef.database.dialect.DatabaseDialect;
import jef.database.dialect.type.AutoIncrementMapping;
import jef.database.dialect.type.ColumnMapping;
import jef.database.meta.def.UniqueConstraintDef;
import jef.tools.StringUtils;
import org.apache.commons.lang.RandomStringUtils;
/**
* 建表任务操作
*
* @author jiyi
*
*/
public class TableCreateStatement {
/**
* 表定义
*/
private final List<TableDef> tables = new ArrayList<TableDef>();
public void addTableMeta(String tablename, ITableMetadata meta, DatabaseDialect dialect) {
TableDef tableDef = new TableDef();
tableDef.escapedTablename = DbUtils.escapeColumn(dialect, tablename);
tableDef.profile=dialect;
Map<String,String> comments=meta.getColumnComments();
tableDef.tableComment=comments.get("#TABLE");
for (ColumnMapping column : meta.getColumns()) {
String c=comments.get(column.fieldName());
processField(column, tableDef, dialect,c);
}
if (!tableDef.NoPkConstraint && !meta.getPKFields().isEmpty()) {
tableDef.addPkConstraint(meta.getPKFields(), dialect, tablename);
}
for(UniqueConstraintDef unique: meta.getUniques()){
tableDef.addUniqueConstraint(unique,meta,dialect);
}
this.tables.add(tableDef);
}
private void processField(ColumnMapping entry, TableDef result, DatabaseDialect dialect,String comment) {
StringBuilder sb = result.getColumnDef();
if (sb.length() > 0)
sb.append(",\n");
String escapedColumnName=entry.getColumnName(dialect, true);
sb.append(" ").append(escapedColumnName).append(" ");
ColumnType vType = entry.get();
if (entry.isPk()) {
vType.setNullable(false);
if (vType instanceof Varchar) {
Varchar vcType = (Varchar) vType;
int check = dialect.getPropertyInt(DbProperty.INDEX_LENGTH_LIMIT);
if (check > 0 && vcType.getLength() > check) {
throw new IllegalArgumentException("The varchar column in " + dialect.getName() + " will not be indexed if length is >" + check);
}
check = dialect.getPropertyInt(DbProperty.INDEX_LENGTH_LIMIT_FIX);
if (check > 0 && vcType.getLength() > check) {
result.charSetFix = dialect.getProperty(DbProperty.INDEX_LENGTH_CHARESET_FIX);
}
}
}
if (entry instanceof AutoIncrementMapping) {
if (dialect.has(Feature.AUTOINCREMENT_NEED_SEQUENCE)) {
int precision = ((AutoIncrement) vType).getPrecision();
addSequence(((AutoIncrementMapping) entry).getSequenceName(dialect), precision);
}
if (dialect.has(Feature.AUTOINCREMENT_MUSTBE_PK)) { // 在一些数据库上,只有主键才能自增,并且此时不能再单独设置主键.
result.NoPkConstraint = true;
}
}
if (entry.getMeta().getEffectPartitionKeys() != null) { // 如果是分表的,自增键退化为常规字段
if (vType instanceof AutoIncrement) {
vType = ((AutoIncrement) vType).toNormalType();
}
}
sb.append(dialect.getCreationComment(vType, true));
if(StringUtils.isNotEmpty(comment)) {
if(dialect.has(Feature.SUPPORT_COMMENT)) {
result.ccmments.add(new PairSS(escapedColumnName,comment));
}else if(dialect.has(Feature.SUPPORT_INLINE_COMMENT)) {
sb.append(" comment '"+comment.replace("'", "''")+"'");
}
}
}
private void addSequence(String seq, int precision) {
sequences.add(new PairIS(precision, seq));
}
/**
* 要创建的Sequence
*/
private final List<PairIS> sequences = new ArrayList<PairIS>();
static class TableDef {
private String escapedTablename;
/**
* MySQL专用。字符集编码
*/
private String charSetFix;
/**
* 列定义
*/
private final StringBuilder columnDefinition = new StringBuilder();
/**
* 表备注
*/
private String tableComment;
/**
* 数据库类型
*/
private DatabaseDialect profile;
/**
* 各个字段备注
*/
private List<PairSS> ccmments = new ArrayList<PairSS>();
/**
* 没有主键约束
*/
private boolean NoPkConstraint;
public String getTableSQL() {
String sql = "CREATE TABLE " + escapedTablename + "(\n" + columnDefinition + "\n)";
if (charSetFix != null) {
sql = sql + charSetFix;
}
if(StringUtils.isNotEmpty(tableComment) && profile.has(Feature.SUPPORT_INLINE_COMMENT)) {
sql=sql+" comment '"+tableComment.replace("'", "''")+"'";
}
return sql;
}
public void addUniqueConstraint(UniqueConstraintDef unique,ITableMetadata meta, DatabaseDialect dialect) {
List<String> columns=unique.toColumnNames(meta, dialect);
StringBuilder sb = getColumnDef();
sb.append(",\n");
String cname=unique.name();
if(StringUtils.isEmpty(cname)){
cname="UC_"+RandomStringUtils.randomAlphanumeric(8).toUpperCase();
}
sb.append(" CONSTRAINT ").append(cname).append(" UNIQUE (");
StringUtils.joinTo(columns, ",", sb);
sb.append(')');
}
public StringBuilder getColumnDef() {
return columnDefinition;
}
public void addPkConstraint(List<ColumnMapping> pkFields, DatabaseDialect profile, String tablename) {
StringBuilder sb = getColumnDef();
sb.append(",\n");
String[] columns = new String[pkFields.size()];
for (int n = 0; n < pkFields.size(); n++) {
columns[n] = pkFields.get(n).getColumnName(profile, true);
}
if (tablename.indexOf('.') > -1) {
tablename = StringUtils.substringAfter(tablename, ".");
}
String pkName = profile.getObjectNameToUse("PK_" + tablename);
sb.append(" CONSTRAINT " + pkName + " PRIMARY KEY(" + StringUtils.join(columns, ',') + ")");
}
public void addTableComment(List<String> result) {
if (StringUtils.isNotEmpty(tableComment) && profile.has(Feature.SUPPORT_COMMENT)) {
result.add("COMMENT ON TABLE " + escapedTablename + " IS '" + tableComment.replace("'", "''") + "'");
}
}
public void addColumnComment(List<String> result) {
for (PairSS column : ccmments) {
String comment=column.getSecond();
if (StringUtils.isNotEmpty(comment)) {
result.add("comment on column " + escapedTablename +"."+column.first+ " is '" + comment.replace("'", "''") + "'");
}
}
}
}
public List<String> getTableSQL() {
List<String> result = new ArrayList<String>(tables.size());
for (TableDef table : tables) {
result.add(table.getTableSQL());
}
return result;
}
public List<String> getOtherContraints() {
return Collections.emptyList();
}
public List<PairIS> getSequences() {
return sequences;
}
public List<String> getComments() {
List<String> result = new ArrayList<String>();
for (TableDef table : tables) {
table.addTableComment(result);
table.addColumnComment(result);
}
return result;
}
}