1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 25 26 import org.apache.derby.iapi.services.sanity.SanityManager; 27 28 import org.apache.derby.iapi.error.StandardException; 29 30 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 31 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 32 import org.apache.derby.iapi.types.TypeId; 33 34 import org.apache.derby.iapi.types.ConcatableDataValue; 35 import org.apache.derby.iapi.types.BitDataValue; 36 37 import org.apache.derby.iapi.sql.compile.TypeCompiler; 38 import org.apache.derby.iapi.types.DataTypeDescriptor; 39 40 import org.apache.derby.iapi.services.compiler.MethodBuilder; 41 import org.apache.derby.iapi.services.compiler.LocalField; 42 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 43 44 import org.apache.derby.iapi.reference.Limits; 45 import org.apache.derby.iapi.reference.SQLState; 46 import org.apache.derby.iapi.reference.ClassName; 47 48 import java.sql.Types ; 49 50 import java.util.Vector ; 51 52 53 59 60 public class ConcatenationOperatorNode extends BinaryOperatorNode 61 { 62 68 public void init(Object leftOperand, Object rightOperand) 69 { 70 super.init(leftOperand, rightOperand, "||", "concatenate", 71 ClassName.ConcatableDataValue, ClassName.ConcatableDataValue); 72 } 73 74 80 public ValueNode bindExpression( 81 FromList fromList, SubqueryList subqueryList, 82 Vector aggregateVector) 83 throws StandardException 84 { 85 leftOperand = leftOperand.bindExpression(fromList, subqueryList, 87 aggregateVector); 88 rightOperand = rightOperand.bindExpression(fromList, subqueryList, 89 aggregateVector); 90 91 97 98 if (leftOperand.requiresTypeFromContext()) 99 { 100 if (rightOperand.requiresTypeFromContext()) 101 { 102 throw StandardException.newException(SQLState.LANG_BINARY_OPERANDS_BOTH_PARMS, 103 operator); 104 } 105 106 TypeId leftType; 107 108 126 if (rightOperand.getTypeId().isBitTypeId()) 127 { 128 if (rightOperand.getTypeId().isBlobTypeId()) 129 leftType = TypeId.getBuiltInTypeId(Types.BLOB); 130 else 131 leftType = TypeId.getBuiltInTypeId(Types.VARBINARY); 132 } 133 else 134 { 135 if (rightOperand.getTypeId().isClobTypeId()) 136 leftType = TypeId.getBuiltInTypeId(Types.CLOB); 137 else 138 leftType = TypeId.getBuiltInTypeId(Types.VARCHAR); 139 } 140 141 leftOperand.setType(new DataTypeDescriptor(leftType, true)); 142 } 143 144 147 if (rightOperand.requiresTypeFromContext()) 148 { 149 TypeId rightType; 150 151 169 if (leftOperand.getTypeId().isBitTypeId()) 170 { 171 if (leftOperand.getTypeId().isBlobTypeId()) 172 rightType = TypeId.getBuiltInTypeId(Types.BLOB); 173 else 174 rightType = TypeId.getBuiltInTypeId(Types.VARBINARY); 175 } 176 else 177 { 178 if (leftOperand.getTypeId().isClobTypeId()) 179 rightType = TypeId.getBuiltInTypeId(Types.CLOB); 180 else 181 rightType = TypeId.getBuiltInTypeId(Types.VARCHAR); 182 } 183 184 rightOperand.setType( 185 new DataTypeDescriptor( 186 rightType, 187 true)); 188 } 189 190 193 if (leftOperand.getTypeId().userType()) 194 { 195 leftOperand = leftOperand.genSQLJavaSQLTree(); 196 } 197 198 201 if (rightOperand.getTypeId().userType()) 202 { 203 rightOperand = rightOperand.genSQLJavaSQLTree(); 204 } 205 206 209 TypeCompiler tc = leftOperand.getTypeCompiler(); 210 if (! (leftOperand.getTypeId().isStringTypeId() || leftOperand.getTypeId().isBitTypeId())) 211 { 212 leftOperand = (ValueNode) 213 getNodeFactory().getNode( 214 C_NodeTypes.CAST_NODE, 215 leftOperand, 216 DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true, 217 tc.getCastToCharWidth( 218 leftOperand.getTypeServices())), 219 getContextManager()); 220 ((CastNode) leftOperand).bindCastNodeOnly(); 221 } 222 tc = rightOperand.getTypeCompiler(); 223 if (! (rightOperand.getTypeId().isStringTypeId() || rightOperand.getTypeId().isBitTypeId())) 224 { 225 rightOperand = (ValueNode) 226 getNodeFactory().getNode( 227 C_NodeTypes.CAST_NODE, 228 rightOperand, 229 DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, true, 230 tc.getCastToCharWidth( 231 rightOperand.getTypeServices())), 232 getContextManager()); 233 ((CastNode) rightOperand).bindCastNodeOnly(); 234 } 235 236 237 242 tc = leftOperand.getTypeCompiler(); 243 setType(resolveConcatOperation( 244 leftOperand.getTypeServices(), 245 rightOperand.getTypeServices())); 246 247 250 if (SanityManager.DEBUG) 251 { 252 if (getTypeServices().getMaximumWidth() > getTypeId().getMaximumMaximumWidth()) 253 { 254 SanityManager.THROWASSERT("The maximum length " + getTypeServices().getMaximumWidth() + 255 " for the result type " + getTypeId().getSQLTypeName() + 256 " can't be greater than it's maximum width of result's typeid" + getTypeId().getMaximumMaximumWidth()); 257 } 258 } 259 260 265 this.setLeftRightInterfaceType(tc.interfaceName()); 266 267 return this; 268 } 269 270 283 private DataTypeDescriptor resolveConcatOperation( 284 DataTypeDescriptor leftType, 285 DataTypeDescriptor rightType 286 ) throws StandardException 287 { 288 TypeId leftTypeId; 289 TypeId rightTypeId; 290 String higherType; 291 int resultLength; 292 boolean nullable; 293 294 leftTypeId = leftType.getTypeId(); 295 rightTypeId = rightType.getTypeId(); 296 297 302 306 307 if (!leftTypeId.isConcatableTypeId() 308 || !rightTypeId.isConcatableTypeId() 309 || (rightTypeId.isBitTypeId() && leftTypeId.isStringTypeId()) 310 || (leftTypeId.isBitTypeId() && rightTypeId.isStringTypeId())) 311 throw StandardException.newException(SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "||", "FUNCTION"); 312 313 317 318 higherType = (leftTypeId.typePrecedence() >= 319 rightTypeId.typePrecedence()) ? 320 leftType.getTypeName() : rightType.getTypeName(); 321 322 323 resultLength = leftType.getMaximumWidth() + 324 rightType.getMaximumWidth(); 325 326 369 if (leftTypeId.getJDBCTypeId() == Types.CHAR || leftTypeId.getJDBCTypeId() == Types.BINARY) 373 { 374 switch (rightTypeId.getJDBCTypeId()) 375 { 376 case Types.CHAR: 377 case Types.BINARY: 378 if (resultLength > Limits.DB2_CHAR_MAXWIDTH) { 379 if (rightTypeId.getJDBCTypeId() == Types.CHAR) 380 higherType = TypeId.VARCHAR_NAME; 382 else 383 higherType = TypeId.VARBIT_NAME; 385 } 386 break; 387 388 case Types.VARCHAR: 389 case Types.VARBINARY: 390 if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH) { 391 if (rightTypeId.getJDBCTypeId() == Types.VARCHAR) 392 higherType = TypeId.LONGVARCHAR_NAME; 394 else 395 higherType = TypeId.LONGVARBIT_NAME; 397 } 398 break; 399 400 case Types.CLOB: 401 case Types.BLOB: 402 resultLength = clobBlobHandling(rightType, leftType); 405 break; 406 } 407 } else if (leftTypeId.getJDBCTypeId() == Types.VARCHAR) { 408 switch (rightTypeId.getJDBCTypeId()) 409 { 410 case Types.CHAR: case Types.VARCHAR: if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH) 413 higherType = TypeId.LONGVARCHAR_NAME; 414 break; 415 416 case Types.CLOB: 417 resultLength = clobBlobHandling(rightType, leftType); 419 break; 420 } 421 } else if (leftTypeId.getJDBCTypeId() == Types.VARBINARY) { 422 switch (rightTypeId.getJDBCTypeId()) 423 { 424 case Types.BINARY: case Types.VARBINARY: if (resultLength > Limits.DB2_CONCAT_VARCHAR_LENGTH) 427 higherType = TypeId.LONGVARBIT_NAME; 428 break; 429 430 case Types.BLOB: 431 resultLength = clobBlobHandling(rightType, leftType); 433 break; 434 } 435 } else if (leftTypeId.getJDBCTypeId() == Types.CLOB || leftTypeId.getJDBCTypeId() == Types.BLOB) { 436 resultLength = clobBlobHandling(leftType, rightType); 445 } else if (rightTypeId.getJDBCTypeId() == Types.CLOB || rightTypeId.getJDBCTypeId() == Types.BLOB) { 446 resultLength = clobBlobHandling(rightType, leftType); 449 } 450 451 if (higherType.equals(TypeId.LONGVARCHAR_NAME)) 454 resultLength = TypeId.LONGVARCHAR_MAXWIDTH; 455 else if (higherType.equals(TypeId.LONGVARBIT_NAME)) 456 resultLength = TypeId.LONGVARBIT_MAXWIDTH; 457 458 459 462 if (SanityManager.DEBUG) 463 { 464 if (resultLength < 0) 465 { 466 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"); 467 } 468 } 469 470 471 nullable = leftType.isNullable() || rightType.isNullable(); 472 473 480 return new DataTypeDescriptor( 481 TypeId.getBuiltInTypeId(higherType), 482 nullable, 483 resultLength 484 ); 485 } 486 487 494 protected void initializeResultField(ExpressionClassBuilder acb, MethodBuilder mb, LocalField resultField) 495 throws StandardException 496 { 497 mb.conditionalIfNull(); acb.generateNull(mb, getTypeCompiler()); mb.startElseCode(); mb.getField(resultField); mb.completeConditional(); } 503 504 private static int clobBlobHandling( 505 DataTypeDescriptor clobBlobType, 506 DataTypeDescriptor otherType 507 ) throws StandardException 508 { 509 int resultLength; 510 511 if (otherType.getTypeId().getJDBCTypeId() == Types.LONGVARCHAR || 512 otherType.getTypeId().getJDBCTypeId() == Types.LONGVARBINARY) { 513 resultLength = clobBlobType.getMaximumWidth() + 32768; 516 } else { 517 resultLength = clobBlobType.getMaximumWidth() + otherType.getMaximumWidth(); 524 } 525 526 if (resultLength < 1) return(Integer.MAX_VALUE); 528 else 529 return(resultLength); 530 531 } 532 } 533 | Popular Tags |