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


001:        /*
002:         * Copyright (c) 1998 - 2005 Versant Corporation
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         * Versant Corporation - initial API and implementation
010:         */
011:        package com.versant.core.jdbc.query;
012:
013:        import com.versant.core.jdo.query.*;
014:        import com.versant.core.jdbc.sql.exp.*;
015:        import com.versant.core.jdbc.sql.exp.AggregateCountStarExp;
016:        import com.versant.core.jdbc.sql.conv.DummyPreparedStmt;
017:        import com.versant.core.jdbc.metadata.*;
018:        import com.versant.core.common.BindingSupportImpl;
019:        import com.versant.core.metadata.MDStatics;
020:        import com.versant.core.metadata.MDStaticUtils;
021:        import com.versant.core.metadata.ClassMetaData;
022:
023:        import java.sql.SQLException;
024:
025:        /**
026:         * Walks a JDOQL Node trees to produce SqlExp trees.
027:         */
028:        public class JDOQLNodeToSqlExp extends NodeVisitorAdapter {
029:
030:            private final JdbcJDOQLCompiler comp;
031:
032:            /**
033:             * This instance can convert Node's that do not need to access a
034:             * JdbcQueryCompiler to SqlExp.
035:             */
036:            public static final JDOQLNodeToSqlExp INSTANCE = new JDOQLNodeToSqlExp();
037:
038:            /**
039:             * Information passed down from a Node to its children via arrive
040:             * callback mechanism.
041:             */
042:            private static class Context {
043:
044:                public SelectExp root;
045:                public SqlExp leftSibling;
046:                public int method;
047:                public Node args;
048:
049:                public Context(SelectExp root) {
050:                    this .root = root;
051:                }
052:
053:                public Context(SelectExp root, SqlExp leftSibling, int method,
054:                        Node args) {
055:                    this .root = root;
056:                    this .leftSibling = leftSibling;
057:                    this .method = method;
058:                    this .args = args;
059:                }
060:            }
061:
062:            public JDOQLNodeToSqlExp(JdbcJDOQLCompiler comp) {
063:                this .comp = comp;
064:            }
065:
066:            private JDOQLNodeToSqlExp() {
067:                this (null);
068:            }
069:
070:            /**
071:             * Convert a Node tree to an SqlExp tree.
072:             */
073:            public SqlExp toSqlExp(Node node, SelectExp root,
074:                    SqlExp leftSibling, int method, Node args) {
075:                return (SqlExp) node.arrive(this , new Context(root,
076:                        leftSibling, method, args));
077:            }
078:
079:            protected Object defaultArrive(Node node, Object msg) {
080:                throw BindingSupportImpl.getInstance().internal(
081:                        "Not implemented: " + node.getClass());
082:            }
083:
084:            public Object arriveFieldNavNode(FieldNavNode node, Object msg) {
085:                Context ctx = (Context) msg;
086:                SelectExp root = ctx.root;
087:                if (node.var == null) {
088:                    JdbcField jdbcField = (JdbcField) node.fmd.storeField;
089:                    JdbcClass targetClass = (JdbcClass) node.targetClass.storeClass;
090:                    SelectExp se;
091:                    Join j = root.findJoin(jdbcField);
092:                    if (j == null) {
093:                        SelectExp leftTableSE = root
094:                                .findTable(jdbcField.mainTable);
095:                        if (leftTableSE == null) {
096:                            throw BindingSupportImpl.getInstance().runtime(
097:                                    "No join to '" + jdbcField.mainTable
098:                                            + "' for nav field '"
099:                                            + jdbcField.fmd.name);
100:                        }
101:
102:                        se = new SelectExp();
103:                        se.table = targetClass.table;
104:                        se.jdbcField = jdbcField;
105:                        if (jdbcField instanceof  JdbcPolyRefField) {
106:                            JdbcPolyRefField pf = (JdbcPolyRefField) jdbcField;
107:                            j = leftTableSE
108:                                    .addJoin(pf.refCols, se.table.pk, se);
109:                            // add a condition to check that the class-id column of
110:                            // the polyref matches the type used in the cast
111:                            j.appendJoinExp(pf.createClassIdMatchExp(root,
112:                                    targetClass.cmd));
113:                        } else {
114:                            j = leftTableSE.addJoin(jdbcField.mainTableCols,
115:                                    se.table.pk, se);
116:                            if (node.cast != null
117:                                    && targetClass.cmd.isInHeirachy()) {
118:                                //join to basetable for classIdJoin
119:                                if (targetClass.classIdCol != null
120:                                        && targetClass.classIdCol.table != se.table) {
121:                                    SelectExp bSe = (SelectExp) root
122:                                            .findTable(targetClass.classIdCol.table);
123:                                    if (bSe == null) {
124:                                        bSe = new SelectExp();
125:                                        bSe.outer = se.outer;
126:                                        bSe.table = targetClass.classIdCol.table;
127:                                        j = se.addJoin(se.table.pk,
128:                                                bSe.table.pk, bSe);
129:                                    }
130:                                }
131:
132:                                // downcast so join must include code to check the
133:                                // class-id column of the target table
134:                                j.appendJoinExp(targetClass
135:                                        .getCheckClassIdExp(se));
136:                            }
137:                        }
138:                    } else {
139:                        se = j.selectExp;
140:                    }
141:                    if (node.childList == null) {
142:                        return null;
143:                    } else {
144:                        return toSqlExp(node.childList, se, ctx.leftSibling,
145:                                ctx.method, ctx.args);
146:                    }
147:                } else {
148:                    return toSqlExp(node.childList, (SelectExp) node.var
149:                            .getStoreExtent(), ctx.leftSibling, ctx.method,
150:                            ctx.args);
151:                }
152:            }
153:
154:            public Object arriveLiteralNode(LiteralNode node, Object msg) {
155:                Context ctx = (Context) msg;
156:                SqlExp leftSibling = ctx.leftSibling;
157:                String value = node.value;
158:                int t;
159:                switch (node.type) {
160:                case LiteralNode.TYPE_OTHER:
161:                    t = LiteralExp.TYPE_OTHER;
162:                    break;
163:                case LiteralNode.TYPE_STRING:
164:                    t = LiteralExp.TYPE_STRING;
165:                    break;
166:                case LiteralNode.TYPE_NULL:
167:                    t = LiteralExp.TYPE_NULL;
168:                    break;
169:                case LiteralNode.TYPE_BOOLEAN:
170:                    t = LiteralExp.TYPE_OTHER;
171:
172:                    /**
173:                     * The idea here is to convert the boolean literal 'true' or
174:                     * 'false' via the converter on the field that it is being compared to.
175:                     * If there is no converter on the field then we expect a 'true'
176:                     * or 'false' constant to work.
177:                     */
178:                    if (ctx.leftSibling instanceof  ColumnExp) {
179:                        ColumnExp cExp = (ColumnExp) leftSibling;
180:                        if (cExp.col.converter == null)
181:                            break;
182:                        DummyPreparedStmt pstmt = new DummyPreparedStmt();
183:                        try {
184:                            cExp.col.converter.set(pstmt, 0, cExp.col,
185:                                    new Boolean(value));
186:                        } catch (SQLException e) {
187:                            //ignore
188:                        }
189:                        value = pstmt.value;
190:                        if (pstmt.toQuote) {
191:                            t = LiteralExp.TYPE_STRING;
192:                        } else {
193:                            t = LiteralExp.TYPE_OTHER;
194:                        }
195:                    }
196:                    break;
197:                case LiteralNode.TYPE_CHAR:
198:                case LiteralNode.TYPE_DOUBLE:
199:                case LiteralNode.TYPE_LONG:
200:                    t = LiteralExp.TYPE_OTHER;
201:                    break;
202:                default:
203:                    throw BindingSupportImpl.getInstance().internal(
204:                            "Unknown literal type: " + node.type);
205:                }
206:
207:                LiteralExp ans = new LiteralExp(t, value);
208:                if (node.type == LiteralNode.TYPE_NULL) {
209:                    // Create a list of LiteralExp's with one entry for each expression
210:                    // on the left hand side. This is to handle references to composite
211:                    // pk classes.
212:                    for (SqlExp pos = ans; (leftSibling = leftSibling.next) != null;) {
213:                        pos = pos.next = new LiteralExp(t, value);
214:                    }
215:                }
216:                return ans;
217:            }
218:
219:            public Object arriveMethodNode(MethodNode node, Object msg) {
220:                Context ctx = (Context) msg;
221:                SelectExp root = ctx.root;
222:                int method = node.getMethod();
223:                Node childList = node.childList;
224:                switch (method) {
225:                case MethodNode.STARTS_WITH:
226:                    return toSqlLike(childList, method, root, false);
227:                case MethodNode.ENDS_WITH:
228:                    return toSqlLike(childList, method, root, true);
229:                case MethodNode.CONTAINS:
230:                case MethodNode.CONTAINS_KEY:
231:                    return toSqlContains(childList, method, root);
232:                case MethodNode.IS_EMPTY:
233:                    return toSqlIsEmpty(childList, root);
234:                case MethodNode.TO_LOWER_CASE:
235:                    return toSqlToLowerCase(childList, method, root);
236:                case MethodNode.SQL:
237:                    return toSqlInline(childList, method, root);
238:                }
239:                throw BindingSupportImpl.getInstance().internal(
240:                        "Unknown method: " + method);
241:            }
242:
243:            private SqlExp toSqlInline(Node childList, int method,
244:                    SelectExp root) {
245:                SqlExp left = toSqlExp(childList, root, null, method, null);
246:                SqlExp right;
247:                if (childList.next != null) {
248:                    right = toSqlExp(childList.next, root, left, method, null);
249:                } else {
250:                    right = null;
251:                }
252:                String template;
253:                if (right == null) {
254:                    template = "$1";
255:                } else if (right instanceof  LiteralExp) {
256:                    template = ((LiteralExp) right).value;
257:                } else {
258:                    throw BindingSupportImpl.getInstance().invalidOperation(
259:                            "Expected literal expression: " + right);
260:                }
261:                return new InlineSqlExp(template, left);
262:            }
263:
264:            private SqlExp toSqlLike(Node childList, int method,
265:                    SelectExp root, boolean endsWith) {
266:                SqlExp left = toSqlExp(childList, root, null, method, null);
267:                SqlExp right = toSqlExp(childList.next, root, left, method,
268:                        null);
269:                if (right instanceof  LiteralExp
270:                        && ((LiteralExp) right).type == LiteralExp.TYPE_STRING) {
271:                    // prepend or append a % to the literal string
272:                    LiteralExp le = (LiteralExp) right;
273:                    if (endsWith)
274:                        le.value = "%" + le.value;
275:                    else
276:                        le.value = le.value + "%";
277:                } else {
278:                    // create a BinaryExp to prepend or append %
279:                    LiteralExp pe = new LiteralExp(LiteralExp.TYPE_STRING, "%");
280:                    if (endsWith)
281:                        right = new BinaryOpExp(pe, BinaryOpExp.CONCAT, right);
282:                    else
283:                        right = new BinaryOpExp(right, BinaryOpExp.CONCAT, pe);
284:                }
285:                return new BinaryOpExp(left, BinaryOpExp.LIKE, right);
286:            }
287:
288:            private SqlExp toSqlIsEmpty(Node childList, SelectExp root) {
289:                if (childList.next != null) {
290:                    throw BindingSupportImpl.getInstance().runtime(
291:                            "isEmpty() does not accept arguments");
292:                }
293:                return toSqlExp(childList, root, null, MethodNode.IS_EMPTY,
294:                        null);
295:            }
296:
297:            private SqlExp toSqlContains(Node childList, int method,
298:                    SelectExp root) {
299:                return toSqlExp(childList, root, null, method, childList.next);
300:            }
301:
302:            private SqlExp toSqlToLowerCase(Node childList, int method,
303:                    SelectExp root) {
304:                if (childList.next != null) {
305:                    throw BindingSupportImpl.getInstance().runtime(
306:                            "toLowerCase() does not accept arguments");
307:                }
308:                SqlExp left = toSqlExp(childList, root, null, method, null);
309:                return new UnaryFunctionExp(left,
310:                        UnaryFunctionExp.FUNC_TO_LOWER_CASE);
311:            }
312:
313:            public Object arriveFieldNode(FieldNode node, Object msg) {
314:                Context ctx = (Context) msg;
315:                int method = ctx.method;
316:                SelectExp root = ctx.root;
317:                Node args = ctx.args;
318:                JdbcField jdbcField = (JdbcField) node.fmd.storeField;
319:
320:                switch (method) {
321:                case MethodNode.IS_EMPTY:
322:                    return jdbcField.toIsEmptySqlExp(comp, root);
323:                case MethodNode.CONTAINS:
324:                    return jdbcField.toContainsSqlExp(comp, root, args);
325:                case MethodNode.CONTAINS_KEY:
326:                    return jdbcField.toContainsKeySqlExp(comp, root, args);
327:                case MethodNode.CONTAINS_PARAM:
328:                    if (jdbcField.mainTableCols.length > 1) {
329:                        throw BindingSupportImpl
330:                                .getInstance()
331:                                .invalidOperation(
332:                                        "This is only supported for single column instances");
333:                    }
334:                    return new CollectionParamExp(jdbcField.toColumnExp(
335:                            SelectExp.createJoinToSuperTable(root, jdbcField),
336:                            true));
337:                }
338:                ;
339:
340:                // This is to detect the scenario where a boolean field is in the jdoql
341:                // expression on its own. eg 'booleanField && name == param'
342:                if (isUnaryBoolExp(node, jdbcField)) {
343:                    ColumnExp cExp = jdbcField.toColumnExp(root, true);
344:
345:                    LiteralExp lExp = new LiteralExp();
346:                    if (cExp.col.converter != null) {
347:                        DummyPreparedStmt pstmt = new DummyPreparedStmt();
348:                        try {
349:                            cExp.col.converter.set(pstmt, 0, cExp.col,
350:                                    new Boolean(true));
351:                        } catch (SQLException e) {
352:                            //ignore
353:                        }
354:
355:                        lExp.value = pstmt.value;
356:                        if (pstmt.toQuote) {
357:                            lExp.type = LiteralExp.TYPE_STRING;
358:                        } else {
359:                            lExp.type = LiteralExp.TYPE_OTHER;
360:                        }
361:                        return new BinaryOpExp(cExp, BinaryOpExp.EQUAL, lExp);
362:                    } else {
363:                        lExp.type = LiteralExp.TYPE_OTHER;
364:                        lExp.value = "true";
365:                        return new BinaryOpExp(cExp, BinaryOpExp.EQUAL, lExp);
366:                    }
367:                }
368:
369:                SelectExp fSe = node.useCandidateExtent ? comp
370:                        .getCandidateSelectExp() : root;
371:                ColumnExp columnExp = jdbcField.toColumnExp(SelectExp
372:                        .createJoinToSuperTable(fSe, jdbcField), true);
373:                if (!isPartOfAggregate(node.parent))
374:                    columnExp.setColAlias(node.asValue);
375:                return columnExp;
376:            }
377:
378:            private static boolean isUnaryBoolExp(Node node, JdbcField jdbcField) {
379:                if (isBooleanType(jdbcField)
380:                        && !(node.parent instanceof  OrderNode)) {
381:                    if (node.parent instanceof  FieldNavNode) {
382:                        return isUnaryBoolExp(node.parent, jdbcField);
383:                    } else if ((node.parent instanceof  AndNode)
384:                            || (node.parent instanceof  OrNode)
385:                            || (node.parent != null && node.parent.parent == null)) {
386:                        return true;
387:                    }
388:                }
389:                return false;
390:            }
391:
392:            private static boolean isBooleanType(JdbcField jdbcField) {
393:                if (jdbcField == null)
394:                    return false;
395:                return ((jdbcField.fmd.typeCode == MDStatics.BOOLEAN) || (jdbcField.fmd.typeCode == MDStatics.BOOLEANW));
396:            }
397:
398:            private static boolean isPartOfAggregate(Node n) {
399:                if (n == null)
400:                    return false;
401:                if (n instanceof  AggregateNode)
402:                    return true;
403:                return isPartOfAggregate(n.parent);
404:            }
405:
406:            public Object arriveEqualNode(EqualNode node, Object msg) {
407:                return arriveEqualOrNotEqual(node, msg, BinaryOpExp.EQUAL);
408:            }
409:
410:            public Object arriveLikeNode(LikeNode node, Object msg) {
411:                return arriveEqualOrNotEqual(node, msg, BinaryOpExp.LIKE);
412:            }
413:
414:            private Object arriveEqualOrNotEqual(EqualNode node, Object msg,
415:                    int op) {
416:                Context ctx = (Context) msg;
417:                SelectExp root = ctx.root;
418:
419:                // If a field is being compared to a null literal then only put
420:                // columns that are not shared in the left expression unless all of
421:                // the columns are shared.
422:                SqlExp left;
423:                Node childList = node.childList;
424:                if (isNullLiteral(childList.next)
425:                        && childList instanceof  FieldNode) {
426:                    JdbcField f = (JdbcField) ((FieldNode) childList).fmd.storeField;
427:                    left = f.toColumnExpForNullLiteralCompare(root);
428:                } else {
429:                    left = toSqlExp(childList, root, null, ctx.method, ctx.args);
430:                }
431:
432:                SqlExp right = toSqlExp(childList.next, root, left, ctx.method,
433:                        ctx.args);
434:                return SqlExp.createBinaryOpExp(left, op, right);
435:            }
436:
437:            private static boolean isNullLiteral(Node n) {
438:                return n instanceof  LiteralNode
439:                        && ((LiteralNode) n).type == LiteralNode.TYPE_NULL;
440:            }
441:
442:            public Object arriveNotEqualNode(NotEqualNode node, Object msg) {
443:                return arriveEqualOrNotEqual(node, msg, BinaryOpExp.NOT_EQUAL);
444:            }
445:
446:            public Object arriveAndNode(AndNode node, Object msg) {
447:                Context ctx = (Context) msg;
448:                Node childList = node.childList;
449:
450:                // Build the list of expressions to be anded together.
451:                SqlExp prev = null, first = null;
452:                for (Node cn = childList; cn != null;) {
453:                    SqlExp e = toSqlExp(cn, ctx.root, prev, ctx.method,
454:                            ctx.args);
455:                    if (first == null) {
456:                        first = e;
457:                    } else if (prev != null) {
458:                        prev.next = e;
459:                    }
460:                    prev = e;
461:
462:                    // See if this expression involves a VarNode. If so process the
463:                    // nodes involving the variable. They become the where clause of
464:                    // the sub select for the variable.
465:                    VarNode vn = extractVar(e);
466:                    if (vn != null) {
467:                        cn = processVarNode(ctx.root, ctx.method, ctx.args, cn,
468:                                vn, e);
469:                    } else {
470:                        cn = cn.next;
471:                    }
472:                }
473:
474:                // if there is now only one entry in the list then return it otherwise
475:                // create a new AndExp for the list
476:                if (first.next == null) {
477:                    return first;
478:                } else {
479:                    return new AndExp(first);
480:                }
481:            }
482:
483:            private static VarNode extractVar(SqlExp e) {
484:                if (e instanceof  ExistsExp && e.childList instanceof  SelectExp) {
485:                    return ((SelectExp) e.childList).var;
486:                } else {
487:                    return null;
488:                }
489:            }
490:
491:            /**
492:             * Process the nodes involving the variable. They become the where clause of
493:             * of the sub select for the variable. This process stops as soon as a node
494:             * is encountered that does not involve the variable i.e. all the variable
495:             * related expressions must be together (as per spec).
496:             *
497:             * @return Next Node for the main loop to process
498:             */
499:            private Node processVarNode(SelectExp root, int method, Node args,
500:                    Node cn, VarNode var, SqlExp vare) {
501:
502:                SelectExp varSelectExp = (SelectExp) var.getStoreExtent();
503:
504:                // Do not use columns from the enclosing query (root) in subquery ON
505:                // join conditions if the database does not allow this. If exclude is
506:                // null then expressions referencing tables in the subquery and
507:                // then enclosing query (root) will be left in the where clause.
508:                // This is required for DB2.
509:                SelectExp exclude;
510:                if (root.table.sqlDriver.isSubQueryJoinMayUseOuterQueryCols()) {
511:                    exclude = root;
512:                } else {
513:                    exclude = null;
514:                }
515:
516:                // build a list of all expressions constraining the variable on first
517:                SqlExp prev = null, first = null;
518:                SqlExp leftSibling = vare;
519:                Node ans = cn.next;
520:                for (; ans != null;) {
521:                    SqlExp e = toSqlExp(ans, root, leftSibling, method, args);
522:                    if (e == null) {
523:                        break;
524:                    }
525:
526:                    SelectExp single = e.getSingleSelectExp(exclude);
527:                    if (single != null) {
528:                        Join join;
529:                        if (single.jdbcField != null) {
530:                            join = varSelectExp.findJoinRec(single.jdbcField);
531:                        } else if (vare instanceof  ExistsExp) {
532:                            join = ((SelectExp) vare.childList)
533:                                    .findJoin(single);
534:                        } else {
535:                            join = null;
536:                        }
537:                        ans = ans.next;
538:                        if (join != null) {
539:                            join.appendJoinExp(e);
540:                            continue;
541:                        } else if (var.getCmd() == null) {
542:                            ((SelectExp) ((ExistsExp) vare).childList)
543:                                    .appendToWhereExp(e);
544:                        }
545:                    } else {
546:                        // recursively process nested variables
547:                        VarNode nested = extractVar(e);
548:                        if (nested != null) {
549:                            ans = processVarNode(root, method, args, ans,
550:                                    nested, e);
551:                        } else {
552:                            ans = ans.next;
553:                        }
554:                    }
555:                    if (first == null) {
556:                        first = e;
557:                    } else {
558:                        prev.next = e;
559:                    }
560:                    leftSibling = e;
561:                    prev = e;
562:                }
563:
564:                // attach the expression list at first to the where of the variable
565:                if (first != null)
566:                    varSelectExp.appendToWhereExp(first);
567:
568:                return ans;
569:            }
570:
571:            public Object arriveOrNode(OrNode node, Object msg) {
572:                Context ctx = (Context) msg;
573:                Node childList = node.childList;
574:
575:                SqlExp e = processOrNodeChild(ctx.root, childList, ctx.args);
576:                if (e == null) {
577:                    return null;
578:                }
579:
580:                SqlExp base = e;
581:                for (Node c = childList.next; c != null; c = c.next) {
582:                    e = e.next = processOrNodeChild(ctx.root, c, ctx.args);
583:                }
584:                mergeOrNodeRedundantExistsSelects(base);
585:                if (base.next == null)
586:                    return base;
587:                return new OrExp(base);
588:            }
589:
590:            private SqlExp processOrNodeChild(SelectExp root, Node c, Node args) {
591:                Join rootJoinList = root.joinList;
592:                root.joinList = null;
593:                SqlExp e = toSqlExp(c, root, null, 0, args);
594:                // if the child expression includes a join (e.g. field navigation)
595:                // then convert it into an ExistsSelectExp
596:                Join j = root.joinList;
597:                if (j != null) {
598:                    // convert the first join into a ExistsSelectExp
599:                    SelectExp se = j.selectExp;
600:                    se.subSelectJoinExp = j.exp;
601:                    se.whereExp = e;
602:                    // make the other joins (if any) joins on this select
603:                    j = se.joinList;
604:                    if (j == null) {
605:                        se.joinList = root.joinList.next;
606:                    } else {
607:                        for (; j.next != null; j = j.next)
608:                            ;
609:                        j.next = root.joinList.next;
610:                    }
611:                    // wrap in an exists exp
612:                    e = new ExistsExp(se, false);
613:                }
614:                root.joinList = rootJoinList;
615:                return e;
616:            }
617:
618:            /**
619:             * Try to merge the list of expressions starting at base. This gets rid
620:             * of redundant 'exists (select ...)' sub queries.
621:             */
622:            private void mergeOrNodeRedundantExistsSelects(SqlExp base) {
623:                for (; base != null;) {
624:                    if (base instanceof  ExistsExp) {
625:                        SqlExp prev = base;
626:                        for (SqlExp target = base.next; target != null;) {
627:                            if (mergeOrNodeRedundantExistsSelects(base, target)) {
628:                                target = prev.next = target.next;
629:                            } else {
630:                                prev = target;
631:                                target = target.next;
632:                            }
633:                        }
634:                    }
635:                    base = base.next;
636:                }
637:            }
638:
639:            /**
640:             * Merge base and e if possible or return false. The expressions can
641:             * be merged if:<p>
642:             * <ol>
643:             * <li>e is an ExistsExp.
644:             * <li>The selectExp's have the same jdbcField.
645:             * <li>The selectExp's do not have any other joins.
646:             * </ol>
647:             */
648:            private boolean mergeOrNodeRedundantExistsSelects(SqlExp base,
649:                    SqlExp e) {
650:                if (!(e instanceof  ExistsExp))
651:                    return false;
652:                SelectExp se = (SelectExp) base.childList;
653:                SelectExp ese = (SelectExp) e.childList;
654:                if (se.jdbcField != ese.jdbcField)
655:                    return false;
656:                //        if (se.joinList != null || ese.joinList != null) return false;
657:                if (!Join.isEqaul(se.joinList, ese.joinList))
658:                    return false;
659:                SqlExp we = se.whereExp;
660:                if (we instanceof  OrExp) { // extend the existing OrExp
661:                    SqlExp pos;
662:                    for (pos = we.childList; pos.next != null; pos = pos.next)
663:                        ;
664:                    pos.next = ese.whereExp;
665:                } else if (se.whereExp != null) { // create an OrExp
666:                    se.whereExp.next = ese.whereExp;
667:                    se.whereExp = new OrExp(se.whereExp);
668:                }
669:                // convert any references to ese into se references
670:                if (ese.whereExp != null)
671:                    ese.whereExp.replaceSelectExpRef(ese, se);
672:                return true;
673:            }
674:
675:            public Object arriveMultiplyNode(MultiplyNode node, Object msg) {
676:                Context ctx = (Context) msg;
677:                Node childList = node.childList;
678:
679:                SqlExp e = processMultiplyNodeChild(ctx.root, childList, null,
680:                        ctx.args);
681:                MultiplyExp ans = new MultiplyExp(e, node.ops);
682:                for (Node c = childList.next; c != null; c = c.next) {
683:                    e = e.next = processMultiplyNodeChild(ctx.root, c, e,
684:                            ctx.args);
685:                }
686:                return ans;
687:            }
688:
689:            private SqlExp processMultiplyNodeChild(SelectExp root, Node c,
690:                    SqlExp leftSibling, Node args) {
691:                SqlExp e = toSqlExp(c, root, leftSibling, 0, args);
692:                if (e.next != null) {
693:                    throw BindingSupportImpl.getInstance().runtime(
694:                            "Expressions consisting of multiple columns may not be used"
695:                                    + "with * or /");
696:                }
697:                return e;
698:            }
699:
700:            public Object arriveAddNode(AddNode node, Object msg) {
701:                Context ctx = (Context) msg;
702:                Node childList = node.childList;
703:                SqlExp e = processAddNodeChild(ctx.root, childList, null,
704:                        ctx.args);
705:                AddExp ans = new AddExp(e, node.ops);
706:                if (node.asValue != null)
707:                    ans.setExpAlias(node.asValue);
708:                for (Node c = childList.next; c != null; c = c.next) {
709:                    e = e.next = processAddNodeChild(ctx.root, c, e, ctx.args);
710:                }
711:                return ans;
712:            }
713:
714:            private SqlExp processAddNodeChild(SelectExp root, Node c,
715:                    SqlExp leftSibling, Node args) {
716:                SqlExp e = toSqlExp(c, root, leftSibling, 0, args);
717:                if (e.next != null) {
718:                    throw BindingSupportImpl.getInstance().runtime(
719:                            "Expressions consisting of multiple columns may not be used"
720:                                    + "with + or -");
721:                }
722:                return e;
723:            }
724:
725:            public Object arriveUnaryOpNode(UnaryOpNode node, Object msg) {
726:                Context ctx = (Context) msg;
727:                return new UnaryOpExp(toSqlExp(node.childList, ctx.root,
728:                        ctx.leftSibling, ctx.method, ctx.args), node.op);
729:            }
730:
731:            public Object arriveCompareOpNode(CompareOpNode node, Object msg) {
732:                Context ctx = (Context) msg;
733:                Node childList = node.childList;
734:                SqlExp left = toSqlExp(childList, ctx.root, null, ctx.method,
735:                        ctx.args);
736:                SqlExp right = toSqlExp(childList.next, ctx.root, left,
737:                        ctx.method, ctx.args);
738:                if (left.next == null && right.next == null) {
739:                    int op;
740:                    switch (node.op) {
741:                    case CompareOpNode.GT:
742:                        op = BinaryOpExp.GT;
743:                        break;
744:                    case CompareOpNode.LT:
745:                        op = BinaryOpExp.LT;
746:                        break;
747:                    case CompareOpNode.GE:
748:                        op = BinaryOpExp.GE;
749:                        break;
750:                    case CompareOpNode.LE:
751:                        op = BinaryOpExp.LE;
752:                        break;
753:                    default:
754:                        throw BindingSupportImpl.getInstance().internal(
755:                                "Unknown op: " + node.op);
756:                    }
757:                    return new BinaryOpExp(left, op, right);
758:                }
759:                throw BindingSupportImpl.getInstance().runtime(
760:                        "Expressions consisting of multiple columns may not be compared "
761:                                + "with >, <, >= or <=\n");
762:            }
763:
764:            public Object arriveUnaryNode(UnaryNode node, Object msg) {
765:                Context ctx = (Context) msg;
766:                return toSqlExp(node.childList, ctx.root, ctx.leftSibling,
767:                        ctx.method, ctx.args);
768:            }
769:
770:            public Object arriveCastNode(CastNode node, Object msg) {
771:                Context ctx = (Context) msg;
772:                return toSqlExp(node.childList, ctx.root, ctx.leftSibling,
773:                        ctx.method, ctx.args);
774:            }
775:
776:            /**
777:             * Add u to the end of the usage list for n.
778:             */
779:            private void addToParamNode(SqlParamUsage u, ParamNode n) {
780:                if (n.usageList == null) {
781:                    n.usageList = u;
782:                } else {
783:                    SqlParamUsage p = (SqlParamUsage) n.usageList;
784:                    for (; p.next != null; p = p.next)
785:                        ;
786:                    p.next = u;
787:                }
788:            }
789:
790:            public Object arriveParamNode(ParamNode node, Object msg) {
791:                Context ctx = (Context) msg;
792:                SqlExp leftSibling = ctx.leftSibling;
793:                SelectExp root = ctx.root;
794:                Node args = ctx.args;
795:
796:                SqlParamUsage u = new SqlParamUsage();
797:                addToParamNode(u, node);
798:                if (leftSibling instanceof  ColumnExp) {
799:                    ColumnExp left = (ColumnExp) leftSibling;
800:                    u.jdbcField = left.jdbcField;
801:                    u.col = left.col;
802:                    SqlExp pos = u.expList = new ParamExp(u.jdbcType, u);
803:                    for (;;) {
804:                        if ((left = (ColumnExp) left.next) == null)
805:                            break;
806:                        pos = pos.next = new ParamExp(left.getJdbcType(), u);
807:                    }
808:                } else {
809:                    if (leftSibling == null) {
810:                        /**
811:                         * Expect this to be a param collection exp
812:                         * The args must be either a FieldNode of a FieldNavNode.
813:                         */
814:                        if (java.util.Collection.class
815:                                .isAssignableFrom(MDStaticUtils
816:                                        .toSimpleClass(node.getType()))
817:                                && (args instanceof  FieldNode || args instanceof  FieldNavNode)) {
818:                            CollectionParamExp collectionParamExp = (CollectionParamExp) toSqlExp(
819:                                    args, root, leftSibling,
820:                                    MethodNode.CONTAINS_PARAM, null);
821:                            u.expList = collectionParamExp;
822:                            u.jdbcField = collectionParamExp.field.jdbcField;
823:                            u.col = collectionParamExp.field.col;
824:                            u.jdbcType = collectionParamExp.field.getJdbcType();
825:                            u.javaTypeCode = collectionParamExp.field
826:                                    .getJavaTypeCode();
827:                            u.classIndex = collectionParamExp.field
828:                                    .getClassIndex();
829:                            return collectionParamExp;
830:                        }
831:                        throw BindingSupportImpl.getInstance().internal(
832:                                "not implemented (leftSibling == null)");
833:                    }
834:                    if (leftSibling.next != null) {
835:                        throw BindingSupportImpl.getInstance().internal(
836:                                "not implemented (leftSibling.next != null)");
837:                    }
838:                    u.expList = new ParamExp(leftSibling.getJdbcType(), u);
839:                }
840:                if (u.jdbcField == null) {
841:                    u.jdbcType = leftSibling.getJdbcType();
842:                    u.javaTypeCode = leftSibling.getJavaTypeCode();
843:                    u.classIndex = leftSibling.getClassIndex();
844:                }
845:                return u.expList;
846:            }
847:
848:            public Object arriveParamNodeProxy(ParamNodeProxy node, Object msg) {
849:                Context ctx = (Context) msg;
850:                return toSqlExp(node.getParamNode(), ctx.root, ctx.leftSibling,
851:                        ctx.method, ctx.args);
852:            }
853:
854:            public Object arriveVarNode(VarNode node, Object msg) {
855:                SelectExp jdbcSelectExp = (SelectExp) node.getStoreExtent();
856:                // return ColumnExp's for the primary key of our table
857:                if (node.getCmd() != null) {
858:                    JdbcColumn[] cols = jdbcSelectExp.table.pk;
859:                    ColumnExp ans = new ColumnExp(cols[0], jdbcSelectExp, null);
860:                    SqlExp e = ans;
861:                    int nc = cols.length;
862:                    for (int i = 1; i < nc; i++) {
863:                        e = e.next = new ColumnExp(cols[i], jdbcSelectExp, null);
864:                    }
865:                    return ans;
866:                } else {
867:                    JdbcLinkCollectionField jdbcField = (JdbcLinkCollectionField) node
868:                            .getFmd().storeField;
869:                    return new ColumnExp(jdbcField.valueColumns[0],
870:                            (SelectExp) node.getFieldExtent(), null);
871:                }
872:            }
873:
874:            public Object arriveVarNodeProxy(VarNodeProxy node, Object msg) {
875:                Context ctx = (Context) msg;
876:                return toSqlExp(node.getVarNode(), ctx.root, ctx.leftSibling,
877:                        ctx.method, ctx.args);
878:            }
879:
880:            public Object arriveReservedFieldNode(ReservedFieldNode node,
881:                    Object msg) {
882:                ClassMetaData target = node.getTarget();
883:                SelectExp candidateSelectExp = comp.getCandidateSelectExp();
884:                JdbcColumn[] pk = ((JdbcClass) target.storeClass).table.pk;
885:                ColumnExp list = new ColumnExp(pk[0], candidateSelectExp, null);
886:                list.cmd = target;
887:                SqlExp e = list;
888:                int nc = pk.length;
889:                for (int i = 1; i < nc; i++) {
890:                    e = e.next = new ColumnExp(pk[i], candidateSelectExp, null);
891:                }
892:                return list;
893:            }
894:
895:            public Object arriveAggregateCountStarNode(
896:                    AggregateCountStarNode node, Object msg) {
897:                return new AggregateCountStarExp(node.asValue);
898:            }
899:
900:            public Object arriveAggregateNode(AggregateNode node, Object msg) {
901:                Context ctx = (Context) msg;
902:                SqlExp se = toSqlExp(node.childList, ctx.root, ctx.leftSibling,
903:                        ctx.method, ctx.args);
904:                String op;
905:                switch (node.getType()) {
906:                case AggregateNode.TYPE_AVG:
907:                    op = "AVG";
908:                    break;
909:                case AggregateNode.TYPE_COUNT:
910:                    op = "COUNT";
911:                    break;
912:                case AggregateNode.TYPE_MAX:
913:                    op = "MAX";
914:                    break;
915:                case AggregateNode.TYPE_MIN:
916:                    op = "MIN";
917:                    break;
918:                case AggregateNode.TYPE_SUM:
919:                    op = "SUM";
920:                    break;
921:                default:
922:                    throw BindingSupportImpl.getInstance().internal(
923:                            "Uknown AggregateNode type " + node.getType());
924:                }
925:                ;
926:                return new AggregateExp(se, op, node.asValue);
927:            }
928:
929:            public Object arriveAsValueNode(AsValueNode node, Object msg) {
930:                return new ColumnExp(node.value);
931:            }
932:
933:            public Object arriveGroupingNode(GroupingNode node, Object msg) {
934:                Context ctx = (Context) msg;
935:                SqlExp head = new SqlExp();
936:                SqlExp current = head;
937:                for (Node n = node.childList; n != null; n = n.next) {
938:                    if (n instanceof  ReservedFieldNode) {
939:                        current.next = new GroupByThisExp();
940:                        current = current.next;
941:                    } else {
942:                        current.next = toSqlExp(n, ctx.root, ctx.leftSibling,
943:                                ctx.method, ctx.args);
944:                        current = current.next;
945:                    }
946:                }
947:                return head.next;
948:            }
949:
950:            public Object arriveResultNode(ResultNode node, Object msg) {
951:                Context ctx = (Context) msg;
952:                SqlExp head = new SqlExp();
953:                SqlExp current = head;
954:                for (Node n = node.childList; n != null; n = n.next) {
955:                    if (n instanceof  ReservedFieldNode)
956:                        continue;
957:                    current.next = toSqlExp(n, ctx.root, ctx.leftSibling,
958:                            ctx.method, ctx.args);
959:                    current = current.next;
960:                }
961:                return head.next;
962:            }
963:
964:            public Object arriveVarBindingNode(VarBindingNode node, Object msg) {
965:                SelectExp se = (SelectExp) node.getVar().getStoreExtent();
966:                return new ExistsExp(se, true);
967:            }
968:
969:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.