--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.SpecialFunctionNode\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.compile.CompilerContext;\r
+\r
+import org.apache.derby.iapi.types.DataTypeDescriptor;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+import org.apache.derby.iapi.services.compiler.LocalField;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+\r
+import java.lang.reflect.Modifier;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.reference.ClassName;\r
+import org.apache.derby.iapi.services.classfile.VMOpcode;\r
+import org.apache.derby.iapi.sql.compile.C_NodeTypes;\r
+\r
+import java.sql.Types;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ SpecialFunctionNode handles system SQL functions.\r
+ A function value is either obtained by a method\r
+ call off the LanguageConnectionContext or Activation.\r
+ LanguageConnectionContext functions are state related to the connection.\r
+ Activation functions are those related to the statement execution.\r
+\r
+ Each SQL function takes no arguments and returns a SQLvalue.\r
+ <P>\r
+ Functions supported:\r
+ <UL>\r
+ <LI> USER\r
+ <LI> CURRENT_USER\r
+ <LI> SESSION_USER\r
+ <LI> SYSTEM_USER\r
+ <LI> CURRENT SCHEMA\r
+ <LI> CURRENT ISOLATION\r
+ <LI> IDENTITY_VAL_LOCAL\r
+\r
+ </UL>\r
+\r
+\r
+ <P>\r
+\r
+ This node is used rather than some use of MethodCallNode for\r
+ runtime performance. MethodCallNode does not provide a fast access\r
+ to the current language connection or activatation, since it is geared\r
+ towards user defined routines.\r
+\r
+\r
+*/\r
+public class SpecialFunctionNode extends ValueNode \r
+{\r
+ /**\r
+ Name of SQL function\r
+ */\r
+ String sqlName;\r
+\r
+ /**\r
+ Java method name\r
+ */\r
+ private String methodName;\r
+\r
+ /**\r
+ Return type of Java method.\r
+ */\r
+ private String methodType;\r
+\r
+ /**\r
+ */\r
+ //private boolean isActivationCall;\r
+\r
+ /**\r
+ * Binding this special function means setting the result DataTypeServices.\r
+ * In this case, the result type is based on the operation requested.\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 \r
+ * SubqueryNodes. Not used in this case.\r
+ * @param aggregateVector The aggregate vector being built as we find \r
+ * AggregateNodes. Not used in this case.\r
+ *\r
+ * @return The new top of the expression tree.\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public ValueNode bindExpression(FromList fromList, SubqueryList subqueryList,\r
+ Vector aggregateVector)\r
+ throws StandardException\r
+ { DataTypeDescriptor dtd;\r
+ int nodeType = getNodeType();\r
+ switch (nodeType)\r
+ {\r
+ case C_NodeTypes.USER_NODE:\r
+ case C_NodeTypes.CURRENT_USER_NODE:\r
+ case C_NodeTypes.SESSION_USER_NODE:\r
+ case C_NodeTypes.SYSTEM_USER_NODE:\r
+ switch (nodeType)\r
+ {\r
+ case C_NodeTypes.USER_NODE: sqlName = "USER"; break;\r
+ case C_NodeTypes.CURRENT_USER_NODE: sqlName = "CURRENT_USER"; break;\r
+ case C_NodeTypes.SESSION_USER_NODE: sqlName = "SESSION_USER"; break;\r
+ case C_NodeTypes.SYSTEM_USER_NODE: sqlName = "SYSTEM_USER"; break;\r
+ }\r
+ methodName = "getAuthorizationId";\r
+ methodType = "java.lang.String";\r
+ dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, false, 128);\r
+ //SQL spec Section 6.4 Syntax Rule 4 says that the collation type \r
+ //of these functions will be the collation of character set \r
+ //SQL_IDENTIFIER. In Derby's case, that will mean, the collation of\r
+ //these functions will be UCS_BASIC. The collation derivation will \r
+ //be implicit. \r
+ dtd.setCollationDerivation(StringDataValue.COLLATION_DERIVATION_IMPLICIT);\r
+ dtd.setCollationType(StringDataValue.COLLATION_TYPE_UCS_BASIC);\r
+ break;\r
+\r
+ case C_NodeTypes.CURRENT_SCHEMA_NODE:\r
+ sqlName = "CURRENT SCHEMA";\r
+ methodName = "getCurrentSchemaName";\r
+ methodType = "java.lang.String";\r
+ dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.VARCHAR, false, 128);\r
+ //This is a Derby specific function but it's collation type will\r
+ //be based on the same rules as for SESSION_USER/CURRENT_USER etc. \r
+ //ie there collation type will be UCS_BASIC. The collation \r
+ //derivation will be implicit. \r
+ dtd.setCollationDerivation(StringDataValue.COLLATION_DERIVATION_IMPLICIT);\r
+ dtd.setCollationType(StringDataValue.COLLATION_TYPE_UCS_BASIC);\r
+ break;\r
+\r
+ case C_NodeTypes.IDENTITY_VAL_NODE:\r
+ sqlName = "IDENTITY_VAL_LOCAL";\r
+ methodName = "getIdentityValue";\r
+ methodType = "java.lang.Long";\r
+ dtd = DataTypeDescriptor.getSQLDataTypeDescriptor("java.math.BigDecimal", 31, 0, true, 31);\r
+ break;\r
+\r
+ case C_NodeTypes.CURRENT_ISOLATION_NODE:\r
+ sqlName = "CURRENT ISOLATION";\r
+ methodName = "getCurrentIsolationLevelStr";\r
+ methodType = "java.lang.String";\r
+ dtd = DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.CHAR, 2);\r
+ //This is a Derby specific function but it's collation type will\r
+ //be based on the same rules as for SESSION_USER/CURRENT_USER etc. \r
+ //ie there collation type will be UCS_BASIC. The collation \r
+ //derivation will be implicit. \r
+ dtd.setCollationDerivation(StringDataValue.COLLATION_DERIVATION_IMPLICIT);\r
+ dtd.setCollationType(StringDataValue.COLLATION_TYPE_UCS_BASIC);\r
+ break;\r
+ default:\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.THROWASSERT("Invalid type for SpecialFunctionNode " + nodeType);\r
+ }\r
+ dtd = null;\r
+ break;\r
+ }\r
+\r
+ checkReliability(sqlName, CompilerContext.USER_ILLEGAL );\r
+ setType(dtd);\r
+\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * Return the variant type for the underlying expression.\r
+ All supported special functions are QUERY_INVARIANT\r
+\r
+ *\r
+ * @return The variant type for the underlying expression.\r
+ */\r
+ protected int getOrderableVariantType()\r
+ {\r
+ return Qualifier.QUERY_INVARIANT;\r
+ }\r
+\r
+ /**\r
+ Generate an expression that returns a DataValueDescriptor and\r
+ calls a method off the language connection or the activation.\r
+ *\r
+ * @param acb The ExpressionClassBuilder for the class being built\r
+ * @param mb The method the code to place the code\r
+ *\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void generateExpression(ExpressionClassBuilder acb,\r
+ MethodBuilder mb)\r
+ throws StandardException\r
+ {\r
+ mb.pushThis();\r
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Activation, "getLanguageConnectionContext",\r
+ ClassName.LanguageConnectionContext, 0);\r
+\r
+ mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, methodType, 0);\r
+\r
+ String fieldType = getTypeCompiler().interfaceName();\r
+ LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, fieldType);\r
+\r
+ acb.generateDataValue(mb, getTypeCompiler(), \r
+ getTypeServices().getCollationType(), field);\r
+ }\r
+\r
+ /*\r
+ print the non-node subfields\r
+ */\r
+ public String toString() {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ return super.toString()+ sqlName;\r
+ }\r
+ else\r
+ {\r
+ return "";\r
+ }\r
+ }\r
+ \r
+ protected boolean isEquivalent(ValueNode o)\r
+ {\r
+ if (isSameNodeType(o))\r
+ {\r
+ SpecialFunctionNode other = (SpecialFunctionNode)o;\r
+ return methodName.equals(other.methodName);\r
+ }\r
+ return false;\r
+ }\r
+}\r