001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.GenericResultDescription
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;
023:
024: import org.apache.derby.iapi.sql.ResultColumnDescriptor;
025: import org.apache.derby.iapi.sql.ResultDescription;
026:
027: import org.apache.derby.iapi.services.sanity.SanityManager;
028:
029: import org.apache.derby.iapi.services.io.StoredFormatIds;
030: import org.apache.derby.iapi.services.io.FormatIdUtil;
031: import org.apache.derby.iapi.services.io.Formatable;
032:
033: import java.io.ObjectOutput;
034: import java.io.ObjectInput;
035: import java.io.IOException;
036:
037: /**
038: * GenericResultDescription: basic implementation of result
039: * description, used in conjunction with the other
040: * implementations in this package. This implementation
041: * of ResultDescription may be used by anyone.
042: *
043: * @author ames
044: */
045: public final class GenericResultDescription implements
046: ResultDescription, Formatable {
047:
048: /********************************************************
049: **
050: ** This class implements Formatable. That means that it
051: ** can write itself to and from a formatted stream. If
052: ** you add more fields to this class, make sure that you
053: ** also write/read them with the writeExternal()/readExternal()
054: ** methods.
055: **
056: ** If, inbetween releases, you add more fields to this class,
057: ** then you should bump the version number emitted by the getTypeFormatId()
058: ** method.
059: **
060: ********************************************************/
061:
062: private ResultColumnDescriptor[] columns;
063: private String statementType;
064:
065: /**
066: * Niladic constructor for Formatable
067: */
068: public GenericResultDescription() {
069: }
070:
071: /**
072: * Build a GenericResultDescription from columns and type
073: *
074: * @param columns an array of col descriptors
075: * @param statementType the type
076: */
077: public GenericResultDescription(ResultColumnDescriptor[] columns,
078: String statementType) {
079: this .columns = columns;
080: this .statementType = statementType;
081: }
082:
083: /**
084: * Build a GenericResultDescription
085: *
086: * @param rd the result description
087: * @param theCols the columns to take from the input rd
088: */
089: public GenericResultDescription(ResultDescription rd, int[] theCols) {
090: if (SanityManager.DEBUG) {
091: SanityManager
092: .ASSERT(theCols != null,
093: "theCols argument to GenericResultDescription is null");
094: }
095:
096: this .columns = new ResultColumnDescriptor[theCols.length];
097: for (int i = 0; i < theCols.length; i++) {
098: columns[i] = rd.getColumnDescriptor(theCols[i]);
099: }
100: this .statementType = rd.getStatementType();
101: }
102:
103: //
104: // ResultDescription interface
105: //
106: /**
107: * @see ResultDescription#getStatementType
108: */
109: public String getStatementType() {
110: return statementType;
111: }
112:
113: /**
114: * @see ResultDescription#getColumnCount
115: */
116: public int getColumnCount() {
117: return (columns == null) ? 0 : columns.length;
118: }
119:
120: public ResultColumnDescriptor[] getColumnInfo() {
121: return columns;
122: }
123:
124: /**
125: * position is 1-based.
126: * @see ResultDescription#getColumnDescriptor
127: */
128: public ResultColumnDescriptor getColumnDescriptor(int position) {
129: return columns[position - 1];
130: }
131:
132: /**
133: * Get a new result description that has been truncated
134: * from input column number. If the input column is
135: * 5, then columns 5 to getColumnCount() are removed.
136: * The new ResultDescription points to the same
137: * ColumnDescriptors (this method performs a shallow
138: * copy.
139: *
140: * @param truncateFrom the starting column to remove
141: *
142: * @return a new ResultDescription
143: */
144: public ResultDescription truncateColumns(int truncateFrom) {
145: if (SanityManager.DEBUG) {
146: if (!(truncateFrom > 0 && columns != null)) {
147: SanityManager.THROWASSERT("bad truncate value: "
148: + truncateFrom + " is too low");
149: }
150: if (truncateFrom > columns.length) {
151: SanityManager.THROWASSERT("bad truncate value: "
152: + truncateFrom + " is too high");
153: }
154: }
155: ResultColumnDescriptor[] newColumns = new ResultColumnDescriptor[truncateFrom - 1];
156: System.arraycopy(columns, 0, newColumns, 0, newColumns.length);
157: return new GenericResultDescription(newColumns, statementType);
158: }
159:
160: //////////////////////////////////////////////
161: //
162: // FORMATABLE
163: //
164: //////////////////////////////////////////////
165: /**
166: * Write this object out
167: *
168: * @param out write bytes here
169: *
170: * @exception IOException thrown on error
171: */
172: public void writeExternal(ObjectOutput out) throws IOException {
173: int len = (columns == null) ? 0 : columns.length;
174:
175: out.writeObject(statementType);
176: out.writeInt(len);
177: while (len-- > 0) {
178: /*
179: ** If we don't have a GenericColumnsDescriptor,
180: ** create one now and use that to write out.
181: ** Do this to avoid writing out query tree
182: ** implementations of ResultColumnDescriptor
183: */
184: if (!(columns[len] instanceof GenericColumnDescriptor)) {
185: columns[len] = new GenericColumnDescriptor(columns[len]);
186: }
187: out.writeObject(columns[len]);
188: }
189: }
190:
191: /**
192: * Read this object from a stream of stored objects.
193: *
194: * @param in read this.
195: *
196: * @exception IOException thrown on error
197: * @exception ClassNotFoundException thrown on error
198: */
199: public void readExternal(ObjectInput in) throws IOException,
200: ClassNotFoundException {
201: int len;
202:
203: columns = null;
204: statementType = (String) in.readObject();
205: len = in.readInt();
206: if (len > 0) {
207: columns = new GenericColumnDescriptor[len];
208: while (len-- > 0) {
209: columns[len] = (ResultColumnDescriptor) in.readObject();
210: }
211: }
212: }
213:
214: /**
215: * Get the formatID which corresponds to this class.
216: *
217: * @return the formatID of this class
218: */
219: public int getTypeFormatId() {
220: return StoredFormatIds.GENERIC_RESULT_DESCRIPTION_V01_ID;
221: }
222:
223: public String toString() {
224: if (SanityManager.DEBUG) {
225: StringBuffer colStr = new StringBuffer();
226: for (int i = 0; i < columns.length; i++) {
227: colStr.append("column[" + i + "]\n");
228: colStr.append(columns[i].toString());
229: }
230: return "GenericResultDescription\n" + "\tStatementType = "
231: + statementType + "\n" + "\tCOLUMNS\n"
232: + colStr.toString();
233: } else {
234: return "";
235: }
236: }
237: }
|