| /* |
| |
| Derby - Class org.apache.derby.impl.sql.compile.DefaultNode |
| |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to you under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| |
| */ |
| |
| package org.apache.derby.impl.sql.compile; |
| |
| import java.util.List; |
| import org.apache.derby.catalog.types.DefaultInfoImpl; |
| import org.apache.derby.iapi.error.StandardException; |
| import org.apache.derby.iapi.services.compiler.MethodBuilder; |
| import org.apache.derby.iapi.services.context.ContextManager; |
| import org.apache.derby.shared.common.sanity.SanityManager; |
| import org.apache.derby.iapi.sql.compile.CompilerContext; |
| import org.apache.derby.iapi.sql.compile.Parser; |
| import org.apache.derby.iapi.sql.compile.Visitable; |
| import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; |
| import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor; |
| import org.apache.derby.iapi.sql.dictionary.DefaultDescriptor; |
| import org.apache.derby.iapi.sql.dictionary.TableDescriptor; |
| |
| /** |
| * DefaultNode represents a column/parameter default. |
| */ |
| public class DefaultNode extends ValueNode |
| { |
| private String columnName; |
| private String defaultText; |
| private ValueNode defaultTree; |
| |
| /** |
| * Constructor for a generated by default as identity column. |
| * |
| * @param cm The context manager |
| */ |
| DefaultNode(ContextManager cm) { |
| super(cm); |
| } |
| |
| /** |
| * Constructor for a column/parameter default. |
| * |
| * @param defaultTree Query tree for default |
| * @param defaultText The text of the default. |
| * @param cm The context manager |
| */ |
| DefaultNode(ValueNode defaultTree, |
| String defaultText, |
| ContextManager cm) { |
| super(cm); |
| this.defaultTree = defaultTree; |
| this.defaultText = defaultText; |
| } |
| |
| /** |
| * Constructor for insert/update |
| * @param columnName The column name for which a default is to be applied |
| */ |
| DefaultNode(String columnName, ContextManager cm) { |
| super(cm); |
| this.columnName = columnName; |
| } |
| |
| /** |
| * Get the text of the default. |
| */ |
| public String getDefaultText() |
| { |
| return defaultText; |
| } |
| |
| /** |
| * Get the query tree for the default. |
| * |
| * @return The query tree for the default. |
| */ |
| ValueNode getDefaultTree() |
| { |
| return defaultTree; |
| } |
| |
| /** |
| * Convert this object to a String. See comments in QueryTreeNode.java |
| * for how this should be done for tree printing. |
| * |
| * @return This object as a String |
| */ |
| @Override |
| public String toString() |
| { |
| if (SanityManager.DEBUG) |
| { |
| return "columnName: " + columnName + "\n" + |
| "defaultText: " + defaultText + "\n" + |
| super.toString(); |
| } |
| else |
| { |
| return ""; |
| } |
| } |
| |
| /** |
| * Prints the sub-nodes of this object. See QueryTreeNode.java for |
| * how tree printing is supposed to work. |
| * |
| * @param depth The depth of this node in the tree |
| */ |
| @Override |
| void printSubNodes(int depth) |
| { |
| if (SanityManager.DEBUG) |
| { |
| super.printSubNodes(depth); |
| |
| if (defaultTree != null) { |
| printLabel(depth, "defaultTree:"); |
| defaultTree.treePrint(depth + 1); |
| } |
| } |
| } |
| |
| |
| /** |
| * Bind this expression. This means binding the sub-expressions, |
| * as well as figuring out what the return type is for this expression. |
| * In this case, there are no sub-expressions, and the return type |
| * is already known, so this is just a stub. |
| * |
| * @param fromList The FROM list for the query this |
| * expression is in, for binding columns. |
| * @param subqueryList The subquery list being built as we find SubqueryNodes |
| * @param aggregates The aggregate list being built as we find AggregateNodes |
| * |
| * @return The new top of the expression tree. |
| * |
| * @exception StandardException Thrown on failure |
| */ |
| @Override |
| ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) |
| throws StandardException |
| { |
| ColumnDescriptor cd; |
| TableDescriptor td; |
| |
| if (SanityManager.DEBUG) |
| { |
| SanityManager.ASSERT(fromList.size() != 0, |
| "fromList expected to be non-empty"); |
| if (! (fromList.elementAt(0) instanceof FromBaseTable)) |
| { |
| SanityManager.THROWASSERT( |
| "fromList.elementAt(0) expected to be instanceof FromBaseTable, not " + |
| fromList.elementAt(0).getClass().getName()); |
| } |
| |
| } |
| // Get the TableDescriptor for the target table |
| td = ((FromBaseTable) fromList.elementAt(0)).getTableDescriptor(); |
| |
| // Get the ColumnDescriptor for the column |
| cd = td.getColumnDescriptor(columnName); |
| if (SanityManager.DEBUG) |
| { |
| SanityManager.ASSERT(cd != null, |
| "cd expected to be non-null"); |
| } |
| |
| /* If we have the default text, then parse and bind it and |
| * return the tree. |
| */ |
| DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd.getDefaultInfo(); |
| if (defaultInfo != null) |
| { |
| String defaultTxt = defaultInfo.getDefaultText(); |
| ValueNode defaultTre = parseDefault( |
| defaultTxt, |
| getLanguageConnectionContext(), |
| getCompilerContext()); |
| |
| /* Query is dependent on the DefaultDescriptor */ |
| DefaultDescriptor defaultDescriptor = cd.getDefaultDescriptor( |
| getDataDictionary()); |
| getCompilerContext().createDependency(defaultDescriptor); |
| |
| return defaultTre.bindExpression( |
| fromList, |
| subqueryList, |
| aggregates); |
| } |
| else |
| { |
| // Default is null |
| return new UntypedNullConstantNode(getContextManager()); |
| } |
| } |
| |
| /** |
| * Parse a default and turn it into a query tree. |
| * |
| * @param defaultText Text of Default. |
| * @param lcc LanguageConnectionContext |
| * @param cc CompilerContext |
| * |
| * @return The parsed default as a query tree. |
| * |
| * @exception StandardException Thrown on failure |
| */ |
| public static ValueNode parseDefault |
| ( |
| String defaultText, |
| LanguageConnectionContext lcc, |
| CompilerContext cc |
| ) |
| throws StandardException |
| { |
| Parser p; |
| ValueNode defaultTree; |
| |
| /* Get a Statement to pass to the parser */ |
| |
| /* We're all set up to parse. We have to build a compilable SQL statement |
| * before we can parse - So, we goober up a VALUES defaultText. |
| */ |
| String values = "VALUES " + defaultText; |
| |
| /* |
| ** Get a new compiler context, so the parsing of the select statement |
| ** doesn't mess up anything in the current context (it could clobber |
| ** the ParameterValueSet, for example). |
| */ |
| CompilerContext newCC = lcc.pushCompilerContext(); |
| |
| p = newCC.getParser(); |
| |
| |
| /* Finally, we can call the parser */ |
| // Since this is always nested inside another SQL statement, so topLevel flag |
| // should be false |
| Visitable qt = p.parseStatement(values); |
| if (SanityManager.DEBUG) |
| { |
| if (! (qt instanceof CursorNode)) |
| { |
| SanityManager.THROWASSERT( |
| "qt expected to be instanceof CursorNode, not " + |
| qt.getClass().getName()); |
| } |
| CursorNode cn = (CursorNode) qt; |
| if (! (cn.getResultSetNode() instanceof RowResultSetNode)) |
| { |
| SanityManager.THROWASSERT( |
| "cn.getResultSetNode() expected to be instanceof RowResultSetNode, not " + |
| cn.getResultSetNode().getClass().getName()); |
| } |
| } |
| |
| defaultTree = ((CursorNode) qt).getResultSetNode().getResultColumns(). |
| elementAt(0).getExpression(); |
| |
| lcc.popCompilerContext(newCC); |
| |
| return defaultTree; |
| } |
| |
| /** |
| * @exception StandardException Thrown on failure |
| */ |
| @Override |
| void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) |
| throws StandardException |
| { |
| if (SanityManager.DEBUG) |
| { |
| SanityManager.THROWASSERT( |
| "generateExpression not expected to be called"); |
| } |
| } |
| |
| /** |
| * @inheritDoc |
| */ |
| boolean isEquivalent(ValueNode other) |
| { |
| return false; |
| } |
| } |