1 | /* |
2 | |
3 | Derby - Class org.apache.derby.impl.sql.GenericResultDescription |
4 | |
5 | Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.impl.sql; |
22 | |
23 | import org.apache.derby.iapi.sql.ResultColumnDescriptor; |
24 | import org.apache.derby.iapi.sql.ResultDescription; |
25 | |
26 | import org.apache.derby.iapi.services.sanity.SanityManager; |
27 | |
28 | import org.apache.derby.iapi.services.io.StoredFormatIds; |
29 | import org.apache.derby.iapi.services.io.FormatIdUtil; |
30 | import org.apache.derby.iapi.services.io.Formatable; |
31 | |
32 | import java.io.ObjectOutput; |
33 | import java.io.ObjectInput; |
34 | import java.io.IOException; |
35 | /** |
36 | * GenericResultDescription: basic implementation of result |
37 | * description, used in conjunction with the other |
38 | * implementations in this package. This implementation |
39 | * of ResultDescription may be used by anyone. |
40 | * |
41 | * @author ames |
42 | */ |
43 | public final class GenericResultDescription |
44 | implements ResultDescription, Formatable |
45 | { |
46 | |
47 | /******************************************************** |
48 | ** |
49 | ** This class implements Formatable. That means that it |
50 | ** can write itself to and from a formatted stream. If |
51 | ** you add more fields to this class, make sure that you |
52 | ** also write/read them with the writeExternal()/readExternal() |
53 | ** methods. |
54 | ** |
55 | ** If, inbetween releases, you add more fields to this class, |
56 | ** then you should bump the version number emitted by the getTypeFormatId() |
57 | ** method. |
58 | ** |
59 | ********************************************************/ |
60 | |
61 | private ResultColumnDescriptor[] columns; |
62 | private String statementType; |
63 | |
64 | /** |
65 | * Niladic constructor for Formatable |
66 | */ |
67 | public GenericResultDescription() |
68 | { |
69 | } |
70 | |
71 | /** |
72 | * Build a GenericResultDescription from columns and type |
73 | * |
74 | * @param columns an array of col descriptors |
75 | * @param statementType the type |
76 | */ |
77 | public GenericResultDescription(ResultColumnDescriptor[] columns, |
78 | String statementType) |
79 | { |
80 | this.columns = columns; |
81 | this.statementType = statementType; |
82 | } |
83 | |
84 | /** |
85 | * Build a GenericResultDescription |
86 | * |
87 | * @param rd the result description |
88 | * @param theCols the columns to take from the input rd |
89 | */ |
90 | public GenericResultDescription |
91 | ( |
92 | ResultDescription rd, |
93 | int[] theCols |
94 | ) |
95 | { |
96 | if (SanityManager.DEBUG) |
97 | { |
98 | SanityManager.ASSERT(theCols != null, "theCols argument to GenericResultDescription is null"); |
99 | } |
100 | |
101 | this.columns = new ResultColumnDescriptor[theCols.length]; |
102 | for (int i = 0; i < theCols.length; i++) |
103 | { |
104 | columns[i] = rd.getColumnDescriptor(theCols[i]); |
105 | } |
106 | this.statementType = rd.getStatementType(); |
107 | } |
108 | |
109 | // |
110 | // ResultDescription interface |
111 | // |
112 | /** |
113 | * @see ResultDescription#getStatementType |
114 | */ |
115 | public String getStatementType() { |
116 | return statementType; |
117 | } |
118 | |
119 | /** |
120 | * @see ResultDescription#getColumnCount |
121 | */ |
122 | public int getColumnCount() |
123 | { |
124 | return (columns == null) ? 0 : columns.length; |
125 | } |
126 | |
127 | public ResultColumnDescriptor[] getColumnInfo() { |
128 | return columns; |
129 | } |
130 | |
131 | /** |
132 | * position is 1-based. |
133 | * @see ResultDescription#getColumnDescriptor |
134 | */ |
135 | public ResultColumnDescriptor getColumnDescriptor(int position) { |
136 | return columns[position-1]; |
137 | } |
138 | |
139 | /** |
140 | * Get a new result description that has been truncated |
141 | * from input column number. If the input column is |
142 | * 5, then columns 5 to getColumnCount() are removed. |
143 | * The new ResultDescription points to the same |
144 | * ColumnDescriptors (this method performs a shallow |
145 | * copy. |
146 | * |
147 | * @param truncateFrom the starting column to remove |
148 | * |
149 | * @return a new ResultDescription |
150 | */ |
151 | public ResultDescription truncateColumns(int truncateFrom) |
152 | { |
153 | if (SanityManager.DEBUG) |
154 | { |
155 | if (!(truncateFrom > 0 && columns != null)) |
156 | { |
157 | SanityManager.THROWASSERT("bad truncate value: "+truncateFrom+" is too low"); |
158 | } |
159 | if (truncateFrom > columns.length) |
160 | { |
161 | SanityManager.THROWASSERT("bad truncate value: "+truncateFrom+" is too high"); |
162 | } |
163 | } |
164 | ResultColumnDescriptor[] newColumns = new ResultColumnDescriptor[truncateFrom-1]; |
165 | System.arraycopy(columns, 0, newColumns, 0, newColumns.length); |
166 | return new GenericResultDescription(newColumns, statementType); |
167 | } |
168 | |
169 | |
170 | ////////////////////////////////////////////// |
171 | // |
172 | // FORMATABLE |
173 | // |
174 | ////////////////////////////////////////////// |
175 | /** |
176 | * Write this object out |
177 | * |
178 | * @param out write bytes here |
179 | * |
180 | * @exception IOException thrown on error |
181 | */ |
182 | public void writeExternal(ObjectOutput out) throws IOException |
183 | { |
184 | int len = (columns == null) ? 0 : columns.length; |
185 | |
186 | out.writeObject(statementType); |
187 | out.writeInt(len); |
188 | while(len-- > 0) |
189 | { |
190 | /* |
191 | ** If we don't have a GenericColumnsDescriptor, |
192 | ** create one now and use that to write out. |
193 | ** Do this to avoid writing out query tree |
194 | ** implementations of ResultColumnDescriptor |
195 | */ |
196 | if (!(columns[len] instanceof |
197 | GenericColumnDescriptor)) |
198 | { |
199 | columns[len] = new GenericColumnDescriptor(columns[len]); |
200 | } |
201 | out.writeObject(columns[len]); |
202 | } |
203 | } |
204 | |
205 | /** |
206 | * Read this object from a stream of stored objects. |
207 | * |
208 | * @param in read this. |
209 | * |
210 | * @exception IOException thrown on error |
211 | * @exception ClassNotFoundException thrown on error |
212 | */ |
213 | public void readExternal(ObjectInput in) |
214 | throws IOException, ClassNotFoundException |
215 | { |
216 | int len; |
217 | |
218 | columns = null; |
219 | statementType = (String)in.readObject(); |
220 | len = in.readInt(); |
221 | if (len > 0) |
222 | { |
223 | columns = new GenericColumnDescriptor[len]; |
224 | while(len-- > 0) |
225 | { |
226 | columns[len] = (ResultColumnDescriptor)in.readObject(); |
227 | } |
228 | } |
229 | } |
230 | |
231 | /** |
232 | * Get the formatID which corresponds to this class. |
233 | * |
234 | * @return the formatID of this class |
235 | */ |
236 | public int getTypeFormatId() { return StoredFormatIds.GENERIC_RESULT_DESCRIPTION_V01_ID; } |
237 | |
238 | |
239 | |
240 | public String toString() |
241 | { |
242 | if (SanityManager.DEBUG) |
243 | { |
244 | StringBuffer colStr = new StringBuffer(); |
245 | for (int i = 0; i < columns.length; i++) |
246 | { |
247 | colStr.append("column["+i+"]\n"); |
248 | colStr.append(columns[i].toString()); |
249 | } |
250 | return "GenericResultDescription\n" + |
251 | "\tStatementType = "+statementType+"\n" + |
252 | "\tCOLUMNS\n" + colStr.toString(); |
253 | } |
254 | else |
255 | { |
256 | return ""; |
257 | } |
258 | } |
259 | } |
260 | |