// This logic also handles the case where both are null, which is not a valid argument
// to resolver.commonTClass.
if (Objects.equal(instances[field], botInstance))
continue;
TClass topClass = tclass(instances[field]);
TClass botClass = tclass(botInstance);
TClass commonTClass = registry.getCastsResolver().commonTClass(topClass, botClass);
if (commonTClass == null) {
throw new AkibanInternalException("no common type found found between row " + (rownum-1)
+ " and " + rownum + " at field " + field);
}
// The two rows have different TClasses at this index, so we'll need at least one of them to
// be casted. Also the common class will be the widest comparable.
needCasts.set(field);
widened.set(field);
boolean eitherIsNullable;
if (botInstance == null)
eitherIsNullable = true;
else
eitherIsNullable = botInstance.nullability();
if ( (!eitherIsNullable) && (instances[field] != null)) {
// bottom is not nullable, and there is a top. See if it's nullable
eitherIsNullable = instances[field].nullability();
}
// need to set a new instances[field]. Rules:
// - if topClass and botClass are the same as common, use picking algorithm
// - else, if one of them == commonTClass, use topInstance or botInstance (whichever is == common)
// - else, use commonTClass.instance()
boolean topIsCommon = (topClass == commonTClass);
boolean botIsCommon = (botClass == commonTClass);
if (topIsCommon && botIsCommon) {
// TODO: The special case here for TClass VARCHAR with mismatched charsets
// is a limitation of the TClass#pickInstance, as there is no current way
// to create a common TInstance for TString with difference charsets.
if (commonTClass instanceof TString &&
botInstance.attribute(StringAttribute.CHARSET) != instances[field].attribute(StringAttribute.CHARSET)) {
;
}
else {
instances[field] = topClass.pickInstance(instances[field], botInstance);
}
}
else if (botIsCommon) {
instances[field] = botInstance;
}
else if (!topIsCommon) { // this of this as "else if (topIsBottom) { <noop> } else { ..."
instances[field] = commonTClass.instance(eitherIsNullable);
}
// See if the top instance is not nullable but should be
if (instances[field] != null) {
instances[field] = instances[field].withNullable(eitherIsNullable);
}
}
}
// See if we need any casts
if (!needCasts.isEmpty()) {
for (int field = 0; field < nfields; field++) {
if (widened.get(field)) {
// A parameter should get a really wide VARCHAR so that it
// won't be truncated because of other non-parameters.
// Also make sure it's VARBINARY, as BINARY means pad, which
// we don't want here.
TClass tclass = TInstance.tClass(instances[field]);
if (tclass instanceof TString) {
if (((TString)tclass).getFixedLength() < 0) {
instances[field] =
typesTranslator.typeClassForString()
.instance(Integer.MAX_VALUE,