📄 aggregatenode.java
字号:
if (distinct) { /* ** For now, we check to see if orderable() returns ** true for this type. In the future we may need ** to check to see if the type implements Orderable ** */ if (!operand.getTypeId().orderable(cf)) { throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION, dts.getTypeId().getSQLTypeName()); } } /* ** Don't allow an untyped null */ if (operand instanceof UntypedNullConstantNode) { throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE_NULL, aggregateName); } } /* ** Ask the aggregate definition whether it can handle ** the input datatype. If an exception is thrown, ** barf. */ try { aggregatorClassName = new StringBuffer(); resultType = uad.getAggregator(dts, aggregatorClassName); } catch (Exception e) { //RESOLVE: would be a good idea to add some additional text to // this error, like during getResultDataType on aggregate x // maybe enhance this error everywhere (seems like execution // should also add some text, at the very least saying during // execution. see Compiltion/Generator/UserExpressionBuilder.java throw StandardException.unexpectedUserException(e); } if (resultType == null) { throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE, aggregateName, operand.getTypeId().getSQLTypeName()); } checkAggregatorClassName(aggregatorClassName.toString()); /* ** Try for a built in type matching the ** type name. */ TypeId compTypeId = TypeId.getBuiltInTypeId(resultType.getTypeName()); /* ** If not built in, it is probably a java type. ** Get the sql type descriptor for that. */ if (compTypeId == null) { compTypeId = TypeId.getSQLTypeForJavaType(resultType.getTypeName()); } /* ** Now set the type. Get a new descriptor ** in case the user returned the same descriptor ** as was passed in. */ setType(new DataTypeDescriptor( compTypeId, resultType.getPrecision(), resultType.getScale(), resultType.isNullable(), resultType.getMaximumWidth() ) ); return this; } /* ** Make sure the aggregator class is ok */ private void checkAggregatorClassName(String className) throws StandardException { className = verifyClassExist(className, false); if (!classInspector.assignableTo(className, "org.apache.derby.iapi.sql.execute.ExecAggregator")) { throw StandardException.newException(SQLState.LANG_BAD_AGGREGATOR_CLASS2, className, aggregateName, operand.getTypeId().getSQLTypeName()); } } /* ** Instantiate the aggregate definition. */ private void instantiateAggDef() throws StandardException { Class theClass = aggregateDefinitionClass; // get the class if (theClass == null) { String aggClassName = aggregateDefinitionClassName; aggClassName = verifyClassExist(aggClassName, false); try { theClass = classInspector.getClass(aggClassName); } catch (Throwable t) { throw StandardException.unexpectedUserException(t); } } // get an instance Object instance = null; try { instance = theClass.newInstance(); } catch (Throwable t) { throw StandardException.unexpectedUserException(t); } if (!(instance instanceof AggregateDefinition)) { throw StandardException.newException(SQLState.LANG_INVALID_USER_AGGREGATE_DEFINITION2, aggregateDefinitionClassName); } if (instance instanceof MaxMinAggregateDefinition) { MaxMinAggregateDefinition temp = (MaxMinAggregateDefinition)instance; if (aggregateName.equals("MAX")) temp.setMaxOrMin(true); else temp.setMaxOrMin(false); } if (instance instanceof SumAvgAggregateDefinition) { SumAvgAggregateDefinition temp1 = (SumAvgAggregateDefinition)instance; if (aggregateName.equals("SUM")) temp1.setSumOrAvg(true); else temp1.setSumOrAvg(false); } this.uad = (AggregateDefinition)instance; setOperator(aggregateName); setMethodName(aggregateDefinitionClassName); } /** * Indicate whether this aggregate is distinct or not. * * @return true/false */ public boolean isDistinct() { return distinct; } /** * Get the class that implements that aggregator for this * node. * * @return the class name */ public String getAggregatorClassName() { return aggregatorClassName.toString(); } /** * Get the class that implements that aggregator for this * node. * * @return the class name */ public String getAggregateName() { return aggregateName; } /** * Get the result column that has a new aggregator. * This aggregator will be fed into the sorter. * * @param the data dictionary * * @return the result column. WARNING: it still needs to be bound * * @exception StandardException on error */ public ResultColumn getNewAggregatorResultColumn(DataDictionary dd) throws StandardException { String className = aggregatorClassName.toString(); TypeId compTypeId = TypeId.getSQLTypeForJavaType(className); /* ** Create a null of the right type. The proper aggregators ** are created dynamically by the SortObservers */ ConstantNode nullNode = getNullNode( compTypeId, getContextManager()); // no params nullNode.bindExpression( null, // from null, // subquery null); // aggregate /* ** Create a result column with this new node below ** it. */ return (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, aggregateName, nullNode, getContextManager()); } /** * Get the aggregate expression in a new result * column. * * @param the data dictionary * * @return the result column. WARNING: it still needs to be bound * * @exception StandardException on error */ public ResultColumn getNewExpressionResultColumn(DataDictionary dd) throws StandardException { ValueNode node; /* ** Create a result column with the aggrergate operand ** it. If there is no operand, then we have a COUNT(*), ** so we'll have to create a new null node and put ** that in place. */ node = (operand == null) ? this.getNewNullResultExpression() : operand; return (ResultColumn) getNodeFactory().getNode( C_NodeTypes.RESULT_COLUMN, "##aggregate expression", node, getContextManager()); } /** * Get the null aggregate result expression * column. * * @return the value node * * @exception StandardException on error */ public ValueNode getNewNullResultExpression() throws StandardException { /* ** Create a result column with the aggrergate operand ** it. */ return getNullNode(this.getTypeId(), getContextManager()); } /** * Do code generation for this unary operator. Should * never be called for an aggregate -- it should be converted * into something else by code generation time. * * @param acb The ExpressionClassBuilder for the class we're generating * @param mb The method the code to place the code * * @return An expression to evaluate this operator * * @exception StandardException Thrown on error */ public void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException { if (SanityManager.DEBUG) { SanityManager.THROWASSERT("generateExpression() should never "+ "be called on an AggregateNode. "+ "replaceAggregatesWithColumnReferences should have " + "been called prior to generateExpression"); } } /** * Print a string ref of this node. * * @return a string representation of this node */ public String toString() { if (SanityManager.DEBUG) { return "Aggregate: "+aggregateName+ "\ndistinct: "+distinct+ super.toString(); } else { return ""; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -