Source Code Cross Referenced for BinaryRelationalOperatorNode.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.BinaryRelationalOperatorNode
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.reference.ClassName;
0025:        import org.apache.derby.iapi.reference.JDBC30Translation;
0026:
0027:        import org.apache.derby.iapi.util.JBitSet;
0028:
0029:        import org.apache.derby.iapi.services.loader.GeneratedMethod;
0030:
0031:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
0032:
0033:        import org.apache.derby.iapi.services.sanity.SanityManager;
0034:
0035:        import org.apache.derby.iapi.error.StandardException;
0036:
0037:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
0038:        import org.apache.derby.iapi.sql.compile.Optimizable;
0039:
0040:        import org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor;
0041:
0042:        import org.apache.derby.iapi.store.access.Qualifier;
0043:        import org.apache.derby.iapi.store.access.ScanController;
0044:
0045:        import org.apache.derby.iapi.types.DataValueDescriptor;
0046:        import org.apache.derby.iapi.types.TypeId;
0047:        import org.apache.derby.iapi.types.DataValueDescriptor;
0048:
0049:        import org.apache.derby.iapi.types.Orderable;
0050:
0051:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
0052:
0053:        import java.sql.Types;
0054:
0055:        /**
0056:         * This class represents the 6 binary operators: LessThan, LessThanEquals,
0057:         * Equals, NotEquals, GreaterThan and GreaterThanEquals.
0058:         *
0059:         * @author Manish Khettry
0060:         */
0061:
0062:        public class BinaryRelationalOperatorNode extends
0063:                BinaryComparisonOperatorNode implements  RelationalOperator {
0064:            private int operatorType;
0065:            /* RelationalOperator Interface */
0066:
0067:            // Visitor for finding base tables beneath optimizables and column
0068:            // references.  Created once and re-used thereafter.
0069:            private BaseTableNumbersVisitor btnVis;
0070:
0071:            // Bit sets for holding base tables beneath optimizables and
0072:            // column references.  Created once and re-used thereafter.
0073:            JBitSet optBaseTables;
0074:            JBitSet valNodeBaseTables;
0075:
0076:            public void init(Object leftOperand, Object rightOperand) {
0077:                String methodName = "";
0078:                String operatorName = "";
0079:
0080:                switch (getNodeType()) {
0081:                case C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE:
0082:                    methodName = "equals";
0083:                    operatorName = "=";
0084:                    operatorType = RelationalOperator.EQUALS_RELOP;
0085:                    break;
0086:
0087:                case C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE:
0088:                    methodName = "greaterOrEquals";
0089:                    operatorName = ">=";
0090:                    operatorType = RelationalOperator.GREATER_EQUALS_RELOP;
0091:                    break;
0092:
0093:                case C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE:
0094:                    methodName = "greaterThan";
0095:                    operatorName = ">";
0096:                    operatorType = RelationalOperator.GREATER_THAN_RELOP;
0097:                    break;
0098:
0099:                case C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE:
0100:                    methodName = "lessOrEquals";
0101:                    operatorName = "<=";
0102:                    operatorType = RelationalOperator.LESS_EQUALS_RELOP;
0103:                    break;
0104:
0105:                case C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE:
0106:                    methodName = "lessThan";
0107:                    operatorName = "<";
0108:                    operatorType = RelationalOperator.LESS_THAN_RELOP;
0109:                    break;
0110:                case C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE:
0111:                    methodName = "notEquals";
0112:                    operatorName = "<>";
0113:                    operatorType = RelationalOperator.NOT_EQUALS_RELOP;
0114:                    break;
0115:
0116:                default:
0117:                    if (SanityManager.DEBUG) {
0118:                        SanityManager
0119:                                .THROWASSERT("init for BinaryRelationalOperator called with wrong nodeType = "
0120:                                        + getNodeType());
0121:                    }
0122:                    break;
0123:                }
0124:                super .init(leftOperand, rightOperand, operatorName, methodName);
0125:                btnVis = null;
0126:            }
0127:
0128:            /** @see RelationalOperator#getColumnOperand */
0129:            public ColumnReference getColumnOperand(Optimizable optTable,
0130:                    int columnPosition) {
0131:                FromTable ft = (FromTable) optTable;
0132:
0133:                // When searching for a matching column operand, we search
0134:                // the entire subtree (if there is one) beneath optTable
0135:                // to see if we can find any FromTables that correspond to
0136:                // either of this op's column references.
0137:
0138:                ColumnReference cr;
0139:                boolean walkSubtree = true;
0140:                if (leftOperand instanceof  ColumnReference) {
0141:                    /*
0142:                     ** The left operand is a column reference.
0143:                     ** Is it the correct column?
0144:                     */
0145:                    cr = (ColumnReference) leftOperand;
0146:                    if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) {
0147:                        /*
0148:                         ** The table is correct, how about the column position?
0149:                         */
0150:                        if (cr.getSource().getColumnPosition() == columnPosition) {
0151:                            /* We've found the correct column - return it */
0152:                            return cr;
0153:                        }
0154:                    }
0155:                    walkSubtree = false;
0156:                }
0157:
0158:                if (rightOperand instanceof  ColumnReference) {
0159:                    /*
0160:                     ** The right operand is a column reference.
0161:                     ** Is it the correct column?
0162:                     */
0163:                    cr = (ColumnReference) rightOperand;
0164:                    if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) {
0165:                        /*
0166:                         ** The table is correct, how about the column position?
0167:                         */
0168:                        if (cr.getSource().getColumnPosition() == columnPosition) {
0169:                            /* We've found the correct column - return it */
0170:                            return cr;
0171:                        }
0172:                    }
0173:                }
0174:
0175:                /* Neither side is the column we're looking for */
0176:                return null;
0177:            }
0178:
0179:            /** @see RelationalOperator#getColumnOperand */
0180:            public ColumnReference getColumnOperand(Optimizable optTable) {
0181:                ColumnReference cr;
0182:
0183:                boolean walkSubtree = true;
0184:                if (leftOperand instanceof  ColumnReference) {
0185:                    /*
0186:                     ** The left operand is a column reference.
0187:                     ** Is it the correct column?
0188:                     */
0189:                    cr = (ColumnReference) leftOperand;
0190:                    if (valNodeReferencesOptTable(cr, (FromTable) optTable,
0191:                            false, walkSubtree)) {
0192:                        /*
0193:                         ** The table is correct.
0194:                         */
0195:                        return cr;
0196:                    }
0197:                    walkSubtree = false;
0198:                }
0199:
0200:                if (rightOperand instanceof  ColumnReference) {
0201:                    /*
0202:                     ** The right operand is a column reference.
0203:                     ** Is it the correct column?
0204:                     */
0205:                    cr = (ColumnReference) rightOperand;
0206:                    if (valNodeReferencesOptTable(cr, (FromTable) optTable,
0207:                            false, walkSubtree)) {
0208:                        /*
0209:                         ** The table is correct
0210:                         */
0211:                        return cr;
0212:                    }
0213:                }
0214:
0215:                /* Neither side is the column we're looking for */
0216:                return null;
0217:            }
0218:
0219:            /**
0220:             * @see RelationalOperator#getExpressionOperand
0221:             */
0222:            public ValueNode getExpressionOperand(int tableNumber,
0223:                    int columnPosition, FromTable ft) {
0224:                ColumnReference cr;
0225:                boolean walkSubtree = true;
0226:
0227:                if (leftOperand instanceof  ColumnReference) {
0228:                    /*
0229:                     ** The left operand is a column reference.
0230:                     ** Is it the correct column?
0231:                     */
0232:                    cr = (ColumnReference) leftOperand;
0233:                    if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) {
0234:                        /*
0235:                         ** The table is correct, how about the column position?
0236:                         */
0237:                        if (cr.getSource().getColumnPosition() == columnPosition) {
0238:                            /*
0239:                             ** We've found the correct column -
0240:                             ** return the other side
0241:                             */
0242:                            return rightOperand;
0243:                        }
0244:                    }
0245:                    walkSubtree = false;
0246:                }
0247:
0248:                if (rightOperand instanceof  ColumnReference) {
0249:                    /*
0250:                     ** The right operand is a column reference.
0251:                     ** Is it the correct column?
0252:                     */
0253:                    cr = (ColumnReference) rightOperand;
0254:                    if (valNodeReferencesOptTable(cr, ft, false, walkSubtree)) {
0255:                        /*
0256:                         ** The table is correct, how about the column position?
0257:                         */
0258:                        if (cr.getSource().getColumnPosition() == columnPosition) {
0259:                            /*
0260:                             ** We've found the correct column -
0261:                             ** return the other side
0262:                             */
0263:                            return leftOperand;
0264:                        }
0265:                    }
0266:                }
0267:
0268:                return null;
0269:            }
0270:
0271:            /**
0272:             * @see RelationalOperator#getOperand
0273:             */
0274:            public ValueNode getOperand(ColumnReference cRef, int refSetSize,
0275:                    boolean otherSide) {
0276:                // Following call will initialize/reset the btnVis,
0277:                // valNodeBaseTables, and optBaseTables fields of this object.
0278:                initBaseTableVisitor(refSetSize, true);
0279:
0280:                // We search for the column reference by getting the *base*
0281:                // table number for each operand and checking to see if
0282:                // that matches the *base* table number for the cRef
0283:                // that we're looking for.  If so, then we the two
0284:                // reference the same table so we go on to check
0285:                // column position.
0286:                try {
0287:
0288:                    // Use optBaseTables for cRef's base table numbers.
0289:                    btnVis.setTableMap(optBaseTables);
0290:                    cRef.accept(btnVis);
0291:
0292:                    // Use valNodeBaseTables for operand base table nums.
0293:                    btnVis.setTableMap(valNodeBaseTables);
0294:
0295:                    ColumnReference cr;
0296:                    if (leftOperand instanceof  ColumnReference) {
0297:                        /*
0298:                         ** The left operand is a column reference.
0299:                         ** Is it the correct column?
0300:                         */
0301:                        cr = (ColumnReference) leftOperand;
0302:                        cr.accept(btnVis);
0303:                        valNodeBaseTables.and(optBaseTables);
0304:                        if (valNodeBaseTables.getFirstSetBit() != -1) {
0305:                            /*
0306:                             ** The table is correct, how about the column position?
0307:                             */
0308:                            if (cr.getSource().getColumnPosition() == cRef
0309:                                    .getColumnNumber()) {
0310:                                /*
0311:                                 ** We've found the correct column -
0312:                                 ** return the appropriate side.
0313:                                 */
0314:                                if (otherSide)
0315:                                    return rightOperand;
0316:                                return leftOperand;
0317:                            }
0318:                        }
0319:                    }
0320:
0321:                    if (rightOperand instanceof  ColumnReference) {
0322:                        /*
0323:                         ** The right operand is a column reference.
0324:                         ** Is it the correct column?
0325:                         */
0326:                        valNodeBaseTables.clearAll();
0327:                        cr = (ColumnReference) rightOperand;
0328:                        cr.accept(btnVis);
0329:                        valNodeBaseTables.and(optBaseTables);
0330:                        if (valNodeBaseTables.getFirstSetBit() != -1) {
0331:                            /*
0332:                             ** The table is correct, how about the column position?
0333:                             */
0334:                            if (cr.getSource().getColumnPosition() == cRef
0335:                                    .getColumnNumber()) {
0336:                                /*
0337:                                 ** We've found the correct column -
0338:                                 ** return the appropriate side
0339:                                 */
0340:                                if (otherSide)
0341:                                    return leftOperand;
0342:                                return rightOperand;
0343:                            }
0344:                        }
0345:                    }
0346:
0347:                } catch (StandardException se) {
0348:                    if (SanityManager.DEBUG) {
0349:                        SanityManager
0350:                                .THROWASSERT("Failed when trying to "
0351:                                        + "find base table number for column reference check:\n"
0352:                                        + se.getMessage());
0353:                    }
0354:                }
0355:
0356:                return null;
0357:            }
0358:
0359:            /**
0360:             * @see RelationalOperator#generateExpressionOperand
0361:             *
0362:             * @exception StandardException		Thrown on error
0363:             */
0364:            public void generateExpressionOperand(Optimizable optTable,
0365:                    int columnPosition, ExpressionClassBuilder acb,
0366:                    MethodBuilder mb) throws StandardException {
0367:                ColumnReference cr;
0368:                FromBaseTable ft;
0369:
0370:                if (SanityManager.DEBUG) {
0371:                    SanityManager.ASSERT(optTable instanceof  FromBaseTable);
0372:                }
0373:                ft = (FromBaseTable) optTable;
0374:
0375:                ValueNode exprOp = getExpressionOperand(ft.getTableNumber(),
0376:                        columnPosition, ft);
0377:
0378:                if (SanityManager.DEBUG) {
0379:                    if (exprOp == null) {
0380:                        SanityManager
0381:                                .THROWASSERT("ColumnReference for correct column (columnPosition = "
0382:                                        + columnPosition
0383:                                        + ", exposed table name = "
0384:                                        + ft.getExposedName()
0385:                                        + ") not found on either side of BinaryRelationalOperator");
0386:                    }
0387:                }
0388:
0389:                exprOp.generateExpression(acb, mb);
0390:            }
0391:
0392:            /** @see RelationalOperator#selfComparison 
0393:             *
0394:             * @exception StandardException		Thrown on error
0395:             */
0396:            public boolean selfComparison(ColumnReference cr)
0397:                    throws StandardException {
0398:                ValueNode otherSide;
0399:                JBitSet tablesReferenced;
0400:
0401:                /*
0402:                 ** Figure out which side the given ColumnReference is on,
0403:                 ** and look for the same table on the other side.
0404:                 */
0405:                if (leftOperand == cr) {
0406:                    otherSide = rightOperand;
0407:                } else if (rightOperand == cr) {
0408:                    otherSide = leftOperand;
0409:                } else {
0410:                    otherSide = null;
0411:                    if (SanityManager.DEBUG) {
0412:                        SanityManager
0413:                                .THROWASSERT("ColumnReference not found on either side of binary comparison.");
0414:                    }
0415:                }
0416:
0417:                tablesReferenced = otherSide.getTablesReferenced();
0418:
0419:                /* Return true if the table we're looking for is in the bit map */
0420:                return tablesReferenced.get(cr.getTableNumber());
0421:            }
0422:
0423:            /** @see RelationalOperator#usefulStartKey */
0424:            public boolean usefulStartKey(Optimizable optTable) {
0425:                /*
0426:                 ** Determine whether this operator is a useful start operator
0427:                 ** with knowledge of whether the key column is on the left or right.
0428:                 */
0429:                int columnSide = columnOnOneSide(optTable);
0430:
0431:                if (columnSide == NEITHER)
0432:                    return false;
0433:                else
0434:                    return usefulStartKey(columnSide == LEFT);
0435:            }
0436:
0437:            /**
0438:             * Return true if a key column for the given table is found on the
0439:             * left side of this operator, false if it is found on the right
0440:             * side of this operator.
0441:             *
0442:             * NOTE: This method assumes that a key column will be found on one
0443:             * side or the other.  If you don't know whether a key column exists,
0444:             * use the columnOnOneSide() method (below).
0445:             *
0446:             * @param optTable	The Optimizable table that we're looking for a key
0447:             *					column on.
0448:             *
0449:             * @return true if a key column for the given table is on the left
0450:             *			side of this operator, false if one is found on the right
0451:             *			side of this operator.
0452:             */
0453:            protected boolean keyColumnOnLeft(Optimizable optTable) {
0454:                ColumnReference cr;
0455:                boolean left = false;
0456:
0457:                /* Is the key column on the left or the right? */
0458:                if (leftOperand instanceof  ColumnReference) {
0459:                    /*
0460:                     ** The left operand is a column reference.
0461:                     ** Is it the correct column?
0462:                     */
0463:                    cr = (ColumnReference) leftOperand;
0464:                    if (valNodeReferencesOptTable(cr, (FromTable) optTable,
0465:                            false, true)) {
0466:                        /* The left operand is the key column */
0467:                        left = true;
0468:                    }
0469:                }
0470:
0471:                // Else the right operand must be the key column.
0472:                if (SanityManager.DEBUG) {
0473:                    if (!left) {
0474:                        SanityManager.ASSERT(
0475:                                (rightOperand instanceof  ColumnReference)
0476:                                        && valNodeReferencesOptTable(
0477:                                                (ColumnReference) rightOperand,
0478:                                                (FromTable) optTable, false,
0479:                                                true),
0480:                                "Key column not found on either side.");
0481:                    }
0482:                }
0483:
0484:                return left;
0485:            }
0486:
0487:            /* Return values for columnOnOneSide */
0488:            protected static final int LEFT = -1;
0489:            protected static final int NEITHER = 0;
0490:            protected static final int RIGHT = 1;
0491:
0492:            /**
0493:             * Determine whether there is a column from the given table on one side
0494:             * of this operator, and if so, which side is it on?
0495:             *
0496:             * @param optTable	The Optimizable table that we're looking for a key
0497:             *					column on.
0498:             *
0499:             * @return	LEFT if there is a column on the left, RIGHT if there is
0500:             *			a column on the right, NEITHER if no column found on either
0501:             *			side.
0502:             */
0503:            protected int columnOnOneSide(Optimizable optTable) {
0504:                ColumnReference cr;
0505:                boolean left = false;
0506:                boolean walkSubtree = true;
0507:
0508:                /* Is a column on the left */
0509:                if (leftOperand instanceof  ColumnReference) {
0510:                    /*
0511:                     ** The left operand is a column reference.
0512:                     ** Is it the correct column?
0513:                     */
0514:                    cr = (ColumnReference) leftOperand;
0515:                    if (valNodeReferencesOptTable(cr, (FromTable) optTable,
0516:                            false, walkSubtree)) {
0517:                        /* Key column found on left */
0518:                        return LEFT;
0519:                    }
0520:                    walkSubtree = false;
0521:                }
0522:
0523:                if (rightOperand instanceof  ColumnReference) {
0524:                    /*
0525:                     ** The right operand is a column reference.
0526:                     ** Is it the correct column?
0527:                     */
0528:                    cr = (ColumnReference) rightOperand;
0529:                    if (valNodeReferencesOptTable(cr, (FromTable) optTable,
0530:                            false, walkSubtree)) {
0531:                        /* Key column found on right */
0532:                        return RIGHT;
0533:                    }
0534:                }
0535:
0536:                return NEITHER;
0537:            }
0538:
0539:            /** @see RelationalOperator#usefulStopKey */
0540:            public boolean usefulStopKey(Optimizable optTable) {
0541:                /*
0542:                 ** Determine whether this operator is a useful start operator
0543:                 ** with knowledge of whether the key column is on the left or right.
0544:                 */
0545:                int columnSide = columnOnOneSide(optTable);
0546:
0547:                if (columnSide == NEITHER)
0548:                    return false;
0549:                else
0550:                    return usefulStopKey(columnSide == LEFT);
0551:            }
0552:
0553:            /**
0554:             * Determine whether this comparison operator is a useful stop key
0555:             * with knowledge of whether the key column is on the left or right.
0556:             *
0557:             * @param left	true means the key column is on the left, false means
0558:             *				it is on the right.
0559:             *
0560:             * @return	true if this is a useful stop key
0561:             */
0562:            /** @see RelationalOperator#generateAbsoluteColumnId */
0563:            public void generateAbsoluteColumnId(MethodBuilder mb,
0564:                    Optimizable optTable) {
0565:                // Get the absolute column position for the column
0566:                int columnPosition = getAbsoluteColumnPosition(optTable);
0567:
0568:                mb.push(columnPosition);
0569:            }
0570:
0571:            /** @see RelationalOperator#generateRelativeColumnId */
0572:            public void generateRelativeColumnId(MethodBuilder mb,
0573:                    Optimizable optTable) {
0574:                // Get the absolute column position for the column
0575:                int columnPosition = getAbsoluteColumnPosition(optTable);
0576:                // Convert the absolute to the relative 0-based column position
0577:                columnPosition = optTable
0578:                        .convertAbsoluteToRelativeColumnPosition(columnPosition);
0579:
0580:                mb.push(columnPosition);
0581:            }
0582:
0583:            /**
0584:             * Get the absolute 0-based column position of the ColumnReference from 
0585:             * the conglomerate for this Optimizable.
0586:             *
0587:             * @param optTable	The Optimizable
0588:             *
0589:             * @return The absolute 0-based column position of the ColumnReference
0590:             */
0591:            private int getAbsoluteColumnPosition(Optimizable optTable) {
0592:                ColumnReference cr;
0593:                ConglomerateDescriptor bestCD;
0594:                int columnPosition;
0595:
0596:                if (keyColumnOnLeft(optTable)) {
0597:                    cr = (ColumnReference) leftOperand;
0598:                } else {
0599:                    cr = (ColumnReference) rightOperand;
0600:                }
0601:
0602:                bestCD = optTable.getTrulyTheBestAccessPath()
0603:                        .getConglomerateDescriptor();
0604:
0605:                /*
0606:                 ** Column positions are one-based, store is zero-based.
0607:                 */
0608:                columnPosition = cr.getSource().getColumnPosition();
0609:
0610:                /*
0611:                 ** If it's an index, find the base column position in the index
0612:                 ** and translate it to an index column position.
0613:                 */
0614:                if (bestCD != null && bestCD.isIndex()) {
0615:                    columnPosition = bestCD.getIndexDescriptor()
0616:                            .getKeyColumnPosition(columnPosition);
0617:
0618:                    if (SanityManager.DEBUG) {
0619:                        SanityManager.ASSERT(columnPosition > 0,
0620:                                "Base column not found in index");
0621:                    }
0622:                }
0623:
0624:                // return the 0-based column position
0625:                return columnPosition - 1;
0626:            }
0627:
0628:            /**
0629:             * @exception StandardException		Thrown on error
0630:             */
0631:            public void generateQualMethod(ExpressionClassBuilder acb,
0632:                    MethodBuilder mb, Optimizable optTable)
0633:                    throws StandardException {
0634:                /* Generate a method that returns the expression */
0635:                MethodBuilder qualMethod = acb.newUserExprFun();
0636:
0637:                /*
0638:                 ** Generate the expression that's on the opposite side
0639:                 ** of the key column
0640:                 */
0641:                if (keyColumnOnLeft(optTable)) {
0642:                    rightOperand.generateExpression(acb, qualMethod);
0643:                } else {
0644:                    leftOperand.generateExpression(acb, qualMethod);
0645:                }
0646:
0647:                qualMethod.methodReturn();
0648:                qualMethod.complete();
0649:
0650:                /* push an expression that evaluates to the GeneratedMethod */
0651:                acb.pushMethodReference(mb, qualMethod);
0652:            }
0653:
0654:            /** @see RelationalOperator#generateOrderedNulls */
0655:            public void generateOrderedNulls(MethodBuilder mb) {
0656:                mb.push(false);
0657:            }
0658:
0659:            /** @see RelationalOperator#orderedNulls */
0660:            public boolean orderedNulls() {
0661:                return false;
0662:            }
0663:
0664:            /** @see RelationalOperator#isQualifier 
0665:             *
0666:             * @exception StandardException		Thrown on error
0667:             */
0668:            public boolean isQualifier(Optimizable optTable, boolean forPush)
0669:                    throws StandardException {
0670:                FromTable ft;
0671:                ValueNode otherSide = null;
0672:                JBitSet tablesReferenced;
0673:                ColumnReference cr = null;
0674:                boolean found = false;
0675:                boolean walkSubtree = true;
0676:
0677:                ft = (FromTable) optTable;
0678:
0679:                if (leftOperand instanceof  ColumnReference) {
0680:                    /*
0681:                     ** The left operand is a column reference.
0682:                     ** Is it the correct column?
0683:                     */
0684:                    cr = (ColumnReference) leftOperand;
0685:                    if (valNodeReferencesOptTable(cr, ft, forPush, walkSubtree)) {
0686:                        otherSide = rightOperand;
0687:                        found = true;
0688:                    }
0689:                    walkSubtree = false;
0690:                }
0691:
0692:                if ((!found) && (rightOperand instanceof  ColumnReference)) {
0693:                    /*
0694:                     ** The right operand is a column reference.
0695:                     ** Is it the correct column?
0696:                     */
0697:                    cr = (ColumnReference) rightOperand;
0698:                    if (valNodeReferencesOptTable(cr, ft, forPush, walkSubtree)) {
0699:                        otherSide = leftOperand;
0700:                        found = true;
0701:                    }
0702:                }
0703:
0704:                /* Have we found a ColumnReference on either side? */
0705:                if (!found) {
0706:                    /*
0707:                     ** Neither side is a ColumnReference to the table we're looking
0708:                     ** for, so it can't be a Qualifier
0709:                     */
0710:                    return false;
0711:                }
0712:
0713:                /*
0714:                 ** One side is a ColumnReference to the correct table.  It is a
0715:                 ** Qualifier if the other side does not refer to the table we are
0716:                 ** optimizing.
0717:                 */
0718:                return !valNodeReferencesOptTable(otherSide, ft, forPush, true);
0719:            }
0720:
0721:            /** 
0722:             * @see RelationalOperator#getOrderableVariantType 
0723:             *
0724:             * @exception StandardException	thrown on error
0725:             */
0726:            public int getOrderableVariantType(Optimizable optTable)
0727:                    throws StandardException {
0728:                /* The Qualifier's orderable is on the opposite side from
0729:                 * the key column.
0730:                 */
0731:                if (keyColumnOnLeft(optTable)) {
0732:                    return rightOperand.getOrderableVariantType();
0733:                } else {
0734:                    return leftOperand.getOrderableVariantType();
0735:                }
0736:            }
0737:
0738:            /** @see RelationalOperator#compareWithKnownConstant */
0739:            public boolean compareWithKnownConstant(Optimizable optTable,
0740:                    boolean considerParameters) {
0741:                ValueNode node = null;
0742:                node = keyColumnOnLeft(optTable) ? rightOperand : leftOperand;
0743:
0744:                if (considerParameters) {
0745:                    return (node instanceof  ConstantNode)
0746:                            || ((node.requiresTypeFromContext()) && (((ParameterNode) node)
0747:                                    .getDefaultValue() != null));
0748:                } else {
0749:                    return node instanceof  ConstantNode;
0750:                }
0751:            }
0752:
0753:            /**
0754:             * @see RelationalOperator#getCompareValue
0755:             *
0756:             * @exception StandardException		Thrown on error
0757:             */
0758:            public DataValueDescriptor getCompareValue(Optimizable optTable)
0759:                    throws StandardException {
0760:                ValueNode node = null;
0761:
0762:                /* The value being compared to is on the opposite side from
0763:                 ** the key column.
0764:                 */
0765:                node = keyColumnOnLeft(optTable) ? rightOperand : leftOperand;
0766:
0767:                if (node instanceof  ConstantNode) {
0768:                    return ((ConstantNode) node).getValue();
0769:                } else if (node.requiresTypeFromContext()) {
0770:                    ParameterNode pn;
0771:                    if (node instanceof  UnaryOperatorNode)
0772:                        pn = ((UnaryOperatorNode) node).getParameterOperand();
0773:                    else
0774:                        pn = (ParameterNode) (node);
0775:                    return pn.getDefaultValue();
0776:                } else {
0777:                    return null;
0778:                }
0779:            }
0780:
0781:            /**
0782:             * Return 50% if this is a comparison with a boolean column, a negative
0783:             * selectivity otherwise.
0784:             */
0785:            protected double booleanSelectivity(Optimizable optTable)
0786:                    throws StandardException {
0787:                TypeId typeId = null;
0788:                double retval = -1.0d;
0789:                int columnSide;
0790:
0791:                columnSide = columnOnOneSide(optTable);
0792:
0793:                if (columnSide == LEFT)
0794:                    typeId = leftOperand.getTypeId();
0795:                else if (columnSide == RIGHT)
0796:                    typeId = rightOperand.getTypeId();
0797:
0798:                if (typeId != null
0799:                        && (typeId.getJDBCTypeId() == Types.BIT || typeId
0800:                                .getJDBCTypeId() == JDBC30Translation.SQL_TYPES_BOOLEAN))
0801:                    retval = 0.5d;
0802:
0803:                return retval;
0804:            }
0805:
0806:            /**
0807:             * The methods generated for this node all are on Orderable.  
0808:             * Overrides this method
0809:             * in BooleanOperatorNode for code generation purposes.
0810:             */
0811:            public String getReceiverInterfaceName() {
0812:                return ClassName.DataValueDescriptor;
0813:            }
0814:
0815:            /**
0816:             * Returns the negation of this operator; negation of Equals is NotEquals.
0817:             */
0818:            BinaryOperatorNode getNegation(ValueNode leftOperand,
0819:                    ValueNode rightOperand) throws StandardException {
0820:                BinaryOperatorNode negation;
0821:                if (SanityManager.DEBUG)
0822:                    SanityManager.ASSERT(dataTypeServices != null,
0823:                            "dataTypeServices is expected to be non-null");
0824:                /* xxxRESOLVE: look into doing this in place instead of allocating a new node */
0825:                negation = (BinaryOperatorNode) getNodeFactory().getNode(
0826:                        getNegationNode(), leftOperand, rightOperand,
0827:                        getContextManager());
0828:                negation.setType(dataTypeServices);
0829:                return negation;
0830:            }
0831:
0832:            /* map current node to its negation */
0833:            private int getNegationNode() {
0834:                switch (getNodeType()) {
0835:                case C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE:
0836:                    return C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE;
0837:
0838:                case C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE:
0839:                    return C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE;
0840:
0841:                case C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE:
0842:                    return C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE;
0843:
0844:                case C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE:
0845:                    return C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE;
0846:
0847:                case C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE:
0848:                    return C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE;
0849:
0850:                case C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE:
0851:                    return C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE;
0852:                }
0853:
0854:                if (SanityManager.DEBUG) {
0855:                    SanityManager
0856:                            .THROWASSERT("getNegationNode called with invalid nodeType: "
0857:                                    + getNodeType());
0858:                }
0859:
0860:                return -1;
0861:            }
0862:
0863:            /**
0864:             * is this is useful start key? for example a predicate of the from
0865:             * <em>column Lessthan 5</em> is not a useful start key but is a useful stop
0866:             * key. However <em>5 Lessthan column </em> is a useful start key.
0867:             *
0868:             * @param columnOnLeft 	is true if the column is the left hand side of the
0869:             * binary operator.
0870:             */
0871:            protected boolean usefulStartKey(boolean columnOnLeft) {
0872:                switch (operatorType) {
0873:                case RelationalOperator.EQUALS_RELOP:
0874:                    return true;
0875:                case RelationalOperator.NOT_EQUALS_RELOP:
0876:                    return false;
0877:                case RelationalOperator.GREATER_THAN_RELOP:
0878:                case RelationalOperator.GREATER_EQUALS_RELOP:
0879:                    // col > 1
0880:                    return columnOnLeft;
0881:                case RelationalOperator.LESS_THAN_RELOP:
0882:                case RelationalOperator.LESS_EQUALS_RELOP:
0883:                    // col < 1
0884:                    return !columnOnLeft;
0885:                default:
0886:                    return false;
0887:                }
0888:
0889:            }
0890:
0891:            /** @see RelationalOperator#usefulStopKey */
0892:            protected boolean usefulStopKey(boolean columnOnLeft) {
0893:                switch (operatorType) {
0894:                case RelationalOperator.EQUALS_RELOP:
0895:                    return true;
0896:                case RelationalOperator.NOT_EQUALS_RELOP:
0897:                    return false;
0898:                case RelationalOperator.GREATER_THAN_RELOP:
0899:                case RelationalOperator.GREATER_EQUALS_RELOP:
0900:                    // col > 1
0901:                    return !columnOnLeft;
0902:                case RelationalOperator.LESS_EQUALS_RELOP:
0903:                case RelationalOperator.LESS_THAN_RELOP:
0904:                    // col < 1
0905:                    return columnOnLeft;
0906:                default:
0907:                    return false;
0908:                }
0909:            }
0910:
0911:            /** @see RelationalOperator#getStartOperator */
0912:            public int getStartOperator(Optimizable optTable) {
0913:                switch (operatorType) {
0914:                case RelationalOperator.EQUALS_RELOP:
0915:                case RelationalOperator.LESS_EQUALS_RELOP:
0916:                case RelationalOperator.GREATER_EQUALS_RELOP:
0917:                    return ScanController.GE;
0918:                case RelationalOperator.LESS_THAN_RELOP:
0919:                case RelationalOperator.GREATER_THAN_RELOP:
0920:                    return ScanController.GT;
0921:                case RelationalOperator.NOT_EQUALS_RELOP:
0922:                    if (SanityManager.DEBUG)
0923:                        SanityManager
0924:                                .THROWASSERT("!= cannot be a start operator");
0925:                    return ScanController.NA;
0926:                default:
0927:                    return ScanController.NA;
0928:
0929:                }
0930:            }
0931:
0932:            /** @see RelationalOperator#getStopOperator */
0933:            public int getStopOperator(Optimizable optTable) {
0934:                switch (operatorType) {
0935:                case RelationalOperator.EQUALS_RELOP:
0936:                case RelationalOperator.GREATER_EQUALS_RELOP:
0937:                case RelationalOperator.LESS_EQUALS_RELOP:
0938:                    return ScanController.GT;
0939:                case RelationalOperator.LESS_THAN_RELOP:
0940:                case RelationalOperator.GREATER_THAN_RELOP:
0941:                    return ScanController.GE;
0942:                case RelationalOperator.NOT_EQUALS_RELOP:
0943:                    if (SanityManager.DEBUG)
0944:                        SanityManager
0945:                                .THROWASSERT("!= cannot be a stop operator");
0946:                    return ScanController.NA;
0947:                default:
0948:                    return ScanController.NA;
0949:                }
0950:            }
0951:
0952:            /** @see RelationalOperator#generateOperator */
0953:            public void generateOperator(MethodBuilder mb, Optimizable optTable) {
0954:                switch (operatorType) {
0955:                case RelationalOperator.EQUALS_RELOP:
0956:                    mb.push(Orderable.ORDER_OP_EQUALS);
0957:                    break;
0958:
0959:                case RelationalOperator.NOT_EQUALS_RELOP:
0960:                    mb.push(Orderable.ORDER_OP_EQUALS);
0961:                    break;
0962:
0963:                case RelationalOperator.LESS_THAN_RELOP:
0964:                case RelationalOperator.GREATER_EQUALS_RELOP:
0965:                    mb
0966:                            .push(keyColumnOnLeft(optTable) ? Orderable.ORDER_OP_LESSTHAN
0967:                                    : Orderable.ORDER_OP_LESSOREQUALS);
0968:                    break;
0969:                case RelationalOperator.LESS_EQUALS_RELOP:
0970:                case RelationalOperator.GREATER_THAN_RELOP:
0971:                    mb
0972:                            .push(keyColumnOnLeft(optTable) ? Orderable.ORDER_OP_LESSOREQUALS
0973:                                    : Orderable.ORDER_OP_LESSTHAN);
0974:
0975:                }
0976:            }
0977:
0978:            /** @see RelationalOperator#generateNegate */
0979:            public void generateNegate(MethodBuilder mb, Optimizable optTable) {
0980:                switch (operatorType) {
0981:                case RelationalOperator.EQUALS_RELOP:
0982:                    mb.push(false);
0983:                    break;
0984:                case RelationalOperator.NOT_EQUALS_RELOP:
0985:                    mb.push(true);
0986:                    break;
0987:                case RelationalOperator.LESS_THAN_RELOP:
0988:                case RelationalOperator.LESS_EQUALS_RELOP:
0989:                    mb.push(!keyColumnOnLeft(optTable));
0990:                    break;
0991:                case RelationalOperator.GREATER_THAN_RELOP:
0992:                case RelationalOperator.GREATER_EQUALS_RELOP:
0993:                    mb.push(keyColumnOnLeft(optTable));
0994:                    break;
0995:                }
0996:
0997:                return;
0998:            }
0999:
1000:            /** @see RelationalOperator#getOperator */
1001:            public int getOperator() {
1002:                return operatorType;
1003:            }
1004:
1005:            /** return the selectivity of this predicate.
1006:             */
1007:            public double selectivity(Optimizable optTable)
1008:                    throws StandardException {
1009:                double retval = booleanSelectivity(optTable);
1010:
1011:                if (retval >= 0.0d)
1012:                    return retval;
1013:
1014:                switch (operatorType) {
1015:                case RelationalOperator.EQUALS_RELOP:
1016:                    return 0.1;
1017:                case RelationalOperator.NOT_EQUALS_RELOP:
1018:                case RelationalOperator.LESS_THAN_RELOP:
1019:                case RelationalOperator.LESS_EQUALS_RELOP:
1020:                case RelationalOperator.GREATER_EQUALS_RELOP:
1021:                    if (getBetweenSelectivity())
1022:                        return 0.5d;
1023:                    /* fallthrough -- only */
1024:                case RelationalOperator.GREATER_THAN_RELOP:
1025:                    return 0.33;
1026:                }
1027:
1028:                return 0.0;
1029:            }
1030:
1031:            /** @see RelationalOperator#getTransitiveSearchClause */
1032:            public RelationalOperator getTransitiveSearchClause(
1033:                    ColumnReference otherCR) throws StandardException {
1034:                return (RelationalOperator) getNodeFactory().getNode(
1035:                        getNodeType(), otherCR, rightOperand,
1036:                        getContextManager());
1037:            }
1038:
1039:            public boolean equalsComparisonWithConstantExpression(
1040:                    Optimizable optTable) {
1041:                if (operatorType != EQUALS_RELOP)
1042:                    return false;
1043:
1044:                boolean retval = false;
1045:                ValueNode comparand = null;
1046:
1047:                int side = columnOnOneSide(optTable);
1048:                if (side == LEFT) {
1049:                    retval = rightOperand.isConstantExpression();
1050:                } else if (side == RIGHT) {
1051:                    retval = leftOperand.isConstantExpression();
1052:                }
1053:
1054:                return retval;
1055:            }
1056:
1057:            /** @see ValueNode#isRelationalOperator */
1058:            public boolean isRelationalOperator() {
1059:                return true;
1060:            }
1061:
1062:            public boolean isBinaryEqualsOperatorNode() {
1063:                return (operatorType == RelationalOperator.EQUALS_RELOP);
1064:            }
1065:
1066:            /** @see ValueNode#optimizableEqualityNode */
1067:            public boolean optimizableEqualityNode(Optimizable optTable,
1068:                    int columnNumber, boolean isNullOkay)
1069:                    throws StandardException {
1070:                if (operatorType != EQUALS_RELOP)
1071:                    return false;
1072:
1073:                ColumnReference cr = getColumnOperand(optTable, columnNumber);
1074:                if (cr == null)
1075:                    return false;
1076:
1077:                if (selfComparison(cr))
1078:                    return false;
1079:
1080:                if (implicitVarcharComparison())
1081:                    return false;
1082:
1083:                return true;
1084:            }
1085:
1086:            /**
1087:             * Return whether or not this binary relational predicate requires an implicit
1088:             * (var)char conversion.  This is important when considering
1089:             * hash join since this type of equality predicate is not currently
1090:             * supported for a hash join.
1091:             *
1092:             * @return	Whether or not an implicit (var)char conversion is required for
1093:             *			this binary relational operator.
1094:             *
1095:             * @exception StandardException		Thrown on error
1096:             */
1097:
1098:            private boolean implicitVarcharComparison()
1099:                    throws StandardException {
1100:                TypeId leftType = leftOperand.getTypeId();
1101:                TypeId rightType = rightOperand.getTypeId();
1102:
1103:                if (leftType.isStringTypeId() && !rightType.isStringTypeId())
1104:                    return true;
1105:
1106:                if (rightType.isStringTypeId() && (!leftType.isStringTypeId()))
1107:                    return true;
1108:
1109:                return false;
1110:            }
1111:
1112:            /* @see BinaryOperatorNode#genSQLJavaSQLTree
1113:             * @see BinaryComparisonOperatorNode#genSQLJavaSQLTree
1114:             */
1115:            public ValueNode genSQLJavaSQLTree() throws StandardException {
1116:                if (operatorType == EQUALS_RELOP)
1117:                    return this ;
1118:
1119:                return super .genSQLJavaSQLTree();
1120:            }
1121:
1122:            /**
1123:             * Take a ResultSetNode and return a column reference that is scoped for
1124:             * for the received ResultSetNode, where "scoped" means that the column
1125:             * reference points to a specific column in the RSN.  This is used for
1126:             * remapping predicates from an outer query down to a subquery. 
1127:             *
1128:             * For example, assume we have the following query:
1129:             *
1130:             *  select * from
1131:             *    (select i,j from t1 union select i,j from t2) X1,
1132:             *    (select a,b from t3 union select a,b from t4) X2
1133:             *  where X1.j = X2.b;
1134:             *
1135:             * Then assume that this BinaryRelationalOperatorNode represents the
1136:             * "X1.j = X2.b" predicate and that the childRSN we received as a
1137:             * parameter represents one of the subqueries to which we want to push
1138:             * the predicate; let's say it's:
1139:             *
1140:             *    select i,j from t1
1141:             *
1142:             * Then what we want to do in this method is map one of the operands
1143:             * X1.j or X2.b (depending on the 'whichSide' parameter) to the childRSN,
1144:             * if possible.  Note that in our example, "X2.b" should _NOT_ be mapped
1145:             * because it doesn't apply to the childRSN for the subquery "select i,j
1146:             * from t1"; thus we should leave it as it is.  "X1.j", however, _does_
1147:             * need to be scoped, and so this method will return a ColumnReference
1148:             * pointing to "T1.j" (or whatever the corresponding column in T1 is).
1149:             *
1150:             * ASSUMPTION: We should only get to this method if we know that
1151:             * exactly one operand in the predicate to which this operator belongs
1152:             * can and should be mapped to the received childRSN. 
1153:             *
1154:             * @param whichSide The operand are we trying to scope (LEFT or RIGHT)
1155:             * @param parentRSNsTables Set of all table numbers referenced by
1156:             *  the ResultSetNode that is _parent_ to the received childRSN.
1157:             *  We need this to make sure we don't scope the operand to a
1158:             *  ResultSetNode to which it doesn't apply.
1159:             * @param childRSN The result set node to which we want to create
1160:             *  a scoped predicate.
1161:             * @param whichRC If not -1 then this tells us which ResultColumn
1162:             *  in the received childRSN we need to use for the scoped predicate;
1163:             *  if -1 then the column position of the scoped column reference
1164:             *  will be stored in this array and passed back to the caller.
1165:             * @return A column reference scoped to the received childRSN, if possible.
1166:             *  If the operand is a ColumnReference that is not supposed to be scoped,
1167:             *  we return a _clone_ of the reference--this is necessary because the
1168:             *  reference is going to be pushed to two places (left and right children
1169:             *  of the parentRSN) and if both children are referencing the same
1170:             *  instance of the column reference, they'll interfere with each other
1171:             *  during optimization.
1172:             */
1173:            public ValueNode getScopedOperand(int whichSide,
1174:                    JBitSet parentRSNsTables, ResultSetNode childRSN,
1175:                    int[] whichRC) throws StandardException {
1176:                ResultColumn rc = null;
1177:                ColumnReference cr = whichSide == LEFT ? (ColumnReference) leftOperand
1178:                        : (ColumnReference) rightOperand;
1179:
1180:                /* When we scope a predicate we only scope one side of it--the
1181:                 * side that is to be evaluated against childRSN.  We figure out
1182:                 * if "cr" is that side by using table numbers, as seen below.
1183:                 * This means that for every scoped predicate there will be one
1184:                 * operand that is scoped and one operand that is not scoped.  
1185:                 * When we get here for the operand that will not be scoped,
1186:                 * we'll just return a clone of that operand.  So in the example
1187:                 * mentioned above, the scoped predicate for the left child of
1188:                 * X1 would be
1189:                 *
1190:                 *   T1.j <scoped> = X2.b <clone> 
1191:                 *
1192:                 * That said, the first thing we need to do is see if this
1193:                 * ColumnReference is supposed to be scoped for childRSN.  We
1194:                 * do that by figuring out what underlying base table the column
1195:                 * reference is pointing to and then seeing if that base table
1196:                 * is included in the list of table numbers from the parentRSN.
1197:                 */
1198:                JBitSet crTables = new JBitSet(parentRSNsTables.size());
1199:                BaseTableNumbersVisitor btnVis = new BaseTableNumbersVisitor(
1200:                        crTables);
1201:                cr.accept(btnVis);
1202:
1203:                /* If the column reference in question is not intended for
1204:                 * the received result set node, just leave the operand as
1205:                 * it is (i.e. return a clone).  In the example mentioned at
1206:                 * the start of this method, this will happen when the operand
1207:                 * is X2.b and childRSN is either "select i,j from t1" or
1208:                 * "select i,j from t2", in which case the operand does not
1209:                 * apply to childRSN.  When we get here and try to map the
1210:                 * "X1.j" operand, though, the following "contains" check will
1211:                 * return true and thus we can go ahead and return a scoped
1212:                 * version of that operand.
1213:                 */
1214:                if (!parentRSNsTables.contains(crTables))
1215:                    return (ColumnReference) cr.getClone();
1216:
1217:                /* Find the target ResultColumn in the received result set.  At
1218:                 * this point we know that we do in fact need to scope the column
1219:                 * reference for childRSN, so go ahead and do it.  The way in
1220:                 * which we get the scope target column differs depending on
1221:                 * if childRSN corresponds to the left or right child of the
1222:                 * UNION node.  Before explaining that, though, note that it's
1223:                 * not good enough to just search for the target column by
1224:                 * name.  The reason is that it's possible the name provided
1225:                 * for the column reference to be scoped doesn't match the
1226:                 * name of the actual underlying column.  Ex.
1227:                 *
1228:                 *  select * from
1229:                 *    (select i,j from t1 union select i,j from t2) X1 (x,y),
1230:                 *    (select a,b from t3 union select a,b from t4) X2
1231:                 *  where X1.x = X2.b;
1232:                 *
1233:                 * If we were scoping "X1.x" and we searched for "x" in the
1234:                 * childRSN "select i,j from t1" we wouldn't find it.
1235:                 *
1236:                 * It is similarly incorrect to search for the target column
1237:                 * by position (DERBY-1633).  This is a bit more subtle, but
1238:                 * if the child to which we're scoping is a subquery whose RCL
1239:                 * does not match the column ordering of the RCL for cr's source
1240:                 * result set, then searching by column position can yield the
1241:                 * wrong results, as well.  For a detailed example of how this
1242:                 * can happen, see the fix description attached to DERBY-1633.
1243:                 * 
1244:                 * So how do we find the target column, then? As mentioned
1245:                 * above, the way in which we get the scope target column
1246:                 * differs depending on if childRSN corresponds to the left
1247:                 * or right child of the parent UNION node.  And that said,
1248:                 * we can tell if we're scoping a left child by looking at
1249:                 * "whichRC" argument: if it is -1 then we know we're scoping
1250:                 * to the left child of a Union; otherwise we're scoping to
1251:                 * the right child.
1252:                 */
1253:                if (whichRC[0] == -1) {
1254:                    /*
1255:                     * For the left side we start by figuring out what the source
1256:                     * result set and column position for "cr" are.  Then, since
1257:                     * a) cr must be pointing to a result column in the parentRSN's
1258:                     * ResultColumnList,  b) we know that the parent RSN is a
1259:                     * SetOperatorNode (at least for now, since we only get here
1260:                     * for Union nodes), and c) SetOpNode's RCLs are built from the
1261:                     * left child's RCL (see bindResultColumns() in SetOperatorNode),
1262:                     * we know that if we search the child's RCL for a reference
1263:                     * whose source result column is the same as cr's source result
1264:                     * column, we'll find a match.  Once found, the position of the
1265:                     * matching column w.r.t childRSN's RCL will be stored in the
1266:                     * whichRC parameter.
1267:                     */
1268:
1269:                    // Find the source result set and source column position of cr.
1270:                    int[] sourceColPos = new int[] { -1 };
1271:                    ResultSetNode sourceRSN = cr
1272:                            .getSourceResultSet(sourceColPos);
1273:
1274:                    if (SanityManager.DEBUG) {
1275:                        /* We assumed that if we made it here "cr" was pointing
1276:                         * to a base table somewhere down the tree.  If that's
1277:                         * true then sourceRSN won't be null.  Make sure our
1278:                         * assumption was correct.
1279:                         */
1280:                        SanityManager.ASSERT(sourceRSN != null,
1281:                                "Failed to find source result set when trying to "
1282:                                        + "scope column reference '"
1283:                                        + cr.getTableName() + "."
1284:                                        + cr.getColumnName());
1285:                    }
1286:
1287:                    // Now search for the corresponding ResultColumn in childRSN.
1288:                    rc = childRSN.getResultColumns().getResultColumn(
1289:                            sourceColPos[0], sourceRSN, whichRC);
1290:                } else {
1291:                    /*
1292:                     * For the right side the story is slightly different.  If we were
1293:                     * to search the right child's RCL for a reference whose source
1294:                     * result column was the same as cr's, we wouldn't find it.  This
1295:                     * is because cr's source result column comes from the left child's
1296:                     * RCL and thus the right child doesn't know about it.  That said,
1297:                     * though, for set operations like UNION, the left and right RCL's
1298:                     * are correlated by position--i.e. the operation occurs between
1299:                     * the nth column in the left RCL and the nth column in the right
1300:                     * RCL.  So given that we will already have found the scope target
1301:                     * in the left child's RCL at the position in whichRC, we know that
1302:                     * that scope target for the right child's RCL is simply the
1303:                     * whichRC'th column in that RCL.
1304:                     */
1305:                    rc = childRSN.getResultColumns()
1306:                            .getResultColumn(whichRC[0]);
1307:                }
1308:
1309:                // rc shouldn't be null; if there was no matching ResultColumn at all,
1310:                // then we shouldn't have made it this far.
1311:                if (SanityManager.DEBUG) {
1312:                    SanityManager.ASSERT(rc != null,
1313:                            "Failed to locate scope target result column when trying to "
1314:                                    + "scope operand '" + cr.getTableName()
1315:                                    + "." + cr.getColumnName() + "'.");
1316:                }
1317:
1318:                /* If the ResultColumn we found has an expression that is a
1319:                 * ColumnReference, then that column reference has all of the
1320:                 * info we need.
1321:                 *
1322:                 * It is, however, possible that the ResultColumn's expression
1323:                 * is NOT a ColumnReference.  For example, the expression would
1324:                 * be a constant expression if childRSN represented something
1325:                 * like:
1326:                 *
1327:                 *   select 1, 1 from t1
1328:                 *
1329:                 * In this case the expression does not directly reference a
1330:                 * column in the underlying result set and is therefore
1331:                 * "scoped" as far as it can go.  This means that the scoped
1332:                 * predicate will not necessarily have column references on
1333:                 * both sides, even though the predicate that we're scoping
1334:                 * will.  That's not a problem, though, since a predicate with
1335:                 * a column reference on one side and a non-ColumnReference
1336:                 * on the other is still valid.
1337:                 */
1338:
1339:                if (rc.getExpression() instanceof  ColumnReference) {
1340:                    /* We create a clone of the column reference and mark
1341:                     * the clone as "scoped" so that we can do the right
1342:                     * thing when it comes time to remap the predicate;
1343:                     * see Predicate.remapScopedPred() for more.
1344:                     */
1345:                    ColumnReference cRef = (ColumnReference) ((ColumnReference) rc
1346:                            .getExpression()).getClone();
1347:                    cRef.markAsScoped();
1348:                    return cRef;
1349:                }
1350:
1351:                /* Else just return rc's expression.  This means the scoped
1352:                 * predicate will have one operand that is _not_ a column
1353:                 * reference--but that's okay, so long as we account for
1354:                 * that when pushing/remapping the scoped predicate down
1355:                 * the query tree (see esp. "isScopedToSourceResultSet()"
1356:                 * in Predicate.java).
1357:                 */
1358:                return rc.getExpression();
1359:            }
1360:
1361:            /**
1362:             * Determine whether or not the received ValueNode (which will
1363:             * usually be a ColumnReference) references either the received
1364:             * optTable or else a base table in the subtree beneath that
1365:             * optTable.
1366:             *
1367:             * @param valNode The ValueNode that has the reference(s).
1368:             * @param optTable The table/subtree node to which we're trying
1369:             *  to find a reference.
1370:             * @param forPush Whether or not we are searching with the intent
1371:             *  to push this operator to the target table.
1372:             * @param walkOptTableSubtree Should we walk the subtree beneath
1373:             *  optTable to find base tables, or not?  Will be false if we've
1374:             *  already done it for the left operand and now we're here
1375:             *  for the right operand.
1376:             * @return True if valNode contains a reference to optTable or
1377:             *  to a base table in the subtree beneath optTable; false
1378:             *  otherwise.
1379:             */
1380:            private boolean valNodeReferencesOptTable(ValueNode valNode,
1381:                    FromTable optTable, boolean forPush,
1382:                    boolean walkOptTableSubtree) {
1383:                // Following call will initialize/reset the btnVis,
1384:                // valNodeBaseTables, and optBaseTables fields of this object.
1385:                initBaseTableVisitor(optTable.getReferencedTableMap().size(),
1386:                        walkOptTableSubtree);
1387:
1388:                boolean found = false;
1389:                try {
1390:
1391:                    // Find all base tables beneath optTable and load them
1392:                    // into this object's optBaseTables map.  This is the
1393:                    // list of table numbers we'll search to see if the
1394:                    // value node references any tables in the subtree at
1395:                    // or beneath optTable.
1396:                    if (walkOptTableSubtree)
1397:                        buildTableNumList(optTable, forPush);
1398:
1399:                    // Now get the base table numbers that are in valNode's
1400:                    // subtree.  In most cases valNode will be a ColumnReference
1401:                    // and this will return a single base table number.
1402:                    btnVis.setTableMap(valNodeBaseTables);
1403:                    valNode.accept(btnVis);
1404:
1405:                    // And finally, see if there's anything in common.
1406:                    valNodeBaseTables.and(optBaseTables);
1407:                    found = (valNodeBaseTables.getFirstSetBit() != -1);
1408:
1409:                } catch (StandardException se) {
1410:                    if (SanityManager.DEBUG) {
1411:                        SanityManager
1412:                                .THROWASSERT("Failed when trying to "
1413:                                        + "find base table numbers for reference check:\n"
1414:                                        + se.getMessage());
1415:                    }
1416:                }
1417:
1418:                return found;
1419:            }
1420:
1421:            /**
1422:             * Initialize the fields used for retrieving base tables in
1423:             * subtrees, which allows us to do a more extensive search
1424:             * for table references.  If the fields have already been
1425:             * created, then just reset their values.
1426:             *
1427:             * @param numTablesInQuery Used for creating JBitSets that
1428:             *  can hold table numbers for the query.
1429:             * @param initOptBaseTables Whether or not we should clear out
1430:             *  or initialize the optBaseTables bit set.
1431:             */
1432:            private void initBaseTableVisitor(int numTablesInQuery,
1433:                    boolean initOptBaseTables) {
1434:                if (valNodeBaseTables == null)
1435:                    valNodeBaseTables = new JBitSet(numTablesInQuery);
1436:                else
1437:                    valNodeBaseTables.clearAll();
1438:
1439:                if (initOptBaseTables) {
1440:                    if (optBaseTables == null)
1441:                        optBaseTables = new JBitSet(numTablesInQuery);
1442:                    else
1443:                        optBaseTables.clearAll();
1444:                }
1445:
1446:                // Now create the visitor.  We give it valNodeBaseTables
1447:                // here for sake of creation, but this can be overridden
1448:                // (namely, by optBaseTables) by the caller of this method.
1449:                if (btnVis == null)
1450:                    btnVis = new BaseTableNumbersVisitor(valNodeBaseTables);
1451:            }
1452:
1453:            /**
1454:             * Create a set of table numbers to search when trying to find
1455:             * which (if either) of this operator's operands reference the
1456:             * received target table.  At the minimum this set should contain
1457:             * the target table's own table number.  After that, if we're
1458:             * _not_ attempting to push this operator (or more specifically,
1459:             * the predicate to which this operator belongs) to the target
1460:             * table, we go on to search the subtree beneath the target
1461:             * table and add any base table numbers to the searchable list.
1462:             *
1463:             * @param ft Target table for which we're building the search
1464:             *  list.
1465:             * @param forPush Whether or not we are searching with the intent
1466:             *  to push this operator to the target table.
1467:             */
1468:            private void buildTableNumList(FromTable ft, boolean forPush)
1469:                    throws StandardException {
1470:                // Start with the target table's own table number.  Note
1471:                // that if ft is an instanceof SingleChildResultSet, its
1472:                // table number could be negative.
1473:                if (ft.getTableNumber() >= 0)
1474:                    optBaseTables.set(ft.getTableNumber());
1475:
1476:                if (forPush)
1477:                    // nothing else to do.
1478:                    return;
1479:
1480:                // Add any table numbers from the target table's
1481:                // reference map.
1482:                optBaseTables.or(ft.getReferencedTableMap());
1483:
1484:                // The table's reference map is not guaranteed to have
1485:                // all of the tables that are actually used--for example,
1486:                // if the table is a ProjectRestrictNode or a JoinNode
1487:                // with a subquery as a child, the ref map will contain
1488:                // the number for the PRN above the subquery, but it
1489:                // won't contain the table numbers referenced by the
1490:                // subquery.  So here we go through and find ALL base
1491:                // table numbers beneath the target node.
1492:                btnVis.setTableMap(optBaseTables);
1493:                ft.accept(btnVis);
1494:                return;
1495:            }
1496:
1497:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.