Source Code Cross Referenced for SelectExp.java in  » Testing » PolePosition-0.20 » com » versant » core » jdbc » sql » exp » 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 » Testing » PolePosition 0.20 » com.versant.core.jdbc.sql.exp 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998 - 2005 Versant Corporation
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         * Versant Corporation - initial API and implementation
0010:         */
0011:        package com.versant.core.jdbc.sql.exp;
0012:
0013:        import com.versant.core.common.Debug;
0014:        import com.versant.core.metadata.ClassMetaData;
0015:        import com.versant.core.metadata.MDStatics;
0016:        import com.versant.core.jdo.query.*;
0017:        import com.versant.core.jdbc.metadata.*;
0018:        import com.versant.core.jdbc.sql.SqlDriver;
0019:        import com.versant.core.jdbc.query.JDOQLNodeToSqlExp;
0020:        import com.versant.core.jdbc.fetch.FetchSpec;
0021:        import com.versant.core.util.CharBuf;
0022:
0023:        import java.util.Map;
0024:
0025:        import com.versant.core.common.BindingSupportImpl;
0026:
0027:        /**
0028:         * A 'select ... from ... where ... order by ...' expression.
0029:         */
0030:        public class SelectExp extends LeafExp {
0031:            public static final ColumnStruct[] EMPTY_COLUMS_STRUCT = new ColumnStruct[0];
0032:
0033:            /**
0034:             * Linked list of expressions to select (null if none).
0035:             */
0036:            public SqlExp selectList;
0037:            /**
0038:             * Is this a 'select distinct'?
0039:             */
0040:            public boolean distinct;
0041:            /**
0042:             * Is this a 'select for update'?
0043:             */
0044:            public boolean forUpdate;
0045:            /**
0046:             * The table to select from.
0047:             */
0048:            public JdbcTable table;
0049:            /**
0050:             * The field that was navigated to get to this table (null if none).
0051:             */
0052:            public JdbcField jdbcField;
0053:            /**
0054:             * The variable this expression belongs to (null if none).
0055:             */
0056:            public VarNode var;
0057:            /**
0058:             * The alias assigned to our table (null if none).
0059:             */
0060:            public String alias;
0061:            /**
0062:             * The 'join' expression for a sub select (null if none). This will end
0063:             * up in the where clause but is kept separately so nested sub selects can
0064:             * be converted into joins easily.
0065:             */
0066:            public SqlExp subSelectJoinExp;
0067:            /**
0068:             * The where clause expression (null if none).
0069:             */
0070:            public SqlExp whereExp;
0071:            /**
0072:             * Linked list of expressions to order by (null if none).
0073:             */
0074:            public SqlExp orderByList;
0075:            public SqlExp resultList;
0076:            public SqlExp groupByList;
0077:            public HavingExp havingExp;
0078:            /**
0079:             * Is table involved in an outer join as the outer table?
0080:             */
0081:            public boolean outer;
0082:            /**
0083:             * Linked list of joins (null if none). Note that the selectExp for
0084:             * each entry in the list may have its own joinList and so on
0085:             * recusively (i.e. this is actually a tree).
0086:             */
0087:            public Join joinList;
0088:
0089:            /**
0090:             * Index of the first column in the select list as of the last call to
0091:             * appendSQL.
0092:             */
0093:            public int selectListStartIndex;
0094:            /**
0095:             * Index of the last charcter of the first column in the select list + 1
0096:             * as of the last call to appendSQL.
0097:             */
0098:            public int selectListFirstColEndIndex;
0099:            /**
0100:             * Index of the last column in the select list + 1 as of the last call
0101:             * to appendSQL.
0102:             */
0103:            public int selectListEndIndex;
0104:            /**
0105:             * Index of the start of the "order by ..." clause as of the last call to
0106:             * appendSQL.
0107:             */
0108:            public int orderByStartIndex;
0109:            /**
0110:             * Index of the end of the "order by ..." clause + 1 as of the last call to
0111:             * appendSQL.
0112:             */
0113:            public int orderByEndIndex;
0114:
0115:            public int selectListCountBeforeAggregate;
0116:
0117:            public FetchSpec fetchSpec;
0118:
0119:            private static final char ALIAS_PREPEND_CONSTANT = 'x';
0120:
0121:            public SelectExp() {
0122:            }
0123:
0124:            public SqlExp createInstance() {
0125:                return new SelectExp();
0126:            }
0127:
0128:            public SqlExp getClone(SqlExp clone, Map cloneMap) {
0129:                SelectExp cst = (SelectExp) clone;
0130:                super .getClone(cst, cloneMap);
0131:
0132:                if (selectList != null)
0133:                    cst.selectList = createClone(selectList, cloneMap);
0134:                cst.distinct = distinct;
0135:                cst.forUpdate = forUpdate;
0136:                cst.table = table;
0137:                cst.jdbcField = jdbcField;
0138:                cst.var = var;
0139:                cst.alias = alias;
0140:                if (subSelectJoinExp != null)
0141:                    cst.subSelectJoinExp = createClone(subSelectJoinExp,
0142:                            cloneMap);
0143:                if (whereExp != null)
0144:                    cst.whereExp = createClone(whereExp, cloneMap);
0145:                if (orderByList != null)
0146:                    cst.orderByList = createClone(orderByList, cloneMap);
0147:                cst.outer = outer;
0148:                if (joinList != null)
0149:                    cst.joinList = joinList.getClone(cloneMap);
0150:                cst.selectListStartIndex = selectListStartIndex;
0151:                cst.selectListEndIndex = selectListEndIndex;
0152:                cst.orderByStartIndex = orderByStartIndex;
0153:                cst.orderByEndIndex = orderByEndIndex;
0154:
0155:                return cst;
0156:            }
0157:
0158:            public String toString() {
0159:                return super .toString() + (outer ? " OUTER " : " ")
0160:                        + table.name
0161:                        + (alias == null ? "" : "aliased to " + alias)
0162:                        + (jdbcField != null ? " " + jdbcField : "")
0163:                        + (var != null ? " " + var : "");
0164:            }
0165:
0166:            /**
0167:             * Count the number of columns in the select list and all joined to lists.
0168:             */
0169:            public int getSelectListColumnCount() {
0170:                if (selectList == null)
0171:                    return 0;
0172:                int count = 0;
0173:                for (SqlExp se = selectList; se != null; se = se.next) {
0174:                    count++;
0175:                }
0176:                count += countSelect(joinList);
0177:                return count;
0178:            }
0179:
0180:            /**
0181:             * Dump debugging info to System.out.
0182:             */
0183:            public void dump(String indent) {
0184:                Debug.OUT.println(indent + this );
0185:                String is = indent + "  ";
0186:                if (selectList != null) {
0187:                    Debug.OUT.println(indent + "selectList");
0188:                    selectList.dumpList(is);
0189:                }
0190:                if (joinList != null) {
0191:                    Debug.OUT.println(indent + "joinList");
0192:                    joinList.dumpList(is);
0193:                }
0194:                if (subSelectJoinExp != null) {
0195:                    Debug.OUT.println(indent + "subSelectJoinExp");
0196:                    subSelectJoinExp.dump(is);
0197:                }
0198:                if (whereExp != null) {
0199:                    Debug.OUT.println(indent + "whereExp");
0200:                    whereExp.dump(is);
0201:                }
0202:                if (orderByList != null) {
0203:                    Debug.OUT.println(indent + "orderByList");
0204:                    orderByList.dumpList(is);
0205:                }
0206:            }
0207:
0208:            /**
0209:             * Add a Join to end of the joinList.
0210:             */
0211:            public void addJoin(Join join) {
0212:                if (joinList == null) {
0213:                    joinList = join;
0214:                } else {
0215:                    for (Join j = joinList;;) {
0216:                        Join next = j.next;
0217:                        if (next == null) {
0218:                            j.next = join;
0219:                            return;
0220:                        }
0221:                        j = next;
0222:                    }
0223:                }
0224:            }
0225:
0226:            /**
0227:             * Add a Join to end of the joinList. This is an attempt to not add uncess.
0228:             * joins.
0229:             */
0230:            public void addJoinMerge(Join aJoin) {
0231:                Join origJoin = aJoin;
0232:                if (joinList == null) {
0233:                    joinList = aJoin;
0234:                } else {
0235:                    getTailJoin(joinList).next = aJoin;
0236:                    addJoinImp(joinList, aJoin, origJoin);
0237:                }
0238:            }
0239:
0240:            private static Join getPrevJoin(Join joinList, Join aJoin) {
0241:                if (joinList.next == null) {
0242:                    throw BindingSupportImpl.getInstance().internal("");
0243:                }
0244:
0245:                for (Join j = joinList;;) {
0246:                    if (j.next == aJoin) {
0247:                        return j;
0248:                    }
0249:                    j = j.next;
0250:                    if (j == null)
0251:                        return null;
0252:                }
0253:            }
0254:
0255:            private static Join getTailJoin(Join joinList) {
0256:                for (Join j = joinList;;) {
0257:                    if (j.next == null)
0258:                        return j;
0259:                    j = j.next;
0260:                }
0261:            }
0262:
0263:            private static void addJoinImp(Join currentJoin, Join aJoinToAdd,
0264:                    Join origJoin) {
0265:                Join j = currentJoin;
0266:                Join restartJoin = null;
0267:                Join stopJoin = getTailJoin(currentJoin);
0268:                for (; j != null;) {
0269:                    if (aJoinToAdd == null) {
0270:                        break;
0271:                    }
0272:                    if (Join.isCurrentEqaul(j, aJoinToAdd)) {
0273:                        /**
0274:                         * Update the whereExp of the origJoin with the new selectExp
0275:                         */
0276:                        if (origJoin.selectExp.whereExp != null) {
0277:                            origJoin.selectExp.whereExp.replaceSelectExpRef(
0278:                                    origJoin.selectExp, j.selectExp);
0279:                        }
0280:
0281:                        Join subCurrentJoin = j.selectExp.joinList;
0282:                        Join subJoinToAdd = aJoinToAdd.selectExp.joinList;
0283:
0284:                        if (subCurrentJoin == null && subJoinToAdd == null) {
0285:                        } else if (subJoinToAdd == null) {
0286:                        } else if (subCurrentJoin == null) {
0287:                            //just set it
0288:                            j.selectExp.joinList = aJoinToAdd.selectExp.joinList;
0289:                            ((JoinExp) aJoinToAdd.selectExp.joinList.exp)
0290:                                    .setLeftTable(j.selectExp);
0291:                        } else {
0292:                            addJoinImp(subJoinToAdd, subCurrentJoin, origJoin);
0293:                        }
0294:                        Join tmpJoin = aJoinToAdd.next;
0295:                        /**
0296:                         * Fix up the lList
0297:                         */
0298:                        getPrevJoin(currentJoin, aJoinToAdd).next = aJoinToAdd.next;
0299:                        aJoinToAdd.next = null;
0300:
0301:                        aJoinToAdd = tmpJoin;
0302:                        j = j.next;
0303:                    } else {
0304:                        if (j.next == stopJoin) {
0305:                            //no match found so move to next aJoinToAdd and to currentJoin
0306:                            aJoinToAdd = aJoinToAdd.next;
0307:                            j = restartJoin;
0308:                        } else {
0309:                            j = j.next;
0310:                        }
0311:                    }
0312:
0313:                }
0314:            }
0315:
0316:            /**
0317:             * Add a join to the end of the join list.
0318:             */
0319:            public Join addJoin(JdbcColumn[] leftCols, JdbcColumn[] rightCols,
0320:                    SelectExp right) {
0321:                if (Debug.DEBUG) {
0322:                    System.out.println("SelectExp.addJoin from " + table.name
0323:                            + " to " + right.table.name);
0324:                    String join = "";
0325:                    if (right.outer) {
0326:                        join = "OUTER";
0327:                    } else {
0328:                        join = "INNER";
0329:                    }
0330:                    System.out.println("--- SelectExp.addJoin from "
0331:                            + leftCols[0].table.name + " -- " + join + " --> "
0332:                            + right.table.name);
0333:                }
0334:                Join j = new Join();
0335:                j.exp = createJoinExp(leftCols, rightCols, right);
0336:                j.selectExp = right;
0337:                addJoin(j);
0338:                return j;
0339:            }
0340:
0341:            /**
0342:             * Search our join list for a join for the field. This is not recursive
0343:             * i.e. it only finds joins in our join list. Returns null if not found.
0344:             * @see #findJoinRec(com.versant.core.jdbc.metadata.JdbcField)
0345:             */
0346:            public Join findJoin(JdbcField jdbcField) {
0347:                for (Join j = joinList; j != null; j = j.next) {
0348:                    if (j.selectExp.jdbcField == jdbcField)
0349:                        return j;
0350:                }
0351:                return null;
0352:            }
0353:
0354:            /**
0355:             * Find a join by table and refField.
0356:             */
0357:            public Join findJoin(JdbcTable table, JdbcField jdbcField) {
0358:                for (Join j = joinList; j != null; j = j.next) {
0359:                    if (j.selectExp.jdbcField == jdbcField
0360:                            && j.selectExp.table == table)
0361:                        return j;
0362:                }
0363:                return null;
0364:            }
0365:
0366:            public SelectExp findTableRecursive(JdbcTable t, JdbcField field) {
0367:                if (t == table && jdbcField == field)
0368:                    return this ;
0369:                for (Join j = joinList; j != null; j = j.next) {
0370:                    if (j.selectExp.table == t
0371:                            && j.selectExp.jdbcField == field)
0372:                        return j.selectExp;
0373:                }
0374:
0375:                for (Join j = joinList; j != null; j = j.next) {
0376:                    SelectExp se = j.selectExp.findTableRecursive(t, field);
0377:                    if (se != null)
0378:                        return se;
0379:                }
0380:                return null;
0381:            }
0382:
0383:            /**
0384:             * Recursively search our join list for a join for the field. Returns null
0385:             * if not found.
0386:             * @see #findJoin(com.versant.core.jdbc.metadata.JdbcField)
0387:             */
0388:            public Join findJoinRec(JdbcField jdbcField) {
0389:                for (Join j = joinList; j != null; j = j.next) {
0390:                    if (j.selectExp.jdbcField == jdbcField)
0391:                        return j;
0392:                    Join ans = j.selectExp.findJoinRec(jdbcField);
0393:                    if (ans != null)
0394:                        return ans;
0395:                }
0396:                return null;
0397:            }
0398:
0399:            /**
0400:             * Search our join list for a join to the expression. This is not recursive
0401:             * i.e. it only finds joins in our join list. Returns null if not found.
0402:             */
0403:            public Join findJoin(SelectExp se) {
0404:                for (Join j = joinList; j != null; j = j.next) {
0405:                    if (j.selectExp == se)
0406:                        return j;
0407:                }
0408:                return null;
0409:            }
0410:
0411:            /**
0412:             * If our table is t then return this. Otherwise search our join list
0413:             * for a join for the table. This is not recursive i.e. it only finds
0414:             * tables in our join list. Returns null if not found.
0415:             */
0416:            public SelectExp findTable(JdbcTable t) {
0417:                if (t == table) {
0418:                    return this ;
0419:                }
0420:                for (Join j = joinList; j != null; j = j.next) {
0421:                    if (j.selectExp.table == t) {
0422:                        return j.selectExp;
0423:                    }
0424:                }
0425:                return null;
0426:            }
0427:
0428:            public SelectExp findTableRecursive(JdbcTable t) {
0429:                if (t == table)
0430:                    return this ;
0431:                for (Join j = joinList; j != null; j = j.next) {
0432:                    if (j.selectExp.table == t)
0433:                        return j.selectExp;
0434:                }
0435:
0436:                for (Join j = joinList; j != null; j = j.next) {
0437:                    SelectExp se = j.selectExp.findTable(t);
0438:                    if (se != null)
0439:                        return se;
0440:                }
0441:                return null;
0442:            }
0443:
0444:            /**
0445:             * Create an expression to join us to right.
0446:             */
0447:            public SqlExp createJoinExp(JdbcColumn[] leftCols,
0448:                    JdbcColumn[] rightCols, SelectExp right) {
0449:                if (leftCols.length == 1) {
0450:                    return new JoinExp(leftCols[0], this , rightCols[0], right);
0451:                } else {
0452:                    JoinExp first = new JoinExp(leftCols[0], this ,
0453:                            rightCols[0], right);
0454:                    int nc = leftCols.length;
0455:                    SqlExp j = first;
0456:                    for (int i = 1; i < nc; i++) {
0457:                        j = j.next = new JoinExp(leftCols[i], this ,
0458:                                rightCols[i], right);
0459:                    }
0460:                    return new AndJoinExp(first);
0461:                }
0462:            }
0463:
0464:            public Join getLastJoin() {
0465:                for (Join j = joinList; j != null; j = j.next) {
0466:                    if (j.next == null) {
0467:                        return j;
0468:                    }
0469:                }
0470:                return null;
0471:            }
0472:
0473:            /**
0474:             * Create an aliases for any tables we may have if we do not already have
0475:             * an alias.
0476:             */
0477:            public int createAlias(int index) {
0478:                if (alias == null) {
0479:                    if (index < 26) {
0480:                        alias = new String(new char[] { (char) (index + 'a') });
0481:                    } else {
0482:                        alias = "t" + index;
0483:                    }
0484:                    ++index;
0485:                    for (Join j = joinList; j != null; j = j.next) {
0486:                        index = j.createAlias(index);
0487:                    }
0488:                    for (SqlExp e = whereExp; e != null; e = e.next) {
0489:                        index = e.createAlias(index);
0490:                    }
0491:                }
0492:                return index;
0493:            }
0494:
0495:            /**
0496:             * Replace any references to old with nw. This is used when redundant
0497:             * joins are removed.
0498:             */
0499:            public void replaceSelectExpRef(SelectExp old, SelectExp nw) {
0500:                if (whereExp != null)
0501:                    whereExp.replaceSelectExpRef(old, nw);
0502:                if (subSelectJoinExp != null)
0503:                    subSelectJoinExp.replaceSelectExpRef(old, nw);
0504:            }
0505:
0506:            /**
0507:             * Normalize this node i.e. transform it into its simplist possible form.
0508:             * This will turn sub selects into joins and so on.
0509:             */
0510:            public SqlExp normalize(SqlDriver driver, SelectExp sel,
0511:                    boolean convertExists) {
0512:                for (Join j = joinList; j != null; j = j.next) {
0513:                    SelectExp se = j.selectExp;
0514:                    se.normalize(driver, sel, convertExists);
0515:                    if (convertExists && se.whereExp != null) {
0516:                        j.findDeepestJoin().appendJoinExp(se.whereExp);
0517:                        se.whereExp = null;
0518:                    }
0519:                }
0520:
0521:                if (whereExp == null)
0522:                    return null;
0523:                SqlExp r = whereExp.normalize(driver, this , convertExists);
0524:                if (r != null)
0525:                    whereExp = r;
0526:
0527:                int cj = whereExp.getConvertToJoin();
0528:                if (cj == SqlExp.YES
0529:                        || (convertExists && cj >= SqlExp.YES_DISTINCT)) {
0530:                    // convert to join
0531:                    boolean not = convertExists
0532:                            && cj == SqlExp.YES_DISTINCT_NOT;
0533:                    SelectExp sub;
0534:                    if (not) {
0535:                        sub = (SelectExp) (whereExp.childList.childList);
0536:                    } else {
0537:                        sub = (SelectExp) (whereExp.childList);
0538:                    }
0539:                    if (sub != null) {
0540:                        Join j = new Join();
0541:                        j.selectExp = sub;
0542:                        j.exp = sub.subSelectJoinExp;
0543:                        sub.subSelectJoinExp = null;
0544:                        if (sub.whereExp != null) { // add to join clause
0545:                            Join jj = j;
0546:                            for (;; jj = jj.selectExp.joinList) {
0547:                                if (jj.selectExp.joinList == null)
0548:                                    break;
0549:                            }
0550:                            jj.appendJoinExp(sub.whereExp);
0551:                            sub.whereExp = null;
0552:                        }
0553:                        addJoin(j);
0554:                    }
0555:                    if (not) {
0556:                        sub.outer = true;
0557:                        whereExp = sub.getOuterJoinNotMatchedExp();
0558:                    } else {
0559:                        whereExp = null;
0560:                    }
0561:                    if (cj >= SqlExp.YES_DISTINCT)
0562:                        distinct = true;
0563:                    return null;
0564:                }
0565:                return null;
0566:            }
0567:
0568:            /**
0569:             * Append SQL for this node to s.
0570:             *
0571:             * @param driver The driver being used
0572:             * @param s      Append the SQL here
0573:             * @param leftSibling
0574:             */
0575:            public void appendSQLImp(SqlDriver driver, CharBuf s,
0576:                    SqlExp leftSibling) {
0577:                // put in the select list (ours and all of our join tables)
0578:                boolean putOrderColsInSelect = driver.isPutOrderColsInSelect();
0579:                boolean selectListAppendedWithOrderByExp = false;
0580:
0581:                //Create a ColumnStruct[] for all the fields in the 'order by' exp.
0582:                ColumnStruct[] orderByStruct = createColumnStruct(orderByList);
0583:
0584:                int start = s.size();
0585:                if (distinct)
0586:                    s.append("SELECT DISTINCT ");
0587:                else
0588:                    s.append("SELECT ");
0589:                selectListStartIndex = s.size();
0590:                int colCount = appendFirstSelect(selectList, driver, s);
0591:                colCount += appendSelect(joinList, driver, s);
0592:                if (Debug.DEBUG) {
0593:                    if (colCount != getSelectListColumnCount()) {
0594:                        throw BindingSupportImpl.getInstance().internal("");
0595:                    }
0596:                }
0597:
0598:                if (orderByList != null) {
0599:                    if (putOrderColsInSelect
0600:                            || (groupByList != null && driver
0601:                                    .putOrderColsInGroupBy())) {
0602:                        selectListAppendedWithOrderByExp = appendSelectForOrderBy(
0603:                                orderByList, driver, s, orderByStruct);
0604:                    }
0605:                }
0606:
0607:                finishSelectList(s, start);
0608:                selectListEndIndex = s.size();
0609:
0610:                // put in the from list
0611:                s.append(" FROM ");
0612:                driver.appendSqlFrom(table, alias, s);
0613:                appendFrom(joinList, driver, s);
0614:
0615:                // put all the expressions for the where clause into a list
0616:                SqlExp list = new SqlExp();
0617:                SqlExp pos = list;
0618:                if (subSelectJoinExp != null)
0619:                    pos = pos.next = subSelectJoinExp;
0620:                if (!driver.isAnsiJoinSyntax()) {
0621:                    findWhereExp(findWhereJoinExp(pos));
0622:                } else {
0623:                    findWhereExp(pos);
0624:                }
0625:
0626:                // build a single expression from this list (joins exps with and)
0627:                SqlExp exp = merge(list.next);
0628:                if (exp != null) {
0629:                    s.append(" WHERE ");
0630:                    exp.appendSQL(driver, s, null);
0631:                }
0632:
0633:                exp = groupByList;
0634:                int gIndex = 1;
0635:                if (exp != null) {
0636:                    boolean this Done = false;
0637:                    s.append(" GROUP BY ");
0638:                    for (;;) {
0639:                        if (gIndex > 1) {
0640:                            s.append(',');
0641:                            s.append(' ');
0642:                        }
0643:                        if (exp instanceof  GroupByThisExp) {
0644:                            if (!this Done) {
0645:                                this Done = true;
0646:                                appendFirstSelect(selectList, driver, s,
0647:                                        selectListCountBeforeAggregate);
0648:                                appendSelect(joinList, driver, s);
0649:                            }
0650:                        } else {
0651:                            // The group by list can contain ColumnExp and OrderExp
0652:                            // expressions. The OrderExp's just wrap a ColumnExp and
0653:                            // add a descending indicator.
0654:                            ColumnExp ce;
0655:                            if (exp instanceof  ColumnExp) {
0656:                                ce = (ColumnExp) exp;
0657:                            } else {
0658:                                ce = (ColumnExp) exp.childList;
0659:                            }
0660:
0661:                            if (ce.isAliasedColumn()) {
0662:                                exp.appendSQL(driver, s, null);
0663:                            } else if (driver.useColumnIndexForGroupBy()) {
0664:                                int i = findIndexInSelectList(selectList,
0665:                                        ce.selectExp, ce.col.name);
0666:                                if (i >= 0) {
0667:                                    s.append(i);
0668:                                } else {
0669:                                    exp.appendSQL(driver, s, null);
0670:                                }
0671:                            } else {
0672:                                exp.appendSQL(driver, s, null);
0673:                            }
0674:                        }
0675:                        gIndex++;
0676:                        if ((exp = exp.next) == null)
0677:                            break;
0678:                    }
0679:                }
0680:
0681:                //update the groupBy expression with fields that was added to the selectlist
0682:                if (selectListAppendedWithOrderByExp && groupByList != null) {
0683:                    appendGroupBy(s, orderByStruct, gIndex == 1, driver);
0684:                }
0685:
0686:                exp = havingExp;
0687:                if (exp != null) {
0688:                    havingExp.appendSQL(driver, s, null);
0689:                }
0690:
0691:                // put in the order by list
0692:                exp = orderByList;
0693:                if (exp != null) {
0694:                    orderByStartIndex = s.size();
0695:                    s.append(" ORDER BY ");
0696:                    if (driver.isUseIndexesForOrderCols()) {
0697:                        int index = 1;
0698:                        boolean first = true;
0699:                        for (;;) {
0700:                            if (first) {
0701:                                first = false;
0702:                            } else {
0703:                                s.append(',');
0704:                                s.append(' ');
0705:                            }
0706:                            // The order by list can contain ColumnExp and OrderExp
0707:                            // expressions. The OrderExp's just wrap a ColumnExp and
0708:                            // add a descending indicator.
0709:                            ColumnExp ce;
0710:                            if (exp instanceof  ColumnExp) {
0711:                                ce = (ColumnExp) exp;
0712:                            } else {
0713:                                ce = (ColumnExp) exp.childList;
0714:                            }
0715:
0716:                            if (ce.isAliasedColumn()) {
0717:                                exp.appendSQL(driver, s, null);
0718:                            } else {
0719:                                ColumnStruct colStruct = orderByStruct[index - 1];
0720:                                int i = colStruct.indexInSelectList;
0721:                                if (i > 0) {
0722:                                    s.append(i);
0723:                                    if (ce != exp) { // exp is OrderExp as it is not ColumnExp
0724:                                        OrderExp oe = (OrderExp) exp;
0725:                                        if (oe.isDesc())
0726:                                            s.append(" DESC");
0727:                                    }
0728:                                } else {
0729:                                    //if appended to selectList
0730:                                    if (colStruct.columnNme != null) {
0731:                                        if (driver.useColAliasForAddedCols()) {
0732:                                            s.append(colStruct.alias);
0733:                                        } else {
0734:                                            s.append(colStruct.columnNme);
0735:                                        }
0736:
0737:                                        if (ce != exp) { // exp is OrderExp as it is not ColumnExp
0738:                                            OrderExp oe = (OrderExp) exp;
0739:                                            if (oe.isDesc())
0740:                                                s.append(" DESC");
0741:                                        }
0742:                                    } else {
0743:                                        exp.appendSQL(driver, s, null);
0744:                                    }
0745:                                }
0746:                            }
0747:                            index++;
0748:                            if ((exp = exp.next) == null)
0749:                                break;
0750:                        }
0751:                    } else {
0752:                        //use the column name
0753:                        int index = 1;
0754:                        boolean first = true;
0755:                        for (; exp != null; exp = exp.next) {
0756:                            if (first) {
0757:                                first = false;
0758:                            } else {
0759:                                s.append(',');
0760:                                s.append(' ');
0761:                            }
0762:                            ColumnExp ce;
0763:                            if (exp instanceof  ColumnExp) {
0764:                                ce = (ColumnExp) exp;
0765:                            } else {
0766:                                ce = (ColumnExp) exp.childList;
0767:                            }
0768:                            if (ce.isAliasedColumn()) {
0769:                                exp.appendSQL(driver, s, null);
0770:                            } else {
0771:                                ColumnStruct colStruct = orderByStruct[index - 1];
0772:                                int i = colStruct.indexInSelectList;
0773:                                if (i > 0) {
0774:                                    exp.appendSQL(driver, s, null);
0775:                                } else {
0776:                                    if (selectListAppendedWithOrderByExp) {
0777:                                        if (driver.useColAliasForAddedCols()) {
0778:                                            s.append(colStruct.alias);
0779:                                        } else {
0780:                                            s.append(colStruct.columnNme);
0781:                                        }
0782:                                        if (ce != exp) { // exp is OrderExp as it is not ColumnExp
0783:                                            OrderExp oe = (OrderExp) exp;
0784:                                            if (oe.isDesc())
0785:                                                s.append(" DESC");
0786:                                        }
0787:                                    } else {
0788:                                        exp.appendSQL(driver, s, null);
0789:                                    }
0790:                                }
0791:                            }
0792:                            index++;
0793:                        }
0794:                    }
0795:                    orderByEndIndex = s.size();
0796:                } else {
0797:                    orderByStartIndex = orderByEndIndex = 0;
0798:                }
0799:
0800:                if (forUpdate
0801:                        && (!distinct || driver
0802:                                .isSelectForUpdateWithDistinctOk())) {
0803:                    char[] a = driver.getSelectForUpdate();
0804:                    if (a != null) {
0805:                        s.append(a);
0806:                        if (driver.isSelectForUpdateAppendTable()) {
0807:                            if (alias == null) {
0808:                                s.append(table.name);
0809:                            } else {
0810:                                s.append(alias);
0811:                            }
0812:                        }
0813:                    }
0814:                }
0815:            }
0816:
0817:            /**
0818:             * Find the index of a matching entry (i.e. same column from same table)
0819:             * in the select list (first is 1) for ce or -1 if none found.
0820:             */
0821:            private int findIndexInSelectList(SqlExp toSearch, SelectExp se,
0822:                    String name) {
0823:                int[] indexArray = new int[2];
0824:                findIndexInSelectListImp(toSearch, se, name, indexArray);
0825:
0826:                if (indexArray[1] == 0) {
0827:                    //must check more
0828:                    findIndexInJoin(joinList, se, name, indexArray);
0829:                }
0830:
0831:                if (indexArray[1] == 1) {
0832:                    return indexArray[0] + 1;
0833:                } else {
0834:                    return -1;
0835:                }
0836:            }
0837:
0838:            private void findIndexInJoin(Join j, SelectExp exp, String name,
0839:                    int[] index) {
0840:                for (; j != null; j = j.next) {
0841:                    SelectExp se = j.selectExp;
0842:                    findIndexInSelectListImp(se.selectList, exp, name, index);
0843:
0844:                    if (index[1] == 0) {
0845:                        findIndexInJoin(se.joinList, exp, name, index);
0846:                    }
0847:                    break;
0848:                }
0849:            }
0850:
0851:            private void findIndexInSelectListImp(SqlExp se, SelectExp exp,
0852:                    String name, int[] index) {
0853:                for (SqlExp e = se; e != null; e = e.next, index[0]++) {
0854:                    if (e instanceof  ColumnExp) {
0855:                        ColumnExp ce = (ColumnExp) e;
0856:                        if (ce.selectExp == exp && ce.col.name.equals(name)) {
0857:                            index[1] = 1;
0858:                            return;
0859:                        }
0860:                    }
0861:                }
0862:            }
0863:
0864:            private static boolean isDesc(SqlExp e) {
0865:                return e instanceof  OrderExp && ((OrderExp) e).isDesc();
0866:            }
0867:
0868:            /**
0869:             * Check that the select list is valid.
0870:             */
0871:            protected void finishSelectList(CharBuf s, int start) {
0872:                int sz = s.size();
0873:                int n = sz - start;
0874:                if (n <= 7) {
0875:                    if (start == 0) {
0876:                        throw BindingSupportImpl.getInstance().internal(
0877:                                "no columns in select list");
0878:                    }
0879:                    s.append('1');
0880:                } else {
0881:                    s.setSize(sz - 2); // remove the extra comma and space
0882:                }
0883:            }
0884:
0885:            /**
0886:             * Recursively append the select lists for all the joins to s using a
0887:             * depth first traversal. NOP if j is null.
0888:             */
0889:            private int appendSelect(Join j, SqlDriver driver, CharBuf s) {
0890:                int count = 0;
0891:                for (; j != null; j = j.next) {
0892:                    SelectExp se = j.selectExp;
0893:                    count += appendSelect(se.selectList, driver, s);
0894:                    count += appendSelect(se.joinList, driver, s);
0895:                }
0896:                return count;
0897:            }
0898:
0899:            /**
0900:             * Recursively count the colums of all joined to selectExp's selectList.
0901:             */
0902:            private int countSelect(Join j) {
0903:                int count = 0;
0904:                for (; j != null; j = j.next) {
0905:                    SelectExp se = j.selectExp;
0906:                    count += countSelect(se.selectList);
0907:                    count += countSelect(se.joinList);
0908:                }
0909:                return count;
0910:            }
0911:
0912:            /**
0913:             * Append all the expressions in the list starting at e. NOP if e is null.
0914:             * Follow each expression with ', '. Record the last index of
0915:             */
0916:            private int appendFirstSelect(SqlExp e, SqlDriver driver, CharBuf s) {
0917:                if (e == null)
0918:                    return 0;
0919:                int count = 1;
0920:                e.appendSQL(driver, s, null);
0921:                selectListFirstColEndIndex = s.size();
0922:                s.append(',');
0923:                s.append(' ');
0924:                for (e = e.next; e != null; e = e.next) {
0925:                    e.appendSQL(driver, s, null);
0926:                    s.append(',');
0927:                    s.append(' ');
0928:                    count++;
0929:                }
0930:                return count;
0931:            }
0932:
0933:            private void appendFirstSelect(SqlExp e, SqlDriver driver,
0934:                    CharBuf s, int columnCount) {
0935:                if (e == null)
0936:                    return;
0937:                e.appendSQL(driver, s, null);
0938:                selectListFirstColEndIndex = s.size();
0939:                int count = 1;
0940:                for (e = e.next; e != null; e = e.next) {
0941:                    if (count++ >= columnCount)
0942:                        break;
0943:                    s.append(',');
0944:                    s.append(' ');
0945:                    e.appendSQL(driver, s, null);
0946:                }
0947:            }
0948:
0949:            /**
0950:             * Append all the expressions in the list starting at e. NOP if e is null.
0951:             * Follow each expression with ', '.
0952:             */
0953:            private int appendSelect(SqlExp e, SqlDriver driver, CharBuf s) {
0954:                int count = 0;
0955:                for (; e != null; e = e.next) {
0956:                    count++;
0957:                    e.appendSQL(driver, s, null);
0958:                    s.append(',');
0959:                    s.append(' ');
0960:                }
0961:                return count;
0962:            }
0963:
0964:            private int countSelect(SqlExp e) {
0965:                int count = 0;
0966:                for (; e != null; e = e.next) {
0967:                    count++;
0968:                }
0969:                return count;
0970:            }
0971:
0972:            /**
0973:             * Append all the expressions in the list starting at e. NOP if e is null.
0974:             * Follow each expression with an alias and ', '. This is used to add
0975:             * columns used in the order by to the select list for databases that
0976:             * require this e.g. informix.
0977:             */
0978:            private boolean appendSelectForOrderBy(SqlExp e, SqlDriver driver,
0979:                    CharBuf s, ColumnStruct[] columnStructs) {
0980:                boolean appended = false;
0981:                int c = 1;
0982:                for (; e != null; e = e.next) {
0983:                    ColumnStruct colStruct = columnStructs[c - 1];
0984:                    if (colStruct.indexInSelectList == -1) {
0985:                        int offset = s.size();
0986:                        if (e instanceof  OrderExp) {
0987:                            e.childList.appendSQL(driver, s, null);
0988:                        } else {
0989:                            e.appendSQL(driver, s, null);
0990:                        }
0991:                        colStruct.columnNme = s.toString(offset, s.size()
0992:                                - offset);
0993:                        colStruct.alias = ALIAS_PREPEND_CONSTANT + "j" + c;
0994:
0995:                        //not in select list
0996:                        s.append(driver.getAliasPrepend());
0997:                        s.append(colStruct.alias);
0998:                        s.append(',');
0999:                        s.append(' ');
1000:                        appended = true;
1001:                    }
1002:                    c++;
1003:                }
1004:                return appended;
1005:            }
1006:
1007:            private ColumnStruct[] createColumnStruct(SqlExp e) {
1008:                SqlExp startExp = e;
1009:                int count = 0;
1010:                for (; e != null; e = e.next) {
1011:                    count++;
1012:                }
1013:                if (count == 0)
1014:                    return EMPTY_COLUMS_STRUCT;
1015:                ColumnStruct[] colStructs = new ColumnStruct[count];
1016:                count = 0;
1017:                e = startExp;
1018:                for (; e != null; e = e.next) {
1019:                    ColumnExp ce;
1020:                    if (e instanceof  ColumnExp) {
1021:                        ce = (ColumnExp) e;
1022:                    } else {
1023:                        ce = (ColumnExp) e.childList;
1024:                    }
1025:                    if (ce.isAliasedColumn()) {
1026:                        colStructs[count++] = new ColumnStruct(0);
1027:                    } else {
1028:                        colStructs[count++] = new ColumnStruct(
1029:                                findIndexInSelectList(selectList, ce.selectExp,
1030:                                        ce.col.name));
1031:                    }
1032:
1033:                }
1034:                return colStructs;
1035:            }
1036:
1037:            /**
1038:             * This is a struct to hold information about the order by columns that were added.
1039:             */
1040:            private class ColumnStruct {
1041:                /**
1042:                 * The alias of the appended column.
1043:                 */
1044:                String alias;
1045:                /**
1046:                 * The columnName of the appended column. This field is only filled in
1047:                 * if this column was appended to the original select exp.
1048:                 */
1049:                String columnNme;
1050:                /**
1051:                 * The index of this column in the select list.
1052:                 */
1053:                int indexInSelectList;
1054:
1055:                public ColumnStruct(int indexInSelectList) {
1056:                    this .indexInSelectList = indexInSelectList;
1057:                }
1058:            }
1059:
1060:            /**
1061:             * Some drivers will automatically add fields that are in the orderBy
1062:             * to the select exp. This method must check to see if these fields
1063:             * are in the groupby and if not it must be added.
1064:             */
1065:            private void appendGroupBy(CharBuf s, ColumnStruct[] columnStructs,
1066:                    boolean first, SqlDriver driver) {
1067:                for (int i = 0; i < columnStructs.length; i++) {
1068:                    ColumnStruct columnStruct = columnStructs[i];
1069:                    if (columnStruct.columnNme != null) {
1070:                        if (first) {
1071:                            first = false;
1072:                        } else {
1073:                            s.append(',');
1074:                        }
1075:                        if (driver.useColAliasForAddedCols()) {
1076:                            s.append(columnStruct.alias);
1077:                        } else {
1078:                            s.append(columnStruct.columnNme);
1079:                        }
1080:                    }
1081:                }
1082:            }
1083:
1084:            /**
1085:             * Recursively append the from list entries for all the joins to s using a
1086:             * depth first traversal. NOP if j is null.
1087:             */
1088:            private void appendFrom(Join j, SqlDriver driver, CharBuf s) {
1089:                for (; j != null; j = j.next) {
1090:                    SelectExp se = j.selectExp;
1091:                    if (j.isMerged())
1092:                        continue;
1093:                    driver.appendSqlFromJoin(se.table, se.alias, j.exp,
1094:                            se.outer, s);
1095:                    appendFrom(se.joinList, driver, s);
1096:                }
1097:            }
1098:
1099:            /**
1100:             * Recursively add all where expressions we can find to list and
1101:             * return the new head of list.
1102:             */
1103:            private SqlExp findWhereExp(SqlExp list) {
1104:                SqlExp e = whereExp;
1105:                if (e != null)
1106:                    list = list.next = e;
1107:                for (Join j = joinList; j != null; j = j.next) {
1108:                    list = j.selectExp.findWhereExp(list);
1109:                }
1110:                return list;
1111:            }
1112:
1113:            /**
1114:             * Recursively add all join expressions we can find to list and
1115:             * return the new head of list.
1116:             */
1117:            private SqlExp findWhereJoinExp(SqlExp list) {
1118:                for (Join j = joinList; j != null; j = j.next) {
1119:                    SqlExp e = j.exp;
1120:                    if (e != null)
1121:                        list = list.next = e;
1122:                    list = j.selectExp.findWhereJoinExp(list);
1123:                }
1124:                return list;
1125:            }
1126:
1127:            /**
1128:             * Combine a list of expressions into a single expression by anding
1129:             * all the expressions together. This flattens nested 'and' expressions.
1130:             */
1131:            private SqlExp merge(SqlExp first) {
1132:                if (first == null)
1133:                    return null;
1134:                if (first.next == null)
1135:                    return first;
1136:                // flatten enclosed 'and' expressions by adding them to the list
1137:                // and processing their children
1138:                for (SqlExp pos = first; pos != null;) {
1139:                    SqlExp e = pos.next;
1140:                    if (e instanceof  AndExp) {
1141:                        pos = pos.next = e.childList;
1142:                        SqlExp f = pos;
1143:                        for (; f.next != null; f = f.next)
1144:                            ;
1145:                        f.next = e.next;
1146:                    } else {
1147:                        pos = e;
1148:                    }
1149:                }
1150:                return new AndExp(first);
1151:            }
1152:
1153:            /**
1154:             * Set our outer flag and follow all our joins and make then outer as
1155:             * well.
1156:             */
1157:            public void setOuterRec() {
1158:                outer = true;
1159:                for (Join j = joinList; j != null; j = j.next) {
1160:                    j.selectExp.setOuterRec();
1161:                }
1162:            }
1163:
1164:            /**
1165:             * Get an expression that is true if this join does not produce a fully
1166:             * populated row (i.e. one or more of the outer most pk columns are null
1167:             * indicating that an outer join was not matched).
1168:             */
1169:            public SqlExp getOuterJoinNotMatchedExp() {
1170:                if (joinList == null) {
1171:                    return new IsNullExp(table.pk[0].toSqlExp(this ));
1172:                } else if (joinList.next == null) {
1173:                    return joinList.selectExp.getOuterJoinNotMatchedExp();
1174:                } else {
1175:                    // join expressions with OrExp
1176:                    SqlExp root = joinList.selectExp
1177:                            .getOuterJoinNotMatchedExp();
1178:                    SqlExp p = root;
1179:                    for (Join j = joinList.next;;) {
1180:                        p = p.next = j.selectExp.getOuterJoinNotMatchedExp();
1181:                        if ((j = j.next) == null)
1182:                            break;
1183:                    }
1184:                    return new OrExp(root);
1185:                }
1186:            }
1187:
1188:            /**
1189:             * Get an expression that is true if this join produces a fully
1190:             * populated row (i.e. all of the outer most pk columns are not null
1191:             * indicating that all outer joins were matched).
1192:             */
1193:            public SqlExp getOuterJoinMatchedExp() {
1194:                if (joinList == null) {
1195:                    return new IsNotNullExp(table.pk[0].toSqlExp(this ));
1196:                } else if (joinList.next == null) {
1197:                    return joinList.selectExp.getOuterJoinMatchedExp();
1198:                } else {
1199:                    // join expressions with AndExp
1200:                    SqlExp root = joinList.selectExp.getOuterJoinMatchedExp();
1201:                    SqlExp p = root;
1202:                    for (Join j = joinList.next;;) {
1203:                        p = p.next = j.selectExp.getOuterJoinMatchedExp();
1204:                        if ((j = j.next) == null)
1205:                            break;
1206:                    }
1207:                    return new AndExp(root);
1208:                }
1209:            }
1210:
1211:            /**
1212:             * Add an order-by expression this to this select.
1213:             */
1214:            public SqlExp addOrderBy(OrderNode[] orders, boolean append) {
1215:                return addOrderBy(orders, append, JDOQLNodeToSqlExp.INSTANCE);
1216:            }
1217:
1218:            /**
1219:             * Add an order-by expression this to this select.
1220:             */
1221:            public SqlExp addOrderBy(OrderNode[] orders, boolean append,
1222:                    JDOQLNodeToSqlExp visitor) {
1223:                // create the order by list including joins to pickup columns as needed
1224:                int len = orders.length;
1225:                SqlExp oePos = null;
1226:                if (append) {
1227:                    oePos = findTailOrderByExp();
1228:                }
1229:                for (int i = 0; i < len; i++) {
1230:                    OrderNode on = orders[i];
1231:                    SelectExp se = this ;
1232:                    Node prevNode = null;
1233:                    for (Node n = on.childList; n != null; n = n.childList) {
1234:                        if (n instanceof  FieldNode) {
1235:                            SelectExp oSe = se;
1236:                            if (prevNode != null
1237:                                    && prevNode instanceof  FieldNavNode) {
1238:                                JdbcField refField = (JdbcField) ((FieldNavNode) prevNode).fmd.storeField;
1239:                                JdbcField orderByField = (JdbcField) ((FieldNode) n).fmd.storeField;
1240:
1241:                                Join join = se.findJoin(orderByField.mainTable,
1242:                                        refField);
1243:                                if (join == null) {
1244:                                    oSe = new SelectExp();
1245:                                    oSe.table = orderByField.mainTable;
1246:                                    oSe.outer = true;
1247:                                    oSe.jdbcField = refField;
1248:
1249:                                    if (refField instanceof  JdbcPolyRefField) {
1250:                                        se
1251:                                                .addJoin(
1252:                                                        ((JdbcPolyRefField) refField).refCols,
1253:                                                        oSe.table.pk, oSe);
1254:                                    } else {
1255:                                        se.addJoin(refField.mainTableCols,
1256:                                                oSe.table.pk, oSe);
1257:                                    }
1258:
1259:                                } else {
1260:                                    oSe = join.selectExp;
1261:                                }
1262:
1263:                            } else if (prevNode == null) {
1264:                                //look to join to superTable if in different table
1265:                                JdbcField orderByField = (JdbcField) ((FieldNode) n).fmd.storeField;
1266:                                if (orderByField.mainTable != se.table) {
1267:                                    oSe = se.findTable(orderByField.mainTable);
1268:                                    if (oSe == null) {
1269:                                        oSe = new SelectExp();
1270:                                        oSe.table = orderByField.mainTable;
1271:                                        oSe.outer = false;
1272:                                        se.addJoin(se.table.pk, oSe.table.pk,
1273:                                                oSe);
1274:                                    }
1275:                                }
1276:                            }
1277:
1278:                            oePos = addOrderExp(handleOrderByFieldNode(
1279:                                    (FieldNode) n, oSe, visitor),
1280:                                    (on.order == OrderNode.ORDER_DESCENDING),
1281:                                    oePos);
1282:                        } else if (n instanceof  AsValueNode) {
1283:                            oePos = addOrderExp(new ColumnExp(
1284:                                    ((AsValueNode) n).value),
1285:                                    (on.order == OrderNode.ORDER_DESCENDING),
1286:                                    oePos);
1287:                        } else if (n instanceof  ReservedFieldNode) {
1288:                            ColumnExp[] cExps = createColumnExpForOrdering(
1289:                                    ((ReservedFieldNode) n).getTarget(), se);
1290:                            for (int j = 0; j < cExps.length; j++) {
1291:                                oePos = addOrderExp(
1292:                                        cExps[j],
1293:                                        (on.order == OrderNode.ORDER_DESCENDING),
1294:                                        oePos);
1295:                            }
1296:                        } else if (n instanceof  FieldNavNode) {
1297:                            se = handleOrderByFieldNavNode((FieldNavNode) n,
1298:                                    se, prevNode);
1299:                        } else {
1300:                            throw BindingSupportImpl.getInstance().internal(
1301:                                    "Invalid node in orders: " + n);
1302:                        }
1303:                        prevNode = n;
1304:                    }
1305:                }
1306:                return oePos;
1307:            }
1308:
1309:            /**
1310:             * Insert the columns at the start of the orderByList as ascending.
1311:             */
1312:            public void prependOrderByForColumns(JdbcColumn[] columns) {
1313:                SqlExp current = orderByList;
1314:
1315:                SqlExp oePos = null;
1316:                ColumnExp[] columnExps = new ColumnExp[columns.length];
1317:                for (int i = 0; i < columnExps.length; i++) {
1318:                    columnExps[i] = new ColumnExp(columns[i], this , null);
1319:                    oePos = addOrderExp(columnExps[i], false, oePos);
1320:                }
1321:
1322:                if (current != null) {
1323:                    oePos.next = current;
1324:                }
1325:            }
1326:
1327:            /**
1328:             * Append the columns at the end of the orderByList as ascending.
1329:             */
1330:            public void appendOrderByForColumns(JdbcColumn[] columns) {
1331:                SqlExp oePos = findTailOrderByExp();
1332:                for (int i = 0; i < columns.length; i++) {
1333:                    if (containsOrderExp(columns[i])) {
1334:                        continue;
1335:                    }
1336:                    oePos = addOrderExp(new ColumnExp(columns[i], this , null),
1337:                            false, oePos);
1338:                }
1339:            }
1340:
1341:            /**
1342:             * Append the column at the end of the orderByList as ascending.
1343:             */
1344:            public void appendOrderByForColumns(JdbcColumn column) {
1345:                SqlExp oePos = findTailOrderByExp();
1346:                if (!containsOrderExp(column)) {
1347:                    oePos = addOrderExp(new ColumnExp(column, this , null),
1348:                            false, oePos);
1349:                }
1350:            }
1351:
1352:            /**
1353:             * Append the orderExp at the end of the current orderExp.
1354:             */
1355:            public void appendOrderByExp(SqlExp orderExp) {
1356:                SqlExp oePos = findTailOrderByExp();
1357:                if (oePos == null) {
1358:                    orderByList = orderExp;
1359:                } else {
1360:                    if (oePos != orderExp) {
1361:                        oePos.next = orderExp;
1362:                    }
1363:                }
1364:            }
1365:
1366:            /**
1367:             * Append the columns to the orderByList
1368:             */
1369:            public void appendOrderByForColumns(JdbcColumn[] columns,
1370:                    SelectExp se) {
1371:                SqlExp oePos = findTailOrderByExp();
1372:                for (int i = 0; i < columns.length; i++) {
1373:                    if (containsOrderExp(columns[i])/* || se.containsOrderExp(columns[i])*/) {
1374:                        continue;
1375:                    }
1376:                    oePos = addOrderExp(new ColumnExp(columns[i], se, null),
1377:                            false, oePos);
1378:                }
1379:            }
1380:
1381:            public boolean containsOrderExp(JdbcColumn jdbcColumn) {
1382:                for (SqlExp e = orderByList; e != null; e = e.next) {
1383:                    if (((ColumnExp) ((OrderExp) e).childList).col == jdbcColumn)
1384:                        return true;
1385:                }
1386:                return false;
1387:            }
1388:
1389:            /**
1390:             * return the tail of the orderExp
1391:             */
1392:            private SqlExp findTailOrderByExp() {
1393:                for (SqlExp e = orderByList; e != null; e = e.next) {
1394:                    if (e.next == null)
1395:                        return e;
1396:                }
1397:                return null;
1398:            }
1399:
1400:            public ColumnExp[] createColumnExpForOrdering(ClassMetaData target,
1401:                    SelectExp root) {
1402:                JdbcColumn[] pk = ((JdbcClass) target.storeClass).table.pk;
1403:                ColumnExp[] columnExps = new ColumnExp[pk.length];
1404:                for (int i = 0; i < pk.length; i++) {
1405:                    columnExps[i] = new ColumnExp(pk[i], root, pk[i].refField);
1406:                }
1407:                return columnExps;
1408:            }
1409:
1410:            private SqlExp addOrderExp(SqlExp list, boolean desc, SqlExp oePos) {
1411:                // add a new OrderExp to the order by list
1412:                OrderExp oe = new OrderExp(list, desc);
1413:                if (oePos == null) {
1414:                    orderByList = oe;
1415:                } else {
1416:                    oePos.next = oe;
1417:                }
1418:                oePos = oe;
1419:                return oePos;
1420:            }
1421:
1422:            /**
1423:             * The idea here is to only add a join if the previous node is a FieldNavNode.
1424:             */
1425:            private SelectExp handleOrderByFieldNavNode(FieldNavNode nav,
1426:                    SelectExp se, Node prevNode) {
1427:                if (prevNode != null && prevNode instanceof  FieldNavNode) {
1428:                    //check if join is needed
1429:                    // see if there is a join to the table for the class we are navigating to
1430:                    JdbcField f = (JdbcField) ((FieldNavNode) prevNode).fmd.storeField;
1431:                    Join j = se.findJoin(f);
1432:                    if (j != null)
1433:                        return j.selectExp;
1434:
1435:                    // no join so add one
1436:                    SelectExp next = new SelectExp();
1437:                    next.jdbcField = f;
1438:                    ClassMetaData targetClass = ((FieldNavNode) prevNode).targetClass;
1439:                    next.table = ((JdbcClass) targetClass.storeClass).table;
1440:                    if (f instanceof  JdbcPolyRefField) {
1441:                        se.addJoin(((JdbcPolyRefField) f).refCols,
1442:                                next.table.pk, next);
1443:                    } else {
1444:                        se.addJoin(f.mainTableCols, next.table.pk, next);
1445:                    }
1446:                    next.outer = f.fmd.nullValue != MDStatics.NULL_VALUE_EXCEPTION;
1447:                    return next;
1448:                } else {
1449:                    return se;
1450:                }
1451:            }
1452:
1453:            private SqlExp handleOrderByFieldNode(FieldNode fn, SelectExp se,
1454:                    JDOQLNodeToSqlExp visitor) {
1455:                if (!(fn.fmd.storeField instanceof  JdbcSimpleField)) {
1456:                    throw BindingSupportImpl.getInstance().internal(
1457:                            "Only simple fields may be used in an "
1458:                                    + "ordering statement: " + fn.fmd);
1459:                }
1460:                SqlExp list = visitor.toSqlExp(fn, se, null, 0, null);
1461:                if (list.childList != null) {
1462:                    throw BindingSupportImpl.getInstance().internal(
1463:                            "Only single column fields may be used in an "
1464:                                    + "ordering statement: " + fn.fmd);
1465:                }
1466:                return list;
1467:            }
1468:
1469:            /**
1470:             * Does this select contain a join to a many table that may produce
1471:             * multiple rows? This is used to decide on setting the distinct flag
1472:             * if this select is converterd into an outer join.
1473:             */
1474:            public boolean isJoinToManyTable() {
1475:                return jdbcField instanceof  JdbcCollectionField;
1476:            }
1477:
1478:            /**
1479:             * Append e to the where clause of this select. This will create a new
1480:             * AndExp if needed.
1481:             */
1482:            public void appendToWhereExp(SqlExp e) {
1483:                whereExp = SqlExp.appendWithAnd(whereExp, e);
1484:            }
1485:
1486:            /**
1487:             * Append e to the subSelectJoinExp clause of this select. This will
1488:             * create a new AndExp if needed.
1489:             */
1490:            public void appendToSubSelectJoinExp(SqlExp e) {
1491:                subSelectJoinExp = SqlExp.appendWithAnd(subSelectJoinExp, e);
1492:            }
1493:
1494:            /**
1495:             * Used to obtain a selectexp for a field. This will add a join to the supertable
1496:             * if not already added.
1497:             */
1498:            public static SelectExp createJoinToSuperTable(SelectExp root,
1499:                    JdbcField jdbcField) {
1500:                return createJoinToSuperTable(
1501:                        root,
1502:                        ((JdbcClass) jdbcField.fmd.classMetaData.storeClass).table);
1503:            }
1504:
1505:            /**
1506:             * Used to obtain a selectexp for a field. This will add a join to the supertable
1507:             * if not already added.
1508:             */
1509:            public static SelectExp createJoinToSuperTable(SelectExp root,
1510:                    SelectExp joinFromExp, JdbcColumn[] lJoinColumns,
1511:                    JdbcField jdbcField) {
1512:                if (Debug.DEBUG) {
1513:                    JdbcRefField.isSubTableOf(root.table,
1514:                            jdbcField.fmd.classMetaData);
1515:                }
1516:                if (root.table != ((JdbcClass) jdbcField.fmd.classMetaData.storeClass).table) {
1517:                    Join join = joinFromExp.findJoin(jdbcField);
1518:                    if (join == null) {
1519:                        SelectExp se = new SelectExp();
1520:                        se.outer = root.outer;
1521:                        se.table = ((JdbcClass) jdbcField.fmd.classMetaData.storeClass).table;
1522:                        joinFromExp.addJoin(lJoinColumns, se.table.pk, se);
1523:                        return se;
1524:                    } else {
1525:                        return join.selectExp;
1526:                    }
1527:                }
1528:                return root;
1529:            }
1530:
1531:            /**
1532:             * Used to obtain a selectexp for a field. This will add a join to the supertable
1533:             * if not already added.
1534:             */
1535:            public static SelectExp createJoinToSuperTable(SelectExp root,
1536:                    JdbcTable table) {
1537:                // If the field is not in the table then join to the sub class table
1538:                SelectExp se = (SelectExp) root.findTable(table);
1539:                if (se == null) {
1540:                    se = new SelectExp();
1541:                    se.outer = root.outer;
1542:                    se.table = table;
1543:                    root.addJoin(root.table.pk, se.table.pk, se);
1544:                }
1545:                return se;
1546:            }
1547:
1548:            public static void dumpJoinList(SelectExp joinFromExp, String val) {
1549:                System.out.println(val + "dumping joinlist");
1550:                Join j = joinFromExp.joinList;
1551:                if (j == null) {
1552:                    System.out.println("-- no joins ");
1553:                    return;
1554:                }
1555:                for (;;) {
1556:                    System.out.println("j = " + j);
1557:                    j = j.next;
1558:                    if (j == null)
1559:                        break;
1560:                }
1561:            }
1562:
1563:            public static void dumpJoinListRec(SelectExp joinFromExp,
1564:                    String indent) {
1565:                Join j = joinFromExp.joinList;
1566:                if (j == null) {
1567:                    //            System.out.println(indent + "-- no joins --");
1568:                    return;
1569:                }
1570:                for (;;) {
1571:                    System.out.println(indent + j);
1572:                    dumpJoinListRec(j.selectExp, indent + "  ");
1573:                    j = j.next;
1574:                    if (j == null)
1575:                        break;
1576:                }
1577:            }
1578:
1579:            public static void mergeJoinList(Join j) {
1580:                if (j == null)
1581:                    return;
1582:                if (j.next == null)
1583:                    return;
1584:
1585:                for (Join nextJoin = j.next; nextJoin != null; nextJoin = nextJoin.next) {
1586:                    if (nextJoin.isMerged()) {
1587:                        continue;
1588:                    }
1589:                    if (Join.isCurrentEqaul(j, nextJoin)) {
1590:                        nextJoin.setMergedWith(j);
1591:                        continue;
1592:                    }
1593:                }
1594:                mergeJoinList(j.selectExp.joinList);
1595:                mergeJoinList(j.next);
1596:            }
1597:
1598:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.