assertTable(context, table);
// if not adapting must provide column name at a minimum
String colName = (given == null) ? null : given.getName();
if (colName == null && !adapt && !fill)
throw new MetaDataException(_loc.get(prefix + "-no-col-name",
context));
// determine the column name based on given info, or template if none;
// also make sure that if the user gave a column name, he didn't try
// to put the column in an unexpected table
if (colName == null)
colName = tmplate.getName();
int dotIdx = colName.lastIndexOf('.');
if (dotIdx == 0)
colName = colName.substring(1);
else if (dotIdx != -1) {
findTable(context, colName.substring(0, dotIdx), table,
null, null);
colName = colName.substring(dotIdx + 1);
}
// find existing column
Column col = table.getColumn(colName);
if (col == null && !adapt)
throw new MetaDataException(_loc.get(prefix + "-bad-col-name",
context, colName, table));
MappingRepository repos = (MappingRepository) context.getRepository();
DBDictionary dict = repos.getDBDictionary();
// use information from template column by default, allowing any
// user-given specifics to override it
int type = tmplate.getType();
int size = tmplate.getSize();
if (type == Types.OTHER)
type = dict.getJDBCType(tmplate.getJavaType(), size == -1);
boolean ttype = true;
int otype = type;
String typeName = tmplate.getTypeName();
Boolean notNull = null;
if (tmplate.isNotNullExplicit())
notNull = (tmplate.isNotNull()) ? Boolean.TRUE : Boolean.FALSE;
int decimals = tmplate.getDecimalDigits();
String defStr = tmplate.getDefaultString();
boolean autoAssign = tmplate.isAutoAssigned();
boolean relationId = tmplate.isRelationId();
String targetField = tmplate.getTargetField();
if (given != null) {
// use given type if provided, but warn if it isn't compatible with
// the expected column type
if (given.getType() != Types.OTHER) {
ttype = false;
if (compat && !given.isCompatible(type, typeName, size,
decimals)) {
Log log = repos.getLog();
if (log.isWarnEnabled())
log.warn(_loc.get(prefix + "-incompat-col",
context, colName, Schemas.getJDBCName(type)));
}
otype = given.getType();
type = dict.getPreferredType(otype);
}
typeName = given.getTypeName();
size = given.getSize();
decimals = given.getDecimalDigits();
// leave this info as the template defaults unless the user
// explicitly turns it on in the given column
if (given.isNotNullExplicit())
notNull = (given.isNotNull()) ? Boolean.TRUE : Boolean.FALSE;
if (given.getDefaultString() != null)
defStr = given.getDefaultString();
if (given.isAutoAssigned())
autoAssign = true;
if (given.isRelationId())
relationId = true;
}
// default char column size if original type is char (test original
// type rather than final type because orig might be clob, translated
// to an unsized varchar, which is supported by some dbs)
if (size == 0 && (otype == Types.VARCHAR || otype == Types.CHAR))
size = dict.characterColumnSize;
// create column, or make sure existing column matches expected type
if (col == null) {
col = table.addColumn(colName);
col.setType(type);
} else if ((compat || !ttype) && !col.isCompatible(type, typeName,
size, decimals)) {
// if existing column isn't compatible with desired type, die if
// can't adapt, else warn and change the existing column type
Message msg = _loc.get(prefix + "-bad-col", context,
Schemas.getJDBCName(type), col.getDescription());
if (!adapt)
throw new MetaDataException(msg);
Log log = repos.getLog();
if (log.isWarnEnabled())
log.warn(msg);
col.setType(type);