001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.SpecialFunctionNode
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.compile.CompilerContext;
025:
026: import org.apache.derby.iapi.types.DataTypeDescriptor;
027:
028: import org.apache.derby.iapi.services.compiler.MethodBuilder;
029: import org.apache.derby.iapi.services.compiler.LocalField;
030:
031: import org.apache.derby.iapi.services.sanity.SanityManager;
032:
033: import org.apache.derby.iapi.store.access.Qualifier;
034:
035: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
036:
037: import java.lang.reflect.Modifier;
038:
039: import org.apache.derby.iapi.error.StandardException;
040: import org.apache.derby.iapi.reference.ClassName;
041: import org.apache.derby.iapi.services.classfile.VMOpcode;
042: import org.apache.derby.iapi.sql.compile.C_NodeTypes;
043:
044: import java.sql.Types;
045:
046: import java.util.Vector;
047:
048: /**
049: SpecialFunctionNode handles system SQL functions.
050: A function value is either obtained by a method
051: call off the LanguageConnectionContext or Activation.
052: LanguageConnectionContext functions are state related to the connection.
053: Activation functions are those related to the statement execution.
054:
055: Each SQL function takes no arguments and returns a SQLvalue.
056: <P>
057: Functions supported:
058: <UL>
059: <LI> USER
060: <LI> CURRENT_USER
061: <LI> SESSION_USER
062: <LI> SYSTEM_USER
063: <LI> CURRENT SCHEMA
064: <LI> CURRENT ISOLATION
065: <LI> IDENTITY_VAL_LOCAL
066:
067: </UL>
068:
069:
070: <P>
071:
072: This node is used rather than some use of MethodCallNode for
073: runtime performance. MethodCallNode does not provide a fast access
074: to the current language connection or activatation, since it is geared
075: towards user defined routines.
076:
077:
078: */
079: public class SpecialFunctionNode extends ValueNode {
080: /**
081: Name of SQL function
082: */
083: String sqlName;
084:
085: /**
086: Java method name
087: */
088: private String methodName;
089:
090: /**
091: Return type of Java method.
092: */
093: private String methodType;
094:
095: /**
096: */
097: //private boolean isActivationCall;
098: /**
099: * Binding this special function means setting the result DataTypeServices.
100: * In this case, the result type is based on the operation requested.
101: *
102: * @param fromList The FROM list for the statement. This parameter
103: * is not used in this case.
104: * @param subqueryList The subquery list being built as we find
105: * SubqueryNodes. Not used in this case.
106: * @param aggregateVector The aggregate vector being built as we find
107: * AggregateNodes. Not used in this case.
108: *
109: * @return The new top of the expression tree.
110: *
111: * @exception StandardException Thrown on error
112: */
113: public ValueNode bindExpression(FromList fromList,
114: SubqueryList subqueryList, Vector aggregateVector)
115: throws StandardException {
116: DataTypeDescriptor dtd;
117: int nodeType = getNodeType();
118: switch (nodeType) {
119: case C_NodeTypes.USER_NODE:
120: case C_NodeTypes.CURRENT_USER_NODE:
121: case C_NodeTypes.SESSION_USER_NODE:
122: case C_NodeTypes.SYSTEM_USER_NODE:
123: switch (nodeType) {
124: case C_NodeTypes.USER_NODE:
125: sqlName = "USER";
126: break;
127: case C_NodeTypes.CURRENT_USER_NODE:
128: sqlName = "CURRENT_USER";
129: break;
130: case C_NodeTypes.SESSION_USER_NODE:
131: sqlName = "SESSION_USER";
132: break;
133: case C_NodeTypes.SYSTEM_USER_NODE:
134: sqlName = "SYSTEM_USER";
135: break;
136: }
137: methodName = "getAuthorizationId";
138: methodType = "java.lang.String";
139: dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(
140: Types.VARCHAR, false, 128);
141: break;
142:
143: case C_NodeTypes.CURRENT_SCHEMA_NODE:
144: sqlName = "CURRENT SCHEMA";
145: methodName = "getCurrentSchemaName";
146: methodType = "java.lang.String";
147: dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(
148: Types.VARCHAR, false, 128);
149: break;
150:
151: case C_NodeTypes.IDENTITY_VAL_NODE:
152: sqlName = "IDENTITY_VAL_LOCAL";
153: methodName = "getIdentityValue";
154: methodType = "java.lang.Long";
155: dtd = DataTypeDescriptor.getSQLDataTypeDescriptor(
156: "java.math.BigDecimal", 31, 0, true, 31);
157: break;
158:
159: case C_NodeTypes.CURRENT_ISOLATION_NODE:
160: sqlName = "CURRENT ISOLATION";
161: methodName = "getCurrentIsolationLevelStr";
162: methodType = "java.lang.String";
163: dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(
164: Types.CHAR, 2);
165: break;
166: default:
167: if (SanityManager.DEBUG) {
168: SanityManager
169: .THROWASSERT("Invalid type for SpecialFunctionNode "
170: + nodeType);
171: }
172: dtd = null;
173: break;
174: }
175:
176: checkReliability(sqlName, CompilerContext.USER_ILLEGAL);
177: setType(dtd);
178:
179: return this ;
180: }
181:
182: /**
183: * Return the variant type for the underlying expression.
184: All supported special functions are QUERY_INVARIANT
185:
186: *
187: * @return The variant type for the underlying expression.
188: */
189: protected int getOrderableVariantType() {
190: return Qualifier.QUERY_INVARIANT;
191: }
192:
193: /**
194: Generate an expression that returns a DataValueDescriptor and
195: calls a method off the language connection or the activation.
196: *
197: * @param acb The ExpressionClassBuilder for the class being built
198: * @param mb The method the code to place the code
199: *
200: *
201: * @exception StandardException Thrown on error
202: */
203: public void generateExpression(ExpressionClassBuilder acb,
204: MethodBuilder mb) throws StandardException {
205: mb.pushThis();
206: mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Activation,
207: "getLanguageConnectionContext",
208: ClassName.LanguageConnectionContext, 0);
209:
210: mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null,
211: methodName, methodType, 0);
212:
213: String fieldType = getTypeCompiler().interfaceName();
214: LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE,
215: fieldType);
216:
217: acb.generateDataValue(mb, getTypeCompiler(), field);
218: }
219:
220: /*
221: print the non-node subfields
222: */
223: public String toString() {
224: if (SanityManager.DEBUG) {
225: return super .toString() + sqlName;
226: } else {
227: return "";
228: }
229: }
230:
231: protected boolean isEquivalent(ValueNode o) {
232: if (isSameNodeType(o)) {
233: SpecialFunctionNode other = (SpecialFunctionNode) o;
234: return methodName.equals(other.methodName);
235: }
236: return false;
237: }
238: }
|