📄 inlistoperatornode.java
字号:
leftClone = (leftOperand instanceof ColumnReference) ? leftOperand.getClone() : leftOperand; rightBCO = (BinaryComparisonOperatorNode) getNodeFactory().getNode( C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE, leftClone, (ValueNode) rightOperandList.elementAt(elemsDone), getContextManager()); /* Set type info for the operator node */ rightBCO.bindComparisonOperator(); /* Create the AND */ newAnd = (AndNode) getNodeFactory().getNode( C_NodeTypes.AND_NODE, leftSide, rightBCO, getContextManager()); newAnd.postBindFixup(); leftSide = newAnd; } return leftSide; } /** * See if this IN list operator is referencing the same table. * * @param cr The column reference. * * @return true if in list references the same table as in cr. * * @exception StandardException Thrown on error */ public boolean selfReference(ColumnReference cr) throws StandardException { int size = rightOperandList.size(); for (int i = 0; i < size; i++) { ValueNode vn = (ValueNode) rightOperandList.elementAt(i); if (vn.getTablesReferenced().get(cr.getTableNumber())) return true; } return false; } /** * The selectivity for an "IN" predicate is generally very small. * This is an estimate applicable when in list are not all constants. */ public double selectivity(Optimizable optTable) { return 0.3d; } /** * Do code generation for this IN list operator. * * @param acb The ExpressionClassBuilder for the class we're generating * @param mb The MethodBuilder the expression will go into * * @return An Expression to evaluate this operator * * @exception StandardException Thrown on error */ public void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException { int listSize = rightOperandList.size(); String resultTypeName; String receiverType = ClassName.DataValueDescriptor; String leftInterfaceType = ClassName.DataValueDescriptor; String rightInterfaceType = ClassName.DataValueDescriptor + "[]"; if (SanityManager.DEBUG) { SanityManager.ASSERT(listSize > 0, "listSize is expected to be > 0"); } /* ** There are 2 parts to the code generation for an IN list - ** the code in the constructor and the code for the expression evaluation. ** The code that gets generated for the constructor is: ** DataValueDescriptor[] field = new DataValueDescriptor[size]; ** For each element in the IN list that is a constant, we also generate: ** field[i] = rightOperandList[i]; ** ** If the IN list is composed entirely of constants, then we generate the ** the following: ** leftOperand.in(rightOperandList, leftOperand, isNullable(), ordered, result); ** ** Otherwise, we create a new method. This method contains the ** assignment of the non-constant elements into the array and the call to the in() ** method, which is in the new method's return statement. We then return a call ** to the new method. */ receiver = leftOperand; /* Figure out the result type name */ resultTypeName = getTypeCompiler().interfaceName(); // Generate the code to build the array LocalField arrayField = acb.newFieldDeclaration(Modifier.PRIVATE, rightInterfaceType); /* The array gets created in the constructor. * All constant elements in the array are initialized * in the constructor. All non-constant elements, if any, * are initialized each time the IN list is evaluated. */ /* Assign the initializer to the DataValueDescriptor[] field */ MethodBuilder cb = acb.getConstructor(); cb.pushNewArray(ClassName.DataValueDescriptor, listSize); cb.setField(arrayField); /* Set the array elements that are constant */ int numConstants = 0; MethodBuilder nonConstantMethod = null; MethodBuilder currentConstMethod = cb; for (int index = 0; index < listSize; index++) { MethodBuilder setArrayMethod; if (rightOperandList.elementAt(index) instanceof ConstantNode) { numConstants++; /*if too many statements are added to a method, *size of method can hit 65k limit, which will *lead to the class format errors at load time. *To avoid this problem, when number of statements added *to a method is > 2048, remaing statements are added to a new function *and called from the function which created the function. *See Beetle 5135 or 4293 for further details on this type of problem. */ if(currentConstMethod.statementNumHitLimit(1)) { MethodBuilder genConstantMethod = acb.newGeneratedFun("void", Modifier.PRIVATE); currentConstMethod.pushThis(); currentConstMethod.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, genConstantMethod.getName(), "void", 0); //if it is a generate function, close the metod. if(currentConstMethod != cb){ currentConstMethod.methodReturn(); currentConstMethod.complete(); } currentConstMethod = genConstantMethod; } setArrayMethod = currentConstMethod; } else { if (nonConstantMethod == null) nonConstantMethod = acb.newGeneratedFun("void", Modifier.PROTECTED); setArrayMethod = nonConstantMethod; } setArrayMethod.getField(arrayField); // first arg ((ValueNode) rightOperandList.elementAt(index)).generateExpression(acb, setArrayMethod); setArrayMethod.upCast(receiverType); // second arg setArrayMethod.setArrayElement(index); } //if a generated function was created to reduce the size of the methods close the functions. if(currentConstMethod != cb){ currentConstMethod.methodReturn(); currentConstMethod.complete(); } if (nonConstantMethod != null) { nonConstantMethod.methodReturn(); nonConstantMethod.complete(); mb.pushThis(); mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, nonConstantMethod.getName(), "void", 0); } /* ** Call the method for this operator. */ /* ** Generate (field = <left expression>). This assignment is ** used as the receiver of the method call for this operator, ** and the field is used as the left operand: ** ** (field = <left expression>).method(field, <right expression>...) */ //LocalField receiverField = // acb.newFieldDeclaration(Modifier.PRIVATE, receiverType); leftOperand.generateExpression(acb, mb); mb.dup(); //mb.putField(receiverField); // instance for method call /*mb.getField(receiverField);*/ mb.upCast(leftInterfaceType); // first arg mb.getField(arrayField); // second arg mb.push(isOrdered); // third arg mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, 3); } /** * Generate start/stop key for this IN list operator. Bug 3858. * * @param isAsc is the index ascending on the column in question * @param isStartKey are we generating start key or not * @param acb The ExpressionClassBuilder for the class we're generating * @param mb The MethodBuilder the expression will go into * * @return nothing * * @exception StandardException Thrown on error */ public void generateStartStopKey(boolean isAsc, boolean isStartKey, ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException { /* left side of the "in" operator is our "judge" when we try to get * the min/max value of the operands on the right side. Judge's type * is important for us, and is input parameter to min/maxValue. */ int leftTypeFormatId = leftOperand.getTypeId().getTypeFormatId(); int leftJDBCTypeId = leftOperand.getTypeId().isUserDefinedTypeId() ? leftOperand.getTypeId().getJDBCTypeId() : -1; int listSize = rightOperandList.size(); int numLoops, numValInLastLoop, currentOpnd = 0; /* We first calculate how many times (loops) we generate a call to * min/maxValue function accumulatively, since each time it at most * takes 4 input values. An example of the calls generated will be: * minVal(minVal(...minVal(minVal(v1,v2,v3,v4,judge), v5,v6,v7,judge), * ...), vn-1, vn, NULL, judge) * Unused value parameters in the last call are filled with NULLs. */ if (listSize < 5) { numLoops = 1; numValInLastLoop = (listSize - 1) % 4 + 1; } else { numLoops = (listSize - 5) / 3 + 2; numValInLastLoop = (listSize - 5) % 3 + 1; } for (int i = 0; i < numLoops; i++) { /* generate value parameters of min/maxValue */ int numVals = (i == numLoops - 1) ? numValInLastLoop : ((i == 0) ? 4 : 3); for (int j = 0; j < numVals; j++) { ValueNode vn = (ValueNode) rightOperandList.elementAt(currentOpnd++); vn.generateExpression(acb, mb); mb.upCast(ClassName.DataValueDescriptor); } /* since we have fixed number of input values (4), unused ones * in the last loop are filled with NULLs */ int numNulls = (i < numLoops - 1) ? 0 : ((i == 0) ? 4 - numValInLastLoop : 3 - numValInLastLoop); for (int j = 0; j < numNulls; j++) mb.pushNull(ClassName.DataValueDescriptor); /* have to put judge's types in the end */ mb.push(leftTypeFormatId); mb.push(leftJDBCTypeId); /* decide to get min or max value */ String methodName; if ((isAsc && isStartKey) || (! isAsc && ! isStartKey)) methodName = "minValue"; else methodName = "maxValue"; mb.callMethod(VMOpcode.INVOKESTATIC, ClassName.BaseExpressionActivation, methodName, ClassName.DataValueDescriptor, 6); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -