KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > BlobFromLocator


1 /*
2  Copyright (C) 2002-2004 MySQL AB
3
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of version 2 of the GNU General Public License as
6  published by the Free Software Foundation.
7
8  There are special exceptions to the terms and conditions of the GPL
9  as it is applied to this software. View the full text of the
10  exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
11  software distribution.
12
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22
23
24  */

25 package com.mysql.jdbc;
26
27 import java.io.ByteArrayInputStream JavaDoc;
28 import java.io.OutputStream JavaDoc;
29
30 import java.sql.SQLException JavaDoc;
31
32 import java.util.ArrayList JavaDoc;
33 import java.util.List JavaDoc;
34
35 /**
36  * The representation (mapping) in the JavaTM programming language of an SQL
37  * BLOB value. An SQL BLOB is a built-in type that stores a Binary Large Object
38  * as a column value in a row of a database table. The driver implements Blob
39  * using an SQL locator(BLOB), which means that a Blob object contains a logical
40  * pointer to the SQL BLOB data rather than the data itself. A Blob object is
41  * valid for the duration of the transaction in which is was created. Methods in
42  * the interfaces ResultSet, CallableStatement, and PreparedStatement, such as
43  * getBlob and setBlob allow a programmer to access an SQL BLOB value. The Blob
44  * interface provides methods for getting the length of an SQL BLOB (Binary
45  * Large Object) value, for materializing a BLOB value on the client, and for
46  * determining the position of a pattern of bytes within a BLOB value. This
47  * class is new in the JDBC 2.0 API.
48  *
49  * @author Mark Matthews
50  *
51  * @version $Id: BlobFromLocator.java,v 1.1.2.1 2005/05/13 18:58:38 mmatthews
52  * Exp $
53  */

54 public class BlobFromLocator implements java.sql.Blob JavaDoc {
55     private String JavaDoc blobColumnName = null;
56
57     /** The ResultSet that created this BLOB */
58     private ResultSet creatorResultSet;
59
60     private int numColsInResultSet = 0;
61
62     private int numPrimaryKeys = 0;
63
64     private List JavaDoc primaryKeyColumns = null;
65
66     private List JavaDoc primaryKeyValues = null;
67
68     private String JavaDoc quotedId;
69
70     private String JavaDoc tableName = null;
71
72     /**
73      * Creates an updatable BLOB that can update in-place
74      */

75     BlobFromLocator(ResultSet creatorResultSetToSet, int blobColumnIndex)
76             throws SQLException JavaDoc {
77         this.creatorResultSet = creatorResultSetToSet;
78
79         this.numColsInResultSet = this.creatorResultSet.fields.length;
80         this.quotedId = this.creatorResultSet.connection.getMetaData()
81                 .getIdentifierQuoteString();
82
83         if (this.numColsInResultSet > 1) {
84             this.primaryKeyColumns = new ArrayList JavaDoc();
85             this.primaryKeyValues = new ArrayList JavaDoc();
86
87             for (int i = 0; i < this.numColsInResultSet; i++) {
88                 if (this.creatorResultSet.fields[i].isPrimaryKey()) {
89                     StringBuffer JavaDoc keyName = new StringBuffer JavaDoc();
90                     keyName.append(quotedId);
91
92                     String JavaDoc originalColumnName = this.creatorResultSet.fields[i]
93                             .getOriginalName();
94
95                     if (this.creatorResultSet.connection.getIO()
96                             .hasLongColumnInfo()
97                             && (originalColumnName != null)
98                             && (originalColumnName.length() > 0)) {
99                         keyName.append(originalColumnName);
100                     } else {
101                         keyName.append(this.creatorResultSet.fields[i]
102                                 .getName());
103                     }
104
105                     keyName.append(quotedId);
106
107                     this.primaryKeyColumns.add(keyName.toString());
108                     this.primaryKeyValues.add(this.creatorResultSet
109                             .getString(i + 1));
110                 }
111             }
112         } else {
113             notEnoughInformationInQuery();
114         }
115
116         this.numPrimaryKeys = this.primaryKeyColumns.size();
117
118         if (this.numPrimaryKeys == 0) {
119             notEnoughInformationInQuery();
120         }
121
122         if (this.creatorResultSet.fields[0].getOriginalTableName() != null) {
123             StringBuffer JavaDoc tableNameBuffer = new StringBuffer JavaDoc();
124
125             String JavaDoc databaseName = this.creatorResultSet.fields[0]
126                     .getDatabaseName();
127
128             if ((databaseName != null) && (databaseName.length() > 0)) {
129                 tableNameBuffer.append(quotedId);
130                 tableNameBuffer.append(databaseName);
131                 tableNameBuffer.append(quotedId);
132                 tableNameBuffer.append('.');
133             }
134
135             tableNameBuffer.append(quotedId);
136             tableNameBuffer.append(this.creatorResultSet.fields[0]
137                     .getOriginalTableName());
138             tableNameBuffer.append(quotedId);
139
140             this.tableName = tableNameBuffer.toString();
141         } else {
142             StringBuffer JavaDoc tableNameBuffer = new StringBuffer JavaDoc();
143
144             tableNameBuffer.append(quotedId);
145             tableNameBuffer.append(this.creatorResultSet.fields[0]
146                     .getTableName());
147             tableNameBuffer.append(quotedId);
148
149             this.tableName = tableNameBuffer.toString();
150         }
151
152         this.blobColumnName = this.creatorResultSet.getString(blobColumnIndex);
153     }
154
155     /**
156      * Retrieves the BLOB designated by this Blob instance as a stream.
157      *
158      * @return this BLOB represented as a binary stream of bytes.
159      *
160      * @throws SQLException
161      * if a database error occurs
162      */

163     public java.io.InputStream JavaDoc getBinaryStream() throws SQLException JavaDoc {
164         return new ByteArrayInputStream JavaDoc(getBytes(1L, (int) length()));
165     }
166
167     /**
168      * Returns as an array of bytes, part or all of the BLOB value that this
169      * Blob object designates.
170      *
171      * @param pos
172      * where to start the part of the BLOB
173      * @param length
174      * the length of the part of the BLOB you want returned.
175      *
176      * @return the bytes stored in the blob starting at position
177      * <code>pos</code> and having a length of <code>length</code>.
178      *
179      * @throws SQLException
180      * if a database error occurs
181      */

182     public byte[] getBytes(long pos, int length) throws SQLException JavaDoc {
183         java.sql.ResultSet JavaDoc blobRs = null;
184         java.sql.PreparedStatement JavaDoc pStmt = null;
185
186         // FIXME: Needs to use identifiers for column/table names
187
StringBuffer JavaDoc query = new StringBuffer JavaDoc("SELECT SUBSTRING(");
188         query.append(this.blobColumnName);
189         query.append(", ");
190         query.append(pos);
191         query.append(", ");
192         query.append(length);
193         query.append(") FROM ");
194         query.append(this.tableName);
195         query.append(" WHERE ");
196
197         query.append((String JavaDoc) this.primaryKeyColumns.get(0));
198         query.append(" = ?");
199
200         for (int i = 1; i < this.numPrimaryKeys; i++) {
201             query.append(" AND ");
202             query.append((String JavaDoc) this.primaryKeyColumns.get(i));
203             query.append(" = ?");
204         }
205
206         try {
207             // FIXME: Have this passed in instead
208
pStmt = this.creatorResultSet.connection.prepareStatement(query
209                     .toString());
210
211             for (int i = 0; i < this.numPrimaryKeys; i++) {
212                 pStmt.setString(i + 1, (String JavaDoc) this.primaryKeyValues.get(i));
213             }
214
215             blobRs = pStmt.executeQuery();
216
217             if (blobRs.next()) {
218                 return ((com.mysql.jdbc.ResultSet) blobRs).getBytes(1, true);
219             }
220
221             throw new SQLException JavaDoc(
222                     "BLOB data not found! Did primary keys change?",
223                     SQLError.SQL_STATE_GENERAL_ERROR);
224         } finally {
225             if (blobRs != null) {
226                 try {
227                     blobRs.close();
228                 } catch (SQLException JavaDoc sqlEx) {
229                     ; // do nothing
230
}
231
232                 blobRs = null;
233             }
234
235             if (pStmt != null) {
236                 try {
237                     pStmt.close();
238                 } catch (SQLException JavaDoc sqlEx) {
239                     ; // do nothing
240
}
241
242                 pStmt = null;
243             }
244         }
245     }
246
247     /**
248      * Returns the number of bytes in the BLOB value designated by this Blob
249      * object.
250      *
251      * @return the length of this blob
252      *
253      * @throws SQLException
254      * if a database error occurs
255      */

256     public long length() throws SQLException JavaDoc {
257         java.sql.ResultSet JavaDoc blobRs = null;
258         java.sql.PreparedStatement JavaDoc pStmt = null;
259
260         // FIXME: Needs to use identifiers for column/table names
261
StringBuffer JavaDoc query = new StringBuffer JavaDoc("SELECT LENGTH(");
262         query.append(this.blobColumnName);
263         query.append(") FROM ");
264         query.append(this.tableName);
265         query.append(" WHERE ");
266
267         query.append((String JavaDoc) this.primaryKeyColumns.get(0));
268         query.append(" = ?");
269
270         for (int i = 1; i < this.numPrimaryKeys; i++) {
271             query.append(" AND ");
272             query.append((String JavaDoc) this.primaryKeyColumns.get(i));
273             query.append(" = ?");
274         }
275
276         try {
277             // FIXME: Have this passed in instead
278
pStmt = this.creatorResultSet.connection.prepareStatement(query
279                     .toString());
280
281             for (int i = 0; i < this.numPrimaryKeys; i++) {
282                 pStmt.setString(i + 1, (String JavaDoc) this.primaryKeyValues.get(i));
283             }
284
285             blobRs = pStmt.executeQuery();
286
287             if (blobRs.next()) {
288                 return blobRs.getLong(1);
289             }
290
291             throw new SQLException JavaDoc(
292                     "BLOB data not found! Did primary keys change?",
293                     SQLError.SQL_STATE_GENERAL_ERROR);
294         } finally {
295             if (blobRs != null) {
296                 try {
297                     blobRs.close();
298                 } catch (SQLException JavaDoc sqlEx) {
299                     ; // do nothing
300
}
301
302                 blobRs = null;
303             }
304
305             if (pStmt != null) {
306                 try {
307                     pStmt.close();
308                 } catch (SQLException JavaDoc sqlEx) {
309                     ; // do nothing
310
}
311
312                 pStmt = null;
313             }
314         }
315     }
316
317     private void notEnoughInformationInQuery() throws SQLException JavaDoc {
318         throw new SQLException JavaDoc("Emulated BLOB locators must come from "
319                 + "a ResultSet with only one table selected, and all primary "
320                 + "keys selected", SQLError.SQL_STATE_GENERAL_ERROR);
321     }
322
323     /**
324      * @see java.sql.Blob#position(byte[], long)
325      */

326     public long position(byte[] pattern, long start) throws SQLException JavaDoc {
327         java.sql.ResultSet JavaDoc blobRs = null;
328         java.sql.PreparedStatement JavaDoc pStmt = null;
329
330         // FIXME: Needs to use identifiers for column/table names
331
StringBuffer JavaDoc query = new StringBuffer JavaDoc("SELECT LOCATE(");
332         query.append("?, ");
333         query.append(this.blobColumnName);
334         query.append(", ");
335         query.append(start);
336         query.append(") FROM ");
337         query.append(this.tableName);
338         query.append(" WHERE ");
339
340         query.append((String JavaDoc) this.primaryKeyColumns.get(0));
341         query.append(" = ?");
342
343         for (int i = 1; i < this.numPrimaryKeys; i++) {
344             query.append(" AND ");
345             query.append((String JavaDoc) this.primaryKeyColumns.get(i));
346             query.append(" = ?");
347         }
348
349         try {
350             // FIXME: Have this passed in instead
351
pStmt = this.creatorResultSet.connection.prepareStatement(query
352                     .toString());
353             pStmt.setBytes(1, pattern);
354
355             for (int i = 0; i < this.numPrimaryKeys; i++) {
356                 pStmt.setString(i + 2, (String JavaDoc) this.primaryKeyValues.get(i));
357             }
358
359             blobRs = pStmt.executeQuery();
360
361             if (blobRs.next()) {
362                 return blobRs.getLong(1);
363             }
364
365             throw new SQLException JavaDoc(
366                     "BLOB data not found! Did primary keys change?",
367                     SQLError.SQL_STATE_GENERAL_ERROR);
368         } finally {
369             if (blobRs != null) {
370                 try {
371                     blobRs.close();
372                 } catch (SQLException JavaDoc sqlEx) {
373                     ; // do nothing
374
}
375
376                 blobRs = null;
377             }
378
379             if (pStmt != null) {
380                 try {
381                     pStmt.close();
382                 } catch (SQLException JavaDoc sqlEx) {
383                     ; // do nothing
384
}
385
386                 pStmt = null;
387             }
388         }
389     }
390
391     /**
392      * Finds the position of the given pattern in this BLOB.
393      *
394      * @param pattern
395      * the pattern to find
396      * @param start
397      * where to start finding the pattern
398      *
399      * @return the position where the pattern is found in the BLOB, -1 if not
400      * found
401      *
402      * @throws SQLException
403      * if a database error occurs
404      */

405     public long position(java.sql.Blob JavaDoc pattern, long start) throws SQLException JavaDoc {
406         return position(pattern.getBytes(0, (int) pattern.length()), start);
407     }
408
409     /**
410      * @see Blob#setBinaryStream(long)
411      */

412     public OutputStream JavaDoc setBinaryStream(long indexToWriteAt)
413             throws SQLException JavaDoc {
414         throw new NotImplemented();
415     }
416
417     /**
418      * @see Blob#setBytes(long, byte[])
419      */

420     public int setBytes(long writeAt, byte[] bytes) throws SQLException JavaDoc {
421         return setBytes(writeAt, bytes, 0, bytes.length);
422     }
423
424     /**
425      * @see Blob#setBytes(long, byte[], int, int)
426      */

427     public int setBytes(long writeAt, byte[] bytes, int offset, int length)
428             throws SQLException JavaDoc {
429         java.sql.PreparedStatement JavaDoc pStmt = null;
430
431         if ((offset + length) > bytes.length) {
432             length = bytes.length - offset;
433         }
434
435         byte[] bytesToWrite = new byte[length];
436         System.arraycopy(bytes, offset, bytesToWrite, 0, length);
437
438         // FIXME: Needs to use identifiers for column/table names
439
StringBuffer JavaDoc query = new StringBuffer JavaDoc("UPDATE ");
440         query.append(this.tableName);
441         query.append(" SET ");
442         query.append(this.blobColumnName);
443         query.append(" = INSERT(");
444         query.append(this.blobColumnName);
445         query.append(", ");
446         query.append(writeAt);
447         query.append(", ");
448         query.append(length);
449         query.append(", ?) WHERE ");
450
451         query.append((String JavaDoc) this.primaryKeyColumns.get(0));
452         query.append(" = ?");
453
454         for (int i = 1; i < this.numPrimaryKeys; i++) {
455             query.append(" AND ");
456             query.append((String JavaDoc) this.primaryKeyColumns.get(i));
457             query.append(" = ?");
458         }
459
460         try {
461             // FIXME: Have this passed in instead
462
pStmt = this.creatorResultSet.connection.prepareStatement(query
463                     .toString());
464
465             pStmt.setBytes(1, bytesToWrite);
466
467             for (int i = 0; i < this.numPrimaryKeys; i++) {
468                 pStmt.setString(i + 2, (String JavaDoc) this.primaryKeyValues.get(i));
469             }
470
471             int rowsUpdated = pStmt.executeUpdate();
472
473             if (rowsUpdated != 1) {
474                 throw new SQLException JavaDoc(
475                         "BLOB data not found! Did primary keys change?",
476                         SQLError.SQL_STATE_GENERAL_ERROR);
477             }
478         } finally {
479             if (pStmt != null) {
480                 try {
481                     pStmt.close();
482                 } catch (SQLException JavaDoc sqlEx) {
483                     ; // do nothing
484
}
485
486                 pStmt = null;
487             }
488         }
489
490         return (int) length();
491     }
492
493     /**
494      * @see Blob#truncate(long)
495      */

496     public void truncate(long length) throws SQLException JavaDoc {
497         java.sql.PreparedStatement JavaDoc pStmt = null;
498
499         // FIXME: Needs to use identifiers for column/table names
500
StringBuffer JavaDoc query = new StringBuffer JavaDoc("UPDATE ");
501         query.append(this.tableName);
502         query.append(" SET ");
503         query.append(this.blobColumnName);
504         query.append(" = LEFT(");
505         query.append(this.blobColumnName);
506         query.append(", ");
507         query.append(length);
508         query.append(") WHERE ");
509
510         query.append((String JavaDoc) this.primaryKeyColumns.get(0));
511         query.append(" = ?");
512
513         for (int i = 1; i < this.numPrimaryKeys; i++) {
514             query.append(" AND ");
515             query.append((String JavaDoc) this.primaryKeyColumns.get(i));
516             query.append(" = ?");
517         }
518
519         try {
520             // FIXME: Have this passed in instead
521
pStmt = this.creatorResultSet.connection.prepareStatement(query
522                     .toString());
523
524             for (int i = 0; i < this.numPrimaryKeys; i++) {
525                 pStmt.setString(i + 1, (String JavaDoc) this.primaryKeyValues.get(i));
526             }
527
528             int rowsUpdated = pStmt.executeUpdate();
529
530             if (rowsUpdated != 1) {
531                 throw new SQLException JavaDoc(
532                         "BLOB data not found! Did primary keys change?",
533                         SQLError.SQL_STATE_GENERAL_ERROR);
534             }
535         } finally {
536             if (pStmt != null) {
537                 try {
538                     pStmt.close();
539                 } catch (SQLException JavaDoc sqlEx) {
540                     ; // do nothing
541
}
542
543                 pStmt = null;
544             }
545         }
546     }
547 }
548
Popular Tags