📄 unaryoperatornode.java
字号:
break; default: { throw StandardException.newException( SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, methodName, operandType.getSQLTypeName()); } } } // The result type of XMLParse() is always an XML type. setType(DataTypeDescriptor.getBuiltInDataTypeDescriptor( StoredFormatIds.XML_TYPE_ID)); } /** * Bind an XMLSERIALIZE operator. Makes sure the operand type * and target type are both correct, and sets the result type. * * @exception StandardException Thrown on error */ public void bindXMLSerialize() throws StandardException { TypeId operandType; // Check the type of the operand - this function is allowed only on // the XML type. operandType = operand.getTypeId(); if ((operandType != null) && !operandType.isXMLTypeId()) { throw StandardException.newException( SQLState.LANG_UNARY_FUNCTION_BAD_TYPE, methodName, operandType.getSQLTypeName()); } // Check the target type. We only allow string types to be used as // the target type. The targetType is stored as the first Object // in our list of additional parameters, so we have to retrieve // it from there. if (SanityManager.DEBUG) { SanityManager.ASSERT( ((additionalArgs != null) && (additionalArgs.length > 0)), "Failed to locate target type for XMLSERIALIZE operator"); } DataTypeDescriptor targetType = (DataTypeDescriptor)additionalArgs[0]; TypeId targetTypeId = targetType.getTypeId(); switch (targetTypeId.getJDBCTypeId()) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: break; default: { throw StandardException.newException( SQLState.LANG_INVALID_XMLSERIALIZE_TYPE, targetTypeId.getSQLTypeName()); } } // The result type of XMLSerialize() is always a string; which // kind of string is determined by the targetType field. setType(targetType); } /** * Preprocess an expression tree. We do a number of transformations * here (including subqueries, IN lists, LIKE and BETWEEN) plus * subquery flattening. * NOTE: This is done before the outer ResultSetNode is preprocessed. * * @param numTables Number of tables in the DML Statement * @param outerFromList FromList from outer query block * @param outerSubqueryList SubqueryList from outer query block * @param outerPredicateList PredicateList from outer query block * * @return The modified expression * * @exception StandardException Thrown on error */ public ValueNode preprocess(int numTables, FromList outerFromList, SubqueryList outerSubqueryList, PredicateList outerPredicateList) throws StandardException { if (operand != null) { operand = operand.preprocess(numTables, outerFromList, outerSubqueryList, outerPredicateList); } return this; } /** * Categorize this predicate. Initially, this means * building a bit map of the referenced tables for each predicate. * If the source of this ColumnReference (at the next underlying level) * is not a ColumnReference or a VirtualColumnNode then this predicate * will not be pushed down. * * For example, in: * select * from (select 1 from s) a (x) where x = 1 * we will not push down x = 1. * NOTE: It would be easy to handle the case of a constant, but if the * inner SELECT returns an arbitrary expression, then we would have to copy * that tree into the pushed predicate, and that tree could contain * subqueries and method calls. * RESOLVE - revisit this issue once we have views. * * @param referencedTabs JBitSet with bit map of referenced FromTables * @param simplePredsOnly Whether or not to consider method * calls, field references and conditional nodes * when building bit map * * @return boolean Whether or not source.expression is a ColumnReference * or a VirtualColumnNode. * * @exception StandardException Thrown on error */ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly) throws StandardException { return (operand == null) ? false : operand.categorize(referencedTabs, simplePredsOnly); } /** * Remap all ColumnReferences in this tree to be clones of the * underlying expression. * * @return ValueNode The remapped expression tree. * * @exception StandardException Thrown on error */ public ValueNode remapColumnReferencesToExpressions() throws StandardException { if (operand != null) { operand = operand.remapColumnReferencesToExpressions(); } return this; } /** * Return whether or not this expression tree represents a constant expression. * * @return Whether or not this expression tree represents a constant expression. */ public boolean isConstantExpression() { return (operand == null) ? true: operand.isConstantExpression(); } /** @see ValueNode#constantExpression */ public boolean constantExpression(PredicateList whereClause) { return (operand == null) ? true : operand.constantExpression(whereClause); } /** * By default unary operators don't accept ? parameters as operands. * This can be over-ridden for particular unary operators. * * We throw an exception if the parameter doesn't have a datatype * assigned to it yet. * * @return Nothing * * @exception StandardException Thrown if ? parameter doesn't * have a type bound to it yet. * ? parameter where it isn't allowed. */ void bindParameter() throws StandardException { if (operatorType == XMLPARSE_OP) { // According to the SQL/XML standard, the XMLParse parameter // takes a string operand. RESOLVE: We use CLOB here because // an XML string can be arbitrarily long...is this okay? // The SQL/XML spec doesn't state what the type of the param // should be; only that it "shall be a character type". ((ParameterNode) operand).setDescriptor( DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.CLOB)); } else if (operatorType == XMLSERIALIZE_OP) { // For now, since JDBC has no type defined for XML, we // don't allow binding to an XML parameter. throw StandardException.newException( SQLState.LANG_ATTEMPT_TO_BIND_XML); } else if (operand.getTypeServices() == null) { throw StandardException.newException(SQLState.LANG_UNARY_OPERAND_PARM, operator); } } /** * Do code generation for this unary operator. * * @param acb The ExpressionClassBuilder for the class we're generating * @param mb The method the expression will go into * * * @exception StandardException Thrown on error */ public void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException { if (operand == null) return; String resultTypeName = (operatorType == -1) ? getTypeCompiler().interfaceName() : resultInterfaceType; // System.out.println("resultTypeName " + resultTypeName + " method " + methodName); // System.out.println("isBooleanTypeId() " + getTypeId().isBooleanTypeId()); boolean needField = !getTypeId().isBooleanTypeId(); String receiverType = getReceiverInterfaceName(); operand.generateExpression(acb, mb); mb.cast(receiverType); if (needField) { /* Allocate an object for re-use to hold the result of the operator */ LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName); mb.getField(field); int numParams = 1 + addMethodParams(mb); mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, numParams); /* ** Store the result of the method call in the field, so we can re-use ** the object. */ mb.putField(field); } else { int numParams = addMethodParams(mb); mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, numParams); } } /** * Determine the type the binary method is called on. * By default, based on the receiver. * * Override in nodes that use methods on super-interfaces of * the receiver's interface, such as comparisons. * * @exception StandardException Thrown on error */ public String getReceiverInterfaceName() throws StandardException { if (SanityManager.DEBUG) { SanityManager.ASSERT(operand!=null, "cannot get interface without operand"); } if (operatorType != -1) return receiverInterfaceType; return operand.getTypeCompiler().interfaceName(); } /** * Return the variant type for the underlying expression. * The variant type can be: * VARIANT - variant within a scan * (method calls and non-static field access) * SCAN_INVARIANT - invariant within a scan * (column references from outer tables) * QUERY_INVARIANT - invariant within the life of a query * (constant expressions) * CONSTANT - immutable * * @return The variant type for the underlying expression. * @exception StandardException thrown on error */ protected int getOrderableVariantType() throws StandardException { /* ** If we have nothing in the operator, then ** it must be constant. */ return (operand != null) ? operand.getOrderableVariantType() : Qualifier.CONSTANT; } /** * Accept a visitor, and call v.visit() * on child nodes as necessary. * * @param v the visitor * * @exception StandardException on error */ public Visitable accept(Visitor v) throws StandardException { Visitable returnNode = v.visit(this); if (v.skipChildren(this)) { return returnNode; } if (operand != null && !v.stopTraversal()) { operand = (ValueNode)operand.accept(v); } return returnNode; } /** * This method allows different operators to add * primitive arguments to the generated method call, * if needed. * @param mb The MethodBuilder that will make the call. * @return Number of parameters added. */ protected int addMethodParams(MethodBuilder mb) { if (operatorType == XMLPARSE_OP) { // We push whether or not we want to preserve whitespace. mb.push(((Boolean)additionalArgs[0]).booleanValue()); return 1; } if (operatorType == XMLSERIALIZE_OP) { // We push the target type's JDBC type id as well as // the maximum width, since both are required when // we actually perform the operation, and both are // primitive types. DataTypeDescriptor targetType = (DataTypeDescriptor)additionalArgs[0]; mb.push(targetType.getJDBCTypeId()); mb.push(targetType.getMaximumWidth()); return 2; } // Default is to add zero params. return 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -