Source Code Cross Referenced for CastNode.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.CastNode
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.sql.compile;
023:
024:        import org.apache.derby.iapi.services.context.ContextManager;
025:
026:        import org.apache.derby.iapi.services.compiler.MethodBuilder;
027:        import org.apache.derby.iapi.services.compiler.LocalField;
028:
029:        import org.apache.derby.iapi.services.monitor.Monitor;
030:
031:        import org.apache.derby.iapi.services.sanity.SanityManager;
032:
033:        import org.apache.derby.iapi.error.StandardException;
034:
035:        import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
036:
037:        import org.apache.derby.iapi.sql.compile.CompilerContext;
038:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
039:
040:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
041:
042:        import org.apache.derby.iapi.types.DataTypeUtilities;
043:        import org.apache.derby.iapi.types.TypeId;
044:
045:        import org.apache.derby.iapi.reference.SQLState;
046:
047:        import org.apache.derby.iapi.types.DataTypeDescriptor;
048:        import org.apache.derby.iapi.types.DataValueFactory;
049:        import org.apache.derby.iapi.types.DataValueDescriptor;
050:        import org.apache.derby.iapi.types.VariableSizeDataValue;
051:
052:        import org.apache.derby.iapi.sql.compile.TypeCompiler;
053:
054:        import org.apache.derby.iapi.reference.SQLState;
055:        import org.apache.derby.iapi.util.StringUtil;
056:
057:        import org.apache.derby.iapi.reference.ClassName;
058:        import org.apache.derby.iapi.reference.JDBC30Translation;
059:        import org.apache.derby.iapi.services.classfile.VMOpcode;
060:
061:        import org.apache.derby.iapi.types.DataValueDescriptor;
062:
063:        import org.apache.derby.iapi.services.loader.ClassInspector;
064:
065:        import org.apache.derby.iapi.sql.compile.Visitable;
066:        import org.apache.derby.iapi.sql.compile.Visitor;
067:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
068:
069:        import java.lang.reflect.Modifier;
070:
071:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
072:        import org.apache.derby.iapi.types.NumberDataType;
073:
074:        import org.apache.derby.iapi.util.JBitSet;
075:        import org.apache.derby.iapi.util.ReuseFactory;
076:
077:        import org.apache.derby.catalog.AliasInfo;
078:        import org.apache.derby.catalog.TypeDescriptor;
079:
080:        import org.apache.derby.iapi.types.SQLReal;
081:
082:        import java.sql.Date;
083:        import java.sql.Time;
084:        import java.sql.Timestamp;
085:        import java.sql.Types;
086:
087:        import java.util.Vector;
088:
089:        /**
090:         * An CastNode represents a cast expressionr.
091:         *
092:         * @author Jerry Brenner
093:         */
094:
095:        public class CastNode extends ValueNode {
096:            DataTypeDescriptor castTarget;
097:            ValueNode castOperand;
098:            int targetCharType;
099:            TypeId destCTI = null;
100:            TypeId sourceCTI = null;
101:            boolean forDataTypeFunction = false;
102:
103:            /*
104:             ** Static array of valid casts.  Dimentions
105:             ** produce a single boolean which indicates
106:             ** whether the case is possible or not.
107:             */
108:
109:            /**
110:             * Initializer for a CastNode
111:             *
112:             * @param castOperand	The operand of the node
113:             * @param castTarget	DataTypeServices (target type of cast)
114:             *
115:             * @exception StandardException		Thrown on error
116:             */
117:
118:            public void init(Object castOperand, Object castTarget)
119:                    throws StandardException {
120:                this .castOperand = (ValueNode) castOperand;
121:                this .castTarget = (DataTypeDescriptor) castTarget;
122:            }
123:
124:            /**
125:             * Initializer for a CastNode
126:             *
127:             * @param castOperand	The operand of the node
128:             * @param charType		CHAR or VARCHAR JDBC type as target
129:             * @param charLength	target type length
130:             *
131:             * @exception StandardException		Thrown on error
132:             */
133:
134:            public void init(Object castOperand, Object charType,
135:                    Object charLength) throws StandardException {
136:                this .castOperand = (ValueNode) castOperand;
137:                int charLen = ((Integer) charLength).intValue();
138:                targetCharType = ((Integer) charType).intValue();
139:                if (charLen < 0) // unknown, figure out later
140:                    return;
141:                this .castTarget = DataTypeDescriptor
142:                        .getBuiltInDataTypeDescriptor(targetCharType, charLen);
143:            }
144:
145:            /**
146:             * Convert this object to a String.  See comments in QueryTreeNode.java
147:             * for how this should be done for tree printing.
148:             *
149:             * @return		This object as a String
150:             */
151:
152:            public String toString() {
153:                if (SanityManager.DEBUG) {
154:                    return "castTarget: " + castTarget + "\n"
155:                            + super .toString();
156:                } else {
157:                    return "";
158:                }
159:            }
160:
161:            /**
162:             * Prints the sub-nodes of this object.  See QueryTreeNode.java for
163:             * how tree printing is supposed to work.
164:             *
165:             * @param depth		The depth of this node in the tree
166:             */
167:
168:            public void printSubNodes(int depth) {
169:                if (SanityManager.DEBUG) {
170:                    super .printSubNodes(depth);
171:
172:                    if (castOperand != null) {
173:                        printLabel(depth, "castOperand: ");
174:                        castOperand.treePrint(depth + 1);
175:                    }
176:                }
177:            }
178:
179:            protected int getOrderableVariantType() throws StandardException {
180:                return castOperand.getOrderableVariantType();
181:            }
182:
183:            /**
184:             * Set the clause that this node appears in.
185:             *
186:             * @param clause	The clause that this node appears in.
187:             */
188:            public void setClause(int clause) {
189:                super .setClause(clause);
190:                castOperand.setClause(clause);
191:            }
192:
193:            /**
194:             * Bind this expression.  This means binding the sub-expressions,
195:             * as well as figuring out what the return type is for this expression.
196:             *
197:             * @param fromList		The FROM list for the query this
198:             *				expression is in, for binding columns.
199:             * @param subqueryList		The subquery list being built as we find SubqueryNodes
200:             * @param aggregateVector	The aggregate vector being built as we find AggregateNodes
201:             *
202:             * @return	The new top of the expression tree.
203:             *
204:             * @exception StandardException		Thrown on error
205:             */
206:
207:            public ValueNode bindExpression(FromList fromList,
208:                    SubqueryList subqueryList, Vector aggregateVector)
209:                    throws StandardException {
210:                castOperand = castOperand.bindExpression(fromList,
211:                        subqueryList, aggregateVector);
212:
213:                if (castTarget == null) //CHAR or VARCHAR function without specifying target length
214:                {
215:                    DataTypeDescriptor opndType = castOperand.getTypeServices();
216:                    int length = -1;
217:                    TypeId srcTypeId = opndType.getTypeId();
218:                    if (opndType != null) {
219:                        if (srcTypeId.isNumericTypeId()) {
220:                            length = opndType.getPrecision() + 1; // 1 for the sign
221:                            if (opndType.getScale() > 0)
222:                                length += 1; // 1 for the decimal .
223:
224:                        } else {
225:                            TypeId typeid = opndType.getTypeId();
226:                            if (length < 0)
227:                                length = DataTypeUtilities
228:                                        .getColumnDisplaySize(typeid
229:                                                .getJDBCTypeId(), -1);
230:
231:                        }
232:                    }
233:                    if (length < 0)
234:                        length = 1; // same default as in parser
235:                    castTarget = DataTypeDescriptor
236:                            .getBuiltInDataTypeDescriptor(targetCharType,
237:                                    length);
238:
239:                }
240:
241:                /* 
242:                 ** If castOperand is an untyped null, 
243:                 ** then we must set the type.
244:                 */
245:                if (castOperand instanceof  UntypedNullConstantNode) {
246:                    castOperand.setType(castTarget);
247:                }
248:
249:                bindCastNodeOnly();
250:
251:                /* We can't chop out cast above an untyped null because
252:                 * the store can't handle it.
253:                 */
254:                if ((castOperand instanceof  ConstantNode)
255:                        && !(castOperand instanceof  UntypedNullConstantNode)) {
256:                    /* If the castOperand is a typed constant then we do the cast at
257:                     * bind time and return a constant of the correct type.
258:                     * NOTE: This could return an exception, but we're prepared to 
259:                     * deal with that. (NumberFormatException, etc.)
260:                     * We only worry about the easy (and useful)
261:                     * converions at bind time.
262:                     * Here's what we support:
263:                     *			source					destination
264:                     *			------					-----------
265:                     *			boolean					boolean
266:                     *			boolean					char
267:                     *			char					boolean
268:                     *			char					date/time/ts
269:                     *			char					non-decimal numeric
270:                     *			date/time/ts			char
271:                     *			numeric					char
272:                     *			numeric					non-decimal numeric
273:                     */
274:                    /* RESOLVE - to be filled in. */
275:                    ValueNode retNode = this ;
276:                    int sourceJDBCTypeId = sourceCTI.getJDBCTypeId();
277:                    int destJDBCTypeId = destCTI.getJDBCTypeId();
278:
279:                    switch (sourceJDBCTypeId) {
280:                    case Types.BIT:
281:                    case JDBC30Translation.SQL_TYPES_BOOLEAN:
282:                        // (BIT is boolean)
283:                        if (destJDBCTypeId == Types.BIT
284:                                || destJDBCTypeId == JDBC30Translation.SQL_TYPES_BOOLEAN) {
285:                            retNode = castOperand;
286:                        } else if (destJDBCTypeId == Types.CHAR) {
287:                            BooleanConstantNode bcn = (BooleanConstantNode) castOperand;
288:                            String booleanString = bcn.getValueAsString();
289:                            retNode = (ValueNode) getNodeFactory().getNode(
290:                                    C_NodeTypes.CHAR_CONSTANT_NODE,
291:                                    booleanString,
292:                                    ReuseFactory.getInteger(castTarget
293:                                            .getMaximumWidth()),
294:                                    getContextManager());
295:                        }
296:                        break;
297:
298:                    case Types.CHAR:
299:                        retNode = getCastFromCharConstant(destJDBCTypeId);
300:                        break;
301:
302:                    case Types.DATE:
303:                    case Types.TIME:
304:                    case Types.TIMESTAMP:
305:                        if (destJDBCTypeId == Types.CHAR) {
306:                            String castValue = ((UserTypeConstantNode) castOperand)
307:                                    .getObjectValue().toString();
308:                            retNode = (ValueNode) getNodeFactory().getNode(
309:                                    C_NodeTypes.CHAR_CONSTANT_NODE,
310:                                    castValue,
311:                                    ReuseFactory.getInteger(castTarget
312:                                            .getMaximumWidth()),
313:                                    getContextManager());
314:                        }
315:                        break;
316:
317:                    case Types.DECIMAL:
318:                        // ignore decimal -> decimal casts for now
319:                        if (destJDBCTypeId == Types.DECIMAL
320:                                || destJDBCTypeId == Types.NUMERIC)
321:                            break;
322:                        // fall through
323:                    case Types.TINYINT:
324:                    case Types.SMALLINT:
325:                    case Types.INTEGER:
326:                    case Types.BIGINT:
327:                    case Types.DOUBLE:
328:                    case Types.REAL:
329:                        retNode = getCastFromNumericType(
330:                                ((ConstantNode) castOperand).getValue(),
331:                                destJDBCTypeId);
332:                        break;
333:
334:                    }
335:
336:                    // Return the new constant if the cast was performed
337:                    return retNode;
338:                }
339:
340:                return this ;
341:            }
342:
343:            /**
344:             * Bind this node but not its child.  Caller has already bound
345:             * the child.
346:             * This is useful for when we generate a CastNode during binding
347:             * after having already bound the child.
348:             *
349:             * @exception StandardException		Thrown on error
350:             */
351:            public void bindCastNodeOnly() throws StandardException {
352:
353:                /*
354:                 ** The result type is always castTarget.
355:                 */
356:                setType(castTarget);
357:                destCTI = castTarget.getTypeId();
358:                sourceCTI = castOperand.getTypeId();
359:
360:                /* 
361:                 ** If it is a java cast, do some work to make sure
362:                 ** the classes are ok and that they are compatible
363:                 */
364:                if (destCTI.userType()) {
365:                    String className = ((TypeId) dataTypeServices.getTypeId())
366:                            .getCorrespondingJavaTypeName();
367:
368:                    boolean convertCase = !destCTI
369:                            .getClassNameWasDelimitedIdentifier();
370:
371:                    className = verifyClassExist(className, convertCase);
372:
373:                    castTarget = new DataTypeDescriptor(TypeId
374:                            .getUserDefinedTypeId(className, false), true /* assume nullable for now, change it if not nullable */
375:                    );
376:                    setType(castTarget);
377:                    destCTI = castTarget.getTypeId();
378:                }
379:
380:                if (castOperand.requiresTypeFromContext()) {
381:                    bindParameter();
382:                }
383:
384:                /*
385:                 ** If it isn't null, then we have
386:                 ** a cast from one JBMS type to another.  So we
387:                 ** have to figure out if it is legit.
388:                 */
389:                else if (!(castOperand instanceof  UntypedNullConstantNode)) {
390:                    /*
391:                     ** Make sure we can assign the two classes
392:                     */
393:                    TypeCompiler tc = castOperand.getTypeCompiler();
394:                    if (!tc.convertible(destCTI, forDataTypeFunction)) {
395:                        throw StandardException.newException(
396:                                SQLState.LANG_INVALID_CAST, sourceCTI
397:                                        .getSQLTypeName(), destCTI
398:                                        .getSQLTypeName());
399:                    }
400:                }
401:            }
402:
403:            /**
404:             * Get a constant representing the cast from a CHAR to another
405:             * type.  If this is not an "easy" cast to perform, then just
406:             * return this cast node.
407:             * Here's what we think is "easy":
408:             *			source			destination
409:             *			------			-----------
410:             *			char			boolean
411:             *			char			date/time/ts
412:             *			char			non-decimal numeric
413:             *
414:             * @param destJDBCTypeId	The destination JDBC TypeId
415:             *
416:             * @return The new top of the tree (this CastNode or a new Constant)
417:             *
418:             * @exception StandardException		Thrown on error
419:             */
420:            private ValueNode getCastFromCharConstant(int destJDBCTypeId)
421:                    throws StandardException {
422:                String charValue = ((CharConstantNode) castOperand).getString();
423:                String cleanCharValue = StringUtil.SQLToUpperCase(charValue
424:                        .trim());
425:                ValueNode retNode = this ;
426:
427:                switch (destJDBCTypeId) {
428:                case Types.BIT:
429:                case JDBC30Translation.SQL_TYPES_BOOLEAN:
430:                    if (cleanCharValue.equals("TRUE")) {
431:                        return (ValueNode) getNodeFactory().getNode(
432:                                C_NodeTypes.BOOLEAN_CONSTANT_NODE,
433:                                Boolean.TRUE, getContextManager());
434:                    } else if (cleanCharValue.equals("FALSE")) {
435:                        return (ValueNode) getNodeFactory().getNode(
436:                                C_NodeTypes.BOOLEAN_CONSTANT_NODE,
437:                                Boolean.FALSE, getContextManager());
438:                    } else {
439:                        throw StandardException.newException(
440:                                SQLState.LANG_FORMAT_EXCEPTION, "boolean");
441:                    }
442:
443:                case Types.DATE:
444:                    return (ValueNode) getNodeFactory().getNode(
445:                            C_NodeTypes.USERTYPE_CONSTANT_NODE,
446:                            getDataValueFactory().getDateValue(cleanCharValue,
447:                                    false), getContextManager());
448:
449:                case Types.TIMESTAMP:
450:                    return (ValueNode) getNodeFactory()
451:                            .getNode(
452:                                    C_NodeTypes.USERTYPE_CONSTANT_NODE,
453:                                    getDataValueFactory().getTimestampValue(
454:                                            cleanCharValue, false),
455:                                    getContextManager());
456:
457:                case Types.TIME:
458:                    return (ValueNode) getNodeFactory().getNode(
459:                            C_NodeTypes.USERTYPE_CONSTANT_NODE,
460:                            getDataValueFactory().getTimeValue(cleanCharValue,
461:                                    false), getContextManager());
462:
463:                case Types.TINYINT:
464:                case Types.SMALLINT:
465:                case Types.INTEGER:
466:                case Types.BIGINT:
467:                    try {
468:                        // #3756 - Truncate decimal portion for casts to integer
469:                        return getCastFromIntegralType((new Double(
470:                                cleanCharValue)).longValue(), destJDBCTypeId);
471:                    } catch (NumberFormatException nfe) {
472:                        String sqlName = TypeId
473:                                .getBuiltInTypeId(destJDBCTypeId)
474:                                .getSQLTypeName();
475:                        throw StandardException.newException(
476:                                SQLState.LANG_FORMAT_EXCEPTION, sqlName);
477:                    }
478:                case Types.REAL:
479:                    Float floatValue;
480:                    try {
481:                        floatValue = Float.valueOf(cleanCharValue);
482:                    } catch (NumberFormatException nfe) {
483:                        throw StandardException.newException(
484:                                SQLState.LANG_FORMAT_EXCEPTION, "float");
485:                    }
486:                    return (ValueNode) getNodeFactory().getNode(
487:                            C_NodeTypes.FLOAT_CONSTANT_NODE, floatValue,
488:                            getContextManager());
489:                case Types.DOUBLE:
490:                    Double doubleValue;
491:                    try {
492:                        doubleValue = new Double(cleanCharValue);
493:                    } catch (NumberFormatException nfe) {
494:                        throw StandardException.newException(
495:                                SQLState.LANG_FORMAT_EXCEPTION, "double");
496:                    }
497:                    return (ValueNode) getNodeFactory().getNode(
498:                            C_NodeTypes.DOUBLE_CONSTANT_NODE, doubleValue,
499:                            getContextManager());
500:                }
501:
502:                return retNode;
503:            }
504:
505:            /**
506:             * Get a constant representing the cast from an integral type to another
507:             * type.  If this is not an "easy" cast to perform, then just
508:             * return this cast node.
509:             * Here's what we think is "easy":
510:             *			source				destination
511:             *			------				-----------
512:             *			integral type		 non-decimal numeric
513:             *			integral type		 char
514:             *
515:             * @param longValue			integral type as a long to cast from
516:             * @param destJDBCTypeId	The destination JDBC TypeId
517:             *
518:             * @return The new top of the tree (this CastNode or a new Constant)
519:             *
520:             * @exception StandardException		Thrown on error
521:             */
522:            private ValueNode getCastFromIntegralType(long longValue,
523:                    int destJDBCTypeId) throws StandardException {
524:                ValueNode retNode = this ;
525:
526:                switch (destJDBCTypeId) {
527:                case Types.CHAR:
528:                    return (ValueNode) getNodeFactory().getNode(
529:                            C_NodeTypes.CHAR_CONSTANT_NODE,
530:                            Long.toString(longValue),
531:                            ReuseFactory.getInteger(castTarget
532:                                    .getMaximumWidth()), getContextManager());
533:                case Types.TINYINT:
534:                    if (longValue < Byte.MIN_VALUE
535:                            || longValue > Byte.MAX_VALUE) {
536:                        throw StandardException.newException(
537:                                SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
538:                                "TINYINT");
539:                    }
540:                    return (ValueNode) getNodeFactory().getNode(
541:                            C_NodeTypes.TINYINT_CONSTANT_NODE,
542:                            ReuseFactory.getByte((byte) longValue),
543:                            getContextManager());
544:
545:                case Types.SMALLINT:
546:                    if (longValue < Short.MIN_VALUE
547:                            || longValue > Short.MAX_VALUE) {
548:                        throw StandardException.newException(
549:                                SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
550:                                "SHORT");
551:                    }
552:                    return (ValueNode) getNodeFactory().getNode(
553:                            C_NodeTypes.SMALLINT_CONSTANT_NODE,
554:                            ReuseFactory.getShort((short) longValue),
555:                            getContextManager());
556:
557:                case Types.INTEGER:
558:                    if (longValue < Integer.MIN_VALUE
559:                            || longValue > Integer.MAX_VALUE) {
560:                        throw StandardException.newException(
561:                                SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
562:                                "INTEGER");
563:                    }
564:                    return (ValueNode) getNodeFactory().getNode(
565:                            C_NodeTypes.INT_CONSTANT_NODE,
566:                            ReuseFactory.getInteger((int) longValue),
567:                            getContextManager());
568:
569:                case Types.BIGINT:
570:                    return (ValueNode) getNodeFactory().getNode(
571:                            C_NodeTypes.LONGINT_CONSTANT_NODE,
572:                            ReuseFactory.getLong(longValue),
573:                            getContextManager());
574:
575:                case Types.REAL:
576:                    if (Math.abs(longValue) > Float.MAX_VALUE) {
577:                        throw StandardException.newException(
578:                                SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
579:                                "REAL");
580:                    }
581:                    return (ValueNode) getNodeFactory().getNode(
582:                            C_NodeTypes.FLOAT_CONSTANT_NODE,
583:                            new Float((float) longValue), getContextManager());
584:
585:                case Types.DOUBLE:
586:                    return (ValueNode) getNodeFactory()
587:                            .getNode(C_NodeTypes.DOUBLE_CONSTANT_NODE,
588:                                    new Double((double) longValue),
589:                                    getContextManager());
590:                }
591:
592:                return retNode;
593:            }
594:
595:            /**
596:             * Get a constant representing the cast from a non-integral type to another
597:             * type.  If this is not an "easy" cast to perform, then just
598:             * return this cast node.
599:             * Here's what we think is "easy":
600:             *			source				destination
601:             *			------				-----------
602:             *			non-integral type	 non-decimal numeric
603:             *			non-integral type	 char
604:             *
605:             * @param constantValue		non-integral type a a double to cast from
606:             * @param destJDBCTypeId	The destination JDBC TypeId
607:             *
608:             * @return The new top of the tree (this CastNode or a new Constant)
609:             *
610:             * @exception StandardException		Thrown on error
611:             */
612:            private ValueNode getCastFromNumericType(
613:                    DataValueDescriptor constantValue, int destJDBCTypeId)
614:                    throws StandardException {
615:                int nodeType = -1;
616:                Object constantObject = null;
617:
618:                switch (destJDBCTypeId) {
619:                case Types.CHAR:
620:                    nodeType = C_NodeTypes.CHAR_CONSTANT_NODE;
621:                    constantObject = constantValue.getString();
622:                    return (ValueNode) getNodeFactory().getNode(
623:                            nodeType,
624:                            constantObject,
625:                            ReuseFactory.getInteger(castTarget
626:                                    .getMaximumWidth()), getContextManager());
627:
628:                case Types.TINYINT:
629:                    nodeType = C_NodeTypes.TINYINT_CONSTANT_NODE;
630:                    constantObject = new Byte(constantValue.getByte());
631:                    break;
632:
633:                case Types.SMALLINT:
634:                    nodeType = C_NodeTypes.SMALLINT_CONSTANT_NODE;
635:                    constantObject = ReuseFactory.getShort(constantValue
636:                            .getShort());
637:                    break;
638:
639:                case Types.INTEGER:
640:                    nodeType = C_NodeTypes.INT_CONSTANT_NODE;
641:                    constantObject = ReuseFactory.getInteger(constantValue
642:                            .getInt());
643:                    break;
644:
645:                case Types.BIGINT:
646:                    nodeType = C_NodeTypes.LONGINT_CONSTANT_NODE;
647:                    constantObject = ReuseFactory.getLong(constantValue
648:                            .getLong());
649:                    break;
650:
651:                case Types.REAL:
652:                    nodeType = C_NodeTypes.FLOAT_CONSTANT_NODE;
653:                    constantObject = new Float(NumberDataType
654:                            .normalizeREAL(constantValue.getDouble()));
655:                    break;
656:
657:                case Types.DOUBLE:
658:                    // no need to normalize here because no constant could be out of range for a double
659:                    nodeType = C_NodeTypes.DOUBLE_CONSTANT_NODE;
660:                    constantObject = new Double(constantValue.getDouble());
661:                    break;
662:                }
663:
664:                if (nodeType == -1)
665:                    return this ;
666:
667:                return (ValueNode) getNodeFactory().getNode(nodeType,
668:                        constantObject, getContextManager());
669:
670:            }
671:
672:            /**
673:             * Preprocess an expression tree.  We do a number of transformations
674:             * here (including subqueries, IN lists, LIKE and BETWEEN) plus
675:             * subquery flattening.
676:             * NOTE: This is done before the outer ResultSetNode is preprocessed.
677:             *
678:             * @param	numTables			Number of tables in the DML Statement
679:             * @param	outerFromList		FromList from outer query block
680:             * @param	outerSubqueryList	SubqueryList from outer query block
681:             * @param	outerPredicateList	PredicateList from outer query block
682:             *
683:             * @return		The modified expression
684:             *
685:             * @exception StandardException		Thrown on error
686:             */
687:            public ValueNode preprocess(int numTables, FromList outerFromList,
688:                    SubqueryList outerSubqueryList,
689:                    PredicateList outerPredicateList) throws StandardException {
690:                castOperand = castOperand.preprocess(numTables, outerFromList,
691:                        outerSubqueryList, outerPredicateList);
692:                return this ;
693:            }
694:
695:            /**
696:             * Categorize this predicate.  Initially, this means
697:             * building a bit map of the referenced tables for each predicate.
698:             * If the source of this ColumnReference (at the next underlying level) 
699:             * is not a ColumnReference or a VirtualColumnNode then this predicate
700:             * will not be pushed down.
701:             *
702:             * For example, in:
703:             *		select * from (select 1 from s) a (x) where x = 1
704:             * we will not push down x = 1.
705:             * NOTE: It would be easy to handle the case of a constant, but if the
706:             * inner SELECT returns an arbitrary expression, then we would have to copy
707:             * that tree into the pushed predicate, and that tree could contain
708:             * subqueries and method calls.
709:             * RESOLVE - revisit this issue once we have views.
710:             *
711:             * @param referencedTabs	JBitSet with bit map of referenced FromTables
712:             * @param simplePredsOnly	Whether or not to consider method
713:             *							calls, field references and conditional nodes
714:             *							when building bit map
715:             *
716:             * @return boolean		Whether or not source.expression is a ColumnReference
717:             *						or a VirtualColumnNode.
718:             *
719:             * @exception StandardException			Thrown on error
720:             */
721:            public boolean categorize(JBitSet referencedTabs,
722:                    boolean simplePredsOnly) throws StandardException {
723:                return castOperand.categorize(referencedTabs, simplePredsOnly);
724:            }
725:
726:            /**
727:             * Remap all ColumnReferences in this tree to be clones of the
728:             * underlying expression.
729:             *
730:             * @return ValueNode			The remapped expression tree.
731:             *
732:             * @exception StandardException			Thrown on error
733:             */
734:            public ValueNode remapColumnReferencesToExpressions()
735:                    throws StandardException {
736:                castOperand = castOperand.remapColumnReferencesToExpressions();
737:                return this ;
738:            }
739:
740:            /**
741:             * Return whether or not this expression tree represents a constant expression.
742:             *
743:             * @return	Whether or not this expression tree represents a constant expression.
744:             */
745:            public boolean isConstantExpression() {
746:                return castOperand.isConstantExpression();
747:            }
748:
749:            /** @see ValueNode#constantExpression */
750:            public boolean constantExpression(PredicateList whereClause) {
751:                return castOperand.constantExpression(whereClause);
752:            }
753:
754:            /**
755:             * By default unary operators don't accept ? parameters as operands.
756:             * This can be over-ridden for particular unary operators.
757:             *
758:             * @exception StandardException		Always thrown to indicate a
759:             *									? parameter where it isn't allowed.
760:             */
761:
762:            void bindParameter() throws StandardException {
763:                castOperand.setType(castTarget);
764:            }
765:
766:            /**
767:             * Return an Object representing the bind time value of this
768:             * expression tree.  If the expression tree does not evaluate to
769:             * a constant at bind time then we return null.
770:             * This is useful for bind time resolution of VTIs.
771:             * RESOLVE: What do we do for primitives?
772:             *
773:             * @return	An Object representing the bind time value of this expression tree.
774:             *			(null if not a bind time constant.)
775:             *
776:             * @exception StandardException		Thrown on error
777:             */
778:            Object getConstantValueAsObject() throws StandardException {
779:                Object sourceObject = castOperand.getConstantValueAsObject();
780:
781:                // RESOLVE - need to figure out how to handle casts
782:                if (sourceObject == null) {
783:                    return null;
784:                }
785:
786:                // Simple if source and destination are of same type
787:                if (sourceCTI.getCorrespondingJavaTypeName().equals(
788:                        destCTI.getCorrespondingJavaTypeName())) {
789:                    return sourceObject;
790:                }
791:
792:                // RESOLVE - simply return null until we can figure out how to 
793:                // do the cast
794:                return null;
795:            }
796:
797:            /**
798:             * Do code generation for this unary operator.
799:             *
800:             * @param acb	The ExpressionClassBuilder for the class we're generating
801:             * @param mb	The method the code to place the code
802:             *
803:             * @exception StandardException		Thrown on error
804:             */
805:
806:            public void generateExpression(ExpressionClassBuilder acb,
807:                    MethodBuilder mb) throws StandardException {
808:                castOperand.generateExpression(acb, mb);
809:
810:                /* No need to generate code for null constants */
811:                if (castOperand instanceof  UntypedNullConstantNode) {
812:                    return;
813:                }
814:                /* HACK ALERT. When casting a parameter, there
815:                 * is not sourceCTI.  Code generation requires one,
816:                 * so we simply set it to be the same as the
817:                 * destCTI.  The user can still pass whatever
818:                 * type they'd like in as a parameter.
819:                 * They'll get an exception, as expected, if the
820:                 * conversion cannot be performed.
821:                 */
822:                else if (castOperand.requiresTypeFromContext()) {
823:                    sourceCTI = destCTI;
824:                }
825:
826:                genDataValueConversion(acb, mb);
827:            }
828:
829:            private void genDataValueConversion(ExpressionClassBuilder acb,
830:                    MethodBuilder mb) throws StandardException {
831:                MethodBuilder acbConstructor = acb.getConstructor();
832:
833:                String resultTypeName = getTypeCompiler().interfaceName();
834:
835:                /* field = method call */
836:                /* Allocate an object for re-use to hold the result of the operator */
837:                LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE,
838:                        resultTypeName);
839:
840:                /*
841:                 ** Store the result of the method call in the field, so we can re-use
842:                 ** the object.
843:                 */
844:
845:                acb.generateNull(acbConstructor, getTypeCompiler(destCTI));
846:                acbConstructor.setField(field);
847:
848:                /*
849:                	For most types generate
850:
851:                	targetDVD.setValue(sourceDVD);
852:                	
853:                	For source or destination java types generate
854:                	
855:                	Object o = sourceDVD.getObject();
856:                	targetDVD.setObjectForCast(o, o instanceof dest java type, dest java type);
857:
858:                	// optional for variable length types
859:                	targetDVD.setWidth();
860:                 */
861:
862:                if (!sourceCTI.userType() && !destCTI.userType()) {
863:                    mb.getField(field); // targetDVD reference for the setValue method call
864:                    mb.swap();
865:                    mb.upCast(ClassName.DataValueDescriptor);
866:                    mb.callMethod(VMOpcode.INVOKEINTERFACE,
867:                            ClassName.DataValueDescriptor, "setValue", "void",
868:                            1);
869:                } else {
870:                    /* 
871:                     ** generate: expr.getObject()
872:                     */
873:                    mb.callMethod(VMOpcode.INVOKEINTERFACE,
874:                            ClassName.DataValueDescriptor, "getObject",
875:                            "java.lang.Object", 0);
876:
877:                    //castExpr
878:
879:                    mb.getField(field); // instance for the setValue/setObjectForCast method call
880:                    mb.swap(); // push it before the value
881:
882:                    /*
883:                     ** We are casting a java type, generate:
884:                     **
885:                     **		DataValueDescriptor.setObjectForCast(java.lang.Object castExpr, boolean instanceOfExpr, destinationClassName)
886:                     ** where instanceOfExpr is "source instanceof destinationClass".
887:                     **
888:                     */
889:                    String destinationType = getTypeId()
890:                            .getCorrespondingJavaTypeName();
891:
892:                    // at this point method instance and cast result are on the stack
893:                    // we duplicate the cast value in order to perform the instanceof check
894:                    mb.dup();
895:                    mb.isInstanceOf(destinationType);
896:                    mb.push(destinationType);
897:                    mb.callMethod(VMOpcode.INVOKEINTERFACE,
898:                            ClassName.DataValueDescriptor, "setObjectForCast",
899:                            "void", 3);
900:
901:                }
902:
903:                mb.getField(field);
904:
905:                /* 
906:                 ** If we are casting to a variable length datatype, we
907:                 ** have to make sure we have set it to the correct
908:                 ** length.
909:                 */
910:                if (destCTI.variableLength()) {
911:                    boolean isNumber = destCTI.isNumericTypeId();
912:
913:                    // to leave the DataValueDescriptor value on the stack, since setWidth is void
914:                    mb.dup();
915:
916:                    /* setWidth() is on VSDV - upcast since
917:                     * decimal implements subinterface
918:                     * of VSDV.
919:                     */
920:
921:                    mb.push(isNumber ? castTarget.getPrecision() : castTarget
922:                            .getMaximumWidth());
923:                    mb.push(castTarget.getScale());
924:                    mb.push(!sourceCTI.variableLength() || isNumber);
925:                    mb.callMethod(VMOpcode.INVOKEINTERFACE,
926:                            ClassName.VariableSizeDataValue, "setWidth",
927:                            "void", 3);
928:
929:                }
930:            }
931:
932:            /**
933:             * Accept a visitor, and call v.visit()
934:             * on child nodes as necessary.  
935:             * 
936:             * @param v the visitor
937:             *
938:             * @exception StandardException on error
939:             */
940:            public Visitable accept(Visitor v) throws StandardException {
941:                Visitable returnNode = v.visit(this );
942:
943:                if (v.skipChildren(this )) {
944:                    return returnNode;
945:                }
946:
947:                if (castOperand != null && !v.stopTraversal()) {
948:                    castOperand = (ValueNode) castOperand.accept(v);
949:                }
950:
951:                return returnNode;
952:            }
953:
954:            /** set this to be a dataTypeScalarFunction
955:             * 
956:             * @param b true to use function conversion rules
957:             */
958:            public void setForDataTypeFunction(boolean b) {
959:                forDataTypeFunction = b;
960:            }
961:
962:            /** is this a cast node for a data type scalar function?
963:             * @return true if this is  a function, false for regular cast node
964:             *
965:             */
966:            public boolean getForDataTypeFunction() {
967:                return forDataTypeFunction;
968:            }
969:
970:            /**
971:             * {@inheritDoc}
972:             * @throws StandardException 
973:             */
974:            protected boolean isEquivalent(ValueNode o)
975:                    throws StandardException {
976:                if (isSameNodeType(o)) {
977:                    CastNode other = (CastNode) o;
978:                    return castTarget.equals(other.castTarget)
979:                            && castOperand.isEquivalent(other.castOperand);
980:                }
981:                return false;
982:            }
983:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.