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