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