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);
} else if (given != null && given.getType() != Types.OTHER) {
// as long as types are compatible, set column to expected type
col.setType(type);
}
// always set the java type and autoassign to expected values, even on
// an existing column, since we don't get this from the DB
if (compat)
col.setJavaType(tmplate.getJavaType());
else if (col.getJavaType() == JavaTypes.OBJECT) {
if (given != null && given.getJavaType() != JavaTypes.OBJECT)
col.setJavaType(given.getJavaType());
else
col.setJavaType(JavaTypes.getTypeCode
(Schemas.getJavaType(col.getType(), col.getSize(),
col.getDecimalDigits())));
}
col.setAutoAssigned(autoAssign);
col.setRelationId(relationId);
col.setTargetField(targetField);
// we need this for runtime, and the dynamic schema factory might
// not know it, so set it even if not adapting
if (defStr != null)
col.setDefaultString(defStr);
if (notNull != null)
col.setNotNull(notNull.booleanValue());
// add other details if adapting
if (adapt) {
if (typeName != null)
col.setTypeName(typeName);
if (size != 0)
col.setSize(size);
if (decimals != 0)
col.setDecimalDigits(decimals);
}
return col;
}