001: /*
002: Copyright (C) 2002-2007 MySQL AB
003:
004: This program is free software; you can redistribute it and/or modify
005: it under the terms of version 2 of the GNU General Public License as
006: published by the Free Software Foundation.
007:
008: There are special exceptions to the terms and conditions of the GPL
009: as it is applied to this software. View the full text of the
010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
011: software distribution.
012:
013: This program is distributed in the hope that it will be useful,
014: but WITHOUT ANY WARRANTY; without even the implied warranty of
015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: GNU General Public License for more details.
017:
018: You should have received a copy of the GNU General Public License
019: along with this program; if not, write to the Free Software
020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021:
022: */
023:
024: package com.mysql.jdbc;
025:
026: import java.io.InputStream;
027: import java.io.Reader;
028: import java.io.UnsupportedEncodingException;
029: import java.sql.NClob;
030: import java.sql.RowId;
031: import java.sql.SQLException;
032: import java.sql.SQLXML;
033:
034: import com.mysql.jdbc.Connection;
035: import com.mysql.jdbc.Field;
036: import com.mysql.jdbc.NotUpdatable;
037: import com.mysql.jdbc.ResultSetImpl;
038: import com.mysql.jdbc.RowData;
039: import com.mysql.jdbc.SQLError;
040: import com.mysql.jdbc.Statement;
041: import com.mysql.jdbc.exceptions.NotYetImplementedException;
042:
043: public class JDBC4ResultSet extends ResultSetImpl {
044:
045: public JDBC4ResultSet(long updateCount, long updateID,
046: ConnectionImpl conn, StatementImpl creatorStmt) {
047: super (updateCount, updateID, conn, creatorStmt);
048: }
049:
050: public JDBC4ResultSet(String catalog, Field[] fields,
051: RowData tuples, ConnectionImpl conn,
052: StatementImpl creatorStmt) throws SQLException {
053: super (catalog, fields, tuples, conn, creatorStmt);
054: }
055:
056: /**
057: * JDBC 4.0
058: *
059: * <p>
060: * Get the value of a column in the current row as a java.io.Reader.
061: * </p>
062: *
063: * @param columnIndex
064: * the column to get the value from
065: *
066: * @return the value in the column as a java.io.Reader.
067: *
068: * @throws SQLException
069: * if an error occurs
070: */
071: public Reader getNCharacterStream(int columnIndex)
072: throws SQLException {
073: checkColumnBounds(columnIndex);
074:
075: String fieldEncoding = this .fields[columnIndex - 1]
076: .getCharacterSet();
077: if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
078: throw new SQLException(
079: "Can not call getNCharacterStream() when field's charset isn't UTF-8");
080: }
081: return getCharacterStream(columnIndex);
082: }
083:
084: /**
085: * JDBC 4.0
086: *
087: * <p>
088: * Get the value of a column in the current row as a java.io.Reader.
089: * </p>
090: *
091: * @param columnName
092: * the column name to retrieve the value from
093: *
094: * @return the value as a java.io.Reader
095: *
096: * @throws SQLException
097: * if an error occurs
098: */
099: public Reader getNCharacterStream(String columnName)
100: throws SQLException {
101: return getNCharacterStream(findColumn(columnName));
102: }
103:
104: /**
105: * JDBC 4.0 Get a NCLOB column.
106: *
107: * @param i
108: * the first column is 1, the second is 2, ...
109: *
110: * @return an object representing a NCLOB
111: *
112: * @throws SQLException
113: * if an error occurs
114: */
115: public NClob getNClob(int columnIndex) throws SQLException {
116: checkColumnBounds(columnIndex);
117:
118: String fieldEncoding = this .fields[columnIndex - 1]
119: .getCharacterSet();
120: if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
121: throw new SQLException(
122: "Can not call getNClob() when field's charset isn't UTF-8");
123: }
124: if (!this .isBinaryEncoded) {
125: String asString = getStringForNClob(columnIndex);
126:
127: if (asString == null) {
128: return null;
129: }
130:
131: return new com.mysql.jdbc.JDBC4NClob(asString);
132: }
133:
134: return getNativeNClob(columnIndex);
135: }
136:
137: /**
138: * JDBC 4.0 Get a NCLOB column.
139: *
140: * @param colName
141: * the column name
142: *
143: * @return an object representing a NCLOB
144: *
145: * @throws SQLException
146: * if an error occurs
147: */
148: public NClob getNClob(String columnName) throws SQLException {
149: return getNClob(findColumn(columnName));
150: }
151:
152: /**
153: * JDBC 4.0 Get a NCLOB column.
154: *
155: * @param columnIndex
156: * the first column is 1, the second is 2, ...
157: *
158: * @return an object representing a NCLOB
159: *
160: * @throws SQLException
161: * if an error occurs
162: */
163: protected java.sql.NClob getNativeNClob(int columnIndex)
164: throws SQLException {
165: String stringVal = getStringForNClob(columnIndex);
166:
167: if (stringVal == null) {
168: return null;
169: }
170:
171: return getNClobFromString(stringVal, columnIndex);
172: }
173:
174: private String getStringForNClob(int columnIndex)
175: throws SQLException {
176: String asString = null;
177:
178: String forcedEncoding = "UTF-8";
179:
180: try {
181: byte[] asBytes = null;
182:
183: if (!this .isBinaryEncoded) {
184: asBytes = getBytes(columnIndex);
185: } else {
186: asBytes = getNativeBytes(columnIndex, true);
187: }
188:
189: if (asBytes != null) {
190: asString = new String(asBytes, forcedEncoding);
191: }
192: } catch (UnsupportedEncodingException uee) {
193: throw SQLError.createSQLException(
194: "Unsupported character encoding " + forcedEncoding,
195: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
196: }
197:
198: return asString;
199: }
200:
201: private final java.sql.NClob getNClobFromString(String stringVal,
202: int columnIndex) throws SQLException {
203: return new com.mysql.jdbc.JDBC4NClob(stringVal);
204: }
205:
206: /**
207: * JDBC 4.0
208: *
209: * Get the value of a column in the current row as a Java String
210: *
211: * @param columnIndex
212: * the first column is 1, the second is 2...
213: *
214: * @return the column value, null for SQL NULL
215: *
216: * @exception SQLException
217: * if a database access error occurs
218: */
219: public String getNString(int columnIndex) throws SQLException {
220: checkColumnBounds(columnIndex);
221:
222: String fieldEncoding = this .fields[columnIndex - 1]
223: .getCharacterSet();
224: if (fieldEncoding == null || !fieldEncoding.equals("UTF-8")) {
225: throw new SQLException(
226: "Can not call getNString() when field's charset isn't UTF-8");
227: }
228: return getString(columnIndex);
229: }
230:
231: /**
232: * JDBC 4.0
233: *
234: * The following routines simply convert the columnName into a columnIndex
235: * and then call the appropriate routine above.
236: *
237: * @param columnName
238: * is the SQL name of the column
239: *
240: * @return the column value
241: *
242: * @exception SQLException
243: * if a database access error occurs
244: */
245: public String getNString(String columnName) throws SQLException {
246: return getNString(findColumn(columnName));
247: }
248:
249: /**
250: * JDBC 4.0 Update a column with a character stream value. The updateXXX()
251: * methods are used to update column values in the current row, or the
252: * insert row. The updateXXX() methods do not update the underlying
253: * database, instead the updateRow() or insertRow() methods are called to
254: * update the database.
255: *
256: * @param columnIndex
257: * the first column is 1, the second is 2, ...
258: * @param x
259: * the new column value
260: * @param length
261: * the length of the stream
262: *
263: * @exception SQLException
264: * if a database-access error occurs
265: * @throws NotUpdatable
266: * DOCUMENT ME!
267: */
268: public void updateNCharacterStream(int columnIndex, Reader x,
269: int length) throws SQLException {
270: throw new NotUpdatable();
271: }
272:
273: /**
274: * JDBC 4.0 Update a column with a character stream value. The updateXXX()
275: * methods are used to update column values in the current row, or the
276: * insert row. The updateXXX() methods do not update the underlying
277: * database, instead the updateRow() or insertRow() methods are called to
278: * update the database.
279: *
280: * @param columnName
281: * the name of the column
282: * @param reader
283: * the stream to update the column with
284: * @param length
285: * of the stream
286: *
287: * @throws SQLException
288: * if a database-access error occurs
289: */
290: public void updateNCharacterStream(String columnName,
291: Reader reader, int length) throws SQLException {
292: updateNCharacterStream(findColumn(columnName), reader, length);
293: }
294:
295: /**
296: * @see ResultSet#updateNClob(String, NClob)
297: */
298: public void updateNClob(String columnName, NClob nClob)
299: throws SQLException {
300: updateNClob(findColumn(columnName), nClob);
301: }
302:
303: public void updateRowId(int columnIndex, RowId x)
304: throws SQLException {
305: throw new NotUpdatable();
306: }
307:
308: public void updateRowId(String columnName, RowId x)
309: throws SQLException {
310: updateRowId(findColumn(columnName), x);
311: }
312:
313: public int getHoldability() throws SQLException {
314: throw new NotYetImplementedException();
315: }
316:
317: public RowId getRowId(int columnIndex) throws SQLException {
318: throw new NotYetImplementedException();
319: }
320:
321: public RowId getRowId(String columnLabel) throws SQLException {
322: return getRowId(findColumn(columnLabel));
323: }
324:
325: public SQLXML getSQLXML(int columnIndex) throws SQLException {
326: checkColumnBounds(columnIndex);
327:
328: return new JDBC4MysqlSQLXML(this , columnIndex);
329: }
330:
331: public SQLXML getSQLXML(String columnLabel) throws SQLException {
332: return getSQLXML(findColumn(columnLabel));
333: }
334:
335: public synchronized boolean isClosed() throws SQLException {
336: return this .isClosed;
337: }
338:
339: public void updateAsciiStream(int columnIndex, InputStream x)
340: throws SQLException {
341: throw new NotUpdatable();
342:
343: }
344:
345: public void updateAsciiStream(String columnLabel, InputStream x)
346: throws SQLException {
347: updateAsciiStream(findColumn(columnLabel), x);
348:
349: }
350:
351: public void updateAsciiStream(int columnIndex, InputStream x,
352: long length) throws SQLException {
353: throw new NotUpdatable();
354:
355: }
356:
357: public void updateAsciiStream(String columnLabel, InputStream x,
358: long length) throws SQLException {
359: updateAsciiStream(findColumn(columnLabel), x, length);
360: }
361:
362: public void updateBinaryStream(int columnIndex, InputStream x)
363: throws SQLException {
364: throw new NotUpdatable();
365:
366: }
367:
368: public void updateBinaryStream(String columnLabel, InputStream x)
369: throws SQLException {
370: updateBinaryStream(findColumn(columnLabel), x);
371: }
372:
373: public void updateBinaryStream(int columnIndex, InputStream x,
374: long length) throws SQLException {
375: throw new NotUpdatable();
376:
377: }
378:
379: public void updateBinaryStream(String columnLabel, InputStream x,
380: long length) throws SQLException {
381: updateBinaryStream(findColumn(columnLabel), x, length);
382: }
383:
384: public void updateBlob(int columnIndex, InputStream inputStream)
385: throws SQLException {
386: throw new NotUpdatable();
387: }
388:
389: public void updateBlob(String columnLabel, InputStream inputStream)
390: throws SQLException {
391: updateBlob(findColumn(columnLabel), inputStream);
392: }
393:
394: public void updateBlob(int columnIndex, InputStream inputStream,
395: long length) throws SQLException {
396: throw new NotUpdatable();
397:
398: }
399:
400: public void updateBlob(String columnLabel, InputStream inputStream,
401: long length) throws SQLException {
402: updateBlob(findColumn(columnLabel), inputStream, length);
403: }
404:
405: public void updateCharacterStream(int columnIndex, Reader x)
406: throws SQLException {
407: throw new NotUpdatable();
408:
409: }
410:
411: public void updateCharacterStream(String columnLabel, Reader reader)
412: throws SQLException {
413: updateCharacterStream(findColumn(columnLabel), reader);
414: }
415:
416: public void updateCharacterStream(int columnIndex, Reader x,
417: long length) throws SQLException {
418: throw new NotUpdatable();
419:
420: }
421:
422: public void updateCharacterStream(String columnLabel,
423: Reader reader, long length) throws SQLException {
424: updateCharacterStream(findColumn(columnLabel), reader, length);
425: }
426:
427: public void updateClob(int columnIndex, Reader reader)
428: throws SQLException {
429: throw new NotUpdatable();
430:
431: }
432:
433: public void updateClob(String columnLabel, Reader reader)
434: throws SQLException {
435: updateClob(findColumn(columnLabel), reader);
436: }
437:
438: public void updateClob(int columnIndex, Reader reader, long length)
439: throws SQLException {
440: throw new NotUpdatable();
441:
442: }
443:
444: public void updateClob(String columnLabel, Reader reader,
445: long length) throws SQLException {
446: updateClob(findColumn(columnLabel), reader, length);
447: }
448:
449: public void updateNCharacterStream(int columnIndex, Reader x)
450: throws SQLException {
451: throw new NotUpdatable();
452:
453: }
454:
455: public void updateNCharacterStream(String columnLabel, Reader reader)
456: throws SQLException {
457: updateNCharacterStream(findColumn(columnLabel), reader);
458:
459: }
460:
461: public void updateNCharacterStream(int columnIndex, Reader x,
462: long length) throws SQLException {
463: throw new NotUpdatable();
464:
465: }
466:
467: public void updateNCharacterStream(String columnLabel,
468: Reader reader, long length) throws SQLException {
469: updateNCharacterStream(findColumn(columnLabel), reader, length);
470: }
471:
472: public void updateNClob(int columnIndex, NClob nClob)
473: throws SQLException {
474: throw new NotUpdatable();
475:
476: }
477:
478: public void updateNClob(int columnIndex, Reader reader)
479: throws SQLException {
480: throw new NotUpdatable();
481:
482: }
483:
484: public void updateNClob(String columnLabel, Reader reader)
485: throws SQLException {
486: updateNClob(findColumn(columnLabel), reader);
487:
488: }
489:
490: public void updateNClob(int columnIndex, Reader reader, long length)
491: throws SQLException {
492: throw new NotUpdatable();
493: }
494:
495: public void updateNClob(String columnLabel, Reader reader,
496: long length) throws SQLException {
497: updateNClob(findColumn(columnLabel), reader, length);
498: }
499:
500: public void updateNString(int columnIndex, String nString)
501: throws SQLException {
502: throw new NotUpdatable();
503:
504: }
505:
506: public void updateNString(String columnLabel, String nString)
507: throws SQLException {
508: updateNString(findColumn(columnLabel), nString);
509: }
510:
511: public void updateSQLXML(int columnIndex, SQLXML xmlObject)
512: throws SQLException {
513: throw new NotUpdatable();
514:
515: }
516:
517: public void updateSQLXML(String columnLabel, SQLXML xmlObject)
518: throws SQLException {
519: updateSQLXML(findColumn(columnLabel), xmlObject);
520:
521: }
522:
523: /**
524: * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
525: * for an object that does. Returns false otherwise. If this implements the interface then return true,
526: * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
527: * object. If this does not implement the interface and is not a wrapper, return false.
528: * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
529: * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
530: * returns true then calling <code>unwrap</code> with the same argument should succeed.
531: *
532: * @param interfaces a Class defining an interface.
533: * @return true if this implements the interface or directly or indirectly wraps an object that does.
534: * @throws java.sql.SQLException if an error occurs while determining whether this is a wrapper
535: * for an object with the given interface.
536: * @since 1.6
537: */
538: public boolean isWrapperFor(Class<?> iface) throws SQLException {
539: checkClosed();
540:
541: // This works for classes that aren't actually wrapping
542: // anything
543: return iface.isInstance(this );
544: }
545:
546: /**
547: * Returns an object that implements the given interface to allow access to non-standard methods,
548: * or standard methods not exposed by the proxy.
549: * The result may be either the object found to implement the interface or a proxy for that object.
550: * If the receiver implements the interface then that is the object. If the receiver is a wrapper
551: * and the wrapped object implements the interface then that is the object. Otherwise the object is
552: * the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
553: * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
554: *
555: * @param iface A Class defining an interface that the result must implement.
556: * @return an object that implements the interface. May be a proxy for the actual implementing object.
557: * @throws java.sql.SQLException If no object found that implements the interface
558: * @since 1.6
559: */
560: public <T> T unwrap(java.lang.Class<T> iface)
561: throws java.sql.SQLException {
562: try {
563: // This works for classes that aren't actually wrapping
564: // anything
565: return iface.cast(this );
566: } catch (ClassCastException cce) {
567: throw SQLError.createSQLException("Unable to unwrap to "
568: + iface.toString(),
569: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
570: }
571: }
572: }
|