View Javadoc
1   /*
2    * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  package javax.sql.rowset.serial;
26  
27  import java.sql.*;
28  import java.util.Arrays;
29  import java.util.Map;
30  
31  /**
32   * An input stream used for custom mapping user-defined types (UDTs).
33   * An <code>SQLInputImpl</code> object is an input stream that contains a
34   * stream of values that are the attributes of a UDT.
35   * <p>
36   * This class is used by the driver behind the scenes when the method
37   * <code>getObject</code> is called on an SQL structured or distinct type
38   * that has a custom mapping; a programmer never invokes
39   * <code>SQLInputImpl</code> methods directly. They are provided here as a
40   * convenience for those who write <code>RowSet</code> implementations.
41   * <P>
42   * The <code>SQLInputImpl</code> class provides a set of
43   * reader methods analogous to the <code>ResultSet</code> getter
44   * methods.  These methods make it possible to read the values in an
45   * <code>SQLInputImpl</code> object.
46   * <P>
47   * The method <code>wasNull</code> is used to determine whether the
48   * the last value read was SQL <code>NULL</code>.
49   * <P>When the method <code>getObject</code> is called with an
50   * object of a class implementing the interface <code>SQLData</code>,
51   * the JDBC driver calls the method <code>SQLData.getSQLType</code>
52   * to determine the SQL type of the UDT being custom mapped. The driver
53   * creates an instance of <code>SQLInputImpl</code>, populating it with the
54   * attributes of the UDT.  The driver then passes the input
55   * stream to the method <code>SQLData.readSQL</code>, which in turn
56   * calls the <code>SQLInputImpl</code> reader methods
57   * to read the attributes from the input stream.
58   * @since 1.5
59   * @see java.sql.SQLData
60   */
61  public class SQLInputImpl implements SQLInput {
62  
63      /**
64       * <code>true</code> if the last value returned was <code>SQL NULL</code>;
65       * <code>false</code> otherwise.
66       */
67      private boolean lastValueWasNull;
68  
69      /**
70       * The current index into the array of SQL structured type attributes
71       * that will be read from this <code>SQLInputImpl</code> object and
72       * mapped to the fields of a class in the Java programming language.
73       */
74      private int idx;
75  
76      /**
77       * The array of attributes to be read from this stream.  The order
78       * of the attributes is the same as the order in which they were
79       * listed in the SQL definition of the UDT.
80       */
81      private Object attrib[];
82  
83      /**
84       * The type map to use when the method <code>readObject</code>
85       * is invoked. This is a <code>java.util.Map</code> object in which
86       * there may be zero or more entries.  Each entry consists of the
87       * fully qualified name of a UDT (the value to be mapped) and the
88       * <code>Class</code> object for a class that implements
89       * <code>SQLData</code> (the Java class that defines how the UDT
90       * will be mapped).
91       */
92      private Map<String,Class<?>> map;
93  
94  
95      /**
96       * Creates an <code>SQLInputImpl</code> object initialized with the
97       * given array of attributes and the given type map. If any of the
98       * attributes is a UDT whose name is in an entry in the type map,
99       * the attribute will be mapped according to the corresponding
100      * <code>SQLData</code> implementation.
101      *
102      * @param attributes an array of <code>Object</code> instances in which
103      *        each element is an attribute of a UDT. The order of the
104      *        attributes in the array is the same order in which
105      *        the attributes were defined in the UDT definition.
106      * @param map a <code>java.util.Map</code> object containing zero or more
107      *        entries, with each entry consisting of 1) a <code>String</code>
108      *        giving the fully
109      *        qualified name of the UDT and 2) the <code>Class</code> object
110      *        for the <code>SQLData</code> implementation that defines how
111      *        the UDT is to be mapped
112      * @throws SQLException if the <code>attributes</code> or the <code>map</code>
113      *        is a <code>null</code> value
114      */
115 
116     public SQLInputImpl(Object[] attributes, Map<String,Class<?>> map)
117         throws SQLException
118     {
119         if ((attributes == null) || (map == null)) {
120             throw new SQLException("Cannot instantiate a SQLInputImpl " +
121             "object with null parameters");
122         }
123         // assign our local reference to the attribute stream
124         attrib = Arrays.copyOf(attributes, attributes.length);
125         // init the index point before the head of the stream
126         idx = -1;
127         // set the map
128         this.map = map;
129     }
130 
131 
132     /**
133      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
134      * as an <code>Object</code> in the Java programming language.
135      *
136      * @return the next value in the input stream
137      *         as an <code>Object</code> in the Java programming language
138      * @throws SQLException if the read position is located at an invalid
139      *         position or if there are no further values in the stream
140      */
141     private Object getNextAttribute() throws SQLException {
142         if (++idx >= attrib.length) {
143             throw new SQLException("SQLInputImpl exception: Invalid read " +
144                                    "position");
145         } else {
146             lastValueWasNull = attrib[idx] == null;
147             return attrib[idx];
148         }
149     }
150 
151 
152     //================================================================
153     // Methods for reading attributes from the stream of SQL data.
154     // These methods correspond to the column-accessor methods of
155     // java.sql.ResultSet.
156     //================================================================
157 
158     /**
159      * Retrieves the next attribute in this <code>SQLInputImpl</code> object as
160      * a <code>String</code> in the Java programming language.
161      * <p>
162      * This method does not perform type-safe checking to determine if the
163      * returned type is the expected type; this responsibility is delegated
164      * to the UDT mapping as defined by a <code>SQLData</code>
165      * implementation.
166      * <p>
167      * @return the next attribute in this <code>SQLInputImpl</code> object;
168      *     if the value is <code>SQL NULL</code>, return <code>null</code>
169      * @throws SQLException if the read position is located at an invalid
170      *     position or if there are no further values in the stream.
171      */
172     public String readString() throws SQLException {
173         return  (String)getNextAttribute();
174     }
175 
176     /**
177      * Retrieves the next attribute in this <code>SQLInputImpl</code> object as
178      * a <code>boolean</code> in the Java programming language.
179      * <p>
180      * This method does not perform type-safe checking to determine if the
181      * returned type is the expected type; this responsibility is delegated
182      * to the UDT mapping as defined by a <code>SQLData</code>
183      * implementation.
184      * <p>
185      * @return the next attribute in this <code>SQLInputImpl</code> object;
186      *     if the value is <code>SQL NULL</code>, return <code>null</code>
187      * @throws SQLException if the read position is located at an invalid
188      *     position or if there are no further values in the stream.
189      */
190     public boolean readBoolean() throws SQLException {
191         Boolean attrib = (Boolean)getNextAttribute();
192         return  (attrib == null) ? false : attrib.booleanValue();
193     }
194 
195     /**
196      * Retrieves the next attribute in this <code>SQLInputImpl</code> object as
197      * a <code>byte</code> in the Java programming language.
198      * <p>
199      * This method does not perform type-safe checking to determine if the
200      * returned type is the expected type; this responsibility is delegated
201      * to the UDT mapping as defined by a <code>SQLData</code>
202      * implementation.
203      * <p>
204      * @return the next attribute in this <code>SQLInputImpl</code> object;
205      *     if the value is <code>SQL NULL</code>, return <code>null</code>
206      * @throws SQLException if the read position is located at an invalid
207      *     position or if there are no further values in the stream
208      */
209     public byte readByte() throws SQLException {
210         Byte attrib = (Byte)getNextAttribute();
211         return  (attrib == null) ? 0 : attrib.byteValue();
212     }
213 
214     /**
215      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
216      * as a <code>short</code> in the Java programming language.
217      * <P>
218      * This method does not perform type-safe checking to determine if the
219      * returned type is the expected type; this responsibility is delegated
220      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
221      * <P>
222      * @return the next attribute in this <code>SQLInputImpl</code> object;
223      *       if the value is <code>SQL NULL</code>, return <code>null</code>
224      * @throws SQLException if the read position is located at an invalid
225      *       position or if there are no more values in the stream
226      */
227     public short readShort() throws SQLException {
228         Short attrib = (Short)getNextAttribute();
229         return (attrib == null) ? 0 : attrib.shortValue();
230     }
231 
232     /**
233      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
234      * as an <code>int</code> in the Java programming language.
235      * <P>
236      * This method does not perform type-safe checking to determine if the
237      * returned type is the expected type; this responsibility is delegated
238      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
239      * <P>
240      * @return the next attribute in this <code>SQLInputImpl</code> object;
241      *       if the value is <code>SQL NULL</code>, return <code>null</code>
242      * @throws SQLException if the read position is located at an invalid
243      *       position or if there are no more values in the stream
244      */
245     public int readInt() throws SQLException {
246         Integer attrib = (Integer)getNextAttribute();
247         return (attrib == null) ? 0 : attrib.intValue();
248     }
249 
250     /**
251      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
252      * as a <code>long</code> in the Java programming language.
253      * <P>
254      * This method does not perform type-safe checking to determine if the
255      * returned type is the expected type; this responsibility is delegated
256      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
257      * <P>
258      * @return the next attribute in this <code>SQLInputImpl</code> object;
259      *       if the value is <code>SQL NULL</code>, return <code>null</code>
260      * @throws SQLException if the read position is located at an invalid
261      *       position or if there are no more values in the stream
262      */
263     public long readLong() throws SQLException {
264         Long attrib = (Long)getNextAttribute();
265         return (attrib == null) ? 0 : attrib.longValue();
266     }
267 
268     /**
269      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
270      * as a <code>float</code> in the Java programming language.
271      * <P>
272      * This method does not perform type-safe checking to determine if the
273      * returned type is the expected type; this responsibility is delegated
274      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
275      * <P>
276      * @return the next attribute in this <code>SQLInputImpl</code> object;
277      *       if the value is <code>SQL NULL</code>, return <code>null</code>
278      * @throws SQLException if the read position is located at an invalid
279      *       position or if there are no more values in the stream
280      */
281     public float readFloat() throws SQLException {
282         Float attrib = (Float)getNextAttribute();
283         return (attrib == null) ? 0 : attrib.floatValue();
284     }
285 
286     /**
287      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
288      * as a <code>double</code> in the Java programming language.
289      * <P>
290      * This method does not perform type-safe checking to determine if the
291      * returned type is the expected type; this responsibility is delegated
292      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
293      * <P>
294      * @return the next attribute in this <code>SQLInputImpl</code> object;
295      *       if the value is <code>SQL NULL</code>, return <code>null</code>
296      * @throws SQLException if the read position is located at an invalid
297      *       position or if there are no more values in the stream
298      */
299     public double readDouble() throws SQLException {
300         Double attrib = (Double)getNextAttribute();
301         return (attrib == null)  ? 0 :  attrib.doubleValue();
302     }
303 
304     /**
305      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
306      * as a <code>java.math.BigDecimal</code>.
307      * <P>
308      * This method does not perform type-safe checking to determine if the
309      * returned type is the expected type; this responsibility is delegated
310      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
311      * <P>
312      * @return the next attribute in this <code>SQLInputImpl</code> object;
313      *       if the value is <code>SQL NULL</code>, return <code>null</code>
314      * @throws SQLException if the read position is located at an invalid
315      *       position or if there are no more values in the stream
316      */
317     public java.math.BigDecimal readBigDecimal() throws SQLException {
318         return (java.math.BigDecimal)getNextAttribute();
319     }
320 
321     /**
322      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
323      * as an array of bytes.
324      * <p>
325      * This method does not perform type-safe checking to determine if the
326      * returned type is the expected type; this responsibility is delegated
327      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
328      * <P>
329      * @return the next attribute in this <code>SQLInputImpl</code> object;
330      *       if the value is <code>SQL NULL</code>, return <code>null</code>
331      * @throws SQLException if the read position is located at an invalid
332      *       position or if there are no more values in the stream
333      */
334     public byte[] readBytes() throws SQLException {
335         return (byte[])getNextAttribute();
336     }
337 
338     /**
339      * Retrieves the next attribute in this <code>SQLInputImpl</code> as
340      * a <code>java.sql.Date</code> object.
341      * <P>
342      * This method does not perform type-safe checking to determine if the
343      * returned type is the expected type; this responsibility is delegated
344      * to the UDT mapping as defined by a <code>SQLData</code> implementation.
345      * <P>
346      * @return the next attribute in this <code>SQLInputImpl</code> object;
347      *       if the value is <code>SQL NULL</code>, return <code>null</code>
348      * @throws SQLException if the read position is located at an invalid
349      *       position or if there are no more values in the stream
350      */
351     public java.sql.Date readDate() throws SQLException {
352         return (java.sql.Date)getNextAttribute();
353     }
354 
355     /**
356      * Retrieves the next attribute in this <code>SQLInputImpl</code> object as
357      * a <code>java.sql.Time</code> object.
358      * <P>
359      * This method does not perform type-safe checking to determine if the
360      * returned type is the expected type as this responsibility is delegated
361      * to the UDT mapping as implemented by a <code>SQLData</code>
362      * implementation.
363      *
364      * @return the attribute; if the value is <code>SQL NULL</code>, return
365      * <code>null</code>
366      * @throws SQLException if the read position is located at an invalid
367      * position; or if there are no further values in the stream.
368      */
369     public java.sql.Time readTime() throws SQLException {
370         return (java.sql.Time)getNextAttribute();
371     }
372 
373     /**
374      * Retrieves the next attribute in this <code>SQLInputImpl</code> object as
375      * a <code>java.sql.Timestamp</code> object.
376      *
377      * @return the attribute; if the value is <code>SQL NULL</code>, return
378      * <code>null</code>
379      * @throws SQLException if the read position is located at an invalid
380      * position; or if there are no further values in the stream.
381      */
382     public java.sql.Timestamp readTimestamp() throws SQLException {
383         return (java.sql.Timestamp)getNextAttribute();
384     }
385 
386     /**
387      * Retrieves the next attribute in this <code>SQLInputImpl</code> object
388      * as a stream of Unicode characters.
389      * <P>
390      * This method does not perform type-safe checking to determine if the
391      * returned type is the expected type as this responsibility is delegated
392      * to the UDT mapping as implemented by a <code>SQLData</code>
393      * implementation.
394      *
395      * @return the attribute; if the value is <code>SQL NULL</code>, return <code>null</code>
396      * @throws SQLException if the read position is located at an invalid
397      * position; or if there are no further values in the stream.
398      */
399     public java.io.Reader readCharacterStream() throws SQLException {
400         return (java.io.Reader)getNextAttribute();
401     }
402 
403     /**
404      * Returns the next attribute in this <code>SQLInputImpl</code> object
405      * as a stream of ASCII characters.
406      * <P>
407      * This method does not perform type-safe checking to determine if the
408      * returned type is the expected type as this responsibility is delegated
409      * to the UDT mapping as implemented by a <code>SQLData</code>
410      * implementation.
411      *
412      * @return the attribute; if the value is <code>SQL NULL</code>,
413      * return <code>null</code>
414      * @throws SQLException if the read position is located at an invalid
415      * position; or if there are no further values in the stream.
416      */
417     public java.io.InputStream readAsciiStream() throws SQLException {
418         return (java.io.InputStream)getNextAttribute();
419     }
420 
421     /**
422      * Returns the next attribute in this <code>SQLInputImpl</code> object
423      * as a stream of uninterpreted bytes.
424      * <P>
425      * This method does not perform type-safe checking to determine if the
426      * returned type is the expected type as this responsibility is delegated
427      * to the UDT mapping as implemented by a <code>SQLData</code>
428      * implementation.
429      *
430      * @return the attribute; if the value is <code>SQL NULL</code>, return
431      * <code>null</code>
432      * @throws SQLException if the read position is located at an invalid
433      * position; or if there are no further values in the stream.
434      */
435     public java.io.InputStream readBinaryStream() throws SQLException {
436         return (java.io.InputStream)getNextAttribute();
437     }
438 
439     //================================================================
440     // Methods for reading items of SQL user-defined types from the stream.
441     //================================================================
442 
443     /**
444      * Retrieves the value at the head of this <code>SQLInputImpl</code>
445      * object as an <code>Object</code> in the Java programming language.  The
446      * actual type of the object returned is determined by the default
447      * mapping of SQL types to types in the Java programming language unless
448      * there is a custom mapping, in which case the type of the object
449      * returned is determined by this stream's type map.
450      * <P>
451      * The JDBC technology-enabled driver registers a type map with the stream
452      * before passing the stream to the application.
453      * <P>
454      * When the datum at the head of the stream is an SQL <code>NULL</code>,
455      * this method returns <code>null</code>.  If the datum is an SQL
456      * structured or distinct type with a custom mapping, this method
457      * determines the SQL type of the datum at the head of the stream,
458      * constructs an object of the appropriate class, and calls the method
459      * <code>SQLData.readSQL</code> on that object. The <code>readSQL</code>
460      * method then calls the appropriate <code>SQLInputImpl.readXXX</code>
461      * methods to retrieve the attribute values from the stream.
462      *
463      * @return the value at the head of the stream as an <code>Object</code>
464      *         in the Java programming language; <code>null</code> if
465      *         the value is SQL <code>NULL</code>
466      * @throws SQLException if the read position is located at an invalid
467      * position; or if there are no further values in the stream.
468      */
469     public Object readObject() throws SQLException {
470         Object attrib = getNextAttribute();
471         if (attrib instanceof Struct) {
472             Struct s = (Struct)attrib;
473             // look up the class in the map
474             Class<?> c = map.get(s.getSQLTypeName());
475             if (c != null) {
476                 // create new instance of the class
477                 SQLData obj = null;
478                 try {
479                     obj = (SQLData)c.newInstance();
480                 } catch (java.lang.InstantiationException ex) {
481                     throw new SQLException("Unable to instantiate: " +
482                             ex.getMessage());
483                 } catch (java.lang.IllegalAccessException ex) {
484                     throw new SQLException("Unable to instantiate: " +
485                             ex.getMessage());
486                 }
487                 // get the attributes from the struct
488                 Object attribs[] = s.getAttributes(map);
489                 // create the SQLInput "stream"
490                 SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
491                 // read the values...
492                 obj.readSQL(sqlInput, s.getSQLTypeName());
493                 return obj;
494             }
495         }
496         return attrib;
497     }
498 
499     /**
500      * Retrieves the value at the head of this <code>SQLInputImpl</code> object
501      * as a <code>Ref</code> object in the Java programming language.
502      *
503      * @return a <code>Ref</code> object representing the SQL
504      *         <code>REF</code> value at the head of the stream; if the value
505      *         is <code>SQL NULL</code> return <code>null</code>
506      * @throws SQLException if the read position is located at an invalid
507      *         position; or if there are no further values in the stream.
508      */
509     public Ref readRef() throws SQLException {
510         return (Ref)getNextAttribute();
511     }
512 
513     /**
514      * Retrieves the <code>BLOB</code> value at the head of this
515      * <code>SQLInputImpl</code> object as a <code>Blob</code> object
516      * in the Java programming language.
517      * <P>
518      * This method does not perform type-safe checking to determine if the
519      * returned type is the expected type as this responsibility is delegated
520      * to the UDT mapping as implemented by a <code>SQLData</code>
521      * implementation.
522      *
523      * @return a <code>Blob</code> object representing the SQL
524      *         <code>BLOB</code> value at the head of this stream;
525      *         if the value is <code>SQL NULL</code>, return
526      *         <code>null</code>
527      * @throws SQLException if the read position is located at an invalid
528      * position; or if there are no further values in the stream.
529      */
530     public Blob readBlob() throws SQLException {
531         return (Blob)getNextAttribute();
532     }
533 
534     /**
535      * Retrieves the <code>CLOB</code> value at the head of this
536      * <code>SQLInputImpl</code> object as a <code>Clob</code> object
537      * in the Java programming language.
538      * <P>
539      * This method does not perform type-safe checking to determine if the
540      * returned type is the expected type as this responsibility is delegated
541      * to the UDT mapping as implemented by a <code>SQLData</code>
542      * implementation.
543      *
544      * @return a <code>Clob</code> object representing the SQL
545      *         <code>CLOB</code> value at the head of the stream;
546      *         if the value is <code>SQL NULL</code>, return
547      *         <code>null</code>
548      * @throws SQLException if the read position is located at an invalid
549      * position; or if there are no further values in the stream.
550      */
551     public Clob readClob() throws SQLException {
552         return (Clob)getNextAttribute();
553     }
554 
555     /**
556      * Reads an SQL <code>ARRAY</code> value from the stream and
557      * returns it as an <code>Array</code> object in the Java programming
558      * language.
559      * <P>
560      * This method does not perform type-safe checking to determine if the
561      * returned type is the expected type as this responsibility is delegated
562      * to the UDT mapping as implemented by a <code>SQLData</code>
563      * implementation.
564      *
565      * @return an <code>Array</code> object representing the SQL
566      *         <code>ARRAY</code> value at the head of the stream; *
567      *         if the value is <code>SQL NULL</code>, return
568      *         <code>null</code>
569      * @throws SQLException if the read position is located at an invalid
570      * position; or if there are no further values in the stream.
571 
572      */
573     public Array readArray() throws SQLException {
574         return (Array)getNextAttribute();
575     }
576 
577     /**
578      * Ascertains whether the last value read from this
579      * <code>SQLInputImpl</code> object was <code>null</code>.
580      *
581      * @return <code>true</code> if the SQL value read most recently was
582      *         <code>null</code>; otherwise, <code>false</code>; by default it
583      *         will return false
584      * @throws SQLException if an error occurs determining the last value
585      *         read was a <code>null</code> value or not;
586      */
587     public boolean wasNull() throws SQLException {
588         return lastValueWasNull;
589     }
590 
591     /**
592      * Reads an SQL <code>DATALINK</code> value from the stream and
593      * returns it as an <code>URL</code> object in the Java programming
594      * language.
595      * <P>
596      * This method does not perform type-safe checking to determine if the
597      * returned type is the expected type as this responsibility is delegated
598      * to the UDT mapping as implemented by a <code>SQLData</code>
599      * implementation.
600      *
601      * @return an <code>URL</code> object representing the SQL
602      *         <code>DATALINK</code> value at the head of the stream; *
603      *         if the value is <code>SQL NULL</code>, return
604      *         <code>null</code>
605      * @throws SQLException if the read position is located at an invalid
606      * position; or if there are no further values in the stream.
607      */
608     public java.net.URL readURL() throws SQLException {
609         return (java.net.URL)getNextAttribute();
610     }
611 
612     //---------------------------- JDBC 4.0 -------------------------
613 
614     /**
615      * Reads an SQL <code>NCLOB</code> value from the stream and returns it as a
616      * <code>Clob</code> object in the Java programming language.
617      *
618      * @return a <code>NClob</code> object representing data of the SQL <code>NCLOB</code> value
619      * at the head of the stream; <code>null</code> if the value read is
620      * SQL <code>NULL</code>
621      * @exception SQLException if a database access error occurs
622      * @since 1.6
623      */
624      public NClob readNClob() throws SQLException {
625         return (NClob)getNextAttribute();
626      }
627 
628     /**
629      * Reads the next attribute in the stream and returns it as a <code>String</code>
630      * in the Java programming language. It is intended for use when
631      * accessing  <code>NCHAR</code>,<code>NVARCHAR</code>
632      * and <code>LONGNVARCHAR</code> columns.
633      *
634      * @return the attribute; if the value is SQL <code>NULL</code>, returns <code>null</code>
635      * @exception SQLException if a database access error occurs
636      * @since 1.6
637      */
638     public String readNString() throws SQLException {
639         return (String)getNextAttribute();
640     }
641 
642     /**
643      * Reads an SQL <code>XML</code> value from the stream and returns it as a
644      * <code>SQLXML</code> object in the Java programming language.
645      *
646      * @return a <code>SQLXML</code> object representing data of the SQL <code>XML</code> value
647      * at the head of the stream; <code>null</code> if the value read is
648      * SQL <code>NULL</code>
649      * @exception SQLException if a database access error occurs
650      * @since 1.6
651      */
652     public SQLXML readSQLXML() throws SQLException {
653         return (SQLXML)getNextAttribute();
654     }
655 
656     /**
657      * Reads an SQL <code>ROWID</code> value from the stream and returns it as a
658      * <code>RowId</code> object in the Java programming language.
659      *
660      * @return a <code>RowId</code> object representing data of the SQL <code>ROWID</code> value
661      * at the head of the stream; <code>null</code> if the value read is
662      * SQL <code>NULL</code>
663      * @exception SQLException if a database access error occurs
664      * @since 1.6
665      */
666     public RowId readRowId() throws SQLException {
667         return  (RowId)getNextAttribute();
668     }
669 
670 
671 }