1 21 22 package org.apache.derby.impl.sql.compile; 23 24 import org.apache.derby.iapi.sql.compile.C_NodeTypes; 25 import org.apache.derby.iapi.sql.compile.NodeFactory; 26 27 import org.apache.derby.iapi.sql.dictionary.DataDictionary; 28 import org.apache.derby.iapi.types.DataTypeDescriptor; 29 30 import org.apache.derby.iapi.error.StandardException; 31 import org.apache.derby.iapi.reference.SQLState; 32 33 import org.apache.derby.impl.sql.compile.ExpressionClassBuilder; 34 import org.apache.derby.iapi.services.compiler.MethodBuilder; 35 36 import org.apache.derby.iapi.services.sanity.SanityManager; 37 38 import org.apache.derby.iapi.store.access.Qualifier; 39 40 import org.apache.derby.iapi.util.JBitSet; 41 42 import java.util.Vector ; 43 44 52 53 public class ColumnReference extends ValueNode 54 { 55 String columnName; 56 57 62 TableName tableName; 63 64 private int tableNumber; 65 66 private int columnNumber; 67 68 private ResultColumn source; 69 70 71 ResultColumn origSource; 72 private String origName; 73 int origTableNumber = -1; 74 int origColumnNumber = -1; 75 76 77 79 private boolean replacesAggregate; 80 81 private int nestingLevel = -1; 82 private int sourceLevel = -1; 83 84 87 private boolean scoped; 88 89 92 private java.util.ArrayList remaps; 93 94 106 107 public void init(Object columnName, 108 Object tableName, 109 Object tokBeginOffset, 110 Object tokEndOffset 111 ) 112 { 113 this.columnName = (String ) columnName; 114 this.tableName = (TableName) tableName; 115 this.setBeginOffset(((Integer ) tokBeginOffset).intValue()); 116 this.setEndOffset(((Integer ) tokEndOffset).intValue()); 117 tableNumber = -1; 118 remaps = null; 119 } 120 121 127 128 public void init(Object columnName, Object tableName) 129 { 130 this.columnName = (String ) columnName; 131 this.tableName = (TableName) tableName; 132 tableNumber = -1; 133 remaps = null; 134 } 135 136 142 143 public String toString() 144 { 145 if (SanityManager.DEBUG) 146 { 147 return "columnName: " + columnName + "\n" + 148 "tableNumber: " + tableNumber + "\n" + 149 "columnNumber: " + columnNumber + "\n" + 150 "replacesAggregate: " + replacesAggregate + "\n" + 151 "tableName: " + ( ( tableName != null) ? tableName.toString() : "null") + "\n" + 152 "nestingLevel: " + nestingLevel + "\n" + 153 "sourceLevel: " + sourceLevel + "\n" + 154 super.toString(); 155 } 156 else 157 { 158 return ""; 159 } 160 } 161 162 168 169 public void printSubNodes(int depth) 170 { 171 if (SanityManager.DEBUG) 172 { 173 super.printSubNodes(depth); 174 175 if (source != null) 176 { 177 printLabel(depth, "source: "); 178 source.treePrint(depth + 1); 179 } 180 } 181 } 182 183 188 boolean getCorrelated() 189 { 190 if (SanityManager.DEBUG) 191 { 192 SanityManager.ASSERT(nestingLevel != -1, 193 "nestingLevel on "+columnName+" is not expected to be -1"); 194 SanityManager.ASSERT(sourceLevel != -1, 195 "sourceLevel on "+columnName+" is not expected to be -1"); 196 } 197 return sourceLevel != nestingLevel; 198 } 199 200 206 void setNestingLevel(int nestingLevel) 207 { 208 if (SanityManager.DEBUG) 209 { 210 SanityManager.ASSERT(nestingLevel != -1, 211 "nestingLevel is not expected to be -1"); 212 } 213 this.nestingLevel = nestingLevel; 214 } 215 216 221 int getNestingLevel() 222 { 223 return nestingLevel; 224 } 225 226 232 void setSourceLevel(int sourceLevel) 233 { 234 if (SanityManager.DEBUG) 235 { 236 SanityManager.ASSERT(sourceLevel != -1, 237 "sourceLevel is not expected to be -1"); 238 } 239 this.sourceLevel = sourceLevel; 240 } 241 242 247 int getSourceLevel() 248 { 249 return sourceLevel; 250 } 251 252 258 public void markGeneratedToReplaceAggregate() 259 { 260 replacesAggregate = true; 261 } 262 263 270 public boolean getGeneratedToReplaceAggregate() 271 { 272 return replacesAggregate; 273 } 274 275 282 public ValueNode getClone() 283 throws StandardException 284 { 285 ColumnReference newCR = (ColumnReference) getNodeFactory().getNode( 286 C_NodeTypes.COLUMN_REFERENCE, 287 columnName, 288 tableName, 289 getContextManager()); 290 291 newCR.copyFields(this); 292 return newCR; 293 } 294 295 302 public void copyFields(ColumnReference oldCR) 303 throws StandardException 304 { 305 super.copyFields(oldCR); 306 307 tableName = oldCR.getTableNameNode(); 308 tableNumber = oldCR.getTableNumber(); 309 columnNumber = oldCR.getColumnNumber(); 310 source = oldCR.getSource(); 311 nestingLevel = oldCR.getNestingLevel(); 312 sourceLevel = oldCR.getSourceLevel(); 313 replacesAggregate = oldCR.getGeneratedToReplaceAggregate(); 314 scoped = oldCR.isScoped(); 315 } 316 317 334 335 public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, 336 Vector aggregateVector) 337 throws StandardException 338 { 339 ResultColumn matchingRC; 340 341 if (SanityManager.DEBUG) 342 { 343 SanityManager.ASSERT(fromList != null, "fromList is expected to be non-null"); 344 } 345 346 if (fromList.size() == 0) 347 { 348 throw StandardException.newException(SQLState.LANG_ILLEGAL_COLUMN_REFERENCE, columnName); 349 } 350 351 matchingRC = fromList.bindColumnReference(this); 352 353 354 if (matchingRC == null) 355 { 356 throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, getSQLColumnName()); 357 } 358 359 362 columnNumber = matchingRC.getColumnPosition(); 363 364 return this; 365 } 366 367 375 376 public String getSQLColumnName() 377 { 378 if (tableName == null) 379 return columnName; 380 381 return tableName.toString() + "." + columnName; 382 } 383 384 389 390 public String getColumnName() 391 { 392 return columnName; 393 } 394 395 400 401 public void setColumnName(String columnName) 402 { 403 this.columnName = columnName; 404 } 405 406 411 412 public int getTableNumber() 413 { 414 return tableNumber; 415 } 416 417 422 423 public void setTableNumber(int tableNumber) 424 { 425 if (SanityManager.DEBUG) 426 { 427 SanityManager.ASSERT(tableNumber != -1, 428 "tableNumber not expected to be -1"); 429 } 430 this.tableNumber = tableNumber; 431 } 432 433 442 443 public String getTableName() 444 { 445 return ( ( tableName != null) ? tableName.getTableName() : null ); 446 } 447 448 458 459 public String getSourceTableName() 460 { 461 return ((source != null) ? source.getTableName() : null); 462 } 463 464 474 public String getSourceSchemaName() throws StandardException 475 { 476 return ((source != null) ? source.getSchemaName() : null); 477 } 478 479 485 public boolean updatableByCursor() 486 { 487 return ((source != null) ? source.updatableByCursor() : false); 488 } 489 490 494 public TableName getTableNameNode() 495 { 496 return tableName; 497 } 498 499 public void setTableNameNode(TableName tableName) 500 { 501 this.tableName = tableName; 502 } 503 504 509 510 public int getColumnNumber() 511 { 512 return columnNumber; 513 } 514 515 521 522 public void setColumnNumber(int colNum) 523 { 524 this.columnNumber = colNum; 525 } 526 527 532 533 public ResultColumn getSource() 534 { 535 return source; 536 } 537 538 543 544 public void setSource(ResultColumn source) 545 { 546 this.source = source; 547 } 548 549 558 public ValueNode putAndsOnTop() 559 throws StandardException 560 { 561 BinaryComparisonOperatorNode equalsNode; 562 BooleanConstantNode trueNode; 563 NodeFactory nodeFactory = getNodeFactory(); 564 ValueNode andNode; 565 566 trueNode = (BooleanConstantNode) nodeFactory.getNode( 567 C_NodeTypes.BOOLEAN_CONSTANT_NODE, 568 Boolean.TRUE, 569 getContextManager()); 570 equalsNode = (BinaryComparisonOperatorNode) 571 nodeFactory.getNode( 572 C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE, 573 this, 574 trueNode, 575 getContextManager()); 576 577 equalsNode.bindComparisonOperator(); 578 andNode = (ValueNode) nodeFactory.getNode( 579 C_NodeTypes.AND_NODE, 580 equalsNode, 581 trueNode, 582 getContextManager()); 583 ((AndNode) andNode).postBindFixup(); 584 return andNode; 585 } 586 587 619 public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly) 620 { 621 if (SanityManager.DEBUG) 622 SanityManager.ASSERT(tableNumber >= 0, 623 "tableNumber is expected to be non-negative"); 624 referencedTabs.set(tableNumber); 625 626 return ( ! replacesAggregate ) && 627 ( (source.getExpression() instanceof ColumnReference) || 628 (source.getExpression() instanceof VirtualColumnNode) || 629 (source.getExpression() instanceof ConstantNode)); 630 } 631 632 641 public void remapColumnReferences() 642 { 643 ValueNode expression = source.getExpression(); 644 645 if (SanityManager.DEBUG) 646 { 647 } 650 651 if ( ! ( (expression instanceof VirtualColumnNode) || 652 (expression instanceof ColumnReference) ) 653 ) 654 { 655 return; 656 } 657 658 667 if (scoped && (origSource != null)) 668 { 669 if (remaps == null) 670 remaps = new java.util.ArrayList (); 671 remaps.add(new RemapInfo( 672 columnNumber, tableNumber, columnName, source)); 673 } 674 else 675 { 676 origSource = source; 677 origName = columnName; 678 origColumnNumber = columnNumber; 679 origTableNumber = tableNumber; 680 } 681 682 683 source = getSourceResultColumn(); 684 columnName = source.getName(); 685 columnNumber = source.getColumnPosition(); 686 687 if (source.getExpression() instanceof ColumnReference) 688 { 689 ColumnReference cr = (ColumnReference) source.getExpression(); 690 tableNumber = cr.getTableNumber(); 691 if (SanityManager.DEBUG) 692 { 693 if (tableNumber == -1 && ! cr.getGeneratedToReplaceAggregate()) 696 { 697 SanityManager.THROWASSERT( 698 "tableNumber not expected to be -1, origName = " + origName); 699 } 700 } 701 } 702 } 703 704 public void unRemapColumnReferences() 705 { 706 if (origSource == null) 707 return; 708 709 if (SanityManager.DEBUG) 710 { 711 } 714 715 if ((remaps == null) || (remaps.size() == 0)) 716 { 717 source = origSource; 718 origSource = null; 719 columnName = origName; 720 origName = null; 721 tableNumber = origTableNumber; 722 columnNumber = origColumnNumber; 723 } 724 else 725 { 726 RemapInfo rI = (RemapInfo)remaps.remove(remaps.size() - 1); 729 source = rI.getSource(); 730 columnName = rI.getColumnName(); 731 tableNumber = rI.getTableNumber(); 732 columnNumber = rI.getColumnNumber(); 733 rI = null; 734 if (remaps.size() == 0) 735 remaps = null; 736 } 737 } 738 739 745 protected boolean hasBeenRemapped() 746 { 747 return (origSource != null); 748 } 749 750 754 public ResultColumn getSourceResultColumn() 755 { 756 ValueNode expression = source.getExpression(); 757 758 759 if (expression instanceof VirtualColumnNode) 760 { 761 return ((VirtualColumnNode) expression).getSourceResultColumn(); 762 } 763 else 764 { 765 774 return ((ColumnReference) expression).getSourceResultColumn(); 775 } 776 } 777 778 786 public ValueNode remapColumnReferencesToExpressions() 787 throws StandardException 788 { 789 ResultColumn rc; 790 ResultColumn sourceRC = source; 791 792 793 if (! source.isRedundant()) 794 { 795 return this; 796 } 797 798 801 for (rc = source; rc != null && rc.isRedundant(); ) 802 { 803 ResultColumn nextRC = null; 804 ValueNode expression = rc.getExpression(); 805 806 807 if (expression instanceof VirtualColumnNode) 808 { 809 nextRC = ((VirtualColumnNode) expression).getSourceResultColumn(); 810 } 811 else if (expression instanceof ColumnReference) 812 { 813 nextRC = ((ColumnReference) expression).getSourceResultColumn(); 814 } 815 else 816 { 817 nextRC = null; 818 } 819 820 if (nextRC != null && nextRC.isRedundant()) 821 { 822 sourceRC = nextRC; 823 } 824 rc = nextRC; 825 } 826 827 if (SanityManager.DEBUG) 828 { 829 if (sourceRC == null) 830 { 831 SanityManager.THROWASSERT( 832 "sourceRC is expected to be non-null for " + 833 columnName); 834 } 835 836 if ( ! sourceRC.isRedundant()) 837 { 838 SanityManager.THROWASSERT( 839 "sourceRC is expected to be redundant for " + 840 columnName); 841 } 842 } 843 844 849 if (sourceRC.getExpression() instanceof VirtualColumnNode) 850 { 851 VirtualColumnNode vcn = 852 (VirtualColumnNode) (sourceRC.getExpression()); 853 ResultSetNode rsn = vcn.getSourceResultSet(); 854 if (rsn instanceof FromTable) 855 { 856 tableNumber = ((FromTable) rsn).getTableNumber(); 857 if (SanityManager.DEBUG) 858 { 859 SanityManager.ASSERT(tableNumber != -1, 860 "tableNumber not expected to be -1"); 861 } 862 } 863 else 864 { 865 if (SanityManager.DEBUG) 866 { 867 SanityManager.THROWASSERT("rsn expected to be a FromTable, but is a " + rsn.getClass().getName()); 868 } 869 } 870 source = ((VirtualColumnNode) sourceRC.getExpression()). 871 getSourceResultColumn(); 872 return this; 873 } 874 else 875 { 876 return sourceRC.getExpression().getClone(); 877 } 878 } 879 880 886 void getTablesReferenced(JBitSet refs) 887 { 888 if (refs.size() < tableNumber) 889 refs.grow(tableNumber); 890 891 if (tableNumber != -1) refs.set(tableNumber); 893 } 894 895 900 public boolean isCloneable() 901 { 902 return true; 903 } 904 905 906 public boolean constantExpression(PredicateList whereClause) 907 { 908 return whereClause.constantColumn(this); 909 } 910 911 924 public void generateExpression(ExpressionClassBuilder acb, 925 MethodBuilder mb) 926 throws StandardException 927 { 928 int sourceResultSetNumber = source.getResultSetNumber(); 929 930 932 933 939 if (source.isRedundant()) 940 { 941 source.generateExpression(acb, mb); 942 return; 943 } 944 945 if (SanityManager.DEBUG) 946 { 947 if (sourceResultSetNumber < 0) 948 { 949 SanityManager.THROWASSERT("sourceResultSetNumber expected to be >= 0 for " + getTableName() + "." + getColumnName()); 950 } 951 } 952 953 963 acb.pushColumnReference(mb, sourceResultSetNumber, 964 source.getVirtualColumnId()); 965 966 mb.cast(getTypeCompiler().interfaceName()); 967 968 969 } 970 971 981 982 public String getSchemaName() 983 { 984 return ( ( tableName != null) ? tableName.getSchemaName() : null ); 985 } 986 987 999 protected int getOrderableVariantType() 1000 { 1001 return Qualifier.SCAN_INVARIANT; 1003 } 1004 1005 1010 boolean pointsToColumnReference() 1011 { 1012 return (source.getExpression() instanceof ColumnReference); 1013 } 1014 1015 1021 public DataTypeDescriptor getTypeServices() throws StandardException 1022 { 1023 DataTypeDescriptor dtd = super.getTypeServices(); 1024 if( dtd == null && source != null) 1025 { 1026 dtd = source.getTypeServices(); 1027 if( dtd != null) 1028 setType( dtd); 1029 } 1030 return dtd; 1031 } 1033 1046 protected ResultSetNode getSourceResultSet(int [] colNum) 1047 throws StandardException 1048 { 1049 if (source == null) 1050 { 1051 1060 return null; 1061 } 1062 1063 ValueNode rcExpr = null; 1064 ResultColumn rc = getSource(); 1065 1066 1069 rcExpr = rc.getExpression(); 1070 colNum[0] = getColumnNumber(); 1071 1072 1078 while ((rcExpr != null) && 1079 (rc.isRedundant() || (rcExpr instanceof ColumnReference))) 1080 { 1081 if (rcExpr instanceof ColumnReference) 1082 { 1083 colNum[0] = ((ColumnReference)rcExpr).getColumnNumber(); 1084 rc = ((ColumnReference)rcExpr).getSource(); 1085 } 1086 1087 1095 while (rc.isRedundant()) 1096 { 1097 rcExpr = rc.getExpression(); 1098 if (rcExpr instanceof VirtualColumnNode) 1099 rc = ((VirtualColumnNode)rcExpr).getSourceResultColumn(); 1100 else if (rcExpr instanceof ColumnReference) 1101 { 1102 colNum[0] = ((ColumnReference)rcExpr).getColumnNumber(); 1103 rc = ((ColumnReference)rcExpr).getSource(); 1104 } 1105 else 1106 { 1107 1114 rcExpr = null; 1115 break; 1116 } 1117 } 1118 rcExpr = rc.getExpression(); 1119 } 1120 1121 if ((rcExpr != null) && (rcExpr instanceof VirtualColumnNode)) 1126 return ((VirtualColumnNode)rcExpr).getSourceResultSet(); 1127 1128 colNum[0] = -1; 1131 return null; 1132 } 1133 1134 protected boolean isEquivalent(ValueNode o) throws StandardException 1135 { 1136 if (!isSameNodeType(o)) { 1137 return false; 1138 } 1139 ColumnReference other = (ColumnReference)o; 1140 return (tableNumber == other.tableNumber 1141 && columnName.equals(other.getColumnName())); 1142 } 1143 1144 1149 protected void markAsScoped() 1150 { 1151 scoped = true; 1152 } 1153 1154 1157 protected boolean isScoped() 1158 { 1159 return scoped; 1160 } 1161 1162 1167 private class RemapInfo 1168 { 1169 int colNum; 1170 int tableNum; 1171 String colName; 1172 ResultColumn source; 1173 1174 RemapInfo(int cNum, int tNum, String cName, ResultColumn rc) 1175 { 1176 colNum = cNum; 1177 tableNum = tNum; 1178 colName = cName; 1179 source = rc; 1180 } 1181 1182 int getColumnNumber() { return colNum; } 1183 int getTableNumber() { return tableNum; } 1184 String getColumnName() { return colName; } 1185 ResultColumn getSource() { return source; } 1186 1187 void setColNumber(int cNum) { colNum = cNum; } 1188 void setTableNumber(int tNum) { tableNum = tNum; } 1189 void setColName(String cName) { colName = cName; } 1190 void setSource(ResultColumn rc) { source = rc; } 1191 } 1192} 1193 | Popular Tags |