Source Code Cross Referenced for ColumnReference.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » sql » compile » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.sql.compile 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.sql.compile.ColumnReference
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to you under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.impl.sql.compile;
0023:
0024:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
0025:        import org.apache.derby.iapi.sql.compile.NodeFactory;
0026:
0027:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
0028:        import org.apache.derby.iapi.types.DataTypeDescriptor;
0029:
0030:        import org.apache.derby.iapi.error.StandardException;
0031:        import org.apache.derby.iapi.reference.SQLState;
0032:
0033:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
0034:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
0035:
0036:        import org.apache.derby.iapi.services.sanity.SanityManager;
0037:
0038:        import org.apache.derby.iapi.store.access.Qualifier;
0039:
0040:        import org.apache.derby.iapi.util.JBitSet;
0041:
0042:        import java.util.Vector;
0043:
0044:        /**
0045:         * A ColumnReference represents a column in the query tree.  The parser generates a
0046:         * ColumnReference for each column reference.  A column refercence could be a column in
0047:         * a base table, a column in a view (which could expand into a complex
0048:         * expression), or a column in a subquery in the FROM clause.
0049:         *
0050:         * @author Jerry Brenner
0051:         */
0052:
0053:        public class ColumnReference extends ValueNode {
0054:            String columnName;
0055:
0056:            /*
0057:             ** This is the user-specified table name.  It will be null if the
0058:             ** user specifies a column without a table name.  Leave it null even
0059:             ** when the column is bound as it is only used in binding.
0060:             */
0061:            TableName tableName;
0062:            /* The table this column reference is bound to */
0063:            private int tableNumber;
0064:            /* The column number in the underlying base table */
0065:            private int columnNumber;
0066:            /* This is where the value for this column reference will be coming from */
0067:            private ResultColumn source;
0068:
0069:            /* For unRemapping */
0070:            ResultColumn origSource;
0071:            private String origName;
0072:            int origTableNumber = -1;
0073:            int origColumnNumber = -1;
0074:
0075:            /* Reuse generated code where possible */
0076:            //Expression genResult;
0077:            private boolean replacesAggregate;
0078:
0079:            private int nestingLevel = -1;
0080:            private int sourceLevel = -1;
0081:
0082:            /* Whether or not this column reference been scoped for the
0083:               sake of predicate pushdown.
0084:             */
0085:            private boolean scoped;
0086:
0087:            /* List of saved remap data if this ColumnReference is scoped
0088:               and has been remapped multiple times.
0089:             */
0090:            private java.util.ArrayList remaps;
0091:
0092:            /**
0093:             * Initializer.
0094:             * This one is called by the parser where we could
0095:             * be dealing with delimited identifiers.
0096:             *
0097:             * @param columnName	The name of the column being referenced
0098:             * @param tableName		The qualification for the column
0099:             * @param tokBeginOffset begin position of token for the column name 
0100:             *					identifier from parser.
0101:             * @param tokEndOffset	end position of token for the column name 
0102:             *					identifier from parser.
0103:             */
0104:
0105:            public void init(Object columnName, Object tableName,
0106:                    Object tokBeginOffset, Object tokEndOffset) {
0107:                this .columnName = (String) columnName;
0108:                this .tableName = (TableName) tableName;
0109:                this .setBeginOffset(((Integer) tokBeginOffset).intValue());
0110:                this .setEndOffset(((Integer) tokEndOffset).intValue());
0111:                tableNumber = -1;
0112:                remaps = null;
0113:            }
0114:
0115:            /**
0116:             * Initializer.
0117:             *
0118:             * @param columnName	The name of the column being referenced
0119:             * @param tableName		The qualification for the column
0120:             */
0121:
0122:            public void init(Object columnName, Object tableName) {
0123:                this .columnName = (String) columnName;
0124:                this .tableName = (TableName) tableName;
0125:                tableNumber = -1;
0126:                remaps = null;
0127:            }
0128:
0129:            /**
0130:             * Convert this object to a String.  See comments in QueryTreeNode.java
0131:             * for how this should be done for tree printing.
0132:             *
0133:             * @return	This object as a String
0134:             */
0135:
0136:            public String toString() {
0137:                if (SanityManager.DEBUG) {
0138:                    return "columnName: "
0139:                            + columnName
0140:                            + "\n"
0141:                            + "tableNumber: "
0142:                            + tableNumber
0143:                            + "\n"
0144:                            + "columnNumber: "
0145:                            + columnNumber
0146:                            + "\n"
0147:                            + "replacesAggregate: "
0148:                            + replacesAggregate
0149:                            + "\n"
0150:                            + "tableName: "
0151:                            + ((tableName != null) ? tableName.toString()
0152:                                    : "null") + "\n" + "nestingLevel: "
0153:                            + nestingLevel + "\n" + "sourceLevel: "
0154:                            + sourceLevel + "\n" + super .toString();
0155:                } else {
0156:                    return "";
0157:                }
0158:            }
0159:
0160:            /**
0161:             * Prints the sub-nodes of this object.  See QueryTreeNode.java for
0162:             * how tree printing is supposed to work.
0163:             *
0164:             * @param depth		The depth of this node in the tree
0165:             */
0166:
0167:            public void printSubNodes(int depth) {
0168:                if (SanityManager.DEBUG) {
0169:                    super .printSubNodes(depth);
0170:
0171:                    if (source != null) {
0172:                        printLabel(depth, "source: ");
0173:                        source.treePrint(depth + 1);
0174:                    }
0175:                }
0176:            }
0177:
0178:            /**
0179:             * Return whether or not this CR is correlated.
0180:             *
0181:             * @return Whether or not this CR is correlated.
0182:             */
0183:            boolean getCorrelated() {
0184:                if (SanityManager.DEBUG) {
0185:                    SanityManager.ASSERT(nestingLevel != -1, "nestingLevel on "
0186:                            + columnName + " is not expected to be -1");
0187:                    SanityManager.ASSERT(sourceLevel != -1, "sourceLevel on "
0188:                            + columnName + " is not expected to be -1");
0189:                }
0190:                return sourceLevel != nestingLevel;
0191:            }
0192:
0193:            /**
0194:             * Set the nesting level for this CR.  (The nesting level
0195:             * at which the CR appears.)
0196:             *
0197:             * @param nestingLevel	The Nesting level at which the CR appears.
0198:             */
0199:            void setNestingLevel(int nestingLevel) {
0200:                if (SanityManager.DEBUG) {
0201:                    SanityManager.ASSERT(nestingLevel != -1,
0202:                            "nestingLevel is not expected to be -1");
0203:                }
0204:                this .nestingLevel = nestingLevel;
0205:            }
0206:
0207:            /**
0208:             * Get the nesting level for this CR.
0209:             *
0210:             * @return	The nesting level for this CR.
0211:             */
0212:            int getNestingLevel() {
0213:                return nestingLevel;
0214:            }
0215:
0216:            /**
0217:             * Set the source level for this CR.  (The nesting level
0218:             * of the source of the CR.)
0219:             *
0220:             * @param sourceLevel	The Nesting level of the source of the CR.
0221:             */
0222:            void setSourceLevel(int sourceLevel) {
0223:                if (SanityManager.DEBUG) {
0224:                    SanityManager.ASSERT(sourceLevel != -1,
0225:                            "sourceLevel is not expected to be -1");
0226:                }
0227:                this .sourceLevel = sourceLevel;
0228:            }
0229:
0230:            /**
0231:             * Get the source level for this CR.
0232:             *
0233:             * @return	The source level for this CR.
0234:             */
0235:            int getSourceLevel() {
0236:                return sourceLevel;
0237:            }
0238:
0239:            /**
0240:             * Mark this node as being generated to replace an aggregate.
0241:             * (Useful for replacing aggregates in the HAVING clause with 
0242:             * column references to the matching aggregate in the 
0243:             * user's SELECT.
0244:             */
0245:            public void markGeneratedToReplaceAggregate() {
0246:                replacesAggregate = true;
0247:            }
0248:
0249:            /**
0250:             * Determine whether or not this node was generated to
0251:             * replace an aggregate in the user's SELECT.
0252:             *
0253:             * @return boolean	Whether or not this node was generated to replace
0254:             *					an aggregate in the user's SELECT.
0255:             */
0256:            public boolean getGeneratedToReplaceAggregate() {
0257:                return replacesAggregate;
0258:            }
0259:
0260:            /**
0261:             * Return a clone of this node.
0262:             *
0263:             * @return ValueNode	A clone of this node.
0264:             *
0265:             * @exception StandardException			Thrown on error
0266:             */
0267:            public ValueNode getClone() throws StandardException {
0268:                ColumnReference newCR = (ColumnReference) getNodeFactory()
0269:                        .getNode(C_NodeTypes.COLUMN_REFERENCE, columnName,
0270:                                tableName, getContextManager());
0271:
0272:                newCR.copyFields(this );
0273:                return newCR;
0274:            }
0275:
0276:            /**
0277:             * Copy all of the "appropriate fields" for a shallow copy.
0278:             *
0279:             * @param oldCR		The ColumnReference to copy from.
0280:             *
0281:             * @exception StandardException			Thrown on error
0282:             */
0283:            public void copyFields(ColumnReference oldCR)
0284:                    throws StandardException {
0285:                super .copyFields(oldCR);
0286:
0287:                tableName = oldCR.getTableNameNode();
0288:                tableNumber = oldCR.getTableNumber();
0289:                columnNumber = oldCR.getColumnNumber();
0290:                source = oldCR.getSource();
0291:                nestingLevel = oldCR.getNestingLevel();
0292:                sourceLevel = oldCR.getSourceLevel();
0293:                replacesAggregate = oldCR.getGeneratedToReplaceAggregate();
0294:                scoped = oldCR.isScoped();
0295:            }
0296:
0297:            /**
0298:             * Bind this expression.  This means binding the sub-expressions,
0299:             * as well as figuring out what the return type is for this expression.
0300:             *
0301:             * NOTE: We must explicitly check for a null FromList here, column reference
0302:             * without a FROM list, as the grammar allows the following:
0303:             *			insert into t1 values(c1)
0304:             *
0305:             * @param fromList		The FROM list for the query this
0306:             *				expression is in, for binding columns.
0307:             * @param subqueryList		The subquery list being built as we find SubqueryNodes
0308:             * @param aggregateVector	The aggregate vector being built as we find AggregateNodes
0309:             *
0310:             * @return	The new top of the expression tree.
0311:             *
0312:             * @exception StandardException		Thrown on error
0313:             */
0314:
0315:            public ValueNode bindExpression(FromList fromList,
0316:                    SubqueryList subqueryList, Vector aggregateVector)
0317:                    throws StandardException {
0318:                ResultColumn matchingRC;
0319:
0320:                if (SanityManager.DEBUG) {
0321:                    SanityManager.ASSERT(fromList != null,
0322:                            "fromList is expected to be non-null");
0323:                }
0324:
0325:                if (fromList.size() == 0) {
0326:                    throw StandardException.newException(
0327:                            SQLState.LANG_ILLEGAL_COLUMN_REFERENCE, columnName);
0328:                }
0329:
0330:                matchingRC = fromList.bindColumnReference(this );
0331:
0332:                /* Error if no match found in fromList */
0333:                if (matchingRC == null) {
0334:                    throw StandardException.newException(
0335:                            SQLState.LANG_COLUMN_NOT_FOUND, getSQLColumnName());
0336:                }
0337:
0338:                /* Set the columnNumber from the base table.
0339:                 * Useful for optimizer and generation.
0340:                 */
0341:                columnNumber = matchingRC.getColumnPosition();
0342:
0343:                return this ;
0344:            }
0345:
0346:            /**
0347:             * Get the column name for purposes of error
0348:             * messages or debugging. This returns the column
0349:             * name as used in the SQL statement. Thus if it was qualified
0350:             * with a table, alias name that will be included.
0351:             *
0352:             * @return	The  column name in the form [[schema.]table.]column
0353:             */
0354:
0355:            public String getSQLColumnName() {
0356:                if (tableName == null)
0357:                    return columnName;
0358:
0359:                return tableName.toString() + "." + columnName;
0360:            }
0361:
0362:            /**
0363:             * Get the name of this column
0364:             *
0365:             * @return	The name of this column
0366:             */
0367:
0368:            public String getColumnName() {
0369:                return columnName;
0370:            }
0371:
0372:            /**
0373:             * Set the name of this column
0374:             *
0375:             * @param columnName	The name of this column
0376:             */
0377:
0378:            public void setColumnName(String columnName) {
0379:                this .columnName = columnName;
0380:            }
0381:
0382:            /**
0383:             * Get the table number for this ColumnReference.
0384:             *
0385:             * @return	int The table number for this ColumnReference
0386:             */
0387:
0388:            public int getTableNumber() {
0389:                return tableNumber;
0390:            }
0391:
0392:            /**
0393:             * Set this ColumnReference to refer to the given table number.
0394:             *
0395:             * @param tableNumber	The table number this ColumnReference will refer to
0396:             */
0397:
0398:            public void setTableNumber(int tableNumber) {
0399:                if (SanityManager.DEBUG) {
0400:                    SanityManager.ASSERT(tableNumber != -1,
0401:                            "tableNumber not expected to be -1");
0402:                }
0403:                this .tableNumber = tableNumber;
0404:            }
0405:
0406:            /**
0407:             * Get the user-supplied table name of this column.  This will be null
0408:             * if the user did not supply a name (for example, select a from t).
0409:             * The method will return B for this example, select b.a from t as b
0410:             * The method will return T for this example, select t.a from t
0411:             *
0412:             * @return	The user-supplied name of this column.  Null if no user-
0413:             * 		supplied name.
0414:             */
0415:
0416:            public String getTableName() {
0417:                return ((tableName != null) ? tableName.getTableName() : null);
0418:            }
0419:
0420:            /**
0421:             * Get the name of the underlying(base) table this column comes from, if any.
0422:             * Following example queries will all return T
0423:             * select a from t
0424:             * select b.a from t as b
0425:             * select t.a from t
0426:             *
0427:             * @return	The name of the base table that this column comes from.
0428:             *			Null if not a ColumnReference.
0429:             */
0430:
0431:            public String getSourceTableName() {
0432:                return ((source != null) ? source.getTableName() : null);
0433:            }
0434:
0435:            /**
0436:             * Get the name of the schema for the Column's base table, if any.
0437:             * Following example queries will all return APP (assuming user is in schema APP)
0438:             * select t.a from t
0439:             * select b.a from t as b
0440:             * select app.t.a from t
0441:             *
0442:             * @return	The name of the schema for Column's base table. If the column
0443:             *		is not in a schema (i.e. is a derived column), it returns NULL.
0444:             */
0445:            public String getSourceSchemaName() throws StandardException {
0446:                return ((source != null) ? source.getSchemaName() : null);
0447:            }
0448:
0449:            /**
0450:             * Is the column wirtable by the cursor or not. (ie, is it in the list of FOR UPDATE columns list)
0451:             *
0452:             * @return TRUE, if the column is a base column of a table and is 
0453:             * writable by cursor.
0454:             */
0455:            public boolean updatableByCursor() {
0456:                return ((source != null) ? source.updatableByCursor() : false);
0457:            }
0458:
0459:            /**
0460:              Return the table name as the node it is.
0461:              @return the column's table name.
0462:             */
0463:            public TableName getTableNameNode() {
0464:                return tableName;
0465:            }
0466:
0467:            public void setTableNameNode(TableName tableName) {
0468:                this .tableName = tableName;
0469:            }
0470:
0471:            /**
0472:             * Get the column number for this ColumnReference.
0473:             *
0474:             * @return	int The column number for this ColumnReference
0475:             */
0476:
0477:            public int getColumnNumber() {
0478:                return columnNumber;
0479:            }
0480:
0481:            /**
0482:             * Set the column number for this ColumnReference.  This is
0483:             * used when scoping predicates for pushdown.
0484:             *
0485:             * @param colNum The new column number.
0486:             */
0487:
0488:            public void setColumnNumber(int colNum) {
0489:                this .columnNumber = colNum;
0490:            }
0491:
0492:            /**
0493:             * Get the source this columnReference
0494:             *
0495:             * @return	The source of this columnReference
0496:             */
0497:
0498:            public ResultColumn getSource() {
0499:                return source;
0500:            }
0501:
0502:            /**
0503:             * Set the source this columnReference
0504:             *
0505:             * @param source	The source of this columnReference
0506:             */
0507:
0508:            public void setSource(ResultColumn source) {
0509:                this .source = source;
0510:            }
0511:
0512:            /**
0513:             * Do the 1st step in putting an expression into conjunctive normal
0514:             * form.  This step ensures that the top level of the expression is
0515:             * a chain of AndNodes.
0516:             *
0517:             * @return		The modified expression
0518:             *
0519:             * @exception StandardException		Thrown on error
0520:             */
0521:            public ValueNode putAndsOnTop() throws StandardException {
0522:                BinaryComparisonOperatorNode equalsNode;
0523:                BooleanConstantNode trueNode;
0524:                NodeFactory nodeFactory = getNodeFactory();
0525:                ValueNode andNode;
0526:
0527:                trueNode = (BooleanConstantNode) nodeFactory.getNode(
0528:                        C_NodeTypes.BOOLEAN_CONSTANT_NODE, Boolean.TRUE,
0529:                        getContextManager());
0530:                equalsNode = (BinaryComparisonOperatorNode) nodeFactory
0531:                        .getNode(C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE, this ,
0532:                                trueNode, getContextManager());
0533:                /* Set type info for the operator node */
0534:                equalsNode.bindComparisonOperator();
0535:                andNode = (ValueNode) nodeFactory.getNode(C_NodeTypes.AND_NODE,
0536:                        equalsNode, trueNode, getContextManager());
0537:                ((AndNode) andNode).postBindFixup();
0538:                return andNode;
0539:            }
0540:
0541:            /**
0542:             * Categorize this predicate.  Initially, this means
0543:             * building a bit map of the referenced tables for each predicate.
0544:             * If the source of this ColumnReference (at the next underlying level) 
0545:             * is not a ColumnReference or a VirtualColumnNode then this predicate
0546:             * will not be pushed down.
0547:             *
0548:             * For example, in:
0549:             *		select * from (select 1 from s) a (x) where x = 1
0550:             * we will not push down x = 1.
0551:             * NOTE: It would be easy to handle the case of a constant, but if the
0552:             * inner SELECT returns an arbitrary expression, then we would have to copy
0553:             * that tree into the pushed predicate, and that tree could contain
0554:             * subqueries and method calls.
0555:             *
0556:             * Also, don't allow a predicate to be pushed down if it contains a
0557:             * ColumnReference that replaces an aggregate.  This can happen if
0558:             * the aggregate is in the HAVING clause.  In this case, we would be
0559:             * pushing the predicate into the SelectNode that evaluates the aggregate,
0560:             * which doesn't make sense, since the having clause is supposed to be
0561:             * applied to the result of the SelectNode.
0562:             *
0563:             * RESOLVE - revisit this issue once we have views.
0564:             *
0565:             * @param referencedTabs	JBitSet with bit map of referenced FromTables
0566:             * @param simplePredsOnly	Whether or not to consider method
0567:             *							calls, field references and conditional nodes
0568:             *							when building bit map
0569:             *
0570:             * @return boolean		Whether or not source.expression is a ColumnReference
0571:             *						or a VirtualColumnNode or a ConstantNode.
0572:             */
0573:            public boolean categorize(JBitSet referencedTabs,
0574:                    boolean simplePredsOnly) {
0575:                if (SanityManager.DEBUG)
0576:                    SanityManager.ASSERT(tableNumber >= 0,
0577:                            "tableNumber is expected to be non-negative");
0578:                referencedTabs.set(tableNumber);
0579:
0580:                return (!replacesAggregate)
0581:                        && ((source.getExpression() instanceof  ColumnReference)
0582:                                || (source.getExpression() instanceof  VirtualColumnNode) || (source
0583:                                .getExpression() instanceof  ConstantNode));
0584:            }
0585:
0586:            /**
0587:             * Remap all of the ColumnReferences in this expression tree
0588:             * to point to the ResultColumn that is 1 level under their
0589:             * current source ResultColumn.
0590:             * This is useful for pushing down single table predicates.
0591:             *
0592:             * RESOLVE: Once we start pushing join clauses, we will need to walk the
0593:             * ResultColumn/VirtualColumnNode chain for them to remap the references.
0594:             */
0595:            public void remapColumnReferences() {
0596:                ValueNode expression = source.getExpression();
0597:
0598:                if (SanityManager.DEBUG) {
0599:                    // SanityManager.ASSERT(origSource == null,
0600:                    // 		"Trying to remap ColumnReference twice without unremapping it.");
0601:                }
0602:
0603:                if (!((expression instanceof  VirtualColumnNode) || (expression instanceof  ColumnReference))) {
0604:                    return;
0605:                }
0606:
0607:                /* Scoped column references are a special case: they can be
0608:                 * remapped several times (once for every ProjectRestrictNode
0609:                 * through which the scoped ColumnReference is pushed before
0610:                 * reaching its target result set) and will be un-remapped
0611:                 * several times, as well (as the scoped predicate is "pulled"
0612:                 * back up the query tree to it's original location).  So we
0613:                 * have to keep track of the "orig" info for every remap
0614:                 * operation, not just for the most recent one.
0615:                 */
0616:                if (scoped && (origSource != null)) {
0617:                    if (remaps == null)
0618:                        remaps = new java.util.ArrayList();
0619:                    remaps.add(new RemapInfo(columnNumber, tableNumber,
0620:                            columnName, source));
0621:                } else {
0622:                    origSource = source;
0623:                    origName = columnName;
0624:                    origColumnNumber = columnNumber;
0625:                    origTableNumber = tableNumber;
0626:                }
0627:
0628:                /* Find the matching ResultColumn */
0629:                source = getSourceResultColumn();
0630:                columnName = source.getName();
0631:                columnNumber = source.getColumnPosition();
0632:
0633:                if (source.getExpression() instanceof  ColumnReference) {
0634:                    ColumnReference cr = (ColumnReference) source
0635:                            .getExpression();
0636:                    tableNumber = cr.getTableNumber();
0637:                    if (SanityManager.DEBUG) {
0638:                        // if dummy cr generated to replace aggregate, it may not have table number
0639:                        // because underneath can be more than 1 table.
0640:                        if (tableNumber == -1
0641:                                && !cr.getGeneratedToReplaceAggregate()) {
0642:                            SanityManager
0643:                                    .THROWASSERT("tableNumber not expected to be -1, origName = "
0644:                                            + origName);
0645:                        }
0646:                    }
0647:                }
0648:            }
0649:
0650:            public void unRemapColumnReferences() {
0651:                if (origSource == null)
0652:                    return;
0653:
0654:                if (SanityManager.DEBUG) {
0655:                    // SanityManager.ASSERT(origSource != null,
0656:                    // 	"Trying to unremap a ColumnReference that was not remapped.");
0657:                }
0658:
0659:                if ((remaps == null) || (remaps.size() == 0)) {
0660:                    source = origSource;
0661:                    origSource = null;
0662:                    columnName = origName;
0663:                    origName = null;
0664:                    tableNumber = origTableNumber;
0665:                    columnNumber = origColumnNumber;
0666:                } else {
0667:                    // This CR is multiply-remapped, so undo the most
0668:                    // recent (and only the most recent) remap operation.
0669:                    RemapInfo rI = (RemapInfo) remaps.remove(remaps.size() - 1);
0670:                    source = rI.getSource();
0671:                    columnName = rI.getColumnName();
0672:                    tableNumber = rI.getTableNumber();
0673:                    columnNumber = rI.getColumnNumber();
0674:                    rI = null;
0675:                    if (remaps.size() == 0)
0676:                        remaps = null;
0677:                }
0678:            }
0679:
0680:            /**
0681:             * Returns true if this ColumnReference has been remapped; false
0682:             * otherwise.
0683:             *
0684:             * @return Whether or not this ColumnReference has been remapped.
0685:             */
0686:            protected boolean hasBeenRemapped() {
0687:                return (origSource != null);
0688:            }
0689:
0690:            /*
0691:             * Get the ResultColumn that the source points to.  This is useful for
0692:             * getting what the source will be after this ColumnReference is remapped.
0693:             */
0694:            public ResultColumn getSourceResultColumn() {
0695:                ValueNode expression = source.getExpression();
0696:
0697:                /* Find the matching ResultColumn */
0698:                if (expression instanceof  VirtualColumnNode) {
0699:                    return ((VirtualColumnNode) expression)
0700:                            .getSourceResultColumn();
0701:                } else {
0702:                    /* RESOLVE - If expression is a ColumnReference, then we are hitting
0703:                     * the top of a query block (derived table or view.)
0704:                     * In order to be able to push the expression down into the next
0705:                     * query block, it looks like we should reset the contents of the
0706:                     * current ColumnReference to be the same as expression.  (This probably
0707:                     * only means names and tableNumber.)  We would then "rebind" the top
0708:                     * level predicate somewhere up the call stack and see if we could push
0709:                     * the predicate through.
0710:                     */
0711:                    return ((ColumnReference) expression)
0712:                            .getSourceResultColumn();
0713:                }
0714:            }
0715:
0716:            /**
0717:             * Remap all ColumnReferences in this tree to be clones of the
0718:             * underlying expression.
0719:             *
0720:             * @return ValueNode			The remapped expression tree.
0721:             *
0722:             * @exception StandardException			Thrown on error
0723:             */
0724:            public ValueNode remapColumnReferencesToExpressions()
0725:                    throws StandardException {
0726:                ResultColumn rc;
0727:                ResultColumn sourceRC = source;
0728:
0729:                /* Nothing to do if we are not pointing to a redundant RC */
0730:                if (!source.isRedundant()) {
0731:                    return this ;
0732:                }
0733:
0734:                /* Find the last redundant RC in the chain.  We
0735:                 * want to clone its expression.
0736:                 */
0737:                for (rc = source; rc != null && rc.isRedundant();) {
0738:                    ResultColumn nextRC = null;
0739:                    ValueNode expression = rc.getExpression();
0740:
0741:                    /* Find the matching ResultColumn */
0742:                    if (expression instanceof  VirtualColumnNode) {
0743:                        nextRC = ((VirtualColumnNode) expression)
0744:                                .getSourceResultColumn();
0745:                    } else if (expression instanceof  ColumnReference) {
0746:                        nextRC = ((ColumnReference) expression)
0747:                                .getSourceResultColumn();
0748:                    } else {
0749:                        nextRC = null;
0750:                    }
0751:
0752:                    if (nextRC != null && nextRC.isRedundant()) {
0753:                        sourceRC = nextRC;
0754:                    }
0755:                    rc = nextRC;
0756:                }
0757:
0758:                if (SanityManager.DEBUG) {
0759:                    if (sourceRC == null) {
0760:                        SanityManager
0761:                                .THROWASSERT("sourceRC is expected to be non-null for "
0762:                                        + columnName);
0763:                    }
0764:
0765:                    if (!sourceRC.isRedundant()) {
0766:                        SanityManager
0767:                                .THROWASSERT("sourceRC is expected to be redundant for "
0768:                                        + columnName);
0769:                    }
0770:                }
0771:
0772:                /* If last expression is a VCN, then we can't clone it.
0773:                 * Instead, we just reset our source to point to the
0774:                 * source of the VCN, those chopping out the layers.
0775:                 * Otherwise, we return a clone of the underlying expression.
0776:                 */
0777:                if (sourceRC.getExpression() instanceof  VirtualColumnNode) {
0778:                    VirtualColumnNode vcn = (VirtualColumnNode) (sourceRC
0779:                            .getExpression());
0780:                    ResultSetNode rsn = vcn.getSourceResultSet();
0781:                    if (rsn instanceof  FromTable) {
0782:                        tableNumber = ((FromTable) rsn).getTableNumber();
0783:                        if (SanityManager.DEBUG) {
0784:                            SanityManager.ASSERT(tableNumber != -1,
0785:                                    "tableNumber not expected to be -1");
0786:                        }
0787:                    } else {
0788:                        if (SanityManager.DEBUG) {
0789:                            SanityManager
0790:                                    .THROWASSERT("rsn expected to be a FromTable, but is a "
0791:                                            + rsn.getClass().getName());
0792:                        }
0793:                    }
0794:                    source = ((VirtualColumnNode) sourceRC.getExpression())
0795:                            .getSourceResultColumn();
0796:                    return this ;
0797:                } else {
0798:                    return sourceRC.getExpression().getClone();
0799:                }
0800:            }
0801:
0802:            /** 
0803:             * Update the table map to reflect the source
0804:             * of this CR.
0805:             *
0806:             * @param refs	The table map.
0807:             */
0808:            void getTablesReferenced(JBitSet refs) {
0809:                if (refs.size() < tableNumber)
0810:                    refs.grow(tableNumber);
0811:
0812:                if (tableNumber != -1) // it may not be set if replacesAggregate is true
0813:                    refs.set(tableNumber);
0814:            }
0815:
0816:            /**
0817:             * Return whether or not this expression tree is cloneable.
0818:             *
0819:             * @return boolean	Whether or not this expression tree is cloneable.
0820:             */
0821:            public boolean isCloneable() {
0822:                return true;
0823:            }
0824:
0825:            /** @see ValueNode#constantExpression */
0826:            public boolean constantExpression(PredicateList whereClause) {
0827:                return whereClause.constantColumn(this );
0828:            }
0829:
0830:            /**
0831:             * ColumnReference's are to the current row in the system.
0832:             * This lets us generate
0833:             * a faster get that simply returns the column from the
0834:             * current row, rather than getting the value out and
0835:             * returning that, only to have the caller (in the situations
0836:             * needed) stuffing it back into a new column holder object.
0837:             * We will assume the general generate() path is for getting
0838:             * the value out, and use generateColumn() when we want to
0839:             * keep the column wrapped.
0840:             *
0841:             * @exception StandardException		Thrown on error
0842:             */
0843:            public void generateExpression(ExpressionClassBuilder acb,
0844:                    MethodBuilder mb) throws StandardException {
0845:                int sourceResultSetNumber = source.getResultSetNumber();
0846:
0847:                //PUSHCOMPILE
0848:                /* Reuse generated code, where possible */
0849:
0850:                /*
0851:                 ** If the source is redundant, return the generation of its source.
0852:                 ** Most redundant nodes will be flattened out by this point, but
0853:                 ** in at least one case (elimination of redundant ProjectRestricts
0854:                 ** during generation) we don't do this.
0855:                 */
0856:                if (source.isRedundant()) {
0857:                    source.generateExpression(acb, mb);
0858:                    return;
0859:                }
0860:
0861:                if (SanityManager.DEBUG) {
0862:                    if (sourceResultSetNumber < 0) {
0863:                        SanityManager
0864:                                .THROWASSERT("sourceResultSetNumber expected to be >= 0 for "
0865:                                        + getTableName()
0866:                                        + "."
0867:                                        + getColumnName());
0868:                    }
0869:                }
0870:
0871:                /* The ColumnReference is from an immediately underlying ResultSet.
0872:                 * The Row for that ResultSet is Activation.row[sourceResultSetNumber], 
0873:                 * where sourceResultSetNumber is the resultSetNumber for that ResultSet.
0874:                 *
0875:                 * The generated java is the expression:
0876:                 *	(<interface>) this.row[sourceResultSetNumber].getColumn(#columnId);
0877:                 *
0878:                 * where <interface> is the appropriate Datatype protocol interface
0879:                 * for the type of the column.
0880:                 */
0881:                acb.pushColumnReference(mb, sourceResultSetNumber, source
0882:                        .getVirtualColumnId());
0883:
0884:                mb.cast(getTypeCompiler().interfaceName());
0885:
0886:                /* Remember generated code for possible resuse */
0887:            }
0888:
0889:            /**
0890:             * Get the user-supplied schema name of this column.  This will be null
0891:             * if the user did not supply a name (for example, select t.a from t).
0892:             * Another example for null return value (for example, select b.a from t as b).
0893:             * But for following query select app.t.a from t, this will return APP
0894:             * Code generation of aggregate functions relies on this method
0895:             *
0896:             * @return	The user-supplied schema name of this column.  Null if no user-
0897:             * 		supplied name.
0898:             */
0899:
0900:            public String getSchemaName() {
0901:                return ((tableName != null) ? tableName.getSchemaName() : null);
0902:            }
0903:
0904:            /**
0905:             * Return the variant type for the underlying expression.
0906:             * The variant type can be:
0907:             *		VARIANT				- variant within a scan
0908:             *							  (method calls and non-static field access)
0909:             *		SCAN_INVARIANT		- invariant within a scan
0910:             *							  (column references from outer tables)
0911:             *		QUERY_INVARIANT		- invariant within the life of a query
0912:             *							  (constant expressions)
0913:             *
0914:             * @return	The variant type for the underlying expression.
0915:             */
0916:            protected int getOrderableVariantType() {
0917:                // ColumnReferences are invariant for the life of the scan
0918:                return Qualifier.SCAN_INVARIANT;
0919:            }
0920:
0921:            /**
0922:             * Return whether or not the source of this ColumnReference is itself a ColumnReference.
0923:             *
0924:             * @return Whether or not the source of this ColumnReference is itself a ColumnReference.
0925:             */
0926:            boolean pointsToColumnReference() {
0927:                return (source.getExpression() instanceof  ColumnReference);
0928:            }
0929:
0930:            /**
0931:             * Get the DataTypeServices from this Node.
0932:             *
0933:             * @return	The DataTypeServices from this Node.  This
0934:             *		may be null if the node isn't bound yet.
0935:             */
0936:            public DataTypeDescriptor getTypeServices()
0937:                    throws StandardException {
0938:                DataTypeDescriptor dtd = super .getTypeServices();
0939:                if (dtd == null && source != null) {
0940:                    dtd = source.getTypeServices();
0941:                    if (dtd != null)
0942:                        setType(dtd);
0943:                }
0944:                return dtd;
0945:            } // end of getTypeServices
0946:
0947:            /**
0948:             * Find the source result set for this ColumnReference and
0949:             * return it.  Also, when the source result set is found,
0950:             * return the position (within the source result set's RCL)
0951:             * of the column referenced by this ColumnReference.  The
0952:             * position is returned vai the colNum parameter.
0953:             *
0954:             * @param colNum Place to store the position of the column
0955:             *  to which this ColumnReference points (position is w.r.t
0956:             *  the source result set).
0957:             * @return The source result set for this ColumnReference;
0958:             *  null if there is no source result set.
0959:             */
0960:            protected ResultSetNode getSourceResultSet(int[] colNum)
0961:                    throws StandardException {
0962:                if (source == null) {
0963:                    /* this can happen if column reference is pointing to a column
0964:                     * that is not from a base table.  For example, if we have a
0965:                     * VALUES clause like
0966:                     *
0967:                     *    (values (1, 2), (3, 4)) V1 (i, j)
0968:                     *
0969:                     * and then a column reference to VI.i, the column reference
0970:                     * won't have a source.
0971:                     */
0972:                    return null;
0973:                }
0974:
0975:                ValueNode rcExpr = null;
0976:                ResultColumn rc = getSource();
0977:
0978:                // Walk the ResultColumn->ColumnReference chain until we
0979:                // find a ResultColumn whose expression is a VirtualColumnNode.
0980:
0981:                rcExpr = rc.getExpression();
0982:                colNum[0] = getColumnNumber();
0983:
0984:                /* We have to make sure we enter this loop if rc is redundant,
0985:                 * so that we can navigate down to the actual source result
0986:                 * set (DERBY-1777). If rc *is* redundant, then rcExpr is not
0987:                 * guaranteed to be a ColumnReference, so we have to check
0988:                 * for that case inside the loop.
0989:                 */
0990:                while ((rcExpr != null)
0991:                        && (rc.isRedundant() || (rcExpr instanceof  ColumnReference))) {
0992:                    if (rcExpr instanceof  ColumnReference) {
0993:                        colNum[0] = ((ColumnReference) rcExpr)
0994:                                .getColumnNumber();
0995:                        rc = ((ColumnReference) rcExpr).getSource();
0996:                    }
0997:
0998:                    /* If "rc" is redundant then that means it points to another
0999:                     * ResultColumn that in turn points to the source expression.
1000:                     * This can happen in cases where "rc" points to a subquery
1001:                     * that has been flattened into the query above it (flattening
1002:                     * of subqueries occurs during preprocessing).  In that case
1003:                     * we want to skip over the redundant rc and find the
1004:                     * ResultColumn that actually holds the source expression.
1005:                     */
1006:                    while (rc.isRedundant()) {
1007:                        rcExpr = rc.getExpression();
1008:                        if (rcExpr instanceof  VirtualColumnNode)
1009:                            rc = ((VirtualColumnNode) rcExpr)
1010:                                    .getSourceResultColumn();
1011:                        else if (rcExpr instanceof  ColumnReference) {
1012:                            colNum[0] = ((ColumnReference) rcExpr)
1013:                                    .getColumnNumber();
1014:                            rc = ((ColumnReference) rcExpr).getSource();
1015:                        } else {
1016:                            /* If rc isn't pointing to a VirtualColumnNode nor
1017:                             * to a ColumnReference, then it's not pointing to
1018:                             * a result set.  It could, for example, be pointing
1019:                             * to a constant node or to the result of an aggregate
1020:                             * or function.  Break out of both loops and return
1021:                             * null since there is no source result set.
1022:                             */
1023:                            rcExpr = null;
1024:                            break;
1025:                        }
1026:                    }
1027:                    rcExpr = rc.getExpression();
1028:                }
1029:
1030:                // If we found a VirtualColumnNode, return the VirtualColumnNode's
1031:                // sourceResultSet.  The column within that sourceResultSet that
1032:                // is referenced by this ColumnReference is also returned, via
1033:                // the colNum parameter, and was set above.
1034:                if ((rcExpr != null) && (rcExpr instanceof  VirtualColumnNode))
1035:                    return ((VirtualColumnNode) rcExpr).getSourceResultSet();
1036:
1037:                // If we get here then the ColumnReference doesn't reference
1038:                // a result set, so return null.
1039:                colNum[0] = -1;
1040:                return null;
1041:            }
1042:
1043:            protected boolean isEquivalent(ValueNode o)
1044:                    throws StandardException {
1045:                if (!isSameNodeType(o)) {
1046:                    return false;
1047:                }
1048:                ColumnReference other = (ColumnReference) o;
1049:                return (tableNumber == other.tableNumber && columnName
1050:                        .equals(other.getColumnName()));
1051:            }
1052:
1053:            /**
1054:             * Mark this column reference as "scoped", which means that it
1055:             * was created (as a clone of another ColumnReference) to serve
1056:             * as the left or right operand of a scoped predicate.
1057:             */
1058:            protected void markAsScoped() {
1059:                scoped = true;
1060:            }
1061:
1062:            /**
1063:             * Return whether or not this ColumnReference is scoped.
1064:             */
1065:            protected boolean isScoped() {
1066:                return scoped;
1067:            }
1068:
1069:            /**
1070:             * Helper class to keep track of remap data when a ColumnReference
1071:             * is remapped multiple times.  This allows the CR to be UN-
1072:             * remapped multiple times, as well.
1073:             */
1074:            private class RemapInfo {
1075:                int colNum;
1076:                int tableNum;
1077:                String colName;
1078:                ResultColumn source;
1079:
1080:                RemapInfo(int cNum, int tNum, String cName, ResultColumn rc) {
1081:                    colNum = cNum;
1082:                    tableNum = tNum;
1083:                    colName = cName;
1084:                    source = rc;
1085:                }
1086:
1087:                int getColumnNumber() {
1088:                    return colNum;
1089:                }
1090:
1091:                int getTableNumber() {
1092:                    return tableNum;
1093:                }
1094:
1095:                String getColumnName() {
1096:                    return colName;
1097:                }
1098:
1099:                ResultColumn getSource() {
1100:                    return source;
1101:                }
1102:
1103:                void setColNumber(int cNum) {
1104:                    colNum = cNum;
1105:                }
1106:
1107:                void setTableNumber(int tNum) {
1108:                    tableNum = tNum;
1109:                }
1110:
1111:                void setColName(String cName) {
1112:                    colName = cName;
1113:                }
1114:
1115:                void setSource(ResultColumn rc) {
1116:                    source = rc;
1117:                }
1118:            }
1119:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.