Source Code Cross Referenced for AggregateNode.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.AggregateNode
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:
026:        import org.apache.derby.iapi.services.sanity.SanityManager;
027:        import org.apache.derby.iapi.services.loader.ClassInspector;
028:        import org.apache.derby.iapi.services.loader.ClassFactory;
029:
030:        import org.apache.derby.iapi.error.StandardException;
031:
032:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
033:
034:        import org.apache.derby.iapi.sql.compile.CompilerContext;
035:        import org.apache.derby.iapi.sql.compile.C_NodeTypes;
036:
037:        import org.apache.derby.iapi.types.DataTypeDescriptor;
038:        import org.apache.derby.iapi.types.TypeId;
039:        import org.apache.derby.iapi.reference.SQLState;
040:
041:        import org.apache.derby.iapi.sql.dictionary.DataDictionary;
042:        import org.apache.derby.iapi.sql.execute.ExecAggregator;
043:
044:        import org.apache.derby.iapi.error.StandardException;
045:        import org.apache.derby.iapi.reference.SQLState;
046:
047:        import org.apache.derby.impl.sql.compile.ActivationClassBuilder;
048:        import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
049:
050:        import org.apache.derby.catalog.AliasInfo;
051:        import org.apache.derby.catalog.TypeDescriptor;
052:
053:        import org.apache.derby.impl.sql.compile.CountAggregateDefinition;
054:        import org.apache.derby.impl.sql.compile.MaxMinAggregateDefinition;
055:        import org.apache.derby.impl.sql.compile.SumAvgAggregateDefinition;
056:
057:        import java.util.Vector;
058:
059:        /**
060:         * An Aggregate Node is a node that reprsents a set function/aggregate.
061:         * It used for all system aggregates as well as user defined aggregates.
062:         *
063:         * @author jamie
064:         */
065:
066:        public class AggregateNode extends UnaryOperatorNode {
067:            private boolean distinct;
068:
069:            private AggregateDefinition uad;
070:            private StringBuffer aggregatorClassName;
071:            private String aggregateDefinitionClassName;
072:            private Class aggregateDefinitionClass;
073:            private ClassInspector classInspector;
074:            private String aggregateName;
075:
076:            /*
077:             ** We wind up pushing all aggregates into a different
078:             ** resultColumnList.  When we do this (in 
079:             ** replaceAggregateWithColumnReference), we return a
080:             ** column reference and create a new result column.
081:             ** This is used to store that result column.
082:             */
083:            private ResultColumn generatedRC;
084:            private ColumnReference generatedRef;
085:
086:            /**
087:             * Intializer.  Used for user defined and internally defined aggregates.
088:             * Called when binding a StaticMethodNode that we realize is an aggregate.
089:             *
090:             * @param operand	the value expression for the aggregate
091:             * @param uadClass	the class name for user aggregate definition for the aggregate
092:             *					or the Class for the internal aggregate type.
093:             * @param distinct	boolean indicating whether this is distinct
094:             *					or not.
095:             * @param aggregateName	the name of the aggregate from the user's perspective,
096:             *					e.g. MAX
097:             *
098:             * @exception StandardException on error
099:             */
100:            public void init(Object operand, Object uadClass, Object distinct,
101:                    Object aggregateName) throws StandardException {
102:                super .init(operand);
103:                this .aggregateName = (String) aggregateName;
104:
105:                if (uadClass instanceof  String) {
106:                    this .aggregateDefinitionClassName = (String) uadClass;
107:                    this .distinct = ((Boolean) distinct).booleanValue();
108:                } else {
109:                    this .aggregateDefinitionClass = (Class) uadClass;
110:                    this .aggregateDefinitionClassName = aggregateDefinitionClass
111:                            .getName();
112:
113:                    // Distinct is meaningless for min and max
114:                    if (!aggregateDefinitionClass
115:                            .equals(MaxMinAggregateDefinition.class)) {
116:                        this .distinct = ((Boolean) distinct).booleanValue();
117:                    }
118:                }
119:            }
120:
121:            /**
122:             * Replace aggregates in the expression tree with a ColumnReference to
123:             * that aggregate, append the aggregate to the supplied RCL (assumed to
124:             * be from the child ResultSetNode) and return the ColumnReference.
125:             * This is useful for pushing aggregates in the Having clause down to
126:             * the user's select at parse time.  It is also used for moving around 
127:             * Aggregates in the select list when creating the Group By node.  In 
128:             * that case it is called <B> after </B> bind time, so we need to create
129:             * the column differently.
130:             *
131:             * @param rcl	The RCL to append to.
132:             * @param tableNumber	The tableNumber for the new ColumnReference
133:             *
134:             * @return ValueNode	The (potentially) modified tree.
135:             *
136:             * @exception StandardException			Thrown on error
137:             */
138:            public ValueNode replaceAggregatesWithColumnReferences(
139:                    ResultColumnList rcl, int tableNumber)
140:                    throws StandardException {
141:
142:                /*
143:                 ** This call is idempotent.  Do
144:                 ** the right thing if we have already
145:                 ** replaced ourselves.
146:                 */
147:                if (generatedRef == null) {
148:                    String generatedColName;
149:                    CompilerContext cc = getCompilerContext();
150:                    generatedColName = "SQLCol" + cc.getNextColumnNumber();
151:                    generatedRC = (ResultColumn) getNodeFactory().getNode(
152:                            C_NodeTypes.RESULT_COLUMN, generatedColName, this ,
153:                            getContextManager());
154:                    generatedRC.markGenerated();
155:
156:                    /*
157:                     ** Parse time.	
158:                     */
159:                    if (getTypeServices() == null) {
160:                        generatedRef = (ColumnReference) getNodeFactory()
161:                                .getNode(C_NodeTypes.COLUMN_REFERENCE,
162:                                        generatedColName, null,
163:                                        getContextManager());
164:                    } else {
165:                        generatedRef = (ColumnReference) getNodeFactory()
166:                                .getNode(C_NodeTypes.COLUMN_REFERENCE,
167:                                        generatedRC.getName(), null,
168:                                        getContextManager());
169:                        generatedRef.setType(this .getTypeServices());
170:                    }
171:                    // RESOLVE - unknown nesting level, but not correlated, so nesting levels must be 0
172:                    generatedRef.setNestingLevel(0);
173:                    generatedRef.setSourceLevel(0);
174:                    if (tableNumber != -1) {
175:                        generatedRef.setTableNumber(tableNumber);
176:                    }
177:
178:                    rcl.addResultColumn(generatedRC);
179:
180:                    /* 
181:                     ** Mark the ColumnReference as being generated to replace
182:                     ** an aggregate
183:                     */
184:                    generatedRef.markGeneratedToReplaceAggregate();
185:                } else {
186:                    rcl.addResultColumn(generatedRC);
187:                }
188:
189:                return generatedRef;
190:            }
191:
192:            /**
193:             * Get the AggregateDefinition.
194:             *
195:             * @return The AggregateDefinition
196:             */
197:            AggregateDefinition getAggregateDefinition() {
198:                return uad;
199:            }
200:
201:            /**
202:             * Get the generated ResultColumn where this
203:             * aggregate now resides after a call to 
204:             * replaceAggregatesWithColumnReference().
205:             *
206:             * @return the result column
207:             */
208:            public ResultColumn getGeneratedRC() {
209:                if (SanityManager.DEBUG) {
210:                    SanityManager
211:                            .ASSERT(
212:                                    generatedRC != null,
213:                                    "generatedRC is null.  replaceAggregateWithColumnReference() "
214:                                            + "has not been called on this AggergateNode.  Make sure "
215:                                            + "the node is under a ResultColumn as expected.");
216:                }
217:
218:                return generatedRC;
219:            }
220:
221:            /**
222:             * Get the generated ColumnReference to this
223:             * aggregate after the parent called
224:             * replaceAggregatesWithColumnReference().
225:             *
226:             * @return the column reference
227:             */
228:            public ColumnReference getGeneratedRef() {
229:                if (SanityManager.DEBUG) {
230:                    SanityManager
231:                            .ASSERT(
232:                                    generatedRef != null,
233:                                    "generatedRef is null.  replaceAggregateWithColumnReference() "
234:                                            + "has not been called on this AggergateNode.  Make sure "
235:                                            + "the node is under a ResultColumn as expected.");
236:                }
237:                return generatedRef;
238:            }
239:
240:            /**
241:             * Bind this operator.  Determine the type of the subexpression,
242:             * and pass that into the UserAggregate.
243:             *
244:             * @param fromList			The query's FROM list
245:             * @param subqueryList		The subquery list being built as we find SubqueryNodes
246:             * @param aggregateVector	The aggregate list being built as we find AggregateNodes
247:             *
248:             * @return	The new top of the expression tree.
249:             *
250:             * @exception StandardException		Thrown on error
251:             */
252:            public ValueNode bindExpression(FromList fromList,
253:                    SubqueryList subqueryList, Vector aggregateVector)
254:                    throws StandardException {
255:                TypeId outType;
256:                TypeId inputType = null;
257:                Class inputClass = null;
258:                String inputTypeName = null;
259:                Class inputInterfaceClass = null;
260:                String inputInterfaceName = null;
261:                DataTypeDescriptor dts = null;
262:                TypeDescriptor resultType = null;
263:                ClassFactory cf;
264:
265:                cf = getClassFactory();
266:                classInspector = cf.getClassInspector();
267:
268:                instantiateAggDef();
269:
270:                /* Add ourselves to the aggregateVector before we do anything else */
271:                aggregateVector.addElement(this );
272:
273:                super .bindExpression(fromList, subqueryList, aggregateVector);
274:
275:                if (operand != null) {
276:                    /*
277:                     ** Make sure that we don't have an aggregate 
278:                     ** IMMEDIATELY below us.  Don't search below
279:                     ** any ResultSetNodes.
280:                     */
281:                    HasNodeVisitor visitor = new HasNodeVisitor(
282:                            this .getClass(), ResultSetNode.class);
283:                    operand.accept(visitor);
284:                    if (visitor.hasNode()) {
285:                        throw StandardException
286:                                .newException(
287:                                        SQLState.LANG_USER_AGGREGATE_CONTAINS_AGGREGATE,
288:                                        aggregateName);
289:                    }
290:
291:                    /*
292:                     ** Check the type of the operand.  Make sure that the user
293:                     ** defined aggregate can handle the operand datatype.
294:                     */
295:                    dts = operand.getTypeServices();
296:
297:                    /* Convert count(nonNullableColumn) to count(*)	*/
298:                    if (uad instanceof  CountAggregateDefinition
299:                            && !dts.isNullable()) {
300:                        setOperator(aggregateName);
301:                        setMethodName(aggregateName);
302:                    }
303:
304:                    /*
305:                     ** If we have a distinct, then the value expression
306:                     ** MUST implement Orderable because we are going
307:                     ** to process it using it as part of a sort.
308:                     */
309:                    if (distinct) {
310:                        /*
311:                         ** For now, we check to see if orderable() returns
312:                         ** true for this type.  In the future we may need
313:                         ** to check to see if the type implements Orderable
314:                         **
315:                         */
316:                        if (!operand.getTypeId().orderable(cf)) {
317:                            throw StandardException
318:                                    .newException(
319:                                            SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION,
320:                                            dts.getTypeId().getSQLTypeName());
321:                        }
322:
323:                    }
324:
325:                    /*
326:                     ** Don't allow an untyped null
327:                     */
328:                    if (operand instanceof  UntypedNullConstantNode) {
329:                        throw StandardException.newException(
330:                                SQLState.LANG_USER_AGGREGATE_BAD_TYPE_NULL,
331:                                aggregateName);
332:                    }
333:                }
334:
335:                /*
336:                 ** Ask the aggregate definition whether it can handle
337:                 ** the input datatype.  If an exception is thrown,
338:                 ** barf.
339:                 */
340:                try {
341:                    aggregatorClassName = new StringBuffer();
342:                    resultType = uad.getAggregator(dts, aggregatorClassName);
343:                } catch (Exception e) {
344:                    //RESOLVE: would be a good idea to add some additional text to
345:                    // this error, like during getResultDataType on aggregate x
346:                    // maybe enhance this error everywhere (seems like execution
347:                    // should also add some text, at the very least saying during
348:                    // execution.  see Compiltion/Generator/UserExpressionBuilder.java
349:                    throw StandardException.unexpectedUserException(e);
350:                }
351:
352:                if (resultType == null) {
353:                    throw StandardException
354:                            .newException(
355:                                    SQLState.LANG_USER_AGGREGATE_BAD_TYPE,
356:                                    aggregateName, operand.getTypeId()
357:                                            .getSQLTypeName());
358:                }
359:
360:                checkAggregatorClassName(aggregatorClassName.toString());
361:
362:                /*
363:                 ** Try for a built in type matching the
364:                 ** type name.  
365:                 */
366:                TypeId compTypeId = TypeId.getBuiltInTypeId(resultType
367:                        .getTypeName());
368:                /*
369:                 ** If not built in, it is probably a java type.
370:                 ** Get the sql type descriptor for that.  
371:                 */
372:                if (compTypeId == null) {
373:                    compTypeId = TypeId.getSQLTypeForJavaType(resultType
374:                            .getTypeName());
375:                }
376:
377:                /*
378:                 ** Now set the type.  Get a new descriptor
379:                 ** in case the user returned the same descriptor
380:                 ** as was passed in.
381:                 */
382:                setType(new DataTypeDescriptor(compTypeId, resultType
383:                        .getPrecision(), resultType.getScale(), resultType
384:                        .isNullable(), resultType.getMaximumWidth()));
385:
386:                return this ;
387:            }
388:
389:            /*
390:             ** Make sure the aggregator class is ok
391:             */
392:            private void checkAggregatorClassName(String className)
393:                    throws StandardException {
394:                className = verifyClassExist(className, false);
395:
396:                if (!classInspector.assignableTo(className,
397:                        "org.apache.derby.iapi.sql.execute.ExecAggregator")) {
398:                    throw StandardException
399:                            .newException(SQLState.LANG_BAD_AGGREGATOR_CLASS2,
400:                                    className, aggregateName, operand
401:                                            .getTypeId().getSQLTypeName());
402:                }
403:            }
404:
405:            /*
406:             ** Instantiate the aggregate definition.
407:             */
408:            private void instantiateAggDef() throws StandardException {
409:                Class theClass = aggregateDefinitionClass;
410:
411:                // get the class
412:                if (theClass == null) {
413:                    String aggClassName = aggregateDefinitionClassName;
414:                    aggClassName = verifyClassExist(aggClassName, false);
415:
416:                    try {
417:                        theClass = classInspector.getClass(aggClassName);
418:                    } catch (Throwable t) {
419:                        throw StandardException.unexpectedUserException(t);
420:                    }
421:                }
422:
423:                // get an instance
424:                Object instance = null;
425:                try {
426:                    instance = theClass.newInstance();
427:                } catch (Throwable t) {
428:                    throw StandardException.unexpectedUserException(t);
429:                }
430:
431:                if (!(instance instanceof  AggregateDefinition)) {
432:                    throw StandardException.newException(
433:                            SQLState.LANG_INVALID_USER_AGGREGATE_DEFINITION2,
434:                            aggregateDefinitionClassName);
435:                }
436:
437:                if (instance instanceof  MaxMinAggregateDefinition) {
438:                    MaxMinAggregateDefinition temp = (MaxMinAggregateDefinition) instance;
439:                    if (aggregateName.equals("MAX"))
440:                        temp.setMaxOrMin(true);
441:                    else
442:                        temp.setMaxOrMin(false);
443:                }
444:
445:                if (instance instanceof  SumAvgAggregateDefinition) {
446:                    SumAvgAggregateDefinition temp1 = (SumAvgAggregateDefinition) instance;
447:                    if (aggregateName.equals("SUM"))
448:                        temp1.setSumOrAvg(true);
449:                    else
450:                        temp1.setSumOrAvg(false);
451:                }
452:
453:                this .uad = (AggregateDefinition) instance;
454:
455:                setOperator(aggregateName);
456:                setMethodName(aggregateDefinitionClassName);
457:
458:            }
459:
460:            /**
461:             * Indicate whether this aggregate is distinct or not.
462:             *
463:             * @return 	true/false
464:             */
465:            public boolean isDistinct() {
466:                return distinct;
467:            }
468:
469:            /**
470:             * Get the class that implements that aggregator for this
471:             * node.
472:             *
473:             * @return the class name
474:             */
475:            public String getAggregatorClassName() {
476:                return aggregatorClassName.toString();
477:            }
478:
479:            /**
480:             * Get the class that implements that aggregator for this
481:             * node.
482:             *
483:             * @return the class name
484:             */
485:            public String getAggregateName() {
486:                return aggregateName;
487:            }
488:
489:            /**
490:             * Get the result column that has a new aggregator.
491:             * This aggregator will be fed into the sorter.
492:             *
493:             * @param dd	the data dictionary
494:             *
495:             * @return the result column.  WARNING: it still needs to be bound
496:             *
497:             * @exception StandardException on error
498:             */
499:            public ResultColumn getNewAggregatorResultColumn(DataDictionary dd)
500:                    throws StandardException {
501:                String className = aggregatorClassName.toString();
502:
503:                TypeId compTypeId = TypeId.getSQLTypeForJavaType(className);
504:
505:                /*
506:                 ** Create a null of the right type.  The proper aggregators
507:                 ** are created dynamically by the SortObservers
508:                 */
509:                ConstantNode nullNode = getNullNode(compTypeId,
510:                        getContextManager()); // no params
511:
512:                nullNode.bindExpression(null, // from
513:                        null, // subquery
514:                        null); // aggregate
515:
516:                /*
517:                 ** Create a result column with this new node below
518:                 ** it.
519:                 */
520:                return (ResultColumn) getNodeFactory().getNode(
521:                        C_NodeTypes.RESULT_COLUMN, aggregateName, nullNode,
522:                        getContextManager());
523:            }
524:
525:            /**
526:             * Get the aggregate expression in a new result
527:             * column.
528:             *
529:             * @param dd the data dictionary
530:             *
531:             * @return the result column.  WARNING: it still needs to be bound
532:             *
533:             * @exception StandardException on error
534:             */
535:            public ResultColumn getNewExpressionResultColumn(DataDictionary dd)
536:                    throws StandardException {
537:                ValueNode node;
538:                /*
539:                 ** Create a result column with the aggrergate operand
540:                 ** it.  If there is no operand, then we have a COUNT(*),
541:                 ** so we'll have to create a new null node and put
542:                 ** that in place.
543:                 */
544:                node = (operand == null) ? this .getNewNullResultExpression()
545:                        : operand;
546:
547:                return (ResultColumn) getNodeFactory().getNode(
548:                        C_NodeTypes.RESULT_COLUMN, "##aggregate expression",
549:                        node, getContextManager());
550:            }
551:
552:            /**
553:             * Get the null aggregate result expression
554:             * column.
555:             *
556:             * @return the value node
557:             *
558:             * @exception StandardException on error
559:             */
560:            public ValueNode getNewNullResultExpression()
561:                    throws StandardException {
562:                /*
563:                 ** Create a result column with the aggrergate operand
564:                 ** it.
565:                 */
566:                return getNullNode(this .getTypeId(), getContextManager());
567:            }
568:
569:            /**
570:             * Do code generation for this unary operator.  Should
571:             * never be called for an aggregate -- it should be converted
572:             * into something else by code generation time.
573:             *
574:             * @param acb	The ExpressionClassBuilder for the class we're generating
575:             * @param mb	The method the code to place the code
576:             *
577:             * @exception StandardException		Thrown on error
578:             */
579:            public void generateExpression(ExpressionClassBuilder acb,
580:                    MethodBuilder mb) throws StandardException {
581:                if (SanityManager.DEBUG) {
582:                    SanityManager
583:                            .THROWASSERT("generateExpression() should never "
584:                                    + "be called on an AggregateNode.  "
585:                                    + "replaceAggregatesWithColumnReferences should have "
586:                                    + "been called prior to generateExpression");
587:                }
588:            }
589:
590:            /**
591:             * Print a string ref of this node.
592:             *
593:             * @return a string representation of this node 
594:             */
595:            public String toString() {
596:                if (SanityManager.DEBUG) {
597:                    return "Aggregate: " + aggregateName + "\ndistinct: "
598:                            + distinct + super .toString();
599:                } else {
600:                    return "";
601:                }
602:            }
603:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.