001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.DefaultNode
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.context.ContextManager;
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.sql.compile.CompilerContext;
031: import org.apache.derby.iapi.sql.compile.Parser;
032: import org.apache.derby.iapi.sql.compile.C_NodeTypes;
033:
034: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
035:
036: import org.apache.derby.iapi.types.TypeId;
037:
038: import org.apache.derby.iapi.sql.dictionary.ColumnDescriptor;
039: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
040: import org.apache.derby.iapi.sql.dictionary.DefaultDescriptor;
041: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
042:
043: import org.apache.derby.iapi.error.StandardException;
044:
045: import org.apache.derby.impl.sql.compile.ExpressionClassBuilder;
046:
047: import org.apache.derby.catalog.types.DefaultInfoImpl;
048:
049: import java.util.Vector;
050:
051: /**
052: * DefaultNode represents a column/parameter default.
053: */
054: public class DefaultNode extends ValueNode {
055: private String columnName;
056: private String defaultText;
057: private ValueNode defaultTree;
058:
059: /**
060: * Initializer for a column/parameter default.
061: *
062: * @param defaultTree Query tree for default
063: * @param defaultText The text of the default.
064: */
065: public void init(Object defaultTree, Object defaultText) {
066: this .defaultTree = (ValueNode) defaultTree;
067: this .defaultText = (String) defaultText;
068: }
069:
070: /**
071: * Initializer for insert/update
072: *
073: */
074: public void init(Object columnName) {
075: this .columnName = (String) columnName;
076: }
077:
078: /**
079: * Get the text of the default.
080: */
081: public String getDefaultText() {
082: return defaultText;
083: }
084:
085: /**
086: * Get the query tree for the default.
087: *
088: * @return The query tree for the default.
089: */
090: ValueNode getDefaultTree() {
091: return defaultTree;
092: }
093:
094: /**
095: * Convert this object to a String. See comments in QueryTreeNode.java
096: * for how this should be done for tree printing.
097: *
098: * @return This object as a String
099: */
100:
101: public String toString() {
102: if (SanityManager.DEBUG) {
103: return "defaultTree: " + defaultTree + "\n"
104: + "defaultText: " + defaultText + "\n"
105: + super .toString();
106: } else {
107: return "";
108: }
109: }
110:
111: /**
112: * Bind this expression. This means binding the sub-expressions,
113: * as well as figuring out what the return type is for this expression.
114: * In this case, there are no sub-expressions, and the return type
115: * is already known, so this is just a stub.
116: *
117: * @param fromList The FROM list for the query this
118: * expression is in, for binding columns.
119: * @param subqueryList The subquery list being built as we find SubqueryNodes
120: * @param aggregateVector The aggregate vector being built as we find AggregateNodes
121: *
122: * @return The new top of the expression tree.
123: *
124: * @exception StandardException Thrown on failure
125: */
126: public ValueNode bindExpression(FromList fromList,
127: SubqueryList subqueryList, Vector aggregateVector)
128: throws StandardException {
129: ColumnDescriptor cd;
130: TableDescriptor td;
131:
132: if (SanityManager.DEBUG) {
133: SanityManager.ASSERT(fromList.size() != 0,
134: "fromList expected to be non-empty");
135: if (!(fromList.elementAt(0) instanceof FromBaseTable)) {
136: SanityManager
137: .THROWASSERT("fromList.elementAt(0) expected to be instanceof FromBaseTable, not "
138: + fromList.elementAt(0).getClass()
139: .getName());
140: }
141:
142: }
143: // Get the TableDescriptor for the target table
144: td = ((FromBaseTable) fromList.elementAt(0))
145: .getTableDescriptor();
146:
147: // Get the ColumnDescriptor for the column
148: cd = td.getColumnDescriptor(columnName);
149: if (SanityManager.DEBUG) {
150: SanityManager.ASSERT(cd != null,
151: "cd expected to be non-null");
152: }
153:
154: /* If we have the default text, then parse and bind it and
155: * return the tree.
156: */
157: DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd
158: .getDefaultInfo();
159: if (defaultInfo != null) {
160: String defaultText = defaultInfo.getDefaultText();
161: ValueNode defaultTree = parseDefault(defaultText,
162: getLanguageConnectionContext(),
163: getCompilerContext());
164:
165: /* Query is dependent on the DefaultDescriptor */
166: DefaultDescriptor defaultDescriptor = cd
167: .getDefaultDescriptor(getDataDictionary());
168: getCompilerContext().createDependency(defaultDescriptor);
169:
170: return defaultTree.bindExpression(fromList, subqueryList,
171: aggregateVector);
172: } else {
173: // Default is null
174: ValueNode nullNode = (ValueNode) getNodeFactory().getNode(
175: C_NodeTypes.UNTYPED_NULL_CONSTANT_NODE,
176: getContextManager());
177: return nullNode;
178: }
179: }
180:
181: /**
182: * Parse a default and turn it into a query tree.
183: *
184: * @param defaultText Text of Default.
185: * @param lcc LanguageConnectionContext
186: * @param cc CompilerContext
187: *
188: * @return The parsed default as a query tree.
189: *
190: * @exception StandardException Thrown on failure
191: */
192: public static ValueNode parseDefault(String defaultText,
193: LanguageConnectionContext lcc, CompilerContext cc)
194: throws StandardException {
195: Parser p;
196: ValueNode defaultTree;
197:
198: /* Get a Statement to pass to the parser */
199:
200: /* We're all set up to parse. We have to build a compilable SQL statement
201: * before we can parse - So, we goober up a VALUES defaultText.
202: */
203: String values = "VALUES " + defaultText;
204:
205: /*
206: ** Get a new compiler context, so the parsing of the select statement
207: ** doesn't mess up anything in the current context (it could clobber
208: ** the ParameterValueSet, for example).
209: */
210: CompilerContext newCC = lcc.pushCompilerContext();
211:
212: p = newCC.getParser();
213:
214: /* Finally, we can call the parser */
215: // Since this is always nested inside another SQL statement, so topLevel flag
216: // should be false
217: QueryTreeNode qt = p.parseStatement(values);
218: if (SanityManager.DEBUG) {
219: if (!(qt instanceof CursorNode)) {
220: SanityManager
221: .THROWASSERT("qt expected to be instanceof CursorNode, not "
222: + qt.getClass().getName());
223: }
224: CursorNode cn = (CursorNode) qt;
225: if (!(cn.getResultSetNode() instanceof RowResultSetNode)) {
226: SanityManager
227: .THROWASSERT("cn.getResultSetNode() expected to be instanceof RowResultSetNode, not "
228: + cn.getResultSetNode().getClass()
229: .getName());
230: }
231: }
232:
233: defaultTree = ((ResultColumn) ((CursorNode) qt)
234: .getResultSetNode().getResultColumns().elementAt(0))
235: .getExpression();
236:
237: lcc.popCompilerContext(newCC);
238:
239: return defaultTree;
240: }
241:
242: /**
243: * @exception StandardException Thrown on failure
244: */
245: public void generateExpression(ExpressionClassBuilder acb,
246: MethodBuilder mb) throws StandardException {
247: if (SanityManager.DEBUG) {
248: SanityManager
249: .THROWASSERT("generateExpression not expected to be called");
250: }
251: }
252:
253: /**
254: * @inheritDoc
255: */
256: protected boolean isEquivalent(ValueNode other) {
257: return false;
258: }
259: }
|