KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > jdbc > jdbcClob


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb.jdbc;
33
34 import java.io.StringReader JavaDoc;
35 import java.sql.Clob JavaDoc;
36 import java.sql.SQLException JavaDoc;
37
38 import org.hsqldb.Trace;
39 import org.hsqldb.lib.AsciiStringInputStream;
40
41 // boucherb@users 2004-03/04-xx - doc 1.7.2 - javadocs updated; methods put in
42
// correct (historical, interface
43
// declared) order
44
// boucherb@users 2004-03/04-xx - patch 1.7.2 - null check for constructor (a
45
// null CLOB value is Java null,
46
// not a Clob object with null
47
// data);moderate thread safety;
48
// simplification; optimization
49
// of operations between jdbcClob
50
// instances
51

52 /**
53  * The mapping in the Java<sup><font size=-2>TM</font></sup> programming
54  * language for the SQL CLOB type. <p>
55  *
56  * Provides methods for getting the length of an SQL CLOB (Character Large
57  * Object) value, for materializing a CLOB value on the client, and for
58  * searching for a substring or CLOB object within a CLOB value. <p>
59  *
60  * <!-- start Release-specific documentation -->
61  * <div class="ReleaseSpecificDocumentation">
62  * <h3>HSQLDB-Specific Information:</h3> <p>
63  *
64  * Including 1.8.x, the HSQLDB driver does not implement Clob using an SQL
65  * locator(CLOB). That is, an HSQLDB Clob object does not contain a logical
66  * pointer to SQL CLOB data; rather it directly contains an immutable
67  * representation of the data (a String object). As a result, an HSQLDB
68  * Clob object itself is valid beyond the duration of the transaction in which
69  * is was created, although it does not necessarily represent a corresponding
70  * value on the database. <p>
71  *
72  * Currently, the interface methods for updating a CLOB value are
73  * unsupported. However, the truncate method is supported for local use.
74  * </div>
75  * <!-- end release-specific documentation -->
76  *
77  * @author boucherb@users
78  * @version 1.7.2
79  * @since JDK 1.2, HSQLDB 1.7.2
80  */

81 public final class jdbcClob implements Clob JavaDoc {
82
83     volatile String JavaDoc data;
84
85     /**
86      * Constructs a new jdbcClob object wrapping the given character
87      * sequence. <p>
88      *
89      * This constructor is used internally to retrieve result set values as
90      * Clob objects, yet it must be public to allow access from other packages.
91      * As such (in the interest of efficiency) this object maintains a reference
92      * to the given String object rather than making a copy and so it is
93      * gently suggested (in the interest of effective memory management) that
94      * extenal clients using this constructor either take pause to consider
95      * the implications or at least take care to provide a String object whose
96      * internal character buffer is not much larger than required to represent
97      * the value.
98      *
99      * @param data the character sequence representing the Clob value
100      * @throws SQLException if the argument is null
101      */

102     public jdbcClob(final String JavaDoc data) throws SQLException JavaDoc {
103
104         if (data == null) {
105             throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT, "null");
106         }
107
108         this.data = data;
109     }
110
111     /**
112      * Retrieves the number of characters in the <code>CLOB</code> value
113      * designated by this <code>Clob</code> object.
114      *
115      * @return length of the <code>CLOB</code> in characters
116      * @exception SQLException if there is an error accessing the
117      * length of the <code>CLOB</code> value
118      *
119      * @since JDK 1.2, HSQLDB 1.7.2
120      */

121     public long length() throws SQLException JavaDoc {
122
123         final String JavaDoc ldata = data;
124
125         return ldata.length();
126     }
127
128     /**
129      * Retrieves a copy of the specified substring in the <code>CLOB</code>
130      * value designated by this <code>Clob</code> object. The substring begins
131      * at position <code>pos</code> and has up to <code>length</code>
132      * consecutive characters. <p>
133      *
134      * <!-- start release-specific documentation -->
135      * <div class="ReleaseSpecificDocumentation">
136      * <h3>HSQLDB-Specific Information:</h3> <p>
137      *
138      * The official specification above is ambiguous in that it does not
139      * precisely indicate the policy to be observed when
140      * pos > this.length() - length. One policy would be to retrieve the
141      * characters from pos to this.length(). Another would be to throw
142      * an exception. HSQLDB observes the later policy.
143      * </div>
144      * <!-- end release-specific documentation -->
145      *
146      * @param pos the first character of the substring to be extracted.
147      * The first character is at position 1.
148      * @param length the number of consecutive characters to be copied
149      * @return a <code>String</code> that is the specified substring in
150      * the <code>CLOB</code> value designated by this
151      * <code>Clob</code> object
152      * @exception SQLException if there is an error accessing the
153      * <code>CLOB</code> value
154      *
155      * @since JDK 1.2, HSQLDB 1.7.2
156      */

157     public String JavaDoc getSubString(long pos,
158                                final int length) throws SQLException JavaDoc {
159
160         final String JavaDoc ldata = data;
161         final int dlen = ldata.length();
162
163         pos--;
164
165         if (pos < 0 || pos > dlen) {
166             Util.sqlException(Trace.INVALID_JDBC_ARGUMENT,
167                               "pos: " + (pos + 1L));
168         }
169
170         if (length < 0 || length > dlen - pos) {
171             throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT,
172                                     "length: " + length);
173         }
174
175         if (pos == 0 && length == dlen) {
176             return ldata;
177         }
178
179         return ldata.substring((int) pos, (int) pos + length);
180     }
181
182     /**
183      * Retrieves the <code>CLOB</code> value designated by this
184      * <code>Clob</code> object as a <code>java.io.Reader</code> object
185      * (or as a stream of characters).
186      *
187      * @return a <code>java.io.Reader</code> object containing the
188      * <code>CLOB</code> data
189      * @exception SQLException if there is an error accessing the
190      * <code>CLOB</code> value
191      * @see #setCharacterStream
192      *
193      * @since JDK 1.2, HSQLDB 1.7.2
194      */

195     public java.io.Reader JavaDoc getCharacterStream() throws SQLException JavaDoc {
196
197         final String JavaDoc ldata = data;
198
199         return new StringReader JavaDoc(ldata);
200     }
201
202     /**
203      * Retrieves the <code>CLOB</code> value designated by this
204      * <code>Clob</code> object as an ascii stream.
205      *
206      * @return a <code>java.io.InputStream</code> object containing the
207      * <code>CLOB</code> data
208      * @exception SQLException if there is an error accessing the
209      * <code>CLOB</code> value
210      * @see #setAsciiStream
211      *
212      * @since JDK 1.2, HSQLDB 1.7.2
213      */

214     public java.io.InputStream JavaDoc getAsciiStream() throws SQLException JavaDoc {
215
216         final String JavaDoc ldata = data;
217
218         return new AsciiStringInputStream(ldata);
219     }
220
221     /**
222      * Retrieves the character position at which the specified substring
223      * <code>searchstr</code> appears in the SQL <code>CLOB</code> value
224      * represented by this <code>Clob</code> object. The search
225      * begins at position <code>start</code>.
226      *
227      * @param searchstr the substring for which to search
228      * @param start the position at which to begin searching; the
229      * first position is 1
230      * @return the position at which the substring appears or -1 if it is not
231      * present; the first position is 1
232      * @exception SQLException if there is an error accessing the
233      * <code>CLOB</code> value
234      *
235      * @since JDK 1.2, HSQLDB 1.7.2
236      */

237     public long position(final String JavaDoc searchstr,
238                          long start) throws SQLException JavaDoc {
239
240         if (searchstr == null || start > Integer.MAX_VALUE) {
241             return -1;
242         }
243
244         final String JavaDoc ldata = data;
245         final int pos = ldata.indexOf(searchstr, (int) --start);
246
247         return (pos < 0) ? -1
248                          : pos + 1;
249     }
250
251     /**
252      * Retrieves the character position at which the specified
253      * <code>Clob</code> object <code>searchstr</code> appears in this
254      * <code>Clob</code> object. The search begins at position
255      * <code>start</code>.
256      *
257      * @param searchstr the <code>Clob</code> object for which to search
258      * @param start the position at which to begin searching; the first
259      * position is 1
260      * @return the position at which the <code>Clob</code> object appears
261      * or -1 if it is not present; the first position is 1
262      * @exception SQLException if there is an error accessing the
263      * <code>CLOB</code> value
264      *
265      * @since JDK 1.2, HSQLDB 1.7.2
266      */

267     public long position(final Clob JavaDoc searchstr,
268                          long start) throws SQLException JavaDoc {
269
270         if (searchstr == null) {
271             return -1;
272         }
273
274         final String JavaDoc ldata = data;
275         final long dlen = ldata.length();
276         final long sslen = searchstr.length();
277
278         start--; //***** FOIRGOT THIS *******
279

280 // This is potentially much less expensive than materializing a large
281
// substring from some other vendor's CLOB. Indeed, we should probably
282
// do the comparison piecewise, using an in-memory buffer (or temp-files
283
// when available), if it is detected that the input CLOB is very long.
284
if (start > dlen - sslen) {
285             return -1;
286         }
287
288         // by now, we know sslen and start are both < Integer.MAX_VALUE
289
String JavaDoc s;
290
291         if (searchstr instanceof jdbcClob) {
292             s = ((jdbcClob) searchstr).data;
293         } else {
294             s = searchstr.getSubString(1L, (int) sslen);
295         }
296
297         final int pos = ldata.indexOf(s, (int) start);
298
299         return (pos < 0) ? -1
300                          : pos + 1;
301     }
302
303     //---------------------------- jdbc 3.0 -----------------------------------
304

305     /**
306      * Writes the given Java <code>String</code> to the <code>CLOB</code>
307      * value that this <code>Clob</code> object designates at the position
308      * <code>pos</code>. <p>
309      *
310      * <!-- start release-specific documentation -->
311      * <div class="ReleaseSpecificDocumentation">
312      * <h3>HSQLDB-Specific Information:</h3> <p>
313      *
314      * HSLQDB 1.7.2 does not support this feature. <p>
315      *
316      * Calling this method always throws an <code>SQLException</code>.
317      * </div>
318      * <!-- end release-specific documentation -->
319      *
320      * @param pos the position at which to start writing to the
321      * <code>CLOB</code> value that this <code>Clob</code> object
322      * represents
323      * @param str the string to be written to the <code>CLOB</code>
324      * value that this <code>Clob</code> designates
325      * @return the number of characters written
326      * @exception SQLException if there is an error accessing the
327      * <code>CLOB</code> value
328      *
329      * @since JDK 1.4, HSQLDB 1.7.2
330      */

331     public int setString(long pos, String JavaDoc str) throws SQLException JavaDoc {
332         throw Util.notSupported();
333     }
334
335     /**
336      * Writes <code>len</code> characters of <code>str</code>, starting
337      * at character <code>offset</code>, to the <code>CLOB</code> value
338      * that this <code>Clob</code> represents. <p>
339      *
340      * <!-- start release-specific documentation -->
341      * <div class="ReleaseSpecificDocumentation">
342      * <h3>HSQLDB-Specific Information:</h3> <p>
343      *
344      * HSLQDB 1.7.2 does not support this feature. <p>
345      *
346      * Calling this method always throws an <code>SQLException</code>.
347      * </div>
348      * <!-- end release-specific documentation -->
349      *
350      * @param pos the position at which to start writing to this
351      * <code>CLOB</code> object
352      * @param str the string to be written to the <code>CLOB</code>
353      * value that this <code>Clob</code> object represents
354      * @param offset the offset into <code>str</code> to start reading
355      * the characters to be written
356      * @param len the number of characters to be written
357      * @return the number of characters written
358      * @exception SQLException if there is an error accessing the
359      * <code>CLOB</code> value
360      *
361      * @since JDK 1.4, HSQLDB 1.7.2
362      */

363     public int setString(long pos, String JavaDoc str, int offset,
364                          int len) throws SQLException JavaDoc {
365         throw Util.notSupported();
366     }
367
368     /**
369      * Retrieves a stream to be used to write Ascii characters to the
370      * <code>CLOB</code> value that this <code>Clob</code> object represents,
371      * starting at position <code>pos</code>. <p>
372      *
373      * <!-- start release-specific documentation -->
374      * <div class="ReleaseSpecificDocumentation">
375      * <h3>HSQLDB-Specific Information:</h3> <p>
376      *
377      * HSLQDB 1.7.2 does not support this feature. <p>
378      *
379      * Calling this method always throws an <code>SQLException</code>.
380      * </div>
381      * <!-- end release-specific documentation -->
382      *
383      * @param pos the position at which to start writing to this
384      * <code>CLOB</code> object
385      * @return the stream to which ASCII encoded characters can be written
386      * @exception SQLException if there is an error accessing the
387      * <code>CLOB</code> value
388      * @see #getAsciiStream
389      *
390      * @since JDK 1.4, HSQLDB 1.7.2
391      */

392     public java.io.OutputStream JavaDoc setAsciiStream(long pos) throws SQLException JavaDoc {
393         throw Util.notSupported();
394     }
395
396     /**
397      * Retrieves a stream to be used to write a stream of Unicode characters
398      * to the <code>CLOB</code> value that this <code>Clob</code> object
399      * represents, at position <code>pos</code>. <p>
400      *
401      * <!-- start release-specific documentation -->
402      * <div class="ReleaseSpecificDocumentation">
403      * <h3>HSQLDB-Specific Information:</h3> <p>
404      *
405      * HSLQDB 1.7.2 does not support this feature. <p>
406      *
407      * Calling this method always throws an <code>SQLException</code>.
408      * </div>
409      * <!-- end release-specific documentation -->
410      *
411      * @param pos the position at which to start writing to the
412      * <code>CLOB</code> value
413      *
414      * @return a stream to which Unicode encoded characters can be written
415      * @exception SQLException if there is an error accessing the
416      * <code>CLOB</code> value
417      * @see #getCharacterStream
418      *
419      * @since JDK 1.4, HSQLDB 1.7.2
420      */

421     public java.io.Writer JavaDoc setCharacterStream(long pos) throws SQLException JavaDoc {
422         throw Util.notSupported();
423     }
424
425     /**
426      * Truncates the <code>CLOB</code> value that this <code>Clob</code>
427      * designates to have a length of <code>len</code>
428      * characters. <p>
429      *
430      * <!-- start release-specific documentation -->
431      * <div class="ReleaseSpecificDocumentation">
432      * <h3>HSQLDB-Specific Information:</h3> <p>
433      *
434      * This operation affects only the client-side value; it has no effect upon
435      * the value as it is stored in the database.
436      * </div>
437      * <!-- end release-specific documentation -->
438      *
439      * @param len the length, in bytes, to which the <code>CLOB</code> value
440      * should be truncated
441      * @exception SQLException if there is an error accessing the
442      * <code>CLOB</code> value
443      *
444      * @since JDK 1.4, HSQLDB 1.7.2
445      */

446     public void truncate(final long len) throws SQLException JavaDoc {
447
448         final String JavaDoc ldata = data;
449         final long dlen = ldata.length();
450         final long chars = len >> 1;
451
452         if (chars == dlen) {
453
454             // nothing has changed, so there's nothing to be done
455
} else if (len < 0 || chars > dlen) {
456             throw Util.sqlException(Trace.INVALID_JDBC_ARGUMENT,
457                                     Long.toString(len));
458         } else {
459
460             // use new String() to ensure we get rid of slack
461
data = new String JavaDoc(ldata.substring(0, (int) chars));
462         }
463     }
464 }
465
Popular Tags