001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.HasVariantValueNodeVisitor
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.sanity.SanityManager;
025: import org.apache.derby.iapi.sql.compile.Visitable;
026: import org.apache.derby.iapi.sql.compile.Visitor;
027:
028: import org.apache.derby.iapi.store.access.Qualifier;
029: import org.apache.derby.iapi.error.StandardException;
030:
031: /**
032: * Find out if we have a value node with variant type less than what the
033: * caller desires, anywhere below us. Stop traversal as soon as we find one.
034: * This is used in two places: one to check the values clause of an insert
035: * statement; i.e
036: * <pre>
037: * insert into <table> values (?, 1, foobar());
038: * </pre>
039: * If all the expressions in the values clause are QUERY_INVARIANT (and an
040: * exception is made for parameters) then we can cache the results in the
041: * RowResultNode. This is useful when we have a prepared insert statement which
042: * is repeatedly executed.
043: * <p>
044: * The second place where this is used is to check if a subquery can be
045: * materialized or not.
046: * @see org.apache.derby.iapi.store.access.Qualifier
047: *
048: * @author jamie
049: */
050: public class HasVariantValueNodeVisitor implements Visitor {
051: private boolean hasVariant;
052: private int variantType;
053: private boolean ignoreParameters;
054:
055: /**
056: * Construct a visitor
057: */
058: public HasVariantValueNodeVisitor() {
059: this .variantType = Qualifier.VARIANT;
060: this .ignoreParameters = false;
061: if (SanityManager.DEBUG) {
062: SanityManager.ASSERT(
063: Qualifier.VARIANT < Qualifier.SCAN_INVARIANT,
064: "qualifier constants not ordered as expected");
065: SanityManager
066: .ASSERT(
067: Qualifier.SCAN_INVARIANT < Qualifier.QUERY_INVARIANT,
068: "qualifier constants not ordered as expected");
069: }
070: }
071:
072: /**
073: * Construct a visitor. Pass in the variant
074: * type. We look for nodes that are less
075: * than or equal to this variant type. E.g.,
076: * if the variantType is Qualifier.SCAN_VARIANT,
077: * then any node that is either VARIANT or
078: * SCAN_VARIANT will cause the visitor to
079: * consider it variant.
080: *
081: * @param variantType the type of variance we consider
082: * variant
083: * @param ignoreParameters should I ignore parameter nodes?
084: */
085: public HasVariantValueNodeVisitor(int variantType,
086: boolean ignoreParameters) {
087: this .variantType = variantType;
088: this .ignoreParameters = ignoreParameters;
089:
090: if (SanityManager.DEBUG) {
091: SanityManager.ASSERT(variantType >= Qualifier.VARIANT,
092: "bad variantType");
093: // note: there is no point in (variantType == Qualifier.CONSTANT) so throw an
094: // exception for that case too
095: SanityManager.ASSERT(
096: variantType <= Qualifier.QUERY_INVARIANT,
097: "bad variantType");
098: }
099: }
100:
101: ////////////////////////////////////////////////
102: //
103: // VISITOR INTERFACE
104: //
105: ////////////////////////////////////////////////
106:
107: /**
108: * If we have found the target node, we are done.
109: *
110: * @param node the node to process
111: *
112: * @return me
113: *
114: * @exception StandardException on error
115: */
116: public Visitable visit(Visitable node) throws StandardException {
117: if (node instanceof ValueNode) {
118: if (ignoreParameters
119: && ((ValueNode) node).requiresTypeFromContext())
120: return node;
121:
122: if (((ValueNode) node).getOrderableVariantType() <= variantType) {
123: hasVariant = true;
124: }
125: }
126: return node;
127: }
128:
129: public boolean skipChildren(Visitable node) {
130: return false;
131: }
132:
133: /**
134: * Stop traversal if we found the target node
135: *
136: * @return true/false
137: */
138: public boolean stopTraversal() {
139: return hasVariant;
140: }
141:
142: ////////////////////////////////////////////////
143: //
144: // CLASS INTERFACE
145: //
146: ////////////////////////////////////////////////
147: /**
148: * Indicate whether we found the node in
149: * question
150: *
151: * @return true/false
152: */
153: public boolean hasVariant() {
154: return hasVariant;
155: }
156: }
|