1a21e004e1a727d2ef337b83c0d9b3b8021e9894
[phpeclipse.git] / archive / net.sourceforge.phpeclipse.quantum.sql / src / com / quantum / sql / SQLStandardResultSetResults.java
1 package com.quantum.sql;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.Reader;
7 import java.io.UnsupportedEncodingException;
8 import java.sql.Connection;
9 import java.sql.ResultSet;
10 import java.sql.ResultSetMetaData;
11 import java.sql.SQLException;
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import com.quantum.model.Bookmark;
16 import com.quantum.model.Entity;
17
18
19 /**
20  * @author BC
21  */
22 public class SQLStandardResultSetResults extends SQLResultSetResults implements Scrollable {
23
24         /**
25          * Some columns -- especially BLOBS and CLOBS can be very wide.  This variable
26          * sets the maximum width of the column.
27          */
28     private static final int MAX_COLUMN_WIDTH = 1024 * 2;
29         
30         private boolean hasMore = false;
31         private int start = 1;
32         private int numberOfRowsPerPage;
33         private int totalNumberOfRows = -1;
34
35         private boolean fullMode = false;
36         
37         /**
38          * @param bookmark
39          * @param query
40          * @param encoding
41          * @param numberOfRowsPerPage
42          */
43         protected SQLStandardResultSetResults(
44                         Bookmark bookmark, String query, Entity entity,
45                         int numberOfRowsPerPage) {
46                 super(query, bookmark, entity);
47                 this.numberOfRowsPerPage = numberOfRowsPerPage;
48         }
49
50         static SQLResultSetResults create(
51                         ResultSet set, Bookmark bookmark, 
52                         String query, Entity entity, int numberOfRows) throws SQLException {
53
54                 SQLStandardResultSetResults results = new SQLStandardResultSetResults(
55                                 bookmark, query, entity, numberOfRows);
56                 
57                 results.parseResultSet(set);
58                 
59                 return results;
60         }
61         
62         /**
63          * @param set
64          * @param encoding
65          * @param numberOfRows
66          * @param results
67          * @param columnCount
68          * @throws SQLException
69          */
70         protected void parseResultSet(ResultSet set) throws SQLException {
71                 int rowCount = 1;
72                 
73                 ResultSetMetaData metaData = set.getMetaData();
74                 int columnCount = metaData.getColumnCount();
75                 List columns = new ArrayList();
76                 for (int i = 1; i <= columnCount; i++) {
77                         columns.add(new Column(
78                                         metaData.getColumnName(i), 
79                                         metaData.getColumnTypeName(i),
80                                         metaData.getColumnDisplaySize(i)));
81                 }
82                 setColumns((Column[]) columns.toArray(new Column[columns.size()]));
83                 
84                 boolean exitEarly = false;
85                 int firstRow = (this.fullMode) ? 0 : this.start;
86                 int lastRow = (this.fullMode) ? Integer.MAX_VALUE : this.start + this.numberOfRowsPerPage - 1;
87                 List rowList = new ArrayList();
88                 while (set.next()) {
89                         boolean disable = this.start < 1 || lastRow < 1;
90                         if (disable || ((rowCount >= firstRow) && (rowCount <= lastRow))) {
91                                 List row = new ArrayList();
92                                 for (int i = 1, length = columns.size(); i <= length; i++) {
93                                         String value = null;
94                                         if (getColumn(i).getSize() < MAX_COLUMN_WIDTH) {
95                                                 value = getEncodedString(set, getEncoding(), i);
96                                         } else {
97                                                 try {
98                                                         if ("".equals(getEncoding())) { //$NON-NLS-1$
99                                                                 value = getStringFromCharacterSteam(set, i);
100                                                         } else {
101                                                                 value = getEncodedStringFromBinaryStream(set, getEncoding(), i);
102                                                         }
103                                                 } catch (IOException e) {
104                                                         value = set.getString(i);
105                                                 } catch (RuntimeException e) {
106                                                         // hack for mysql which doesn't implement
107                                                         // character streams
108                                                         value = set.getString(i);
109                                                 }
110                                         }
111                                         if (value == null && !set.wasNull()) {
112                                                 value = set.getString(i);
113                                         }
114                                         row.add(value == null || set.wasNull() ? "<NULL>" : value); //$NON-NLS-1$
115                                 }
116                                 rowList.add(new Row(row));
117                         }
118                         rowCount++;
119                         if (!disable && (rowCount > lastRow)) {
120                                 exitEarly = true;
121                                 break;
122                         }
123                 }
124                 if (exitEarly) {
125                         this.hasMore = set.next();
126                 } else {
127                         this.totalNumberOfRows = Math.max(0, rowCount-1);
128                         this.hasMore = false;
129                 }
130                 setRows((Row[]) rowList.toArray(new Row[rowList.size()]));
131         }
132
133
134         /**
135          * @param set
136          * @param encoding
137          * @param columnNumber
138          * @throws SQLException
139          * @throws IOException
140          * @throws UnsupportedEncodingException
141          */
142         private String getEncodedStringFromBinaryStream(ResultSet set, String encoding, int columnNumber) 
143                         throws SQLException, IOException, UnsupportedEncodingException {
144                 InputStream binaryStream = set.getBinaryStream(columnNumber);
145                 if (binaryStream != null) {
146                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
147                         try {
148                                 for (int c = binaryStream.read(), count = 0; 
149                                         c >= 0 && count <= MAX_COLUMN_WIDTH; 
150                                         c = binaryStream.read(), count++) {
151                                         baos.write(c);
152                                 }
153                         } finally {
154                                 binaryStream.close();
155                         }
156                         return new String(baos.toByteArray(), encoding);
157                 } else {
158                         return null;
159                 }
160         }
161
162
163         /**
164          * @param set
165          * @param columnNumber
166          * @throws SQLException
167          * @throws IOException
168          */
169         private String getStringFromCharacterSteam(ResultSet set, int columnNumber) 
170                         throws SQLException, IOException {
171                 Reader reader = set.getCharacterStream(columnNumber);
172                 if (reader != null) {
173                         StringBuffer buffer = new StringBuffer();
174                         int retVal = reader.read();
175                         int count = 0;
176                         while (retVal >= 0) {
177                                 buffer.append((char) retVal);
178                                 retVal = reader.read();
179                                 count++;
180                                 if (count > MAX_COLUMN_WIDTH) {
181                                         buffer.append("...>>>"); //$NON-NLS-1$
182                                         break;
183                                 }
184                         }
185                         reader.close();
186                         return buffer.toString();
187                 } else {
188                         return null;
189                 }
190         }
191
192
193         /**
194          * @param set
195          * @param encoding
196          * @param index
197          * @return
198          * @throws SQLException
199          */
200         private String getEncodedString(ResultSet set, String encoding, int index) 
201                         throws SQLException {
202                 try {
203                         return encoding == null || encoding.trim().length() == 0 
204                                 ? set.getString(index) 
205                                 : new String(set.getBytes(index), encoding);
206                 } catch (UnsupportedEncodingException e) {
207                         return set.getString(index);
208                 }
209         }
210
211         public boolean hasMore() {
212                 return this.hasMore;
213         }
214         
215         public int getTotalNumberOfRows() {
216                 return this.totalNumberOfRows;
217         }
218         public void nextPage(Connection connection) throws SQLException {
219                 if (hasNextPage()) {
220                         this.start += this.numberOfRowsPerPage;
221                         refresh(connection);
222                 }
223         }
224
225         /* (non-Javadoc)
226          * @see com.quantum.sql.Scrollable#previousPage(java.sql.Connection)
227          */
228         public void previousPage(Connection connection) throws SQLException {
229                 if (hasPreviousPage()) {
230                         this.start = Math.max(1, this.start - this.numberOfRowsPerPage);
231                         refresh(connection);
232                 }
233         }
234
235         /* (non-Javadoc)
236          * @see com.quantum.sql.Scrollable#hasNextPage()
237          */
238         public boolean hasNextPage() {
239                 return this.hasMore;
240         }
241
242         /* (non-Javadoc)
243          * @see com.quantum.sql.Scrollable#hasPreviousPage()
244          */
245         public boolean hasPreviousPage() {
246                 return this.start > 1;
247         }
248
249         public void setFullMode(boolean fullMode) {
250                 this.fullMode = fullMode;
251         }
252         public boolean isFullMode() {
253                 return this.fullMode;
254         }
255
256         /* (non-Javadoc)
257          * @see com.quantum.sql.Scrollable#getStart()
258          */
259         public int getStart() {
260                 return getRowCount() == 0 ? 0 : (this.fullMode ? 1 : this.start);
261         }
262
263         /* (non-Javadoc)
264          * @see com.quantum.sql.Scrollable#getEnd()
265          */
266         public int getEnd() {
267                 return this.fullMode 
268                         ? getRowCount() 
269                         : this.start + getRowCount() - 1;
270         }
271
272         /* (non-Javadoc)
273          * @see com.quantum.sql.Scrollable#getLast()
274          */
275         public int getLast() {
276                 return this.totalNumberOfRows;
277         }
278         
279         
280         public void setFilterSort(FilterSort filterSort) {
281                 super.setFilterSort(filterSort);
282                 this.start = 1;
283         }
284 }