001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.CurrentRowLocationNode
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.sql.dictionary.DataDictionary;
025: import org.apache.derby.iapi.types.TypeId;
026: import org.apache.derby.iapi.types.DataValueDescriptor;
027: import org.apache.derby.iapi.types.DataTypeDescriptor;
028: import org.apache.derby.iapi.types.RefDataValue;
029: import org.apache.derby.iapi.types.RowLocation;
030: import org.apache.derby.iapi.sql.execute.CursorResultSet;
031:
032: import org.apache.derby.iapi.services.compiler.ClassBuilder;
033: import org.apache.derby.iapi.services.compiler.MethodBuilder;
034: import org.apache.derby.iapi.services.compiler.LocalField;
035:
036: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
037:
038: import java.lang.reflect.Modifier;
039: import org.apache.derby.iapi.reference.ClassName;
040:
041: import org.apache.derby.iapi.services.classfile.VMOpcode;
042:
043: import org.apache.derby.iapi.error.StandardException;
044:
045: import org.apache.derby.catalog.TypeDescriptor;
046:
047: import java.util.Vector;
048:
049: /**
050: * The CurrentRowLocation operator is used by DELETE and UPDATE to get the
051: * RowLocation of the current row for the target table. The bind() operations
052: * for DELETE and UPDATE add a column to the target list of the SelectNode
053: * that represents the ResultSet to be deleted or updated.
054: */
055:
056: public class CurrentRowLocationNode extends ValueNode {
057: /**
058: * Binding this expression means setting the result DataTypeServices.
059: * In this case, the result type is always the same.
060: *
061: * @param fromList The FROM list for the statement. This parameter
062: * is not used in this case.
063: * @param subqueryList The subquery list being built as we find SubqueryNodes
064: * @param aggregateVector The aggregate vector being built as we find AggregateNodes
065: *
066: * @return The new top of the expression tree.
067: *
068: * @exception StandardException Thrown on error
069: */
070:
071: public ValueNode bindExpression(FromList fromList,
072: SubqueryList subqueryList, Vector aggregateVector)
073: throws StandardException {
074: setType(new DataTypeDescriptor(TypeId
075: .getBuiltInTypeId(TypeId.REF_NAME), false /* Not nullable */
076: ));
077: return this ;
078: }
079:
080: /**
081: * CurrentRowLocationNode is used in updates and deletes. See generate() in
082: * UpdateNode and DeleteNode to get the full overview of generate(). This
083: * class is responsible for generating the method that will return the RowLocation
084: * for the next row to be updated or deleted.
085: *
086: * This routine will generate a method of the form:
087: *
088: * private SQLRef fieldx;
089: *
090: * ...
091: *
092: * public DataValueDescriptor exprx()
093: * throws StandardException
094: * {
095: * return fieldx = <SQLRefConstructor>(
096: * "result set member".getRowLocation(),
097: * fieldx);
098: * }
099: * and return the generated code:
100: * exprx()
101: *
102: * ("result set member" is a member of the generated class added by UpdateNode or
103: * DeleteNode.)
104: * This exprx function is used within another exprx function,
105: * and so doesn't need a static field or to be public; but
106: * at present, it has both.
107: *
108: * fieldx is a generated field that is initialized to null when the
109: * activation is constructed. getSQLRef will re-use fieldx on calls
110: * after the first call, rather than allocate a new SQLRef for each call.
111: *
112: * @param acb The ExpressionClassBuilder for the class being built
113: *
114: *
115: * @exception StandardException Thrown on error
116: */
117: public void generateExpression(ExpressionClassBuilder acb,
118: MethodBuilder mbex) throws StandardException {
119: /* Generate a new method */
120: /* only used within the other exprFuns, so can be private */
121: MethodBuilder mb = acb.newGeneratedFun(
122: ClassName.DataValueDescriptor, Modifier.PROTECTED);
123:
124: /* Allocate an object for re-use to hold the result of the operator */
125: LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE,
126: ClassName.RefDataValue);
127:
128: /* Fill in the body of the method
129: * generates:
130: * return TypeFactory.getSQLRef(this.ROWLOCATIONSCANRESULTSET.getRowLocation());
131: * and adds it to exprFun
132: */
133:
134: mb.pushThis();
135: mb.getField((String) null, acb
136: .getRowLocationScanResultSetName(),
137: ClassName.CursorResultSet);
138: mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
139: "getRowLocation", ClassName.RowLocation, 0);
140:
141: acb.generateDataValue(mb, getTypeCompiler(), field);
142:
143: /*
144: ** Store the result of the method call in the field, so we can re-use
145: ** the object.
146: */
147: mb.putField(field);
148:
149: /* Stuff the full expression into a return statement and add that to the
150: * body of the new method.
151: */
152: mb.methodReturn();
153:
154: // complete the method
155: mb.complete();
156:
157: /* Generate the call to the new method */
158: mbex.pushThis();
159: mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb
160: .getName(), ClassName.DataValueDescriptor, 0);
161: }
162:
163: protected boolean isEquivalent(ValueNode o) {
164: return false;
165: }
166: }
|