001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.StaticClassFieldReferenceNode
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.services.monitor.Monitor;
025:
026: import org.apache.derby.iapi.services.compiler.MethodBuilder;
027:
028: import org.apache.derby.iapi.services.sanity.SanityManager;
029:
030: import org.apache.derby.iapi.error.StandardException;
031:
032: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
033: import org.apache.derby.iapi.reference.SQLState;
034:
035: import org.apache.derby.iapi.services.loader.ClassInspector;
036:
037: import org.apache.derby.iapi.store.access.Qualifier;
038:
039: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
040: import org.apache.derby.iapi.sql.compile.CompilerContext;
041:
042: import org.apache.derby.iapi.util.JBitSet;
043:
044: import java.lang.reflect.Member;
045: import java.lang.reflect.Modifier;
046:
047: import java.util.Vector;
048:
049: /**
050: * A StaticClassFieldReferenceNode represents a Java static field reference from
051: * a Class (as opposed to an Object). Field references can be
052: * made in DML (as expressions).
053: *
054: * @author Jerry Brenner
055: */
056:
057: public final class StaticClassFieldReferenceNode extends JavaValueNode {
058: /*
059: ** Name of the field.
060: */
061: private String fieldName;
062:
063: /* The class name */
064: private String javaClassName;
065: private boolean classNameDelimitedIdentifier;
066:
067: /**
068: The field we are going to access.
069: */
070: private Member field;
071:
072: /**
073: * Initializer for a StaticClassFieldReferenceNode
074: *
075: * @param javaClassName The class name
076: * @param fieldName The field name
077: */
078: public void init(Object javaClassName, Object fieldName,
079: Object classNameDelimitedIdentifier) {
080: this .fieldName = (String) fieldName;
081: this .javaClassName = (String) javaClassName;
082: this .classNameDelimitedIdentifier = ((Boolean) classNameDelimitedIdentifier)
083: .booleanValue();
084: }
085:
086: /**
087: * Bind this expression. This means binding the sub-expressions,
088: * as well as figuring out what the return type is for this expression.
089: *
090: * @param fromList The FROM list for the query this
091: * expression is in, for binding columns.
092: * @param subqueryList The subquery list being built as we find SubqueryNodes
093: * @param aggregateVector The aggregate vector being built as we find AggregateNodes
094: *
095: * @return Nothing
096: *
097: * @exception StandardException Thrown on error
098: */
099:
100: public JavaValueNode bindExpression(FromList fromList,
101: SubqueryList subqueryList, Vector aggregateVector)
102: throws StandardException {
103: ClassInspector classInspector = getClassFactory()
104: .getClassInspector();
105:
106: if (((getCompilerContext().getReliability() & CompilerContext.INTERNAL_SQL_ILLEGAL) != 0)
107: || !javaClassName.startsWith("java.sql.")) {
108:
109: throw StandardException.newException(
110: SQLState.LANG_SYNTAX_ERROR, javaClassName + "::"
111: + fieldName);
112: }
113:
114: javaClassName = verifyClassExist(javaClassName,
115: !classNameDelimitedIdentifier);
116:
117: /*
118: ** Find the field that is public.
119: */
120: field = classInspector.findPublicField(javaClassName,
121: fieldName, true);
122: /* Get the field type */
123: setJavaTypeName(classInspector.getType(field));
124:
125: return this ;
126:
127: }
128:
129: /**
130: * Preprocess an expression tree. We do a number of transformations
131: * here (including subqueries, IN lists, LIKE and BETWEEN) plus
132: * subquery flattening.
133: * NOTE: This is done before the outer ResultSetNode is preprocessed.
134: *
135: * @param numTables Number of tables in the DML Statement
136: * @param outerFromList FromList from outer query block
137: * @param outerSubqueryList SubqueryList from outer query block
138: * @param outerPredicateList PredicateList from outer query block
139: *
140: * @exception StandardException Thrown on error
141: */
142: public void preprocess(int numTables, FromList outerFromList,
143: SubqueryList outerSubqueryList,
144: PredicateList outerPredicateList) throws StandardException {
145: }
146:
147: /**
148: * Categorize this predicate. Initially, this means
149: * building a bit map of the referenced tables for each predicate.
150: * If the source of this ColumnReference (at the next underlying level)
151: * is not a ColumnReference or a VirtualColumnNode then this predicate
152: * will not be pushed down.
153: *
154: * For example, in:
155: * select * from (select 1 from s) a (x) where x = 1
156: * we will not push down x = 1.
157: * NOTE: It would be easy to handle the case of a constant, but if the
158: * inner SELECT returns an arbitrary expression, then we would have to copy
159: * that tree into the pushed predicate, and that tree could contain
160: * subqueries and method calls.
161: * RESOLVE - revisit this issue once we have views.
162: *
163: * @param referencedTabs JBitSet with bit map of referenced FromTables
164: * @param simplePredsOnly Whether or not to consider method
165: * calls, field references and conditional nodes
166: * when building bit map
167: *
168: * @return boolean Whether or not source.expression is a ColumnReference
169: * or a VirtualColumnNode.
170: */
171: public boolean categorize(JBitSet referencedTabs,
172: boolean simplePredsOnly) {
173: return true;
174: }
175:
176: /**
177: * Remap all ColumnReferences in this tree to be clones of the
178: * underlying expression.
179: *
180: * @return JavaValueNode The remapped expression tree.
181: *
182: * @exception StandardException Thrown on error
183: */
184: public JavaValueNode remapColumnReferencesToExpressions()
185: throws StandardException {
186: return this ;
187: }
188:
189: /**
190: * Return the variant type for the underlying expression.
191: * The variant type can be:
192: * VARIANT - variant within a scan
193: * (method calls and non-static field access)
194: * SCAN_INVARIANT - invariant within a scan
195: * (column references from outer tables)
196: * QUERY_INVARIANT - invariant within the life of a query
197: * CONSTANT - constant
198: *
199: * @return The variant type for the underlying expression.
200: */
201: protected int getOrderableVariantType() {
202: if (SanityManager.DEBUG) {
203: SanityManager.ASSERT(field != null,
204: "field is expected to be non-null");
205: }
206: /* Static field references are invariant for the life
207: * of the query, non-static are variant.
208: */
209: if (Modifier.isFinal(field.getModifiers())) {
210: return Qualifier.CONSTANT;
211: } else {
212: return Qualifier.VARIANT;
213: }
214: }
215:
216: /**
217: * @see QueryTreeNode#generate
218: *
219: * @exception StandardException Thrown on error
220: */
221: public void generateExpression(ExpressionClassBuilder acb,
222: MethodBuilder mb) throws StandardException {
223: /*
224: ** Generate the following:
225: **
226: ** <javaClassName>.<field name>
227: */
228:
229: mb.getStaticField(field.getDeclaringClass().getName(),
230: fieldName, getJavaTypeName());
231: }
232:
233: }
|