1 | /* ============================================================= |
2 | * SmallSQL : a free Java DBMS library for the Java(tm) platform |
3 | * ============================================================= |
4 | * |
5 | * (C) Copyright 2004-2006, by Volker Berlin. |
6 | * |
7 | * Project Info: http://www.smallsql.de/ |
8 | * |
9 | * This library is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU Lesser General Public License as published by |
11 | * the Free Software Foundation; either version 2.1 of the License, or |
12 | * (at your option) any later version. |
13 | * |
14 | * This library is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
17 | * License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with this library; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
22 | * USA. |
23 | * |
24 | * [Java is a trademark or registered trademark of Sun Microsystems, Inc. |
25 | * in the United States and other countries.] |
26 | * |
27 | * --------------- |
28 | * MemoryResult.java |
29 | * --------------- |
30 | * Author: Volker Berlin |
31 | * |
32 | */ |
33 | package smallsql.database; |
34 | |
35 | import java.sql.*; |
36 | import java.util.ArrayList; |
37 | import java.util.List; |
38 | |
39 | |
40 | /** |
41 | * @author Volker Berlin |
42 | * |
43 | */ |
44 | class MemoryResult extends DataSource { |
45 | |
46 | ExpressionValue[] currentRow; |
47 | private final Columns columns = new Columns(); |
48 | private int rowIdx = -1; |
49 | private List rowList = new ArrayList(); // List of ExpressionGroup[] |
50 | |
51 | /** |
52 | * Only for extends classes. |
53 | */ |
54 | MemoryResult(){} |
55 | |
56 | |
57 | /** |
58 | * Constructor for DatabaseMetaData. ResultSets that not based on a store. |
59 | */ |
60 | MemoryResult(Object[][] data, int colCount) throws SQLException{ |
61 | for(int c=0; c<colCount; c++){ |
62 | Column column = new Column(); |
63 | column.setDataType(SQLTokenizer.NULL); |
64 | columns.add( column ); |
65 | } |
66 | for(int r=0; r<data.length; r++){ |
67 | Object[] row = data[r]; |
68 | ExpressionValue[] rowValues = new ExpressionValue[row.length]; |
69 | addRow(rowValues); |
70 | for(int c=0; c<colCount; c++){ |
71 | ExpressionValue expr = rowValues[c] = new ExpressionValue(); |
72 | expr.set( row[c], -1); |
73 | Column column = columns.get(c); |
74 | if(expr.getDataType() != SQLTokenizer.NULL){ |
75 | column.setDataType(expr.getDataType()); |
76 | } |
77 | if(expr.getPrecision() > column.getPrecision()){ |
78 | column.setPrecision(expr.getPrecision()); |
79 | } |
80 | } |
81 | } |
82 | } |
83 | |
84 | final void addRow(ExpressionValue[] row){ |
85 | rowList.add(row); |
86 | } |
87 | |
88 | |
89 | /** |
90 | * Return a Column to descript the meta data |
91 | * @param colIdx the index of the column starting with 0. |
92 | */ |
93 | final Column getColumn(int colIdx){ |
94 | return columns.get(colIdx); |
95 | } |
96 | |
97 | |
98 | /** |
99 | * Add a column to the list of Columns. This should call only form COnstructor. |
100 | * @param column |
101 | */ |
102 | final void addColumn(Column column){ |
103 | columns.add(column); |
104 | } |
105 | |
106 | /*============================================================================== |
107 | |
108 | Methods for Interface RowSource |
109 | |
110 | ==============================================================================*/ |
111 | |
112 | |
113 | final boolean isScrollable(){ |
114 | return true; |
115 | } |
116 | |
117 | |
118 | final void beforeFirst(){ |
119 | rowIdx = -1; |
120 | currentRow = null; |
121 | } |
122 | |
123 | final boolean isBeforeFirst(){ |
124 | return rowIdx < 0; |
125 | } |
126 | |
127 | final boolean isFirst(){ |
128 | return rowIdx == 0 && currentRow != null; |
129 | } |
130 | |
131 | final boolean first(){ |
132 | rowIdx = 0; |
133 | return move(); |
134 | } |
135 | |
136 | final boolean previous(){ |
137 | if(rowIdx-- < 0) rowIdx = -1; |
138 | return move(); |
139 | } |
140 | |
141 | final boolean next(){ |
142 | rowIdx++; |
143 | return move(); |
144 | } |
145 | |
146 | final boolean last(){ |
147 | rowIdx = rowList.size() - 1; |
148 | return move(); |
149 | } |
150 | |
151 | |
152 | final boolean isLast(){ |
153 | return rowIdx == rowList.size() - 1 && currentRow != null; |
154 | } |
155 | |
156 | final boolean isAfterLast(){ |
157 | return rowIdx >= rowList.size(); |
158 | } |
159 | |
160 | final void afterLast(){ |
161 | rowIdx = rowList.size(); |
162 | currentRow = null; |
163 | } |
164 | |
165 | |
166 | final boolean absolute(int row) throws SQLException{ |
167 | if(row == 0) throw Utils.createSQLException("Row 0 is invalid for method absolute()."); |
168 | rowIdx = (row > 0) ? |
169 | Math.min( row, rowList.size() ) : |
170 | Math.min( row +rowList.size(), -1 ); |
171 | return move(); |
172 | } |
173 | |
174 | |
175 | final boolean relative(int rows){ |
176 | if(rows == 0) return (currentRow != null); |
177 | rowIdx = Math.min( Math.max( rowIdx + rows, -1), rowList.size()); |
178 | return move(); |
179 | } |
180 | |
181 | |
182 | final int getRow(){ |
183 | return currentRow == null ? 0 : rowIdx+1; |
184 | } |
185 | |
186 | |
187 | final long getRowPosition(){ |
188 | return rowIdx; |
189 | } |
190 | |
191 | |
192 | final void setRowPosition(long rowPosition) throws Exception{ |
193 | rowIdx = (int)rowPosition; |
194 | move(); |
195 | } |
196 | |
197 | |
198 | final boolean rowInserted(){ |
199 | return false; |
200 | } |
201 | |
202 | |
203 | final boolean rowDeleted(){ |
204 | return false; |
205 | } |
206 | |
207 | |
208 | void nullRow(){ |
209 | throw new Error(); |
210 | } |
211 | |
212 | |
213 | void noRow(){ |
214 | currentRow = null; |
215 | } |
216 | |
217 | |
218 | final private boolean move(){ |
219 | if(rowIdx < rowList.size() && rowIdx >= 0){ |
220 | currentRow = (ExpressionValue[])rowList.get(rowIdx); |
221 | return true; |
222 | } |
223 | currentRow = null; |
224 | return false; |
225 | } |
226 | |
227 | /*======================================================================= |
228 | |
229 | Methods for Data Access |
230 | |
231 | =======================================================================*/ |
232 | |
233 | boolean isNull( int colIdx ) throws Exception{ |
234 | return get( colIdx ).isNull(); |
235 | } |
236 | |
237 | |
238 | boolean getBoolean( int colIdx ) throws Exception{ |
239 | return get( colIdx ).getBoolean(); |
240 | } |
241 | |
242 | int getInt( int colIdx ) throws Exception{ |
243 | return get( colIdx ).getInt(); |
244 | } |
245 | |
246 | long getLong( int colIdx ) throws Exception{ |
247 | return get( colIdx ).getLong(); |
248 | } |
249 | |
250 | float getFloat( int colIdx ) throws Exception{ |
251 | return get( colIdx ).getFloat(); |
252 | } |
253 | |
254 | double getDouble( int colIdx ) throws Exception{ |
255 | return get( colIdx ).getDouble(); |
256 | } |
257 | |
258 | long getMoney( int colIdx ) throws Exception{ |
259 | return get( colIdx ).getMoney(); |
260 | } |
261 | |
262 | MutableNumeric getNumeric( int colIdx ) throws Exception{ |
263 | return get( colIdx ).getNumeric(); |
264 | } |
265 | |
266 | Object getObject( int colIdx ) throws Exception{ |
267 | return get( colIdx ).getObject(); |
268 | } |
269 | |
270 | String getString( int colIdx ) throws Exception{ |
271 | return get( colIdx ).getString(); |
272 | } |
273 | |
274 | |
275 | byte[] getBytes( int colIdx ) throws Exception{ |
276 | return get( colIdx ).getBytes(); |
277 | } |
278 | |
279 | |
280 | int getDataType( int colIdx ){ |
281 | return columns.get( colIdx ).getDataType(); |
282 | //return get( colIdx ).getDataType(); // problems if no currentRow |
283 | } |
284 | |
285 | |
286 | final TableView getTableView(){ |
287 | return null; |
288 | } |
289 | |
290 | |
291 | final void deleteRow() throws Exception{ |
292 | throw Utils.createSQLException("ResultSet is read only."); |
293 | } |
294 | |
295 | |
296 | final void updateRow(Expression[] updateValues) throws Exception{ |
297 | throw Utils.createSQLException("ResultSet is read only."); |
298 | } |
299 | |
300 | |
301 | final void insertRow(Expression[] updateValues) throws Exception{ |
302 | throw Utils.createSQLException("ResultSet is read only."); |
303 | } |
304 | |
305 | |
306 | |
307 | |
308 | /*==================================================== |
309 | Helper functions |
310 | ===================================================*/ |
311 | |
312 | /** |
313 | * Returns the current Expression for the columnIdx. |
314 | * The columnIdx starts at 0. |
315 | * There is no index check. |
316 | */ |
317 | private Expression get(int colIdx) throws Exception{ |
318 | if(currentRow == null) throw Utils.createSQLException("No current row."); |
319 | return currentRow[ colIdx ]; |
320 | } |
321 | |
322 | |
323 | /** |
324 | * Return size of the ResultSet. |
325 | */ |
326 | int getRowCount(){ |
327 | return rowList.size(); |
328 | } |
329 | |
330 | |
331 | void execute() throws Exception{ |
332 | rowList.clear(); |
333 | } |
334 | } |