--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.HasVariantValueNodeVisitor\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.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.compile.Visitable; \r
+import org.apache.derby.iapi.sql.compile.Visitor;\r
+\r
+\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+/**\r
+ * Find out if we have a value node with variant type less than what the\r
+ * caller desires, anywhere below us. Stop traversal as soon as we find one.\r
+ * This is used in two places: one to check the values clause of an insert\r
+ * statement; i.e \r
+ * <pre>\r
+ * insert into <table> values (?, 1, foobar());\r
+ * </pre>\r
+ * If all the expressions in the values clause are QUERY_INVARIANT (and an\r
+ * exception is made for parameters) then we can cache the results in the\r
+ * RowResultNode. This is useful when we have a prepared insert statement which\r
+ * is repeatedly executed.\r
+ * <p>\r
+ * The second place where this is used is to check if a subquery can be\r
+ * materialized or not. \r
+ * @see org.apache.derby.iapi.store.access.Qualifier \r
+ *\r
+ */\r
+public class HasVariantValueNodeVisitor implements Visitor\r
+{\r
+ private boolean hasVariant;\r
+ private int variantType;\r
+ private boolean ignoreParameters;\r
+\r
+\r
+ /**\r
+ * Construct a visitor\r
+ */\r
+ public HasVariantValueNodeVisitor()\r
+ {\r
+ this.variantType = Qualifier.VARIANT;\r
+ this.ignoreParameters = false;\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(Qualifier.VARIANT < Qualifier.SCAN_INVARIANT, "qualifier constants not ordered as expected");\r
+ SanityManager.ASSERT(Qualifier.SCAN_INVARIANT < Qualifier.QUERY_INVARIANT, "qualifier constants not ordered as expected");\r
+ } \r
+ }\r
+\r
+ \r
+ /**\r
+ * Construct a visitor. Pass in the variant\r
+ * type. We look for nodes that are less\r
+ * than or equal to this variant type. E.g.,\r
+ * if the variantType is Qualifier.SCAN_VARIANT,\r
+ * then any node that is either VARIANT or\r
+ * SCAN_VARIANT will cause the visitor to \r
+ * consider it variant.\r
+ *\r
+ * @param variantType the type of variance we consider\r
+ * variant\r
+ * @param ignoreParameters should I ignore parameter nodes?\r
+ */\r
+ public HasVariantValueNodeVisitor(int variantType, boolean ignoreParameters)\r
+ {\r
+ this.variantType = variantType;\r
+ this.ignoreParameters = ignoreParameters;\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(variantType >= Qualifier.VARIANT, "bad variantType");\r
+ // note: there is no point in (variantType == Qualifier.CONSTANT) so throw an\r
+ // exception for that case too\r
+ SanityManager.ASSERT(variantType <= Qualifier.QUERY_INVARIANT, "bad variantType");\r
+ } \r
+ }\r
+ \r
+ ////////////////////////////////////////////////\r
+ //\r
+ // VISITOR INTERFACE\r
+ //\r
+ ////////////////////////////////////////////////\r
+\r
+ /**\r
+ * If we have found the target node, we are done.\r
+ *\r
+ * @param node the node to process\r
+ *\r
+ * @return me\r
+ *\r
+ * @exception StandardException on error\r
+ */\r
+ public Visitable visit(Visitable node) throws StandardException\r
+ {\r
+ if (node instanceof ValueNode)\r
+ {\r
+ if (ignoreParameters && ((ValueNode)node).requiresTypeFromContext())\r
+ return node;\r
+ \r
+ if (((ValueNode)node).getOrderableVariantType() <= variantType)\r
+ {\r
+ hasVariant = true;\r
+ }\r
+ }\r
+ return node;\r
+ }\r
+\r
+ public boolean skipChildren(Visitable node)\r
+ {\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Stop traversal if we found the target node\r
+ *\r
+ * @return true/false\r
+ */\r
+ public boolean stopTraversal()\r
+ {\r
+ return hasVariant;\r
+ }\r
+\r
+ ////////////////////////////////////////////////\r
+ //\r
+ // CLASS INTERFACE\r
+ //\r
+ ////////////////////////////////////////////////\r
+ /**\r
+ * Indicate whether we found the node in\r
+ * question\r
+ *\r
+ * @return true/false\r
+ */\r
+ public boolean hasVariant()\r
+ {\r
+ return hasVariant;\r
+ }\r
+}\r