001: /*
002: * tsResultSet.java - Result Set object for tinySQL.
003: *
004: * Copyright 1996, Brian C. Jepson
005: * (bjepson@ids.net)
006: * $Author: davis $
007: * $Date: 2004/12/18 21:26:18 $
008: * $Revision: 1.1 $
009: *
010: * This library is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU Lesser General Public
012: * License as published by the Free Software Foundation; either
013: * version 2.1 of the License, or (at your option) any later version.
014: *
015: * This library is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
018: * Lesser General Public License for more details.
019: *
020: * You should have received a copy of the GNU Lesser General Public
021: * License along with this library; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
023: */
024:
025: package com.sqlmagic.tinysql;
026:
027: import java.util.*;
028: import java.lang.*;
029: import java.io.*;
030: import java.sql.*;
031:
032: /*
033: *
034: * tsResultSet - object to hold query results
035: *
036: * @author Thomas Morgner <mgs@sherito.org> Changed tsResultSet to support java.sql.Types,
037: * a custom fetchsize, and storing a state for unfinished queries.
038: * I also marked all members as private and use access-Functions to set or query
039: * this ResultSets properties.
040: */
041: public class tsResultSet {
042:
043: private Vector rows;// = new Vector(); // all the rows
044: private Vector rsColumns;// = new Vector(); // all the tsColumn objects
045: private Vector selectColumns;// = new Vector(); // all the selected columns
046: private Vector orderByColumns;// = new Vector(); // all ORDER BY columns
047: private Vector tables; // SQL-Query information
048: private tinySQLWhere whereC;
049:
050: private int fetchsize;
051: private int windowStart;
052: private int level;
053: private tinySQL dbengine;
054: private Hashtable sTables;
055: private String orderType;
056: private boolean distinct;
057: private int type;
058: private boolean eof;
059: private boolean groupedColumns = false;
060: public String newLine = System.getProperty("line.separator");
061:
062: /*
063: * The constructor with no arguments is provided for the Metadata
064: * ResulSets.
065: */
066: public tsResultSet() {
067: this ((tinySQLWhere) null, (tinySQL) null);
068: }
069:
070: public tsResultSet(tinySQLWhere w, tinySQL dbeng) {
071: dbengine = dbeng;
072: windowStart = 0;
073: whereC = w;
074: rows = new Vector();
075: rsColumns = new Vector();
076: selectColumns = new Vector();
077: orderByColumns = new Vector();
078: tables = new Vector();
079: }
080:
081: /*
082: * This method sets the initial state of the ResultSet, including adding
083: * any grouping or ordering information. If the ResultSet contains
084: * summary functions, then a single row is added to the ResultSet initially.
085: * If no rows are found that match any specified where clauses, this initial
086: * row will be returned.
087: */
088: public void setState(int pstate, Hashtable ptables,
089: String inputOrderType, boolean inputDistinct)
090: throws tinySQLException {
091: int i;
092: tsRow record = new tsRow();
093: tsColumn initializeColumn;
094: sTables = ptables;
095: orderType = inputOrderType;
096: distinct = inputDistinct;
097: level = pstate;
098: if (groupedColumns) {
099: /*
100: * Initialize the ResultSet with any not null summary functions
101: * such as COUNT = 0
102: */
103: for (i = 0; i < rsColumns.size(); i++) {
104: initializeColumn = (tsColumn) rsColumns.elementAt(i);
105: /*
106: * Evaluate all functions before adding the
107: * column to the output record.
108: */
109: initializeColumn.updateFunctions();
110: if (initializeColumn.isNotNull())
111: record.put(initializeColumn.name, initializeColumn
112: .getString());
113: }
114: addRow(record);
115: }
116: }
117:
118: public void setType(int type) {
119: if ((type == ResultSet.TYPE_FORWARD_ONLY)
120: || (type == ResultSet.TYPE_SCROLL_SENSITIVE)
121: || (type == ResultSet.TYPE_SCROLL_INSENSITIVE))
122:
123: this .type = type;
124: }
125:
126: public int getType() {
127: return type;
128: }
129:
130: public void setFetchSize(int i) {
131: fetchsize = i;
132: }
133:
134: public int getFetchSize() {
135: return fetchsize;
136: }
137:
138: public void addColumn(tsColumn col) {
139: int i;
140: boolean addTable;
141: tinySQLTable checkTable;
142: rsColumns.addElement(col);
143: if (col.getContext("SELECT"))
144: selectColumns.addElement(col);
145: if (col.getContext("ORDER"))
146: orderByColumns.addElement(col);
147: if (col.isGroupedColumn())
148: groupedColumns = true;
149: /*
150: * Add the table that this column belongs to if required
151: */
152: addTable = true;
153: if (col.columnTable != (tinySQLTable) null) {
154: for (i = 0; i < tables.size(); i++) {
155: checkTable = (tinySQLTable) tables.elementAt(i);
156: if (checkTable.table.equals(col.columnTable.table)) {
157: addTable = false;
158: break;
159: }
160: }
161: if (addTable) {
162: tables.addElement(col.columnTable);
163: }
164: }
165: }
166:
167: public boolean isGrouped() {
168: return groupedColumns;
169: }
170:
171: public boolean getMoreResults(int newPos, int fetchsize) {
172: this .fetchsize = fetchsize;
173: if (dbengine != null) {
174: try {
175: if (type != ResultSet.TYPE_SCROLL_INSENSITIVE) {
176: rows.removeAllElements();
177: windowStart = newPos;
178: }
179: dbengine.contSelectStatement(this );
180: if (level != 0) {
181: eof = false;
182: return eof;
183: }
184: } catch (tinySQLException e) {
185: }
186: }
187: eof = true;
188: return eof;
189: }
190:
191: /*
192: * The following method adds a row to the ResultSet. If sortRows is true then
193: * the row will be added to the appriate location in the ResultSet (which
194: * defaults to the sort order of the columns being fetched). If sort os false
195: * the row is just appended.
196: */
197: public boolean addRow(tsRow row) {
198: return addRow(row, true);
199: }
200:
201: public boolean addRow(tsRow row, boolean sortRows) {
202: int i;
203: boolean sortUp = true;
204: tsRow sortRow;
205: if (!sortRows) {
206: rows.addElement(row);
207: return true;
208: }
209: if (orderType != (String) null)
210: if (orderType.startsWith("DESC"))
211: sortUp = false;
212: /*
213: * Pass the list of ORDER BY columns to the new row to enable
214: * compareTo method.
215: */
216: row.setOrderBy(orderByColumns);
217: if (rows.size() > 0) {
218: /*
219: * Insert or append the row depending upon the ORDER BY
220: * conditions and a comparison of the new and the existing row.
221: */
222: if (sortUp) {
223: for (i = rows.size() - 1; i > -1; i--) {
224: sortRow = (tsRow) rows.elementAt(i);
225: if (row.compareTo(sortRow) < 0)
226: continue;
227: if (row.compareTo(sortRow) == 0 & distinct)
228: return true;
229: if (i == rows.size() - 1)
230: rows.addElement(row);
231: else
232: rows.insertElementAt(row, i + 1);
233: return true;
234: }
235: } else {
236: for (i = rows.size() - 1; i > -1; i--) {
237: sortRow = (tsRow) rows.elementAt(i);
238: if (row.compareTo(sortRow) > 0)
239: continue;
240: if (row.compareTo(sortRow) == 0 & distinct)
241: return true;
242: if (i == rows.size() - 1)
243: rows.addElement(row);
244: else
245: rows.insertElementAt(row, i + 1);
246: return true;
247: }
248: }
249: rows.insertElementAt(row, 0);
250: return true;
251: }
252: rows.addElement(row);
253: if ((fetchsize > 0) && (rows.size() >= fetchsize))
254: return false;
255: return true;
256: }
257:
258: /*
259: * The following methods update a particular row in the result set.
260: */
261: public void updateRow(tsRow inputRow) {
262: updateRow(inputRow, rows.size() - 1);
263: }
264:
265: public void updateRow(tsRow inputRow, int rowIndex) {
266: rows.setElementAt(inputRow, rowIndex);
267: }
268:
269: public Vector getTables() {
270: return tables;
271: }
272:
273: public int getLevel() {
274: return level;
275: }
276:
277: public void setLevel(int l) {
278: level = l;
279: }
280:
281: public Hashtable getTableState() {
282: return sTables;
283: }
284:
285: public tinySQLWhere getWhereClause() {
286: return whereC;
287: }
288:
289: /*
290: * Returns the number of SELECT columns in the result set
291: */
292: public int getColumnCount() {
293: return selectColumns.size();
294: }
295:
296: /*
297: * Returns the number of columns in the result set including ORDER BY,
298: * GROUP BY columns.
299: */
300: public int numcols() {
301: return rsColumns.size();
302: }
303:
304: /*
305: * Update all the columns in the ResultSet.
306: */
307: public void updateColumns(String inputColumnName,
308: String inputColumnValue) throws tinySQLException {
309: int i;
310: tsColumn tcol;
311: for (i = 0; i < rsColumns.size(); i++) {
312: tcol = (tsColumn) rsColumns.elementAt(i);
313: tcol.update(inputColumnName, inputColumnValue);
314: }
315: }
316:
317: /*
318: * Returns the number of rows in the result set.
319: */
320: public int size() {
321: return rows.size();
322: }
323:
324: /*
325: * Returns the tsRow at a given row offset (starts with zero).
326: *
327: * @param i the row offset/index
328: */
329: public tsRow rowAt(int row) {
330: int i;
331: if (row >= (windowStart + rows.size())) {
332: getMoreResults(row, fetchsize);
333: }
334: i = row - windowStart;
335: if (i < rows.size()) {
336: return (tsRow) rows.elementAt(i);
337: }
338: return null;
339: }
340:
341: /*
342: * Returns the tsColumn at a given column offset (starts with zero).
343: * The second argument is true if all columns (as opposed to just SELECT
344: * columns ) are to be returned.
345: */
346: public tsColumn columnAtIndex(int i) {
347: return columnAtIndex(i, false);
348: }
349:
350: public tsColumn columnAtIndex(int i, boolean allColumns) {
351: if (allColumns)
352: return (tsColumn) rsColumns.elementAt(i);
353: else
354: return (tsColumn) selectColumns.elementAt(i);
355:
356: }
357:
358: /*
359: * Debugging method to dump out the result set
360: */
361: public String toString() {
362: int i;
363: tsColumn tcol;
364: StringBuffer outputBuffer;
365: /*
366: * Display columns
367: */
368: outputBuffer = new StringBuffer(newLine
369: + "Columns in ResultSet" + newLine);
370: for (i = 0; i < rsColumns.size(); i++) {
371: tcol = (tsColumn) rsColumns.elementAt(i);
372: outputBuffer.append(tcol.toString());
373: }
374: outputBuffer.append(newLine + "Rows in tsResultSet" + newLine);
375: for (i = 0; i < size(); i++) {
376: tsRow row = rowAt(i);
377: outputBuffer.append(row.toString() + newLine);
378: }
379: return outputBuffer.toString();
380: }
381: }
|