1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 25 26 import org.apache.derby.iapi.services.context.ContextService; 27 28 import org.apache.derby.iapi.services.loader.ClassFactory; 29 30 import org.apache.derby.iapi.services.sanity.SanityManager; 31 32 import org.apache.derby.iapi.services.info.JVMInfo; 33 import org.apache.derby.iapi.services.io.StoredFormatIds; 34 35 import org.apache.derby.iapi.error.StandardException; 36 37 import org.apache.derby.iapi.types.DataTypeDescriptor; 38 import org.apache.derby.iapi.types.DataTypeDescriptor; 39 import org.apache.derby.iapi.types.DataValueFactory; 40 import org.apache.derby.iapi.types.NumberDataValue; 41 import org.apache.derby.iapi.types.TypeId; 42 43 import org.apache.derby.iapi.sql.compile.TypeCompiler; 44 45 import org.apache.derby.iapi.reference.ClassName; 46 import org.apache.derby.iapi.reference.Limits; 47 import org.apache.derby.iapi.reference.SQLState; 48 import org.apache.derby.iapi.services.compiler.LocalField; 49 import org.apache.derby.iapi.services.compiler.MethodBuilder; 50 51 56 57 public final class NumericTypeCompiler extends BaseTypeCompiler 58 { 59 60 public String interfaceName() 61 { 62 return ClassName.NumberDataValue; 63 } 64 65 68 69 public String getCorrespondingPrimitiveTypeName() 70 { 71 72 int formatId = getStoredFormatIdFromTypeId(); 73 switch (formatId) 74 { 75 case StoredFormatIds.DOUBLE_TYPE_ID: 76 return "double"; 77 78 case StoredFormatIds.INT_TYPE_ID: 79 return "int"; 80 81 case StoredFormatIds.LONGINT_TYPE_ID: 82 return "long"; 83 84 case StoredFormatIds.REAL_TYPE_ID: 85 return "float"; 86 87 case StoredFormatIds.SMALLINT_TYPE_ID: 88 return "short"; 89 90 case StoredFormatIds.TINYINT_TYPE_ID: 91 return "byte"; 92 93 case StoredFormatIds.DECIMAL_TYPE_ID: 94 default: 95 if (SanityManager.DEBUG) 96 { 97 SanityManager.THROWASSERT( 98 "unexpected formatId in getCorrespondingPrimitiveTypeName() - " + formatId); 99 } 100 return null; 101 } 102 } 103 104 111 public String getPrimitiveMethodName() 112 { 113 int formatId = getStoredFormatIdFromTypeId(); 114 switch (formatId) 115 { 116 case StoredFormatIds.DOUBLE_TYPE_ID: 117 return "getDouble"; 118 119 case StoredFormatIds.INT_TYPE_ID: 120 return "getInt"; 121 122 case StoredFormatIds.LONGINT_TYPE_ID: 123 return "getLong"; 124 125 case StoredFormatIds.REAL_TYPE_ID: 126 return "getFloat"; 127 128 case StoredFormatIds.SMALLINT_TYPE_ID: 129 return "getShort"; 130 131 case StoredFormatIds.TINYINT_TYPE_ID: 132 return "getByte"; 133 134 case StoredFormatIds.DECIMAL_TYPE_ID: 135 default: 136 if (SanityManager.DEBUG) 137 { 138 SanityManager.THROWASSERT( 139 "unexpected formatId in getPrimitiveMethodName() - " + formatId); 140 } 141 return null; 142 } 143 } 144 145 148 public int getCastToCharWidth(DataTypeDescriptor dts) 149 { 150 int formatId = getStoredFormatIdFromTypeId(); 151 switch (formatId) 152 { 153 case StoredFormatIds.DECIMAL_TYPE_ID: 154 return dts.getPrecision() + 2; 156 157 case StoredFormatIds.DOUBLE_TYPE_ID: 158 return TypeCompiler.DOUBLE_MAXWIDTH_AS_CHAR; 159 160 case StoredFormatIds.INT_TYPE_ID: 161 return TypeCompiler.INT_MAXWIDTH_AS_CHAR; 162 163 case StoredFormatIds.LONGINT_TYPE_ID: 164 return TypeCompiler.LONGINT_MAXWIDTH_AS_CHAR; 165 166 case StoredFormatIds.REAL_TYPE_ID: 167 return TypeCompiler.REAL_MAXWIDTH_AS_CHAR; 168 169 case StoredFormatIds.SMALLINT_TYPE_ID: 170 return TypeCompiler.SMALLINT_MAXWIDTH_AS_CHAR; 171 172 case StoredFormatIds.TINYINT_TYPE_ID: 173 return TypeCompiler.TINYINT_MAXWIDTH_AS_CHAR; 174 175 default: 176 if (SanityManager.DEBUG) 177 { 178 SanityManager.THROWASSERT( 179 "unexpected formatId in getCastToCharWidth() - " + formatId); 180 } 181 return 0; 182 } 183 } 184 185 190 public DataTypeDescriptor 191 resolveArithmeticOperation(DataTypeDescriptor leftType, 192 DataTypeDescriptor rightType, 193 String operator) 194 throws StandardException 195 { 196 NumericTypeCompiler higherTC; 197 DataTypeDescriptor higherType; 198 boolean nullable; 199 int precision, scale, maximumWidth; 200 201 206 if (SanityManager.DEBUG) 207 SanityManager.ASSERT(leftType.getTypeId().isNumericTypeId(), 208 "The left type is supposed to be a number because we're resolving an arithmetic operator"); 209 210 TypeId leftTypeId = leftType.getTypeId(); 211 TypeId rightTypeId = rightType.getTypeId(); 212 213 boolean supported = true; 214 215 if ( ! (rightTypeId.isNumericTypeId()) ) 216 { 217 supported = false; 218 } 219 220 if (TypeCompiler.MOD_OP.equals(operator)) { 221 switch (leftTypeId.getJDBCTypeId()) { 222 case java.sql.Types.TINYINT: 223 case java.sql.Types.SMALLINT: 224 case java.sql.Types.INTEGER: 225 case java.sql.Types.BIGINT: 226 break; 227 default: 228 supported = false; 229 break; 230 } 231 switch (rightTypeId.getJDBCTypeId()) { 232 case java.sql.Types.TINYINT: 233 case java.sql.Types.SMALLINT: 234 case java.sql.Types.INTEGER: 235 case java.sql.Types.BIGINT: 236 break; 237 default: 238 supported = false; 239 break; 240 } 241 242 } 243 244 if (!supported) { 245 throw StandardException.newException(SQLState.LANG_BINARY_OPERATOR_NOT_SUPPORTED, 246 operator, 247 leftType.getTypeId().getSQLTypeName(), 248 rightType.getTypeId().getSQLTypeName() 249 ); 250 } 251 252 255 if (rightTypeId.typePrecedence() > leftTypeId.typePrecedence()) 256 { 257 higherType = rightType; 258 higherTC = (NumericTypeCompiler) getTypeCompiler(rightTypeId); 259 } 260 else 261 { 262 higherType = leftType; 263 higherTC = (NumericTypeCompiler) getTypeCompiler(leftTypeId); 264 } 265 266 270 precision = higherTC.getPrecision(operator, leftType, rightType); 271 scale = higherTC.getScale(operator, leftType, rightType); 272 273 if (higherType.getTypeId().isDecimalTypeId()) 274 { 275 maximumWidth = (scale > 0) ? precision + 3 : precision + 1; 276 277 280 if (maximumWidth < precision) 281 { 282 maximumWidth = Integer.MAX_VALUE; 283 } 284 } 285 else 286 { 287 maximumWidth = higherType.getMaximumWidth(); 288 } 289 290 291 nullable = leftType.isNullable() || rightType.isNullable(); 292 293 300 return new DataTypeDescriptor( 301 higherType.getTypeId(), 302 precision, 303 scale, 304 nullable, 305 maximumWidth 306 ); 307 } 308 309 public boolean comparable(TypeId otherType, 310 boolean forEquals, 311 ClassFactory cf) 312 { 313 return numberComparable(otherType, forEquals, cf); 314 } 315 316 317 318 public boolean convertible(TypeId otherType, boolean forDataTypeFunction) 319 { 320 return (numberConvertible(otherType, forDataTypeFunction)); 321 322 } 323 324 329 public boolean compatible(TypeId otherType) 330 { 331 return (otherType.isNumericTypeId()); 333 } 334 335 336 public boolean storable(TypeId otherType, ClassFactory cf) 337 { 338 return numberStorable(getTypeId(), otherType, cf); 339 } 340 341 345 protected String dataValueMethodName() 346 { 347 if (getStoredFormatIdFromTypeId() == StoredFormatIds.DECIMAL_TYPE_ID) 348 return "getDecimalDataValue"; 349 else 350 return super.dataValueMethodName(); 351 } 352 353 protected String nullMethodName() 354 { 355 int formatId = getStoredFormatIdFromTypeId(); 356 switch (formatId) 357 { 358 case StoredFormatIds.DECIMAL_TYPE_ID: 359 return "getNullDecimal"; 360 361 case StoredFormatIds.DOUBLE_TYPE_ID: 362 return "getNullDouble"; 363 364 case StoredFormatIds.INT_TYPE_ID: 365 return "getNullInteger"; 366 367 case StoredFormatIds.LONGINT_TYPE_ID: 368 return "getNullLong"; 369 370 case StoredFormatIds.REAL_TYPE_ID: 371 return "getNullFloat"; 372 373 case StoredFormatIds.SMALLINT_TYPE_ID: 374 return "getNullShort"; 375 376 case StoredFormatIds.TINYINT_TYPE_ID: 377 return "getNullByte"; 378 379 default: 380 if (SanityManager.DEBUG) 381 { 382 SanityManager.THROWASSERT( 383 "unexpected formatId in nullMethodName() - " + formatId); 384 } 385 return null; 386 } 387 } 388 389 401 private int getPrecision(String operator, 402 DataTypeDescriptor leftType, 403 DataTypeDescriptor rightType) 404 { 405 if (getStoredFormatIdFromTypeId() != StoredFormatIds.DECIMAL_TYPE_ID) 407 { 408 return leftType.getPrecision(); 409 } 410 411 long lscale = (long)leftType.getScale(); 412 long rscale = (long)rightType.getScale(); 413 long lprec = (long)leftType.getPrecision(); 414 long rprec = (long)rightType.getPrecision(); 415 long val; 416 417 421 if (operator == null) 422 { 423 val = this.getScale(operator, leftType, rightType) + 424 Math.max(lprec - lscale, rprec - rscale); 425 } 426 else if (operator.equals(TypeCompiler.TIMES_OP)) 427 { 428 val = lprec + rprec; 429 } 430 else if (operator.equals(TypeCompiler.SUM_OP)) 431 { 432 val = lprec - lscale + rprec - rscale + 433 this.getScale(operator, leftType, rightType); 434 } 435 else if (operator.equals(TypeCompiler.DIVIDE_OP)) 436 { 437 val = Math.min(NumberDataValue.MAX_DECIMAL_PRECISION_SCALE, 438 this.getScale(operator, leftType, rightType) + lprec - lscale + rprec); 439 } 440 443 else 444 { 445 449 val = this.getScale(operator, leftType, rightType) + 450 Math.max(lprec - lscale, rprec - rscale) + 1; 451 452 if (val > Limits.DB2_MAX_DECIMAL_PRECISION_SCALE) 453 val = Limits.DB2_MAX_DECIMAL_PRECISION_SCALE; 455 } 456 457 if (val > Integer.MAX_VALUE) 458 { 459 val = Integer.MAX_VALUE; 460 } 461 val = Math.min(NumberDataValue.MAX_DECIMAL_PRECISION_SCALE, val); 462 return (int)val; 463 } 464 465 482 private int getScale(String operator, 483 DataTypeDescriptor leftType, 484 DataTypeDescriptor rightType) 485 { 486 if (getStoredFormatIdFromTypeId() != StoredFormatIds.DECIMAL_TYPE_ID) 488 { 489 return leftType.getScale(); 490 } 491 492 long val; 493 494 long lscale = (long)leftType.getScale(); 495 long rscale = (long)rightType.getScale(); 496 long lprec = (long)leftType.getPrecision(); 497 long rprec = (long)rightType.getPrecision(); 498 499 503 if (TypeCompiler.TIMES_OP.equals(operator)) 504 { 505 val = lscale + rscale; 506 } 507 else if (TypeCompiler.DIVIDE_OP.equals(operator)) 508 { 509 513 LanguageConnectionContext lcc = (LanguageConnectionContext) 514 (ContextService.getContext(LanguageConnectionContext.CONTEXT_ID)); 515 516 val = Math.max(NumberDataValue.MAX_DECIMAL_PRECISION_SCALE - lprec + lscale - rscale, 0); 518 519 } 520 else if (TypeCompiler.AVG_OP.equals(operator)) 521 { 522 val = Math.max(Math.max(lscale, rscale), 523 NumberDataValue.MIN_DECIMAL_DIVIDE_SCALE); 524 } 525 528 else 529 { 530 val = Math.max(lscale, rscale); 531 } 532 533 if (val > Integer.MAX_VALUE) 534 { 535 val = Integer.MAX_VALUE; 536 } 537 val = Math.min(NumberDataValue.MAX_DECIMAL_PRECISION_SCALE, val); 538 return (int)val; 539 } 540 541 542 public void generateDataValue(MethodBuilder mb, 543 LocalField field) 544 { 545 if (!JVMInfo.J2ME && getTypeId().isDecimalTypeId()) 546 { 547 mb.upCast("java.lang.Number"); 552 } 553 554 super.generateDataValue(mb, field); 555 } 556 557 } 558 | Popular Tags |