📄 concatenationoperatornode.java
字号:
} /** * Resolve a concatenation operator * * @param leftType The DataTypeDescriptor of the left operand * @param rightType The DataTypeDescriptor of the right operand * * @return A DataTypeDescriptor telling the result type of the * concatenate operation * * @exception StandardException BinaryOperatorNotSupported * Thrown when a BinaryOperator is 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); } //bug - 5837. long varchar and long binary can't hold more data than their specific limits. If this length is violated by resulting //concatenated string, an exception will be thrown at execute time. if (higherType.equals(TypeId.LONGVARCHAR_NAME)) resultLength = TypeId.LONGVARCHAR_MAXWIDTH; else if (higherType.equals(TypeId.LONGVARBIT_NAME)) resultLength = TypeId.LONGVARBIT_MAXWIDTH; /* ** Result Length can't be negative */ if (SanityManager.DEBUG) { if (resultLength < 0) { SanityManager.THROWASSERT("There should not be an overflow of maximum length for any result type at this point. Overflow for BLOB/CLOB has already been handled earlier"); } } /* The result is nullable if either side is nullable */ nullable = leftType.isNullable() || rightType.isNullable(); /* ** Create a new DataTypeDescriptor that has the correct ** type and nullability. ** ** It's OK to call the implementation of the DataTypeDescriptorFactory ** here, because we're in the same package. */ return new DataTypeDescriptor( TypeId.getBuiltInTypeId(higherType), nullable, resultLength ); } /* *for conatenation operator, we generate code as follows *field = method(p1, p2, field); *what we are ensuring here is if field is null then initialize it to NULL SQLxxx type. *Because of the following, at execution time, SQLxxx concatenate method do not have to *worry about field coming in as null */ protected void initializeResultField(ExpressionClassBuilder acb, MethodBuilder mb, LocalField resultField) { mb.conditionalIfNull();//get the field on the stack and if it is null acb.generateNull(mb, getTypeCompiler());// yes, it is, hence create a NULL SQLxxx type object and put that on stack mb.startElseCode(); //no, it is not null mb.getField(resultField); //so put it back on the stack mb.completeConditional(); //complete if else block } private static int clobBlobHandling( DataTypeDescriptor clobBlobType, DataTypeDescriptor otherType ) throws StandardException { int resultLength; if (otherType.getTypeId().getJDBCTypeId() == Types.LONGVARCHAR || otherType.getTypeId().getJDBCTypeId() == Types.LONGVARBINARY) { //operands CLOB(A), LONG VARCHAR then result is CLOB(MIN(A+32K,2G)) //operands BLOB(A), LONG VARCHAR FOR BIT DATA then result is BLOB(MIN(A+32K,2G)) resultLength = clobBlobType.getMaximumWidth() + 32768; } else { //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), 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), BLOB(B) then result is BLOB(MIN(A+B,2G)) resultLength = clobBlobType.getMaximumWidth() + otherType.getMaximumWidth(); } if (resultLength < 1) //this mean A+B or A+32K is bigger than 2G return(Integer.MAX_VALUE); else return(resultLength); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -