Source Code Cross Referenced for HalfOuterJoinNode.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) 


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.sql.compile.HalfOuterJoinNode
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.sql.compile;
023:
024:        import org.apache.derby.iapi.services.context.ContextManager;
025:
026:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
027:
028:        import org.apache.derby.iapi.services.sanity.SanityManager;
029:
030:        import org.apache.derby.iapi.error.StandardException;
031:
032:        import org.apache.derby.iapi.sql.compile.Optimizable;
033:        import org.apache.derby.iapi.sql.compile.OptimizablePredicate;
034:        import org.apache.derby.iapi.sql.compile.OptimizablePredicateList;
035:        import org.apache.derby.iapi.sql.compile.Optimizer;
036:        import org.apache.derby.iapi.sql.compile.CostEstimate;
037:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
038:
039:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
040:
041:        import org.apache.derby.iapi.sql.Activation;
042:        import org.apache.derby.iapi.sql.ResultSet;
043:
044:        import org.apache.derby.iapi.error.StandardException;
045:
046:        import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
047:
048:        import org.apache.derby.iapi.util.JBitSet;
049:
050:        import java.util.Properties;
051:
052:        /**
053:         * An HalfOuterJoinNode represents a left or a right outer join result set.
054:         * Right outer joins are always transformed into left outer joins during
055:         * preprocessing for simplicity.
056:         *
057:         * @author Jerry Brenner
058:         */
059:
060:        public class HalfOuterJoinNode extends JoinNode {
061:            private boolean rightOuterJoin;
062:            private boolean transformed = false;
063:
064:            /**
065:             * Initializer for a HalfOuterJoinNode.
066:             *
067:             * @param leftResult		The ResultSetNode on the left side of this join
068:             * @param rightResult		The ResultSetNode on the right side of this join
069:             * @param onClause			The ON clause
070:             * @param usingClause		The USING clause
071:             * @param rightOuterJoin	Whether or not this node represents a user
072:             *							specified right outer join
073:             * @param tableProperties	Properties list associated with the table
074:             *
075:             * @exception StandardException		Thrown on error
076:             */
077:
078:            public void init(Object leftResult, Object rightResult,
079:                    Object onClause, Object usingClause, Object rightOuterJoin,
080:                    Object tableProperties) throws StandardException {
081:                super .init(leftResult, rightResult, onClause, usingClause,
082:                        null, tableProperties, null);
083:                this .rightOuterJoin = ((Boolean) rightOuterJoin).booleanValue();
084:
085:                /* We can only flatten an outer join
086:                 * using the null intolerant predicate xform.
087:                 * In that case, we will return an InnerJoin.
088:                 */
089:                flattenableJoin = false;
090:            }
091:
092:            /*
093:             *  Optimizable interface
094:             */
095:
096:            /**
097:             * @see Optimizable#pushOptPredicate
098:             *
099:             * @exception StandardException		Thrown on error
100:             */
101:
102:            public boolean pushOptPredicate(
103:                    OptimizablePredicate optimizablePredicate)
104:                    throws StandardException {
105:                /* We should never push the predicate to joinPredicates as in JoinNode.  joinPredicates
106:                 * should only be predicates relating the two joining tables.  In the case of half join,
107:                 * it is biased.  If the general predicate (not join predicate) contains refernce to right
108:                 * result set, and if doesn't qualify, we shouldn't return the row for the result to be
109:                 * correct, but half join will fill right side NULL and return the row.  So we can only
110:                 * push predicate to the left, as we do in "pushExpression".  bug 5055
111:                 */
112:                FromTable leftFromTable = (FromTable) leftResultSet;
113:                if (leftFromTable.getReferencedTableMap().contains(
114:                        optimizablePredicate.getReferencedMap()))
115:                    return leftFromTable.pushOptPredicate(optimizablePredicate);
116:                return false;
117:            }
118:
119:            /**
120:             * Convert this object to a String.  See comments in QueryTreeNode.java
121:             * for how this should be done for tree printing.
122:             *
123:             * @return	This object as a String
124:             */
125:
126:            public String toString() {
127:                if (SanityManager.DEBUG) {
128:                    return "rightOuterJoin: " + rightOuterJoin + "\n"
129:                            + "transformed: " + transformed + "\n"
130:                            + super .toString();
131:                } else {
132:                    return "";
133:                }
134:            }
135:
136:            /** 
137:             * Put a ProjectRestrictNode on top of each FromTable in the FromList.
138:             * ColumnReferences must continue to point to the same ResultColumn, so
139:             * that ResultColumn must percolate up to the new PRN.  However,
140:             * that ResultColumn will point to a new expression, a VirtualColumnNode, 
141:             * which points to the FromTable and the ResultColumn that is the source for
142:             * the ColumnReference.  
143:             * (The new PRN will have the original of the ResultColumnList and
144:             * the ResultColumns from that list.  The FromTable will get shallow copies
145:             * of the ResultColumnList and its ResultColumns.  ResultColumn.expression
146:             * will remain at the FromTable, with the PRN getting a new 
147:             * VirtualColumnNode for each ResultColumn.expression.)
148:             * We then project out the non-referenced columns.  If there are no referenced
149:             * columns, then the PRN's ResultColumnList will consist of a single ResultColumn
150:             * whose expression is 1.
151:             *
152:             * @param numTables			Number of tables in the DML Statement
153:             * @param gbl				The group by list, if any
154:             * @param fromList			The from list, if any
155:             *
156:             * @return The generated ProjectRestrictNode atop the original FromTable.
157:             *
158:             * @exception StandardException		Thrown on error
159:             */
160:            public ResultSetNode preprocess(int numTables, GroupByList gbl,
161:                    FromList fromList) throws StandardException {
162:                ResultSetNode newTreeTop;
163:
164:                /* Transform right outer joins to the equivalent left outer join */
165:                if (rightOuterJoin) {
166:                    /* Verify that a user specifed right outer join is transformed into
167:                     * a left outer join exactly once.
168:                     */
169:                    if (SanityManager.DEBUG) {
170:                        SanityManager
171:                                .ASSERT(!transformed,
172:                                        "Attempting to transform a right outer join multiple times");
173:                    }
174:
175:                    ResultSetNode tmp = leftResultSet;
176:
177:                    leftResultSet = rightResultSet;
178:                    rightResultSet = tmp;
179:                    transformed = true;
180:                }
181:
182:                newTreeTop = super .preprocess(numTables, gbl, fromList);
183:
184:                return newTreeTop;
185:            }
186:
187:            /**
188:             * Push expressions down to the first ResultSetNode which can do expression
189:             * evaluation and has the same referenced table map.
190:             * RESOLVE - This means only pushing down single table expressions to
191:             * DistinctNodes today.  Once we have a better understanding of how
192:             * the optimizer will work, we can push down join clauses.
193:             *
194:             * @param outerPredicateList	The PredicateList from the outer RS.
195:             *
196:             * @exception StandardException		Thrown on error
197:             */
198:            public void pushExpressions(PredicateList outerPredicateList)
199:                    throws StandardException {
200:                FromTable leftFromTable = (FromTable) leftResultSet;
201:                FromTable rightFromTable = (FromTable) rightResultSet;
202:
203:                /* We only try to push single table predicates to the left.
204:                 * Pushing them to the right would give incorrect semantics.
205:                 * We use the logic for pushing down single table predicates here.
206:                 */
207:                pushExpressionsToLeft(outerPredicateList);
208:
209:                /* Push the pushable outer join predicates to the right.  This is done
210:                 * bottom up, hence at the end of this method, so that outer join
211:                 * conditions only get pushed down 1 level.
212:                 * We use the optimizer's logic for pushing down join clause here.
213:                 */
214:                // Walk joinPredicates backwards due to possible deletes
215:                for (int index = joinPredicates.size() - 1; index >= 0; index--) {
216:                    Predicate predicate;
217:
218:                    predicate = (Predicate) joinPredicates.elementAt(index);
219:                    if (!predicate.getPushable()) {
220:                        continue;
221:                    }
222:
223:                    getRightPredicateList().addPredicate(predicate);
224:
225:                    /* Remove the matching predicate from the outer list */
226:                    joinPredicates.removeElementAt(index);
227:                }
228:
229:                /* Recurse down both sides of tree */
230:                PredicateList noPredicates = (PredicateList) getNodeFactory()
231:                        .getNode(C_NodeTypes.PREDICATE_LIST,
232:                                getContextManager());
233:                leftFromTable.pushExpressions(getLeftPredicateList());
234:                rightFromTable.pushExpressions(noPredicates);
235:            }
236:
237:            /**
238:             * This method determines if (1) the query is a LOJ, and (2) if the LOJ is a candidate for
239:             * reordering (i.e., linearization).  The condition for LOJ linearization is:
240:             * 1. only LOJ in the fromList, i.e., no INNER, no FULL JOINs, no ROJs
241:             * 2. ON clause must be equality join between left and right operands and in CNF (i.e., AND is allowed)
242:             */
243:            public boolean LOJ_reorderable(int numTables)
244:                    throws StandardException {
245:                boolean anyChange = false;
246:
247:                ResultSetNode logicalLeftResultSet; // row-preserving side
248:                ResultSetNode logicalRightResultSet; // null-producing side
249:
250:                // Figure out which is the row-preserving side and which is
251:                // null-producing side.
252:                if (rightOuterJoin) { // right outer join
253:                    logicalLeftResultSet = rightResultSet;
254:                    logicalRightResultSet = leftResultSet;
255:                } else {
256:                    logicalLeftResultSet = leftResultSet;
257:                    logicalRightResultSet = rightResultSet;
258:                }
259:
260:                // Redundantly normalize the ON predicate (it will also be called in preprocess()).
261:                super .normExpressions();
262:
263:                // This is a very simple LOJ of base tables. Do nothing.
264:                if (logicalLeftResultSet instanceof  FromBaseTable
265:                        && logicalRightResultSet instanceof  FromBaseTable)
266:                    return anyChange;
267:
268:                // Recursively check if we can reordering LOJ, and build the table
269:                // references. Note that joins may have been reordered and therefore the
270:                // table references need to be recomputed.
271:                if (logicalLeftResultSet instanceof  HalfOuterJoinNode) {
272:                    anyChange = ((HalfOuterJoinNode) logicalLeftResultSet)
273:                            .LOJ_reorderable(numTables)
274:                            || anyChange;
275:                } else if (!(logicalLeftResultSet instanceof  FromBaseTable)) {// left operand must be either a base table or another LOJ
276:                    // In principle, we don't care about the left operand.  However, we
277:                    // need to re-bind the resultColumns.  If the left operand is a
278:                    // view, we may have to re-bind the where clause etc...
279:                    // We ran into difficulty for the following query:
280:                    //  create view v8 (cv, bv, av) as (select c, b, a from t union select f, e, d from s);
281:                    //  select * from v8 left outer join (s left outer join r on (f = i)) on (e=v8.bv);
282:                    return anyChange;
283:                }
284:
285:                if (logicalRightResultSet instanceof  HalfOuterJoinNode) {
286:                    anyChange = ((HalfOuterJoinNode) logicalRightResultSet)
287:                            .LOJ_reorderable(numTables)
288:                            || anyChange;
289:                } else if (!(logicalRightResultSet instanceof  FromBaseTable)) {// right operand must be either a base table or another LOJ
290:                    return anyChange;
291:                }
292:
293:                // It is much easier to do LOJ reordering if there is no ROJ.
294:                // However, we ran into some problem downstream when we transform an ROJ
295:                // into LOJ -- transformOuterJoin() didn't expect ROJ to be transformed
296:                // into LOJ alread.  So, we skip optimizing ROJ at the moment.
297:                if (rightOuterJoin
298:                        || (logicalRightResultSet instanceof  HalfOuterJoinNode && ((HalfOuterJoinNode) logicalRightResultSet).rightOuterJoin)) {
299:                    return LOJ_bindResultColumns(anyChange);
300:                }
301:
302:                // Build the data structure for testing/doing LOJ reordering.
303:                // Fill in the table references on row-preserving and null-producing sides.
304:                // It may be possible that either operand is a complex view.
305:                JBitSet NPReferencedTableMap; // Null-producing
306:                JBitSet RPReferencedTableMap; // Row-preserving
307:
308:                RPReferencedTableMap = logicalLeftResultSet
309:                        .LOJgetReferencedTables(numTables);
310:                NPReferencedTableMap = logicalRightResultSet
311:                        .LOJgetReferencedTables(numTables);
312:
313:                if ((RPReferencedTableMap == null || NPReferencedTableMap == null)
314:                        && anyChange) {
315:                    return LOJ_bindResultColumns(anyChange);
316:                }
317:
318:                // Check if the predicate is equality predicate in CNF (i.e., AND only)
319:                // and left/right column references must come from either operand.
320:                // That is, we don't allow:
321:                // 1. A=A
322:                // 2. 1=1
323:                // 3. B=C where both B and C are either from left or right operand.
324:
325:                // we probably need to make the joinClause "left-deep" so that we can
326:                // walk it easier.
327:                BinaryRelationalOperatorNode equals;
328:                ValueNode leftCol;
329:                ValueNode rightCol;
330:                AndNode and;
331:                ValueNode left;
332:                ValueNode vn = joinClause;
333:                while (vn instanceof  AndNode) {
334:                    and = (AndNode) vn;
335:                    left = and.getLeftOperand();
336:
337:                    // Make sure that this is an equijoin of the form "C = D" where C
338:                    // and D references tables from both left and right operands.
339:                    if (left instanceof  RelationalOperator
340:                            && ((ValueNode) left).isBinaryEqualsOperatorNode()) {
341:                        equals = (BinaryRelationalOperatorNode) left;
342:                        leftCol = equals.getLeftOperand();
343:                        rightCol = equals.getRightOperand();
344:
345:                        if (!(leftCol instanceof  ColumnReference && rightCol instanceof  ColumnReference))
346:                            return LOJ_bindResultColumns(anyChange);
347:
348:                        boolean refCheck = false;
349:                        boolean leftOperandCheck = false;
350:
351:                        if (RPReferencedTableMap
352:                                .get(((ColumnReference) leftCol)
353:                                        .getTableNumber())) {
354:                            refCheck = true;
355:                            leftOperandCheck = true;
356:                        } else if (NPReferencedTableMap
357:                                .get(((ColumnReference) leftCol)
358:                                        .getTableNumber())) {
359:                            refCheck = true;
360:                        }
361:
362:                        if (refCheck == false)
363:                            return LOJ_bindResultColumns(anyChange);
364:
365:                        refCheck = false;
366:                        if (leftOperandCheck == false
367:                                && RPReferencedTableMap
368:                                        .get(((ColumnReference) rightCol)
369:                                                .getTableNumber())) {
370:                            refCheck = true;
371:                        } else if (leftOperandCheck == true
372:                                && NPReferencedTableMap
373:                                        .get(((ColumnReference) rightCol)
374:                                                .getTableNumber())) {
375:                            refCheck = true;
376:                        }
377:
378:                        if (refCheck == false)
379:                            return LOJ_bindResultColumns(anyChange);
380:                    } else
381:                        return LOJ_bindResultColumns(anyChange); //  get out of here
382:
383:                    vn = and.getRightOperand();
384:                }
385:
386:                // Check if the logical right resultset is a composite inner and as such
387:                // that this current LOJ can be pushed through it.
388:                boolean push = false;
389:                // logical right operand is another LOJ... so we may be able to push the
390:                // join
391:                if (logicalRightResultSet instanceof  HalfOuterJoinNode) {
392:                    // get the Null-producing operand of the child
393:                    JBitSet logicalNPRefTableMap = ((HalfOuterJoinNode) logicalRightResultSet)
394:                            .LOJgetNPReferencedTables(numTables);
395:
396:                    // does the current LOJ join predicate reference
397:                    // logicalNPRefTableMap?  If not, we can push the current
398:                    // join.
399:                    vn = joinClause;
400:                    push = true;
401:                    while (vn instanceof  AndNode) {
402:                        and = (AndNode) vn;
403:                        left = and.getLeftOperand();
404:                        equals = (BinaryRelationalOperatorNode) left;
405:                        leftCol = equals.getLeftOperand();
406:                        rightCol = equals.getRightOperand();
407:
408:                        if (logicalNPRefTableMap
409:                                .get(((ColumnReference) leftCol)
410:                                        .getTableNumber())
411:                                || logicalNPRefTableMap
412:                                        .get(((ColumnReference) rightCol)
413:                                                .getTableNumber())) {
414:                            push = false;
415:                            break;
416:                        }
417:
418:                        vn = and.getRightOperand();
419:                    }
420:                }
421:
422:                // Push the current LOJ into the next level
423:                if (push) {
424:                    // For safety, check the JoinNode data members: they should null or
425:                    // empty list before we proceed.
426:                    if (super .subqueryList.size() != 0
427:                            || ((JoinNode) logicalRightResultSet).subqueryList
428:                                    .size() != 0
429:                            || super .joinPredicates.size() != 0
430:                            || ((JoinNode) logicalRightResultSet).joinPredicates
431:                                    .size() != 0
432:                            || super .usingClause != null
433:                            || ((JoinNode) logicalRightResultSet).usingClause != null)
434:                        return LOJ_bindResultColumns(anyChange); //  get out of here
435:
436:                    anyChange = true; // we are reordering the LOJs.
437:
438:                    ResultSetNode tmp = logicalLeftResultSet;
439:                    ResultSetNode LChild, RChild;
440:
441:                    //            this LOJ
442:                    //            /      \
443:                    //  logicalLeftRS   LogicalRightRS
444:                    //                   /     \
445:                    //                LChild  RChild
446:                    // becomes
447:                    //
448:                    //               this LOJ
449:                    //               /      \
450:                    //     LogicalRightRS   RChild
451:                    //           /     \
452:                    // logicalLeftRS   LChild  <<<  we need to be careful about this order
453:                    //                              as the "LogicalRightRS may be a ROJ
454:                    //
455:
456:                    // handle the lower level LOJ node
457:                    LChild = ((HalfOuterJoinNode) logicalRightResultSet).leftResultSet;
458:                    RChild = ((HalfOuterJoinNode) logicalRightResultSet).rightResultSet;
459:
460:                    ((HalfOuterJoinNode) logicalRightResultSet).rightResultSet = LChild;
461:                    ((HalfOuterJoinNode) logicalRightResultSet).leftResultSet = tmp;
462:
463:                    // switch the ON clause
464:                    vn = joinClause;
465:                    joinClause = ((HalfOuterJoinNode) logicalRightResultSet).joinClause;
466:                    ((HalfOuterJoinNode) logicalRightResultSet).joinClause = vn;
467:
468:                    // No need to switch HalfOuterJoinNode data members for now because
469:                    // we are handling only LOJ.
470:                    // boolean local_rightOuterJoin = rightOuterJoin;
471:                    // boolean local_transformed    = transformed;
472:                    // rightOuterJoin = ((HalfOuterJoinNode)logicalRightResultSet).rightOuterJoin;
473:                    // transformed    = ((HalfOuterJoinNode)logicalRightResultSet).transformed;
474:                    // ((HalfOuterJoinNode)logicalRightResultSet).rightOuterJoin = local_rightOuterJoin;
475:                    // ((HalfOuterJoinNode)logicalRightResultSet).transformed    = local_transformed;
476:
477:                    FromList localFromList = (FromList) getNodeFactory()
478:                            .getNode(C_NodeTypes.FROM_LIST,
479:                                    getNodeFactory().doJoinOrderOptimization(),
480:                                    getContextManager());
481:
482:                    // switch LOJ nodes: by handling the current LOJ node
483:                    leftResultSet = logicalRightResultSet;
484:                    rightResultSet = RChild;
485:
486:                    // rebuild the result columns and re-bind column references
487:                    ((HalfOuterJoinNode) leftResultSet).resultColumns = null;
488:                    ((JoinNode) leftResultSet).bindResultColumns(localFromList); // localFromList is empty
489:
490:                    // left operand must be another LOJ, try again until a fixpoint
491:                    boolean localChange = ((HalfOuterJoinNode) leftResultSet)
492:                            .LOJ_reorderable(numTables);
493:
494:                    // rebuild the result columns and re-bind column references for 'this'
495:                    return LOJ_bindResultColumns(anyChange);
496:                }
497:
498:                return LOJ_bindResultColumns(anyChange);
499:            }
500:
501:            // This method re-binds the result columns which may be referenced in the ON
502:            // clause in this node.
503:            public boolean LOJ_bindResultColumns(boolean anyChange)
504:                    throws StandardException {
505:                if (anyChange) {
506:                    this .resultColumns = null;
507:                    FromList localFromList = (FromList) getNodeFactory()
508:                            .getNode(C_NodeTypes.FROM_LIST,
509:                                    getNodeFactory().doJoinOrderOptimization(),
510:                                    getContextManager());
511:                    ((JoinNode) this ).bindResultColumns(localFromList);
512:                }
513:                return anyChange;
514:            }
515:
516:            /**
517:             * Transform any Outer Join into an Inner Join where applicable.
518:             * (Based on the existence of a null intolerant
519:             * predicate on the inner table.)
520:             *
521:             * @param predicateTree	The predicate tree for the query block
522:             *
523:             * @return The new tree top (OuterJoin or InnerJoin).
524:             *
525:             * @exception StandardException		Thrown on error
526:             */
527:            public FromTable transformOuterJoins(ValueNode predicateTree,
528:                    int numTables) throws StandardException {
529:                ResultSetNode innerRS;
530:
531:                if (predicateTree == null) {
532:                    /* We can't transform this node, so tell both sides of the 
533:                     * outer join that they can't get flattened into outer query block.
534:                     */
535:                    leftResultSet.notFlattenableJoin();
536:                    rightResultSet.notFlattenableJoin();
537:                    return this ;
538:                }
539:
540:                super .transformOuterJoins(predicateTree, numTables);
541:
542:                JBitSet innerMap = new JBitSet(numTables);
543:                if (rightOuterJoin) {
544:                    if (SanityManager.DEBUG) {
545:                        SanityManager
546:                                .ASSERT(!transformed,
547:                                        "right OJ not expected to be transformed into left OJ yet");
548:                    }
549:                    innerRS = leftResultSet;
550:                } else {
551:                    innerRS = rightResultSet;
552:                }
553:
554:                innerRS.fillInReferencedTableMap(innerMap);
555:
556:                /* Walk predicates looking for 
557:                 * a null intolerant predicate on the inner table.
558:                 */
559:                ValueNode vn = predicateTree;
560:                while (vn instanceof  AndNode) {
561:                    AndNode and = (AndNode) vn;
562:                    ValueNode left = and.getLeftOperand();
563:
564:                    /* Skip IS NULL predicates as they are not null intolerant */
565:                    if (left.isInstanceOf(C_NodeTypes.IS_NULL_NODE)) {
566:                        vn = and.getRightOperand();
567:                        continue;
568:                    }
569:
570:                    /* Only consider predicates that are relops */
571:                    if (left instanceof  RelationalOperator) {
572:                        JBitSet refMap = new JBitSet(numTables);
573:                        /* Do not consider method calls, 
574:                         * conditionals, field references, etc. */
575:                        if (!(left.categorize(refMap, true))) {
576:                            vn = and.getRightOperand();
577:                            continue;
578:                        }
579:
580:                        /* If the predicate is a null intolerant predicate
581:                         * on the right side then we can flatten to an
582:                         * inner join.  We do the xform here, flattening
583:                         * will happen later.
584:                         */
585:                        for (int bit = 0; bit < numTables; bit++) {
586:                            if (refMap.get(bit) && innerMap.get(bit)) {
587:                                // OJ -> IJ
588:                                JoinNode ij = (JoinNode) getNodeFactory()
589:                                        .getNode(C_NodeTypes.JOIN_NODE,
590:                                                leftResultSet, rightResultSet,
591:                                                joinClause, null,
592:                                                resultColumns, null, null,
593:                                                getContextManager());
594:                                ij.setTableNumber(tableNumber);
595:                                ij.setSubqueryList(subqueryList);
596:                                ij.setAggregateVector(aggregateVector);
597:                                return ij;
598:                            }
599:                        }
600:                    }
601:
602:                    vn = and.getRightOperand();
603:                }
604:
605:                /* We can't transform this node, so tell both sides of the 
606:                 * outer join that they can't get flattened into outer query block.
607:                 */
608:                leftResultSet.notFlattenableJoin();
609:                rightResultSet.notFlattenableJoin();
610:
611:                return this ;
612:            }
613:
614:            /** @see JoinNode#adjustNumberOfRowsReturned */
615:            protected void adjustNumberOfRowsReturned(CostEstimate costEstimate) {
616:                /*
617:                 ** An outer join returns at least as many rows as in the outer
618:                 ** table. Even if this started as a right outer join, it will
619:                 ** have been transformed to a left outer join by this point.
620:                 */
621:                CostEstimate outerCost = getLeftResultSet().getCostEstimate();
622:
623:                if (costEstimate.rowCount() < outerCost.rowCount()) {
624:                    costEstimate.setCost(costEstimate.getEstimatedCost(),
625:                            outerCost.rowCount(), outerCost.rowCount());
626:                }
627:            }
628:
629:            /**
630:             * Generate the code for an inner join node.
631:             *
632:             * @exception StandardException		Thrown on error
633:             */
634:            public void generate(ActivationClassBuilder acb, MethodBuilder mb)
635:                    throws StandardException {
636:                /* Verify that a user specifed right outer join is transformed into
637:                 * a left outer join exactly once.
638:                 */
639:                if (SanityManager.DEBUG) {
640:                    SanityManager.ASSERT(rightOuterJoin == transformed,
641:                            "rightOuterJoin (" + rightOuterJoin
642:                                    + ") is expected to equal transformed ("
643:                                    + transformed + ")");
644:                }
645:                super .generateCore(acb, mb, LEFTOUTERJOIN);
646:            }
647:
648:            /**
649:             * Generate	and add any arguments specifict to outer joins.
650:             * Generate	the methods (and add them as parameters) for
651:             * returning an empty row from 1 or more sides of an outer join,
652:             * if required.  Pass whether or not this was originally a
653:             * right outer join.
654:             *
655:             * @param acb		The ActivationClassBuilder
656:             * @param mb the method the generate code is to go into
657:             *
658:             * return The args that have been added
659:             *
660:             * @exception StandardException		Thrown on error
661:             */
662:            protected int addOuterJoinArguments(ActivationClassBuilder acb,
663:                    MethodBuilder mb) throws StandardException {
664:                /* Nulls always generated from the right */
665:                rightResultSet.getResultColumns().generateNulls(acb, mb);
666:
667:                /* Was this originally a right outer join? */
668:                mb.push(rightOuterJoin);
669:
670:                return 2;
671:            }
672:
673:            /**
674:             * Return the number of arguments to the join result set.
675:             */
676:            protected int getNumJoinArguments() {
677:                /* We add two more arguments than the superclass does */
678:                return super .getNumJoinArguments() + 2;
679:            }
680:
681:            protected void oneRowRightSide(ActivationClassBuilder acb,
682:                    MethodBuilder mb) {
683:                // always return false for now
684:                mb.push(false);
685:                mb.push(false); //isNotExists?
686:            }
687:
688:            /**
689:             * Return the logical left result set for this qualified
690:             * join node.
691:             * (For RIGHT OUTER JOIN, the left is the right
692:             * and the right is the left and the JOIN is the NIOJ).
693:             */
694:            ResultSetNode getLogicalLeftResultSet() {
695:                if (rightOuterJoin) {
696:                    return rightResultSet;
697:                } else {
698:                    return leftResultSet;
699:                }
700:            }
701:
702:            /**
703:             * Return the logical right result set for this qualified
704:             * join node.
705:             * (For RIGHT OUTER JOIN, the left is the right
706:             * and the right is the left and the JOIN is the NIOJ).
707:             */
708:            ResultSetNode getLogicalRightResultSet() {
709:                if (rightOuterJoin) {
710:                    return leftResultSet;
711:                } else {
712:                    return rightResultSet;
713:                }
714:            }
715:
716:            /**
717:             * Return true if right outer join or false if left outer join
718:             * Used to set Nullability correctly in JoinNode
719:             */
720:            public boolean isRightOuterJoin() {
721:                return rightOuterJoin;
722:            }
723:
724:            // return the Null-producing table references
725:            public JBitSet LOJgetNPReferencedTables(int numTables)
726:                    throws StandardException {
727:                if (rightOuterJoin && !transformed)
728:                    return (JBitSet) leftResultSet
729:                            .LOJgetReferencedTables(numTables);
730:                else
731:                    return (JBitSet) rightResultSet
732:                            .LOJgetReferencedTables(numTables);
733:            }
734:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.