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

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


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.sql.compile.LikeEscapeOperatorNode
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.sql.compile;
023:
024:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
025:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
026:
027:        import org.apache.derby.iapi.services.sanity.SanityManager;
028:
029:        import org.apache.derby.iapi.error.StandardException;
030:
031:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
032:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
033:        import org.apache.derby.iapi.types.TypeId;
034:        import org.apache.derby.iapi.types.StringDataValue;
035:        import org.apache.derby.iapi.types.DataTypeDescriptor;
036:
037:        import org.apache.derby.iapi.sql.compile.TypeCompiler;
038:
039:        import org.apache.derby.iapi.reference.SQLState;
040:
041:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
042:        import org.apache.derby.iapi.services.compiler.LocalField;
043:
044:        import org.apache.derby.iapi.util.ReuseFactory;
045:
046:        import java.lang.reflect.Modifier;
047:        import org.apache.derby.iapi.services.classfile.VMOpcode;
048:
049:        import org.apache.derby.iapi.types.Like;
050:
051:        import java.sql.Types;
052:        import org.apache.derby.iapi.reference.ClassName;
053:
054:        import java.util.Vector;
055:
056:        /**
057:         * This node represents a like comparison operator (no escape)
058:
059:
060:         If the like pattern is a constant or a parameter then if possible
061:         the like is modified to include a >= and < operator. In some cases
062:         the like can be eliminated.
063:
064:
065:         constant or parameter LIKE pattern with prefix followed by optional wild card
066:         e.g. Cloudscape%
067:
068:         CHAR(n), VARCHAR(n) where n < 255
069:
070:         >=   prefix padded with '\u0000' to length n -- e.g. Cloudscape\u0000\u0000
071:         <=   prefix appended with '\uffff' -- e.g. Cloudscape\uffff
072:        
073:         [ can eliminate LIKE if constant. ]
074:
075:        
076:         CHAR(n), VARCHAR(n), LONG VARCHAR where n >= 255
077:
078:         >= prefix backed up one characer
079:         <= prefix appended with '\uffff'
080:
081:         no elimination of like
082:
083:
084:         parameter like pattern starts with wild card
085:
086:         CHAR(n), VARCHAR(n) where n <= 256
087:
088:         >= '\u0000' padded with '\u0000' to length n
089:         <= '\uffff'
090:
091:         no elimination of like
092:
093:         CHAR(n), VARCHAR(n), LONG VARCHAR where n > 256
094:
095:
096:         >= NULL
097:
098:         <= '\uffff'
099:        
100:        
101:         Note that the Unicode value is '\uffff' is defined as not a character value
102:         and can be used by a program for any purpose. We use it to set an upper
103:         bound on a character range with a less than predicate. We only need a single
104:         '\uffff' appended because the string 'Cloudscape\uffff\uffff' is not a valid
105:         String because '\uffff' is not a valid character.
106:        
107:
108:
109:
110:        
111:
112:        
113:
114:
115:         *
116:         * @author ames
117:         * 		converted to TernaryOperatorNode by been
118:         */
119:
120:        public final class LikeEscapeOperatorNode extends TernaryOperatorNode {
121:            boolean addedEquals;
122:            String escape;
123:
124:            /**
125:             * Initializer for a LikeEscapeOperatorNode
126:             *
127:             *	receiver like pattern [ escape escapeValue ]
128:             *
129:             * @param receiver   		The left operand of the like, column, CharConstant or Parameter
130:             * @param leftOperand		The right operand of the like, the pattern
131:             * @param rightOperand		The optional escape clause, null if not present
132:             */
133:
134:            public void init(Object receiver, Object leftOperand,
135:                    Object rightOperand) {
136:                /* By convention, the method name for the like operator is "like" */
137:                // super.init(leftOperand, rightOperand, new Integer(LIKE), null, null);
138:                super .init(receiver, leftOperand, rightOperand, ReuseFactory
139:                        .getInteger(TernaryOperatorNode.LIKE), null);
140:            }
141:
142:            /**
143:             * overrides BindOperatorNode.bindExpression because like has special
144:             * requirements for parameter binding.
145:             *
146:             * @return	The new top of the expression tree.
147:             *
148:             * @exception StandardException thrown on failure
149:             */
150:            public ValueNode bindExpression(FromList fromList,
151:                    SubqueryList subqueryList, Vector aggregateVector)
152:                    throws StandardException {
153:                super .bindExpression(fromList, subqueryList, aggregateVector);
154:
155:                String pattern = null;
156:
157:                // pattern cannot be a column
158:                if (leftOperand instanceof  ColumnReference)
159:                    throw StandardException
160:                            .newException(SQLState.LANG_DB2_LIKE_SYNTAX_ERROR);
161:
162:                // pattern must be a string or a parameter
163:
164:                if (!(leftOperand.requiresTypeFromContext())
165:                        && !(leftOperand.getTypeId().isStringTypeId()))
166:                    throw StandardException.newException(
167:                            SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "LIKE",
168:                            "FUNCTION");
169:
170:                // escape cannot be a column
171:                if (rightOperand != null
172:                        && rightOperand instanceof  ColumnReference) {
173:                    throw StandardException.newException(
174:                            SQLState.LANG_INVALID_ESCAPE_CHARACTER,
175:                            ((ColumnReference) rightOperand).getColumnName());
176:                }
177:
178:                // escape must be a string or a parameter
179:                if ((rightOperand != null)
180:                        && !(rightOperand.requiresTypeFromContext())
181:                        && !(rightOperand.getTypeId().isStringTypeId())) {
182:                    throw StandardException.newException(
183:                            SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "LIKE",
184:                            "FUNCTION");
185:                }
186:
187:                // deal with operand parameters
188:
189:                /* 
190:                 *  Is there a ? parameter on the left?
191:                 *  Do left first because its length is always maximum;
192:                 *  a parameter on the right copies its length from
193:                 *  the left, since it won't match if it is any longer than it.
194:                 */
195:
196:                if (receiver.requiresTypeFromContext()) {
197:                    receiver.setType(new DataTypeDescriptor(TypeId
198:                            .getBuiltInTypeId(Types.VARCHAR), true));
199:                }
200:
201:                /* 
202:                 *  Is there a ? parameter for the PATTERN of LIKE?
203:                 *  Copy from the receiver -- legal if both are parameters,
204:                 *  both will be max length.
205:                 *  REMIND: should nullability be copied, or set to true?
206:                 */
207:
208:                if (leftOperand.requiresTypeFromContext()) {
209:                    /*
210:                     * Set the pattern to the type of the left parameter, if
211:                     * the left is a string, otherwise set it to be VARCHAR. 
212:                     */
213:                    if (receiver.getTypeId().isStringTypeId()) {
214:                        leftOperand.setType(receiver.getTypeServices());
215:                    } else {
216:                        leftOperand.setType(new DataTypeDescriptor(TypeId
217:                                .getBuiltInTypeId(Types.VARCHAR), true));
218:                    }
219:                }
220:
221:                /* 
222:                 *  Is there a ? parameter for the ESCAPE of LIKE?
223:                 *  Copy from the receiver -- legal if both are parameters,
224:                 *  both will be max length.  nullability is set to true.
225:                 */
226:
227:                if (rightOperand != null
228:                        && rightOperand.requiresTypeFromContext()) {
229:                    /*
230:                     * Set the pattern to the type of the left parameter, if
231:                     * the left is a string, otherwise set it to be VARCHAR. 
232:                     */
233:                    if (receiver.getTypeId().isStringTypeId()) {
234:                        rightOperand.setType(receiver.getTypeServices());
235:                    } else {
236:                        rightOperand.setType(new DataTypeDescriptor(TypeId
237:                                .getBuiltInTypeId(Types.VARCHAR), true));
238:                    }
239:                }
240:
241:                bindToBuiltIn();
242:
243:                TypeCompiler receiverTC = receiver.getTypeCompiler();
244:                TypeCompiler leftTC = leftOperand.getTypeCompiler();
245:
246:                /* The receiver must be a string type
247:                 */
248:                if (!receiver.getTypeId().isStringTypeId()) {
249:                    throw StandardException.newException(
250:                            SQLState.LANG_DB2_FUNCTION_INCOMPATIBLE, "LIKE",
251:                            "FUNCTION");
252:
253:                }
254:
255:                /* If either the left or right operands are non-string types,
256:                 * then we generate an implicit cast to VARCHAR.
257:                 */
258:                if (!leftOperand.getTypeId().isStringTypeId()) {
259:                    leftOperand = castArgToString(leftOperand);
260:                    leftTC = leftOperand.getTypeCompiler();
261:                }
262:
263:                if (rightOperand != null) {
264:                    rightOperand = castArgToString(rightOperand);
265:                }
266:
267:                /* Remember whether or not right side is a string constant.
268:                 * We need to remember here so that we can transform 
269:                 * LIKE 'constant' into = 'constant' for national char
270:                 * columns.
271:                 */
272:                boolean leftConstant = (leftOperand instanceof  CharConstantNode);
273:                if (leftConstant) {
274:                    pattern = ((CharConstantNode) leftOperand).getString();
275:                }
276:
277:                boolean rightConstant = (rightOperand instanceof  CharConstantNode);
278:
279:                if (rightConstant) {
280:                    escape = ((CharConstantNode) rightOperand).getString();
281:                    if (escape.length() != 1) {
282:                        throw StandardException.newException(
283:                                SQLState.LANG_INVALID_ESCAPE_CHARACTER, escape);
284:                    }
285:                } else if (rightOperand == null) {
286:                    // No Escape clause: Let optimization continue for the = case below
287:                    rightConstant = true;
288:                }
289:
290:                /* If the left side of LIKE is a ColumnReference and
291:                 * the right side is a string constant without 
292:                 * a wildcard then we transform the LIKE into the 
293:                 * equivalent LIKE AND =.  
294:                 * If we have an escape clause it also must be a constant.
295:                 * These types of transformations are normally done 
296:                 * at preprocess time, but we make an exception 
297:                 * and do this one at bind time because we transform
298:                 * a NOT LIKE 'a' into (a LIKE 'a') = false prior to 
299:                 * preprocessing.
300:                 * The transformed tree will become:
301:                 *			AND
302:                 *		   /   \
303:                 *	     LIKE   =
304:                 */
305:
306:                if (receiver instanceof  ColumnReference && leftConstant
307:                        && rightConstant) {
308:                    if (Like.isOptimizable(pattern)) {
309:                        String newPattern = null;
310:
311:                        /*
312:                         * If our pattern has no pattern chars (after stripping them out
313:                         * for the ESCAPE case), we are good to apply = to this match
314:                         */
315:
316:                        if (escape != null) {
317:                            /* we return a new pattern stripped of ESCAPE chars */
318:                            newPattern = Like.stripEscapesNoPatternChars(
319:                                    pattern, escape.charAt(0));
320:                        } else if (pattern.indexOf('_') == -1
321:                                && pattern.indexOf('%') == -1) {
322:                            newPattern = pattern;
323:                        }
324:
325:                        if (newPattern != null) {
326:                            AndNode newAnd = null;
327:                            BinaryComparisonOperatorNode equals = null;
328:                            ValueNode leftClone = receiver.getClone();
329:
330:                            // Remember that we did xform, see preprocess()
331:                            addedEquals = true;
332:
333:                            equals = (BinaryComparisonOperatorNode) getNodeFactory()
334:                                    .getNode(
335:                                            C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE,
336:                                            leftClone,
337:                                            (ValueNode) getNodeFactory()
338:                                                    .getNode(
339:                                                            C_NodeTypes.CHAR_CONSTANT_NODE,
340:                                                            newPattern,
341:                                                            getContextManager()),
342:                                            getContextManager());
343:
344:                            // Set forQueryRewrite to bypass comparability checks
345:                            equals.setForQueryRewrite(true);
346:                            equals = (BinaryComparisonOperatorNode) equals
347:                                    .bindExpression(fromList, subqueryList,
348:                                            aggregateVector);
349:
350:                            newAnd = (AndNode) getNodeFactory().getNode(
351:                                    C_NodeTypes.AND_NODE, this , equals,
352:                                    getContextManager());
353:                            finishBindExpr();
354:                            newAnd.postBindFixup();
355:                            return newAnd;
356:                        }
357:                    }
358:                }
359:
360:                /* If we are comparing a char with a national char then
361:                 * we generate a cast above the reciever to force preprocess to
362:                 * not attempt any of the > <= optimizations since there is no
363:                 * way to determine the 'next' character for the <= operand.
364:                 */
365:
366:                TypeId leftTypeId = leftOperand.getTypeId();
367:                TypeId receiverTypeId = receiver.getTypeId();
368:
369:                if (receiverTypeId.isNationalStringTypeId()
370:                        && !leftTypeId.isNationalStringTypeId()) {
371:                    receiver = castArgToNationalString(receiver, receiverTC,
372:                            receiverTypeId);
373:                } else if (leftTypeId.isNationalStringTypeId()
374:                        && !receiverTypeId.isNationalStringTypeId()) {
375:                    leftOperand = castArgToNationalString(leftOperand, leftTC,
376:                            leftTypeId);
377:                }
378:
379:                finishBindExpr();
380:
381:                return this ;
382:            }
383:
384:            private ValueNode castArgToNationalString(ValueNode vn,
385:                    TypeCompiler vnTC, TypeId vnTypeId)
386:                    throws StandardException {
387:                ValueNode newNode = (ValueNode) getNodeFactory().getNode(
388:                        C_NodeTypes.CAST_NODE,
389:                        vn,
390:                        new DataTypeDescriptor(vnTypeId, true, vnTC
391:                                .getCastToCharWidth(vn.getTypeServices())),
392:                        getContextManager());
393:                ((CastNode) newNode).bindCastNodeOnly();
394:                return newNode;
395:            }
396:
397:            private void finishBindExpr() throws StandardException {
398:                // deal with compatability of operands and result type
399:                bindComparisonOperator();
400:
401:                /*
402:                 ** The result type of LIKE is Boolean
403:                 */
404:
405:                boolean nullableResult = receiver.getTypeServices()
406:                        .isNullable()
407:                        || leftOperand.getTypeServices().isNullable();
408:
409:                if (rightOperand != null) {
410:                    nullableResult |= rightOperand.getTypeServices()
411:                            .isNullable();
412:                }
413:
414:                setType(new DataTypeDescriptor(TypeId.BOOLEAN_ID,
415:                        nullableResult));
416:            }
417:
418:            /**
419:             * Bind this operator
420:             *
421:             * @exception StandardException		Thrown on error
422:             */
423:
424:            public void bindComparisonOperator() throws StandardException {
425:                TypeId receiverType = receiver.getTypeId();
426:                TypeId leftType = leftOperand.getTypeId();
427:
428:                /*
429:                 ** Check the type of the operands - this function is allowed only on
430:                 ** string types.
431:                 */
432:
433:                if (!receiverType.isStringTypeId()) {
434:                    throw StandardException.newException(
435:                            SQLState.LANG_LIKE_BAD_TYPE, receiverType
436:                                    .getSQLTypeName());
437:                }
438:
439:                if (!leftType.isStringTypeId()) {
440:                    throw StandardException.newException(
441:                            SQLState.LANG_LIKE_BAD_TYPE, leftType
442:                                    .getSQLTypeName());
443:                }
444:
445:                if (rightOperand != null
446:                        && !rightOperand.getTypeId().isStringTypeId()) {
447:                    throw StandardException.newException(
448:                            SQLState.LANG_LIKE_BAD_TYPE, rightOperand
449:                                    .getTypeId().getSQLTypeName());
450:                }
451:
452:            }
453:
454:            /**
455:             * Preprocess an expression tree.  We do a number of transformations
456:             * here (including subqueries, IN lists, LIKE and BETWEEN) plus
457:             * subquery flattening.
458:             * NOTE: This is done before the outer ResultSetNode is preprocessed.
459:             *
460:             * @param	numTables			Number of tables in the DML Statement
461:             * @param	outerFromList		FromList from outer query block
462:             * @param	outerSubqueryList	SubqueryList from outer query block
463:             * @param	outerPredicateList	PredicateList from outer query block
464:             *
465:             * @return		The modified expression
466:             *
467:             * @exception StandardException		Thrown on error
468:             */
469:            public ValueNode preprocess(int numTables, FromList outerFromList,
470:                    SubqueryList outerSubqueryList,
471:                    PredicateList outerPredicateList) throws StandardException {
472:                boolean eliminateLikeComparison = false;
473:                String greaterEqualString = null;
474:                String lessThanString = null;
475:                String pattern;
476:
477:                /* We must 1st preprocess the component parts */
478:                super .preprocess(numTables, outerFromList, outerSubqueryList,
479:                        outerPredicateList);
480:
481:                /* Don't try to optimize for (C)LOB type since it
482:                 * doesn't allow comparison.
483:                 */
484:                if (receiver.getTypeId().getSQLTypeName().equals("CLOB")) {
485:                    return this ;
486:                }
487:                /* No need to consider transformation if we
488:                 * already did transformation that added =
489:                 * at bind time.
490:                 */
491:                if (addedEquals) {
492:                    return this ;
493:                }
494:
495:                /* This is where we do the transformation for LIKE to make it optimizable.
496:                 * c1 LIKE 'asdf%' -> c1 LIKE 'asdf%' AND c1 >= 'asdf' AND c1 < 'asdg'
497:                 * c1 LIKE ? -> c1 LIKE ? and c1 >= ?', where ?' gets calculated at the
498:                 * beginning of execution.
499:                 */
500:                if (!(leftOperand instanceof  CharConstantNode)
501:                        && !(leftOperand.requiresTypeFromContext())) {
502:                    return this ;
503:                }
504:
505:                /* This transformation is only worth doing if it is pushable, ie, if
506:                 * the receiver is a ColumnReference.
507:                 */
508:                if (!(receiver instanceof  ColumnReference)) {
509:                    //
510:                    // We also do an early return here if in bindExpression we found we had
511:                    // a National Char and put a CAST above the receiver.
512:                    //
513:                    return this ;
514:                }
515:
516:                // Build String constants if right side is a constant
517:                if (leftOperand instanceof  CharConstantNode) {
518:                    pattern = ((CharConstantNode) leftOperand).getString();
519:
520:                    if (!Like.isOptimizable(pattern)) {
521:                        return this ;
522:                    }
523:
524:                    int maxWidth = receiver.getTypeServices().getMaximumWidth();
525:                    greaterEqualString = Like.greaterEqualString(pattern,
526:                            escape, maxWidth);
527:
528:                    /* We do not generate the < and we cannot drop the LIKE
529:                     * when doing LIKE on a national char column.
530:                     */
531:                    if (!receiver.getTypeId().isNationalStringTypeId()) {
532:                        lessThanString = Like.lessThanString(pattern, escape,
533:                                maxWidth);
534:                        eliminateLikeComparison = !Like
535:                                .isLikeComparisonNeeded(pattern);
536:                    }
537:                }
538:
539:                //System.out.println(receiver.getTypeServices());
540:                //System.out.println("MAX WIDTH " + receiver.getTypeServices().getMaximumWidth());
541:
542:                /* For some unknown reason we need to clone the receiver if it is
543:                 * a ColumnReference because reusing them in Qualifiers for a scan
544:                 * does not work.  
545:                 */
546:
547:                /* The transformed tree has to be normalized.  Either:
548:                 *			AND									AND
549:                 *		   /   \							   /   \
550:                 *	     LIKE   AND				OR:			 LIKE	AND
551:                 *			   /   \							   /   \
552:                 *			  >=    AND							  >=    TRUE
553:                 *				   /   \
554:                 *				  <     TRUE
555:                 * unless the like string is of the form CONSTANT%, in which
556:                 * case we can do away with the LIKE altogether:
557:                 *			AND									AND
558:                 *		   /   \							   /   \
559:                 *	     >=     AND				OR:			 >=  	TRUE
560:                 *			   /   \
561:                 *			  <    TRUE
562:                 */
563:
564:                AndNode newAnd = null;
565:                ValueNode trueNode = (ValueNode) getNodeFactory().getNode(
566:                        C_NodeTypes.BOOLEAN_CONSTANT_NODE, Boolean.TRUE,
567:                        getContextManager());
568:
569:                /* Create the AND <, if lessThanString is non-null  or 
570:                 * leftOperand is a parameter.
571:                   Currently for a national string we do not add a < than operator
572:                   since we don't know (?) how to calculate such a string.
573:                 */
574:                if (lessThanString != null
575:                        || (leftOperand.requiresTypeFromContext() && !receiver
576:                                .getTypeId().isNationalStringTypeId())) {
577:                    QueryTreeNode likeLTopt;
578:                    if (leftOperand.requiresTypeFromContext()) {
579:                        int maxWidth = receiver.getTypeServices()
580:                                .getMaximumWidth();
581:                        likeLTopt = setupOptimizeStringFromParameter(
582:                                leftOperand, rightOperand,
583:                                "lessThanStringFromParameter", maxWidth);
584:                    } else {
585:                        likeLTopt = getNodeFactory().getNode(
586:                                C_NodeTypes.CHAR_CONSTANT_NODE, lessThanString,
587:                                getContextManager());
588:                    }
589:
590:                    BinaryComparisonOperatorNode lessThan = (BinaryComparisonOperatorNode) getNodeFactory()
591:                            .getNode(
592:                                    C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE,
593:                                    receiver.getClone(), likeLTopt,
594:                                    getContextManager());
595:
596:                    // Disable comparability checks
597:                    lessThan.setForQueryRewrite(true);
598:                    /* Set type info for the operator node */
599:                    lessThan.bindComparisonOperator();
600:
601:                    // Use between selectivity for the <
602:                    lessThan.setBetweenSelectivity();
603:
604:                    /* Create the AND */
605:                    newAnd = (AndNode) getNodeFactory().getNode(
606:                            C_NodeTypes.AND_NODE, lessThan, trueNode,
607:                            getContextManager());
608:                    newAnd.postBindFixup();
609:                }
610:
611:                /* Create the AND >=.  Right side could
612:                 * be a CharConstantNode or a ParameterNode.
613:                 */
614:
615:                ValueNode likeGEopt;
616:                if (leftOperand.requiresTypeFromContext()) {
617:
618:                    // Create an expression off the parameter
619:                    // new SQLChar(Like.greaterEqualString(?));
620:
621:                    int maxWidth = receiver.getTypeServices().getMaximumWidth();
622:                    likeGEopt = setupOptimizeStringFromParameter(leftOperand,
623:                            rightOperand, "greaterEqualStringFromParameter",
624:                            maxWidth);
625:
626:                } else {
627:
628:                    likeGEopt = (ValueNode) getNodeFactory().getNode(
629:                            C_NodeTypes.CHAR_CONSTANT_NODE, greaterEqualString,
630:                            getContextManager());
631:                }
632:
633:                BinaryComparisonOperatorNode greaterEqual = (BinaryComparisonOperatorNode) getNodeFactory()
634:                        .getNode(
635:                                C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE,
636:                                receiver.getClone(), likeGEopt,
637:                                getContextManager());
638:
639:                // Disable comparability checks
640:                greaterEqual.setForQueryRewrite(true);
641:                /* Set type info for the operator node */
642:                greaterEqual.bindComparisonOperator();
643:
644:                // Use between selectivity for the >=
645:                greaterEqual.setBetweenSelectivity();
646:
647:                /* Create the AND */
648:                if (newAnd == null) {
649:                    newAnd = (AndNode) getNodeFactory().getNode(
650:                            C_NodeTypes.AND_NODE, greaterEqual, trueNode,
651:                            getContextManager());
652:                } else {
653:                    newAnd = (AndNode) getNodeFactory().getNode(
654:                            C_NodeTypes.AND_NODE, greaterEqual, newAnd,
655:                            getContextManager());
656:                }
657:                newAnd.postBindFixup();
658:
659:                /* Finally, we put a AND LIKE on top of the left deep tree, but
660:                 * only if it is still necessary.
661:                 */
662:                if (!eliminateLikeComparison) {
663:                    newAnd = (AndNode) getNodeFactory().getNode(
664:                            C_NodeTypes.AND_NODE, this , newAnd,
665:                            getContextManager());
666:                    newAnd.postBindFixup();
667:                }
668:
669:                /* Mark this node as transformed so that we don't get
670:                 * calculated into the selectivity mulitple times.
671:                 */
672:                setTransformed();
673:
674:                return newAnd;
675:            }
676:
677:            /**
678:             * Do code generation for this binary operator.
679:             *
680:             *		This code was copied from BinaryOperatorNode and stripped down
681:             *
682:             * @param acb	The ExpressionClassBuilder for the class we're generating
683:             * @param mb	The method the code to place the code
684:             *
685:             *
686:             * @exception StandardException		Thrown on error
687:             */
688:
689:            public void generateExpression(ExpressionClassBuilder acb,
690:                    MethodBuilder mb) throws StandardException {
691:
692:                /*
693:                 ** if i have a operator.getOrderableType() == constant, then just cache 
694:                 ** it in a field.  if i have QUERY_INVARIANT, then it would be good to
695:                 ** cache it in something that is initialized each execution,
696:                 ** but how?
697:                 */
698:
699:                /*
700:                 ** let the receiver type be determined by an
701:                 ** overridable method so that if methods are
702:                 ** not implemented on the lowest interface of
703:                 ** a class, they can note that in the implementation
704:                 ** of the node that uses the method.
705:                 */
706:                // receiverType = getReceiverInterfaceName();
707:                /*
708:                 ** Generate LHS (field = <receiver operand>). This assignment is
709:                 ** used as the receiver of the method call for this operator.
710:                 **
711:                 **	(<receiver operand>).method(<left operand>,
712:                 **                      <right operand>, [<escaperightOp>,]
713:                 **						<result field>)
714:                 */
715:
716:                receiver.generateExpression(acb, mb); // first arg
717:
718:                receiverInterfaceType = receiver.getTypeCompiler()
719:                        .interfaceName();
720:
721:                mb.upCast(receiverInterfaceType); // cast the method instance
722:
723:                leftOperand.generateExpression(acb, mb);
724:                mb.upCast(leftInterfaceType); // first arg with cast
725:
726:                if (rightOperand != null) {
727:                    rightOperand.generateExpression(acb, mb);
728:                    mb.upCast(rightInterfaceType); // second arg with cast
729:                }
730:
731:                /* Figure out the result type name */
732:                // resultTypeName = getTypeCompiler().interfaceName();
733:                mb.callMethod(VMOpcode.INVOKEINTERFACE, null, methodName,
734:                        resultInterfaceType, rightOperand == null ? 1 : 2);
735:            }
736:
737:            private ValueNode setupOptimizeStringFromParameter(
738:                    ValueNode parameterNode, ValueNode escapeNode,
739:                    String methodName, int maxWidth) throws StandardException {
740:
741:                Vector param;
742:
743:                if (escapeNode != null) {
744:                    param = new Vector(2);
745:                    methodName += "WithEsc";
746:                } else
747:                    param = new Vector(1);
748:
749:                StaticMethodCallNode methodCall = (StaticMethodCallNode) getNodeFactory()
750:                        .getNode(C_NodeTypes.STATIC_METHOD_CALL_NODE,
751:                                methodName, "org.apache.derby.iapi.types.Like",
752:                                getContextManager());
753:
754:                // using a method call directly, thus need internal sql capability
755:                methodCall.internalCall = true;
756:
757:                param.addElement(parameterNode);
758:                if (escapeNode != null)
759:                    param.addElement(escapeNode);
760:
761:                QueryTreeNode maxWidthNode = getNodeFactory().getNode(
762:                        C_NodeTypes.INT_CONSTANT_NODE, new Integer(maxWidth),
763:                        getContextManager());
764:                param.addElement(maxWidthNode);
765:
766:                methodCall.addParms(param);
767:
768:                ValueNode java2SQL = (ValueNode) getNodeFactory().getNode(
769:                        C_NodeTypes.JAVA_TO_SQL_VALUE_NODE, methodCall,
770:                        getContextManager());
771:
772:                java2SQL = (ValueNode) java2SQL
773:                        .bindExpression(null, null, null);
774:
775:                CastNode likeOpt = (CastNode) getNodeFactory().getNode(
776:                        C_NodeTypes.CAST_NODE, java2SQL,
777:                        parameterNode.getTypeServices(), getContextManager());
778:
779:                likeOpt.bindCastNodeOnly();
780:
781:                return likeOpt;
782:            }
783:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.