private DataTypeDescriptor resolveConcatOperation(
DataTypeDescriptor leftType,
DataTypeDescriptor rightType
) throws StandardException
{
TypeId leftTypeId;
TypeId rightTypeId;
String higherType;
int resultLength;
boolean nullable;
leftTypeId = leftType.getTypeId();
rightTypeId = rightType.getTypeId();
/*
** Check the right type to be sure it's a concatable. By convention,
** we call this method off the TypeId of the left operand, so if
** we get here, we know the left operand is a concatable.
*/
/*
** Make sure we haven't been given a char and a
** bit to concatenate.
*/
if (!leftTypeId.isConcatableTypeId()
|| !rightTypeId.isConcatableTypeId()
|| (rightTypeId.isBitTypeId() && leftTypeId.isStringTypeId())
|| (leftTypeId.isBitTypeId() && rightTypeId.isStringTypeId()))
throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "||", "FUNCTION");
/*
** The types aren't the same. The result of the operation is the
** type of higher precedence.
*/
higherType = (leftTypeId.typePrecedence() >=
rightTypeId.typePrecedence()) ?
leftType.getTypeName() : rightType.getTypeName();
/* Get the length of the result */
resultLength = leftType.getMaximumWidth() +
rightType.getMaximumWidth();
/*
** Use following chart to handle overflow
** operands CHAR(A) CHAR(B) and A+B<255 then result is CHAR(A+B)
** operands CHAR FOR BIT DATA(A) CHAR FOR BIT DATA(B) and A+B<255 then result is CHAR FOR BIT DATA(A+B)
**
** operands CHAR(A) CHAR(B) and A+B>254 then result is VARCHAR(A+B)
** operands CHAR FOR BIT DATA(A) CHAR FOR BIT DATA(B) and A+B>254 then result is VARCHAR FOR BIT DATA(A+B)
**
** operands CHAR(A) VARCHAR(B) and A+B<4001 then result is VARCHAR(A+B)
** operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B<4001 then result is VARCHAR FOR BIT DATA(A+B)
**
** operands CHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
** operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
**
** operands CHAR(A) LONG VARCHAR then result is LONG VARCHAR
** operands CHAR FOR BIT DATA(A) LONG VARCHAR FOR BIT DATA then result is LONG VARCHAR FOR BIT DATA
**
** operands VARCHAR(A) VARCHAR(B) and A+B<4001 then result is VARCHAR(A+B)
** operands VARCHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B<4001 then result is VARCHAR FOR BIT DATA(A+B)
**
** operands VARCHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
** operands VARCHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
**
** operands VARCHAR(A) LONG VARCHAR then result is LONG VARCHAR
** operands VARCHAR FOR BIT DATA(A) LONG VARCHAR FOR BIT DATA then result is LONG VARCHAR FOR BIT DATA
**
** operands LONG VARCHAR, LONG VARCHAR then result is LONG VARCHAR
** operands LONG VARCHAR FOR BIT DATA, LONG VARCHAR FOR BIT DATA then result is LONG VARCHAR FOR BIT DATA
**
** operands CLOB(A), CHAR(B) then result is CLOB(MIN(A+B,2G))
** operands CLOB(A), VARCHAR(B) then result is CLOB(MIN(A+B,2G))
** operands CLOB(A), LONG VARCHAR then result is CLOB(MIN(A+32K,2G))
** operands CLOB(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
**
** operands BLOB(A), CHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
** operands BLOB(A), VARCHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
** operands BLOB(A), LONG VARCHAR FOR BIT DATA then result is BLOB(MIN(A+32K,2G))
** operands BLOB(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
**
** operands CHAR(A)/VARCHAR(A)/LONGVARCHAR, LONGVARCHAR and "concatenated string length">32700 does not cause automatic escalation
** to LOB for compatibility with previous releases. Any such cases would result in an error at runtime
**
*/
//in the following code, I can assume that left and right operands both will be either char kind
//of datatypes or they will be both binary kind of datatypes. That's because operand datatypes
//mismatch has already been handled earlier
if (leftTypeId.getJDBCTypeId() == Types.CHAR || leftTypeId.getJDBCTypeId() == Types.BINARY)
{
switch (rightTypeId.getJDBCTypeId())
{
case Types.CHAR:
case Types.BINARY:
if (resultLength > Limits.DB2_CHAR_MAXWIDTH) {
if (rightTypeId.getJDBCTypeId() == Types.CHAR)
//operands CHAR(A) CHAR(B) and A+B>254 then result is VARCHAR(A+B)
higherType = TypeId.VARCHAR_NAME;
else
//operands CHAR FOR BIT DATA(A) CHAR FOR BIT DATA(B) and A+B>254 then result is VARCHAR FOR BIT DATA(A+B)
higherType = TypeId.VARBIT_NAME;
}
break;
case Types.VARCHAR:
case Types.VARBINARY:
if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH) {
if (rightTypeId.getJDBCTypeId() == Types.VARCHAR)
//operands CHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
higherType = TypeId.LONGVARCHAR_NAME;
else
//operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
higherType = TypeId.LONGVARBIT_NAME;
}
break;
case Types.CLOB:
case Types.BLOB:
//operands CHAR(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
//operands CHAR FOR BIT DATA(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
resultLength = clobBlobHandling(rightType, leftType);
break;
}
} else if (leftTypeId.getJDBCTypeId() == Types.VARCHAR) {
switch (rightTypeId.getJDBCTypeId())
{
case Types.CHAR: //operands CHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
case Types.VARCHAR: //operands VARCHAR(A) VARCHAR(B) and A+B>4000 then result is LONG VARCHAR
if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH)
higherType = TypeId.LONGVARCHAR_NAME;
break;
case Types.CLOB:
//operands VARCHAR(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
resultLength = clobBlobHandling(rightType, leftType);
break;
}
} else if (leftTypeId.getJDBCTypeId() == Types.VARBINARY) {
switch (rightTypeId.getJDBCTypeId())
{
case Types.BINARY: //operands CHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
case Types.VARBINARY://operands VARCHAR FOR BIT DATA(A) VARCHAR FOR BIT DATA(B) and A+B>4000 then result is LONG VARCHAR FOR BIT DATA
if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH)
higherType = TypeId.LONGVARBIT_NAME;
break;
case Types.BLOB:
//operands VARCHAR FOR BIT DATA(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
resultLength = clobBlobHandling(rightType, leftType);
break;
}
} else if (leftTypeId.getJDBCTypeId() == Types.CLOB || leftTypeId.getJDBCTypeId() == Types.BLOB) {
//operands CLOB(A), CHAR(B) then result is CLOB(MIN(A+B,2G))
//operands CLOB(A), VARCHAR(B) then result is CLOB(MIN(A+B,2G))
//operands CLOB(A), LONG VARCHAR then result is CLOB(MIN(A+32K,2G))
//operands CLOB(A), CLOB(B) then result is CLOB(MIN(A+B,2G))
//operands BLOB(A), CHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
//operands BLOB(A), VARCHAR FOR BIT DATA(B) then result is BLOB(MIN(A+B,2G))
//operands BLOB(A), LONG VARCHAR FOR BIT DATA then result is BLOB(MIN(A+32K,2G))
//operands BLOB(A), BLOB(B) then result is BLOB(MIN(A+B,2G))
resultLength = clobBlobHandling(leftType, rightType);
} else if (rightTypeId.getJDBCTypeId() == Types.CLOB || rightTypeId.getJDBCTypeId() == Types.BLOB) {
//operands LONG VARCHAR, CLOB(A) then result is CLOB(MIN(A+32K,2G))
//operands LONG VARCHAR FOR BIT DATA, BLOB(A) then result is BLOB(MIN(A+32K,2G))
resultLength = clobBlobHandling(rightType, leftType);
}