--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.StaticClassFieldReferenceNode\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.services.monitor.Monitor;\r
+\r
+import org.apache.derby.iapi.services.compiler.MethodBuilder;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.loader.ClassInspector;\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+\r
+import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+\r
+import org.apache.derby.iapi.util.JBitSet;\r
+\r
+import java.lang.reflect.Member;\r
+import java.lang.reflect.Modifier;\r
+\r
+import java.util.Vector;\r
+\r
+/**\r
+ * A StaticClassFieldReferenceNode represents a Java static field reference from \r
+ * a Class (as opposed to an Object). Field references can be \r
+ * made in DML (as expressions).\r
+ *\r
+ */\r
+\r
+public final class StaticClassFieldReferenceNode extends JavaValueNode\r
+{\r
+ /*\r
+ ** Name of the field.\r
+ */\r
+ private String fieldName;\r
+\r
+ /* The class name */\r
+ private String javaClassName;\r
+ private boolean classNameDelimitedIdentifier;\r
+\r
+ /**\r
+ The field we are going to access.\r
+ */\r
+ private Member field;\r
+\r
+ /**\r
+ * Initializer for a StaticClassFieldReferenceNode\r
+ *\r
+ * @param javaClassName The class name\r
+ * @param fieldName The field name\r
+ */\r
+ public void init(Object javaClassName, Object fieldName, Object classNameDelimitedIdentifier)\r
+ {\r
+ this.fieldName = (String) fieldName;\r
+ this.javaClassName = (String) javaClassName;\r
+ this.classNameDelimitedIdentifier = ((Boolean) classNameDelimitedIdentifier).booleanValue();\r
+ }\r
+\r
+ /**\r
+ * Bind this expression. This means binding the sub-expressions,\r
+ * as well as figuring out what the return type is for this expression.\r
+ *\r
+ * @param fromList The FROM list for the query this\r
+ * expression is in, for binding columns.\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 Nothing\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public JavaValueNode bindExpression(FromList fromList, SubqueryList subqueryList,\r
+ Vector aggregateVector) \r
+ throws StandardException\r
+ {\r
+ ClassInspector classInspector = getClassFactory().getClassInspector();\r
+\r
+\r
+ if (((getCompilerContext().getReliability() & CompilerContext.INTERNAL_SQL_ILLEGAL) != 0)\r
+ || !javaClassName.startsWith("java.sql.")) {\r
+\r
+ throw StandardException.newException(SQLState.LANG_SYNTAX_ERROR, javaClassName + "::" + fieldName);\r
+ }\r
+\r
+ verifyClassExist(javaClassName);\r
+\r
+ /*\r
+ ** Find the field that is public.\r
+ */\r
+ field = classInspector.findPublicField(javaClassName,\r
+ fieldName,\r
+ true);\r
+ /* Get the field type */\r
+ setJavaTypeName( classInspector.getType(field) );\r
+\r
+ return this;\r
+\r
+ }\r
+\r
+ /**\r
+ * Preprocess an expression tree. We do a number of transformations\r
+ * here (including subqueries, IN lists, LIKE and BETWEEN) plus\r
+ * subquery flattening.\r
+ * NOTE: This is done before the outer ResultSetNode is preprocessed.\r
+ *\r
+ * @param numTables Number of tables in the DML Statement\r
+ * @param outerFromList FromList from outer query block\r
+ * @param outerSubqueryList SubqueryList from outer query block\r
+ * @param outerPredicateList PredicateList from outer query block\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void preprocess(int numTables,\r
+ FromList outerFromList,\r
+ SubqueryList outerSubqueryList,\r
+ PredicateList outerPredicateList) \r
+ throws StandardException\r
+ {\r
+ }\r
+\r
+ /**\r
+ * Categorize this predicate. Initially, this means\r
+ * building a bit map of the referenced tables for each predicate.\r
+ * If the source of this ColumnReference (at the next underlying level) \r
+ * is not a ColumnReference or a VirtualColumnNode then this predicate\r
+ * will not be pushed down.\r
+ *\r
+ * For example, in:\r
+ * select * from (select 1 from s) a (x) where x = 1\r
+ * we will not push down x = 1.\r
+ * NOTE: It would be easy to handle the case of a constant, but if the\r
+ * inner SELECT returns an arbitrary expression, then we would have to copy\r
+ * that tree into the pushed predicate, and that tree could contain\r
+ * subqueries and method calls.\r
+ * RESOLVE - revisit this issue once we have views.\r
+ *\r
+ * @param referencedTabs JBitSet with bit map of referenced FromTables\r
+ * @param simplePredsOnly Whether or not to consider method\r
+ * calls, field references and conditional nodes\r
+ * when building bit map\r
+ *\r
+ * @return boolean Whether or not source.expression is a ColumnReference\r
+ * or a VirtualColumnNode.\r
+ */\r
+ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly)\r
+ {\r
+ return true;\r
+ }\r
+\r
+ /**\r
+ * Remap all ColumnReferences in this tree to be clones of the\r
+ * underlying expression.\r
+ *\r
+ * @return JavaValueNode The remapped expression tree.\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public JavaValueNode remapColumnReferencesToExpressions()\r
+ throws StandardException\r
+ {\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * Return the variant type for the underlying expression.\r
+ * The variant type can be:\r
+ * VARIANT - variant within a scan\r
+ * (method calls and non-static field access)\r
+ * SCAN_INVARIANT - invariant within a scan\r
+ * (column references from outer tables)\r
+ * QUERY_INVARIANT - invariant within the life of a query\r
+ * CONSTANT - constant\r
+ *\r
+ * @return The variant type for the underlying expression.\r
+ */\r
+ protected int getOrderableVariantType()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(field != null,\r
+ "field is expected to be non-null");\r
+ }\r
+ /* Static field references are invariant for the life \r
+ * of the query, non-static are variant.\r
+ */\r
+ if (Modifier.isFinal(field.getModifiers()))\r
+ {\r
+ return Qualifier.CONSTANT;\r
+ }\r
+ else\r
+ {\r
+ return Qualifier.VARIANT;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @see QueryTreeNode#generate\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+ public void generateExpression(ExpressionClassBuilder acb,\r
+ MethodBuilder mb)\r
+ throws StandardException\r
+ {\r
+ /*\r
+ ** Generate the following:\r
+ **\r
+ ** <javaClassName>.<field name>\r
+ */\r
+\r
+ mb.getStaticField(field.getDeclaringClass().getName(),\r
+ fieldName,\r
+ getJavaTypeName());\r
+ }\r
+\r
+}\r