--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.CurrentRowLocationNode\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.types.TypeId;\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.RefDataValue;\r
+import org.apache.derby.iapi.types.RowLocation;\r
+import org.apache.derby.iapi.sql.execute.CursorResultSet;\r
+\r
+import org.apache.derby.iapi.services.compiler.ClassBuilder;\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+import java.lang.reflect.Modifier;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.catalog.TypeDescriptor;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * The CurrentRowLocation operator is used by DELETE and UPDATE to get the\r
+ * RowLocation of the current row for the target table. The bind() operations\r
+ * for DELETE and UPDATE add a column to the target list of the SelectNode\r
+ * that represents the ResultSet to be deleted or updated.\r
+ */\r
+\r
+public class CurrentRowLocationNode extends ValueNode\r
+{\r
+ /**\r
+ * Binding this expression means setting the result DataTypeServices.\r
+ * In this case, the result type is always the same.\r
+ *\r
+ * @param fromList The FROM list for the statement. This parameter\r
+ * is not used in this case.\r
+ * @param subqueryList The subquery list being built as we find SubqueryNodes\r
+ * @param aggregateVector The aggregate vector being built as we find AggregateNodes\r
+ *\r
+ * @return The new top of the expression tree.\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,\r
+ Vector aggregateVector)\r
+ throws StandardException\r
+ {\r
+ setType(new DataTypeDescriptor(TypeId.getBuiltInTypeId(TypeId.REF_NAME),\r
+ false /* Not nullable */\r
+ )\r
+ );\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * CurrentRowLocationNode is used in updates and deletes. See generate() in\r
+ * UpdateNode and DeleteNode to get the full overview of generate(). This\r
+ * class is responsible for generating the method that will return the RowLocation\r
+ * for the next row to be updated or deleted.\r
+ *\r
+ * This routine will generate a method of the form:\r
+ *\r
+ * private SQLRef fieldx;\r
+ *\r
+ * ...\r
+ *\r
+ * public DataValueDescriptor exprx()\r
+ * throws StandardException\r
+ * {\r
+ * return fieldx = <SQLRefConstructor>(\r
+ * "result set member".getRowLocation(),\r
+ * fieldx);\r
+ * }\r
+ * and return the generated code:\r
+ * exprx()\r
+ *\r
+ * ("result set member" is a member of the generated class added by UpdateNode or\r
+ * DeleteNode.)\r
+ * This exprx function is used within another exprx function,\r
+ * and so doesn't need a static field or to be public; but\r
+ * at present, it has both. \r
+ *\r
+ * fieldx is a generated field that is initialized to null when the\r
+ * activation is constructed. getSQLRef will re-use fieldx on calls\r
+ * after the first call, rather than allocate a new SQLRef for each call.\r
+ *\r
+ * @param acb The ExpressionClassBuilder for the class being built\r
+ *\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void generateExpression(ExpressionClassBuilder acb,\r
+ MethodBuilder mbex)\r
+ throws StandardException\r
+ {\r
+ /* Generate a new method */\r
+ /* only used within the other exprFuns, so can be private */\r
+ MethodBuilder mb = acb.newGeneratedFun(ClassName.DataValueDescriptor, Modifier.PROTECTED);\r
+ \r
+ /* Allocate an object for re-use to hold the result of the operator */\r
+ LocalField field =\r
+ acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.RefDataValue);\r
+\r
+\r
+ /* Fill in the body of the method\r
+ * generates:\r
+ * return TypeFactory.getSQLRef(this.ROWLOCATIONSCANRESULTSET.getRowLocation());\r
+ * and adds it to exprFun\r
+ */\r
+\r
+ mb.pushThis();\r
+ mb.getField((String)null, acb.getRowLocationScanResultSetName(), ClassName.CursorResultSet);\r
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getRowLocation", ClassName.RowLocation, 0);\r
+\r
+\r
+ acb.generateDataValue(mb, getTypeCompiler(), \r
+ getTypeServices().getCollationType(), field);\r
+\r
+ /*\r
+ ** Store the result of the method call in the field, so we can re-use\r
+ ** the object.\r
+ */\r
+ mb.putField(field);\r
+\r
+ /* Stuff the full expression into a return statement and add that to the\r
+ * body of the new method.\r
+ */\r
+ mb.methodReturn();\r
+\r
+ // complete the method\r
+ mb.complete();\r
+\r
+ /* Generate the call to the new method */\r
+ mbex.pushThis();\r
+ mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), ClassName.DataValueDescriptor, 0);\r
+ }\r
+ \r
+ protected boolean isEquivalent(ValueNode o)\r
+ {\r
+ return false;\r
+ }\r
+}\r