EMMA Coverage Report (generated Fri May 26 15:35:26 CDT 2006)
[all classes][com.mysql.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [BlobFromLocator.java]

nameclass, %method, %block, %line, %
BlobFromLocator.java100% (1/1)45%  (5/11)59%  (592/997)58%  (126.6/217)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BlobFromLocator100% (1/1)45%  (5/11)59%  (592/997)58%  (126.6/217)
getBinaryStream (): InputStream 0%   (0/1)0%   (0/10)0%   (0/1)
notEnoughInformationInQuery (): void 0%   (0/1)0%   (0/6)0%   (0/1)
position (Blob, long): long 0%   (0/1)0%   (0/10)0%   (0/1)
position (byte [], long): long 0%   (0/1)0%   (0/145)0%   (0/34)
setBinaryStream (long): OutputStream 0%   (0/1)0%   (0/4)0%   (0/1)
truncate (long): void 0%   (0/1)0%   (0/132)0%   (0/30)
length (): long 100% (1/1)77%  (99/129)77%  (23.1/30)
getBytes (long, int): byte [] 100% (1/1)80%  (117/147)80%  (27.2/34)
setBytes (long, byte [], int, int): int 100% (1/1)80%  (133/167)82%  (30.2/37)
BlobFromLocator (ResultSet, int): void 100% (1/1)98%  (235/239)96%  (45/47)
setBytes (long, byte []): int 100% (1/1)100% (8/8)100% (1/1)

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 */
25package com.mysql.jdbc;
26 
27import java.io.ByteArrayInputStream;
28import java.io.OutputStream;
29 
30import java.sql.SQLException;
31 
32import java.util.ArrayList;
33import java.util.List;
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 */
54public class BlobFromLocator implements java.sql.Blob {
55        private String 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 primaryKeyColumns = null;
65 
66        private List primaryKeyValues = null;
67 
68        private String quotedId;
69 
70        private String tableName = null;
71 
72        /**
73         * Creates an updatable BLOB that can update in-place
74         */
75        BlobFromLocator(ResultSet creatorResultSetToSet, int blobColumnIndex)
76                        throws SQLException {
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();
85                        this.primaryKeyValues = new ArrayList();
86 
87                        for (int i = 0; i < this.numColsInResultSet; i++) {
88                                if (this.creatorResultSet.fields[i].isPrimaryKey()) {
89                                        StringBuffer keyName = new StringBuffer();
90                                        keyName.append(quotedId);
91 
92                                        String 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 tableNameBuffer = new StringBuffer();
124 
125                        String 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 tableNameBuffer = new StringBuffer();
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 getBinaryStream() throws SQLException {
164                return new ByteArrayInputStream(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 {
183                java.sql.ResultSet blobRs = null;
184                java.sql.PreparedStatement pStmt = null;
185 
186                // FIXME: Needs to use identifiers for column/table names
187                StringBuffer query = new StringBuffer("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) 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) 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) 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(
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 sqlEx) {
229                                        ; // do nothing
230                                }
231 
232                                blobRs = null;
233                        }
234 
235                        if (pStmt != null) {
236                                try {
237                                        pStmt.close();
238                                } catch (SQLException 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 {
257                java.sql.ResultSet blobRs = null;
258                java.sql.PreparedStatement pStmt = null;
259 
260                // FIXME: Needs to use identifiers for column/table names
261                StringBuffer query = new StringBuffer("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) 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) 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) 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(
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 sqlEx) {
299                                        ; // do nothing
300                                }
301 
302                                blobRs = null;
303                        }
304 
305                        if (pStmt != null) {
306                                try {
307                                        pStmt.close();
308                                } catch (SQLException sqlEx) {
309                                        ; // do nothing
310                                }
311 
312                                pStmt = null;
313                        }
314                }
315        }
316 
317        private void notEnoughInformationInQuery() throws SQLException {
318                throw new SQLException("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 {
327                java.sql.ResultSet blobRs = null;
328                java.sql.PreparedStatement pStmt = null;
329 
330                // FIXME: Needs to use identifiers for column/table names
331                StringBuffer query = new StringBuffer("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) 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) 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) 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(
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 sqlEx) {
373                                        ; // do nothing
374                                }
375 
376                                blobRs = null;
377                        }
378 
379                        if (pStmt != null) {
380                                try {
381                                        pStmt.close();
382                                } catch (SQLException 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 pattern, long start) throws SQLException {
406                return position(pattern.getBytes(0, (int) pattern.length()), start);
407        }
408 
409        /**
410         * @see Blob#setBinaryStream(long)
411         */
412        public OutputStream setBinaryStream(long indexToWriteAt)
413                        throws SQLException {
414                throw new NotImplemented();
415        }
416 
417        /**
418         * @see Blob#setBytes(long, byte[])
419         */
420        public int setBytes(long writeAt, byte[] bytes) throws SQLException {
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 {
429                java.sql.PreparedStatement 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 query = new StringBuffer("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) 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) 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) this.primaryKeyValues.get(i));
469                        }
470 
471                        int rowsUpdated = pStmt.executeUpdate();
472 
473                        if (rowsUpdated != 1) {
474                                throw new SQLException(
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 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 {
497                java.sql.PreparedStatement pStmt = null;
498 
499                // FIXME: Needs to use identifiers for column/table names
500                StringBuffer query = new StringBuffer("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) 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) 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) this.primaryKeyValues.get(i));
526                        }
527 
528                        int rowsUpdated = pStmt.executeUpdate();
529 
530                        if (rowsUpdated != 1) {
531                                throw new SQLException(
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 sqlEx) {
540                                        ; // do nothing
541                                }
542 
543                                pStmt = null;
544                        }
545                }
546        }
547}

[all classes][com.mysql.jdbc]
EMMA 2.0.4217 (C) Vladimir Roubtsov