1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.services.context.ContextManager; 25 26 import org.apache.derby.iapi.services.compiler.MethodBuilder; 27 import org.apache.derby.iapi.services.compiler.LocalField; 28 29 import org.apache.derby.iapi.services.monitor.Monitor; 30 31 import org.apache.derby.iapi.services.sanity.SanityManager; 32 33 import org.apache.derby.iapi.error.StandardException; 34 35 import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; 36 37 import org.apache.derby.iapi.sql.compile.CompilerContext; 38 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 39 40 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 41 42 import org.apache.derby.iapi.types.DataTypeUtilities; 43 import org.apache.derby.iapi.types.TypeId; 44 45 import org.apache.derby.iapi.reference.SQLState; 46 47 import org.apache.derby.iapi.types.DataTypeDescriptor; 48 import org.apache.derby.iapi.types.DataValueFactory; 49 import org.apache.derby.iapi.types.DataValueDescriptor; 50 import org.apache.derby.iapi.types.VariableSizeDataValue; 51 52 import org.apache.derby.iapi.sql.compile.TypeCompiler; 53 54 import org.apache.derby.iapi.reference.SQLState; 55 import org.apache.derby.iapi.util.StringUtil; 56 57 import org.apache.derby.iapi.reference.ClassName; 58 import org.apache.derby.iapi.reference.JDBC30Translation; 59 import org.apache.derby.iapi.services.classfile.VMOpcode; 60 61 import org.apache.derby.iapi.types.DataValueDescriptor; 62 63 import org.apache.derby.iapi.services.loader.ClassInspector; 64 65 import org.apache.derby.iapi.sql.compile.Visitable; 66 import org.apache.derby.iapi.sql.compile.Visitor; 67 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 68 69 import java.lang.reflect.Modifier ; 70 71 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 72 import org.apache.derby.iapi.types.NumberDataType; 73 74 import org.apache.derby.iapi.util.JBitSet; 75 import org.apache.derby.iapi.util.ReuseFactory; 76 77 import org.apache.derby.catalog.AliasInfo; 78 import org.apache.derby.catalog.TypeDescriptor; 79 80 import org.apache.derby.iapi.types.SQLReal; 81 82 import java.sql.Date ; 83 import java.sql.Time ; 84 import java.sql.Timestamp ; 85 import java.sql.Types ; 86 87 import java.util.Vector ; 88 89 94 95 public class CastNode extends ValueNode 96 { 97 DataTypeDescriptor castTarget; 98 ValueNode castOperand; 99 int targetCharType; 100 TypeId destCTI = null; 101 TypeId sourceCTI = null; 102 boolean forDataTypeFunction = false; 103 104 109 110 118 119 public void init(Object castOperand, Object castTarget) 120 throws StandardException 121 { 122 this.castOperand = (ValueNode) castOperand; 123 this.castTarget = (DataTypeDescriptor) castTarget; 124 } 125 126 135 136 public void init(Object castOperand, Object charType, Object charLength) 137 throws StandardException 138 { 139 this.castOperand = (ValueNode) castOperand; 140 int charLen = ((Integer ) charLength).intValue(); 141 targetCharType = ((Integer ) charType).intValue(); 142 if (charLen < 0) return; 144 this.castTarget = DataTypeDescriptor.getBuiltInDataTypeDescriptor(targetCharType, charLen); 145 } 146 147 153 154 public String toString() 155 { 156 if (SanityManager.DEBUG) 157 { 158 return "castTarget: " + castTarget + "\n" + 159 super.toString(); 160 } 161 else 162 { 163 return ""; 164 } 165 } 166 167 173 174 public void printSubNodes(int depth) 175 { 176 if (SanityManager.DEBUG) 177 { 178 super.printSubNodes(depth); 179 180 if (castOperand != null) 181 { 182 printLabel(depth, "castOperand: "); 183 castOperand.treePrint(depth + 1); 184 } 185 } 186 } 187 protected int getOrderableVariantType() throws StandardException 188 { 189 return castOperand.getOrderableVariantType(); 190 } 191 192 197 public void setClause(int clause) 198 { 199 super.setClause(clause); 200 castOperand.setClause(clause); 201 } 202 203 216 217 public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, 218 Vector aggregateVector) 219 throws StandardException 220 { 221 castOperand = castOperand.bindExpression( 222 fromList, subqueryList, 223 aggregateVector); 224 225 if (castTarget == null) { 227 DataTypeDescriptor opndType = castOperand.getTypeServices(); 228 int length = -1; 229 TypeId srcTypeId = opndType.getTypeId(); 230 if (opndType != null) 231 { 232 if (srcTypeId.isNumericTypeId()) 233 { 234 length = opndType.getPrecision() + 1; if (opndType.getScale() > 0) 236 length += 1; 238 } 239 else 240 { 241 TypeId typeid = opndType.getTypeId(); 242 if (length < 0) 243 length = DataTypeUtilities.getColumnDisplaySize(typeid.getJDBCTypeId(),-1); 244 245 } 246 } 247 if (length < 0) 248 length = 1; castTarget = DataTypeDescriptor.getBuiltInDataTypeDescriptor(targetCharType, length); 250 251 } 252 253 257 if (castOperand instanceof UntypedNullConstantNode) 258 { 259 castOperand.setType(castTarget); 260 } 261 262 bindCastNodeOnly(); 263 264 267 if ((castOperand instanceof ConstantNode) && 268 !(castOperand instanceof UntypedNullConstantNode)) 269 { 270 288 289 ValueNode retNode = this; 290 int sourceJDBCTypeId = sourceCTI.getJDBCTypeId(); 291 int destJDBCTypeId = destCTI.getJDBCTypeId(); 292 293 switch (sourceJDBCTypeId) 294 { 295 case Types.BIT: 296 case JDBC30Translation.SQL_TYPES_BOOLEAN: 297 if (destJDBCTypeId == Types.BIT || destJDBCTypeId == JDBC30Translation.SQL_TYPES_BOOLEAN) 299 { 300 retNode = castOperand; 301 } 302 else if (destJDBCTypeId == Types.CHAR) 303 { 304 BooleanConstantNode bcn = (BooleanConstantNode) castOperand; 305 String booleanString = bcn.getValueAsString(); 306 retNode = (ValueNode) getNodeFactory().getNode( 307 C_NodeTypes.CHAR_CONSTANT_NODE, 308 booleanString, 309 ReuseFactory.getInteger( 310 castTarget.getMaximumWidth()), 311 getContextManager()); 312 } 313 break; 314 315 case Types.CHAR: 316 retNode = getCastFromCharConstant(destJDBCTypeId); 317 break; 318 319 case Types.DATE: 320 case Types.TIME: 321 case Types.TIMESTAMP: 322 if (destJDBCTypeId == Types.CHAR) 323 { 324 String castValue = 325 ((UserTypeConstantNode) castOperand). 326 getObjectValue(). 327 toString(); 328 retNode = (ValueNode) getNodeFactory().getNode( 329 C_NodeTypes.CHAR_CONSTANT_NODE, 330 castValue, 331 ReuseFactory.getInteger( 332 castTarget.getMaximumWidth()), 333 getContextManager()); 334 } 335 break; 336 337 case Types.DECIMAL: 338 if (destJDBCTypeId == Types.DECIMAL || 340 destJDBCTypeId == Types.NUMERIC) 341 break; 342 case Types.TINYINT: 344 case Types.SMALLINT: 345 case Types.INTEGER: 346 case Types.BIGINT: 347 case Types.DOUBLE: 348 case Types.REAL: 349 retNode = getCastFromNumericType( 350 ((ConstantNode) castOperand).getValue(), 351 destJDBCTypeId); 352 break; 353 354 } 355 356 return retNode; 358 } 359 360 return this; 361 } 362 363 371 public void bindCastNodeOnly() 372 throws StandardException 373 { 374 375 378 setType(castTarget); 379 destCTI = castTarget.getTypeId(); 380 sourceCTI = castOperand.getTypeId(); 381 382 386 if (destCTI.userType()) 387 { 388 String className = ((TypeId) dataTypeServices.getTypeId()).getCorrespondingJavaTypeName(); 389 390 boolean convertCase = ! destCTI.getClassNameWasDelimitedIdentifier(); 391 392 className = verifyClassExist(className, convertCase); 393 394 castTarget = new DataTypeDescriptor(TypeId.getUserDefinedTypeId(className, false), 395 true 396 ); 397 setType(castTarget); 398 destCTI = castTarget.getTypeId(); 399 } 400 401 if (castOperand.requiresTypeFromContext()) 402 { 403 bindParameter(); 404 } 405 406 411 else if (!(castOperand instanceof UntypedNullConstantNode)) 412 { 413 416 TypeCompiler tc = castOperand.getTypeCompiler(); 417 if (! tc.convertible(destCTI, forDataTypeFunction)) 418 { 419 throw StandardException.newException(SQLState.LANG_INVALID_CAST, 420 sourceCTI.getSQLTypeName(), 421 destCTI.getSQLTypeName()); 422 } 423 } 424 } 425 426 443 private ValueNode getCastFromCharConstant(int destJDBCTypeId) 444 throws StandardException 445 { 446 String charValue = ((CharConstantNode) castOperand).getString(); 447 String cleanCharValue = StringUtil.SQLToUpperCase(charValue.trim()); 448 ValueNode retNode = this; 449 450 switch (destJDBCTypeId) 451 { 452 case Types.BIT: 453 case JDBC30Translation.SQL_TYPES_BOOLEAN: 454 if (cleanCharValue.equals("TRUE")) 455 { 456 return (ValueNode) getNodeFactory().getNode( 457 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 458 Boolean.TRUE, 459 getContextManager()); 460 } 461 else if (cleanCharValue.equals("FALSE")) 462 { 463 return (ValueNode) getNodeFactory().getNode( 464 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 465 Boolean.FALSE, 466 getContextManager()); 467 } 468 else 469 { 470 throw StandardException.newException(SQLState.LANG_FORMAT_EXCEPTION, "boolean"); 471 } 472 473 case Types.DATE: 474 return (ValueNode) getNodeFactory().getNode( 475 C_NodeTypes.USERTYPE_CONSTANT_NODE, 476 getDataValueFactory().getDateValue(cleanCharValue, false), 477 getContextManager()); 478 479 case Types.TIMESTAMP: 480 return (ValueNode) getNodeFactory().getNode( 481 C_NodeTypes.USERTYPE_CONSTANT_NODE, 482 getDataValueFactory().getTimestampValue(cleanCharValue, false), 483 getContextManager()); 484 485 case Types.TIME: 486 return (ValueNode) getNodeFactory().getNode( 487 C_NodeTypes.USERTYPE_CONSTANT_NODE, 488 getDataValueFactory().getTimeValue(cleanCharValue, false), 489 getContextManager()); 490 491 case Types.TINYINT: 492 case Types.SMALLINT: 493 case Types.INTEGER: 494 case Types.BIGINT: 495 try 496 { 497 return getCastFromIntegralType((new Double (cleanCharValue)).longValue(), 499 destJDBCTypeId); 500 } 501 catch (NumberFormatException nfe) 502 { 503 String sqlName = TypeId.getBuiltInTypeId(destJDBCTypeId).getSQLTypeName(); 504 throw StandardException.newException(SQLState.LANG_FORMAT_EXCEPTION, sqlName); 505 } 506 case Types.REAL: 507 Float floatValue; 508 try 509 { 510 floatValue = Float.valueOf(cleanCharValue); 511 } 512 catch (NumberFormatException nfe) 513 { 514 throw StandardException.newException(SQLState.LANG_FORMAT_EXCEPTION, "float"); 515 } 516 return (ValueNode) getNodeFactory().getNode( 517 C_NodeTypes.FLOAT_CONSTANT_NODE, 518 floatValue, 519 getContextManager()); 520 case Types.DOUBLE: 521 Double doubleValue; 522 try 523 { 524 doubleValue = new Double (cleanCharValue); 525 } 526 catch (NumberFormatException nfe) 527 { 528 throw StandardException.newException(SQLState.LANG_FORMAT_EXCEPTION, "double"); 529 } 530 return (ValueNode) getNodeFactory().getNode( 531 C_NodeTypes.DOUBLE_CONSTANT_NODE, 532 doubleValue, 533 getContextManager()); 534 } 535 536 return retNode; 537 } 538 539 540 557 private ValueNode getCastFromIntegralType( 558 long longValue, 559 int destJDBCTypeId) 560 throws StandardException 561 { 562 ValueNode retNode = this; 563 564 switch (destJDBCTypeId) 565 { 566 case Types.CHAR: 567 return (ValueNode) getNodeFactory().getNode( 568 C_NodeTypes.CHAR_CONSTANT_NODE, 569 Long.toString(longValue), 570 ReuseFactory.getInteger( 571 castTarget.getMaximumWidth()), 572 getContextManager()); 573 case Types.TINYINT: 574 if (longValue < Byte.MIN_VALUE || 575 longValue > Byte.MAX_VALUE) 576 { 577 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TINYINT"); 578 } 579 return (ValueNode) getNodeFactory().getNode( 580 C_NodeTypes.TINYINT_CONSTANT_NODE, 581 ReuseFactory.getByte((byte) longValue), 582 getContextManager()); 583 584 case Types.SMALLINT: 585 if (longValue < Short.MIN_VALUE || 586 longValue > Short.MAX_VALUE) 587 { 588 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "SHORT"); 589 } 590 return (ValueNode) getNodeFactory().getNode( 591 C_NodeTypes.SMALLINT_CONSTANT_NODE, 592 ReuseFactory.getShort( 593 (short) longValue), 594 getContextManager()); 595 596 case Types.INTEGER: 597 if (longValue < Integer.MIN_VALUE || 598 longValue > Integer.MAX_VALUE) 599 { 600 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER"); 601 } 602 return (ValueNode) getNodeFactory().getNode( 603 C_NodeTypes.INT_CONSTANT_NODE, 604 ReuseFactory.getInteger( 605 (int) longValue), 606 getContextManager()); 607 608 case Types.BIGINT: 609 return (ValueNode) getNodeFactory().getNode( 610 C_NodeTypes.LONGINT_CONSTANT_NODE, 611 ReuseFactory.getLong(longValue), 612 getContextManager()); 613 614 case Types.REAL: 615 if (Math.abs(longValue) > Float.MAX_VALUE) 616 { 617 throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "REAL"); 618 } 619 return (ValueNode) getNodeFactory().getNode( 620 C_NodeTypes.FLOAT_CONSTANT_NODE, 621 new Float ((float) longValue), 622 getContextManager()); 623 624 case Types.DOUBLE: 625 return (ValueNode) getNodeFactory().getNode( 626 C_NodeTypes.DOUBLE_CONSTANT_NODE, 627 new Double ((double) longValue), 628 getContextManager()); 629 } 630 631 return retNode; 632 } 633 634 651 private ValueNode getCastFromNumericType( 652 DataValueDescriptor constantValue, 653 int destJDBCTypeId) 654 throws StandardException 655 { 656 int nodeType = -1; 657 Object constantObject = null; 658 659 switch (destJDBCTypeId) 660 { 661 case Types.CHAR: 662 nodeType = C_NodeTypes.CHAR_CONSTANT_NODE; 663 constantObject = constantValue.getString(); 664 return (ValueNode) getNodeFactory().getNode( 665 nodeType, 666 constantObject, 667 ReuseFactory.getInteger( 668 castTarget.getMaximumWidth()), 669 getContextManager()); 670 671 case Types.TINYINT: 672 nodeType = C_NodeTypes.TINYINT_CONSTANT_NODE; 673 constantObject = new Byte (constantValue.getByte()); 674 break; 675 676 case Types.SMALLINT: 677 nodeType = C_NodeTypes.SMALLINT_CONSTANT_NODE; 678 constantObject = ReuseFactory.getShort(constantValue.getShort()); 679 break; 680 681 case Types.INTEGER: 682 nodeType = C_NodeTypes.INT_CONSTANT_NODE; 683 constantObject = ReuseFactory.getInteger(constantValue.getInt()); 684 break; 685 686 case Types.BIGINT: 687 nodeType = C_NodeTypes.LONGINT_CONSTANT_NODE; 688 constantObject = ReuseFactory.getLong(constantValue.getLong()); 689 break; 690 691 case Types.REAL: 692 nodeType = C_NodeTypes.FLOAT_CONSTANT_NODE; 693 constantObject = new Float (NumberDataType.normalizeREAL(constantValue.getDouble())); 694 break; 695 696 case Types.DOUBLE: 697 nodeType = C_NodeTypes.DOUBLE_CONSTANT_NODE; 699 constantObject = new Double (constantValue.getDouble()); 700 break; 701 } 702 703 if (nodeType == -1) 704 return this; 705 706 707 return (ValueNode) getNodeFactory().getNode( 708 nodeType, 709 constantObject, 710 getContextManager()); 711 712 } 713 714 729 public ValueNode preprocess(int numTables, 730 FromList outerFromList, 731 SubqueryList outerSubqueryList, 732 PredicateList outerPredicateList) 733 throws StandardException 734 { 735 castOperand = castOperand.preprocess(numTables, 736 outerFromList, outerSubqueryList, 737 outerPredicateList); 738 return this; 739 } 740 741 767 public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly) 768 throws StandardException 769 { 770 return castOperand.categorize(referencedTabs, simplePredsOnly); 771 } 772 773 781 public ValueNode remapColumnReferencesToExpressions() 782 throws StandardException 783 { 784 castOperand = castOperand.remapColumnReferencesToExpressions(); 785 return this; 786 } 787 788 793 public boolean isConstantExpression() 794 { 795 return castOperand.isConstantExpression(); 796 } 797 798 799 public boolean constantExpression(PredicateList whereClause) 800 { 801 return castOperand.constantExpression(whereClause); 802 } 803 804 811 812 void bindParameter() 813 throws StandardException 814 { 815 castOperand.setType(castTarget); 816 } 817 818 830 Object getConstantValueAsObject() 831 throws StandardException 832 { 833 Object sourceObject = castOperand.getConstantValueAsObject(); 834 835 if (sourceObject == null) 837 { 838 return null; 839 } 840 841 if (sourceCTI.getCorrespondingJavaTypeName().equals( 843 destCTI.getCorrespondingJavaTypeName())) 844 { 845 return sourceObject; 846 } 847 848 return null; 851 } 852 853 861 862 public void generateExpression(ExpressionClassBuilder acb, 863 MethodBuilder mb) 864 throws StandardException 865 { 866 castOperand.generateExpression(acb, mb); 867 868 869 if (castOperand instanceof UntypedNullConstantNode) 870 { 871 return; 872 } 873 881 else if (castOperand.requiresTypeFromContext()) 882 { 883 sourceCTI = destCTI; 884 } 885 886 genDataValueConversion(acb, mb); 887 } 888 889 private void genDataValueConversion(ExpressionClassBuilder acb, 890 MethodBuilder mb) 891 throws StandardException 892 { 893 MethodBuilder acbConstructor = acb.getConstructor(); 894 895 String resultTypeName = getTypeCompiler().interfaceName(); 896 897 898 899 LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName); 900 901 905 906 acb.generateNull(acbConstructor, getTypeCompiler(destCTI)); 907 acbConstructor.setField(field); 908 909 910 923 924 if (!sourceCTI.userType() && !destCTI.userType()) { 925 mb.getField(field); mb.swap(); 927 mb.upCast(ClassName.DataValueDescriptor); 928 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, 929 "setValue", "void", 1); 930 } 931 else 932 { 933 936 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, 937 "getObject", "java.lang.Object", 0); 938 939 941 mb.getField(field); mb.swap(); 944 951 String destinationType = getTypeId().getCorrespondingJavaTypeName(); 952 953 mb.dup(); 956 mb.isInstanceOf(destinationType); 957 mb.push(destinationType); 958 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, 959 "setObjectForCast", "void", 3); 960 961 } 962 963 mb.getField(field); 964 965 970 if (destCTI.variableLength()) 971 { 972 boolean isNumber = destCTI.isNumericTypeId(); 973 974 mb.dup(); 976 977 981 982 mb.push(isNumber ? castTarget.getPrecision() : castTarget.getMaximumWidth()); 983 mb.push(castTarget.getScale()); 984 mb.push(!sourceCTI.variableLength() || isNumber); 985 mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, 986 "setWidth", "void", 3); 987 988 } 989 } 990 991 999 public Visitable accept(Visitor v) 1000 throws StandardException 1001 { 1002 Visitable returnNode = v.visit(this); 1003 1004 if (v.skipChildren(this)) 1005 { 1006 return returnNode; 1007 } 1008 1009 if (castOperand != null && !v.stopTraversal()) 1010 { 1011 castOperand = (ValueNode)castOperand.accept(v); 1012 } 1013 1014 return returnNode; 1015 } 1016 1017 1021 public void setForDataTypeFunction(boolean b) 1022 { 1023 forDataTypeFunction = b; 1024 } 1025 1026 1030 public boolean getForDataTypeFunction() 1031 { 1032 return forDataTypeFunction; 1033 } 1034 1035 1039 protected boolean isEquivalent(ValueNode o) throws StandardException 1040 { 1041 if (isSameNodeType(o)) 1042 { 1043 CastNode other = (CastNode)o; 1044 return castTarget.equals(other.castTarget) 1045 && castOperand.isEquivalent(other.castOperand); 1046 } 1047 return false; 1048 } 1049} 1050 1051 1052 | Popular Tags |