* not supported on the operand types.
*/
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);
}