0001: /*
0002:
0003: Derby - Class org.apache.derby.impl.jdbc.EmbedResultSet
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to you under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derby.impl.jdbc;
0023:
0024: import org.apache.derby.iapi.services.sanity.SanityManager;
0025:
0026: import org.apache.derby.iapi.error.StandardException;
0027:
0028: import org.apache.derby.iapi.jdbc.EngineResultSet;
0029: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
0030: import org.apache.derby.iapi.sql.conn.StatementContext;
0031:
0032: import org.apache.derby.iapi.sql.ResultSet;
0033: import org.apache.derby.iapi.sql.ParameterValueSet;
0034: import org.apache.derby.iapi.sql.execute.ExecutionFactory;
0035: import org.apache.derby.iapi.sql.execute.ExecCursorTableReference;
0036: import org.apache.derby.iapi.sql.execute.ExecRow;
0037: import org.apache.derby.iapi.sql.execute.NoPutResultSet;
0038: import org.apache.derby.impl.sql.execute.ScrollInsensitiveResultSet;
0039:
0040: import org.apache.derby.iapi.sql.Activation;
0041: import org.apache.derby.iapi.sql.execute.CursorActivation;
0042:
0043: import org.apache.derby.iapi.types.DataTypeDescriptor;
0044: import org.apache.derby.iapi.types.DataValueDescriptor;
0045: import org.apache.derby.iapi.types.RawToBinaryFormatStream;
0046: import org.apache.derby.iapi.types.ReaderToUTF8Stream;
0047: import org.apache.derby.iapi.types.UserDataValue;
0048: import org.apache.derby.iapi.types.VariableSizeDataValue;
0049: import org.apache.derby.iapi.sql.ResultDescription;
0050: import org.apache.derby.iapi.services.io.StreamStorable;
0051:
0052: import org.apache.derby.iapi.services.io.LimitInputStream;
0053: import org.apache.derby.iapi.services.io.NewByteArrayInputStream;
0054: import org.apache.derby.iapi.services.io.LimitReader;
0055: import org.apache.derby.iapi.error.ExceptionSeverity;
0056: import org.apache.derby.iapi.reference.JDBC20Translation;
0057: import org.apache.derby.iapi.reference.JDBC30Translation;
0058: import org.apache.derby.iapi.reference.SQLState;
0059: import org.apache.derby.iapi.util.StringUtil;
0060: import org.apache.derby.iapi.util.ReuseFactory;
0061:
0062: /* can't import these due to name overlap:
0063: import java.sql.ResultSet;
0064: */
0065: import java.sql.Blob;
0066: import java.sql.Clob;
0067: import java.sql.Statement;
0068: import java.sql.SQLException;
0069: import java.sql.SQLWarning;
0070: import java.sql.ResultSetMetaData;
0071: import java.sql.Date;
0072: import java.sql.Time;
0073: import java.sql.Timestamp;
0074: import java.sql.Types;
0075:
0076: import java.io.Reader;
0077: import java.io.InputStream;
0078: import java.io.IOException;
0079: import java.net.URL;
0080:
0081: import java.util.Map;
0082: import java.util.HashMap;
0083: import java.util.Arrays;
0084: import java.util.Calendar;
0085:
0086: /**
0087: * A EmbedResultSet for results from the EmbedStatement family.
0088: <P><B>Supports</B>
0089: <UL>
0090: <LI> JSR 169
0091: </UL>
0092: * @author ames
0093: */
0094:
0095: public abstract class EmbedResultSet extends ConnectionChild implements
0096: EngineResultSet, Comparable {
0097:
0098: // cursor movement
0099: protected static final int FIRST = 1;
0100: protected static final int NEXT = 2;
0101: protected static final int LAST = 3;
0102: protected static final int PREVIOUS = 4;
0103: protected static final int BEFOREFIRST = 5;
0104: protected static final int AFTERLAST = 6;
0105: protected static final int ABSOLUTE = 7;
0106: protected static final int RELATIVE = 8;
0107:
0108: /**
0109: * The currentRow contains the data of the current row of the resultset.
0110: * If the containing row array is null, the cursor is not postioned on a
0111: * row
0112: */
0113: private final ExecRow currentRow;
0114: protected boolean wasNull;
0115:
0116: /**
0117: * Set if this ResultSet is definitely closed.
0118: * If the connection has been closed, or the database
0119: * or system shutdown but the ResultSet has not been
0120: * closed explictly then this may be false. Once
0121: * this object detects the connection is closed
0122: * isClosed will be set to true.
0123: */
0124: boolean isClosed;
0125:
0126: private boolean isOnInsertRow;
0127: private Object currentStream;
0128:
0129: // immutable state
0130: private ResultSet theResults;
0131: private boolean forMetaData;
0132: private ResultSetMetaData rMetaData;
0133: private SQLWarning topWarning;
0134:
0135: /**
0136: This activation is set by EmbedStatement
0137: for a single execution Activation. Ie.
0138: a ResultSet from a Statement.executeQuery().
0139: In this case the closing of this ResultSet will close
0140: the activation or the finalization of the ResultSet
0141: without it being closed will mark the Activation as unused.
0142: c.f. EmbedPreparedStatement.finalize().
0143: */
0144: Activation singleUseActivation;
0145:
0146: // Order of creation
0147: final int order;
0148:
0149: private final ResultDescription resultDescription;
0150:
0151: /**
0152: * A map which maps a column name to a column number.
0153: * Entries only added when accessing columns with the name.
0154: */
0155: private Map columnNameMap;
0156:
0157: // max rows limit for this result set
0158: private int maxRows;
0159: // The Maximum field size limt set for this result set
0160: private final int maxFieldSize;
0161:
0162: /*
0163: * Incase of forward only cursors we limit the number of rows
0164: * returned if the maxRows is set. The following varible is used
0165: * to keep the count of number of rows returned to the user.
0166: */
0167: private int NumberofFetchedRows;
0168:
0169: /**
0170: * The statement object that originally created us.
0171: we hang on to the statement to prevent GC from
0172: closing it under us
0173: */
0174: private final EmbedStatement stmt;
0175:
0176: /**
0177: * The statement that currently owns this ResultSet.
0178: * Statements created in procedures are passed off
0179: * to the Statement that called the procedure.
0180: * This is to avoid the ResultSet being closed
0181: * due to the Statement within the procedure
0182: * or the nested Connection being closed.
0183: */
0184: private EmbedStatement owningStmt;
0185:
0186: /**
0187: * Statement object the application used to
0188: * create this ResultSet.
0189: */
0190: private Statement applicationStmt;
0191:
0192: private long timeoutMillis;
0193:
0194: private final boolean isAtomic;
0195:
0196: private final int concurrencyOfThisResultSet;
0197:
0198: /* updateRow is used to keep the values which are updated with updateXXX()
0199: * calls. It is used by both insertRow() and updateRow().
0200: * It is initialized to null if the resultset is not updatable.
0201: */
0202: private final ExecRow updateRow;
0203:
0204: /* These are the columns which have been updated so far.
0205: */
0206: private boolean[] columnGotUpdated;
0207: private boolean currentRowHasBeenUpdated; //Gets set to true after first updateXXX on a row. Gets reset to false when the cursor moves off the row
0208:
0209: private int fetchDirection;
0210: private int fetchSize;
0211:
0212: /**
0213: * Indicates which columns have already been fetched
0214: * as a stream for a row. Created on-demand by a getXXXStream call.
0215: */
0216: private boolean[] streamUsedFlags;
0217:
0218: /**
0219: * This class provides the glue between the Cloudscape
0220: * resultset and the JDBC resultset, mapping calls-to-calls.
0221: */
0222: public EmbedResultSet(EmbedConnection conn,
0223: ResultSet resultsToWrap, boolean forMetaData,
0224: EmbedStatement stmt, boolean isAtomic) throws SQLException {
0225:
0226: super (conn);
0227:
0228: if (SanityManager.DEBUG)
0229: SanityManager.ASSERT(resultsToWrap != null);
0230: theResults = resultsToWrap;
0231:
0232: // ResultSet's for metadata are single use, they are created
0233: // with a PreparedStatement internally, but that statement is
0234: // never returned to the application.
0235: if (this .forMetaData = forMetaData)
0236: singleUseActivation = resultsToWrap.getActivation();
0237: this .applicationStmt = this .stmt = owningStmt = stmt;
0238:
0239: this .timeoutMillis = stmt == null ? 0L : (long) stmt
0240: .getQueryTimeout() * 1000L;
0241:
0242: this .isAtomic = isAtomic;
0243:
0244: //If the Statement object has CONCUR_READ_ONLY set on it then the concurrency on the ResultSet object will be CONCUR_READ_ONLY also.
0245: //But, if the Statement object has CONCUR_UPDATABLE set on it, then the concurrency on the ResultSet object can be
0246: //CONCUR_READ_ONLY or CONCUR_UPDATABLE depending on whether the underlying language resultset is updateable or not.
0247: //If the underlying language resultset is not updateable, then the concurrency of the ResultSet object will be CONCUR_READ_ONLY
0248: //and a warning will be issued on the ResultSet object.
0249: if (stmt == null)
0250: concurrencyOfThisResultSet = JDBC20Translation.CONCUR_READ_ONLY;
0251: else if (stmt.getResultSetConcurrency() == JDBC20Translation.CONCUR_READ_ONLY)
0252: concurrencyOfThisResultSet = JDBC20Translation.CONCUR_READ_ONLY;
0253: else {
0254: if (!isForUpdate()) { //language resultset not updatable
0255: concurrencyOfThisResultSet = JDBC20Translation.CONCUR_READ_ONLY;
0256: SQLWarning w = StandardException
0257: .newWarning(SQLState.QUERY_NOT_QUALIFIED_FOR_UPDATABLE_RESULTSET);
0258: addWarning(w);
0259: } else
0260: concurrencyOfThisResultSet = JDBC20Translation.CONCUR_UPDATABLE;
0261: }
0262:
0263: // Fill in the column types
0264: resultDescription = theResults.getResultDescription();
0265: final ExecutionFactory factory = conn.getLanguageConnection()
0266: .getLanguageConnectionFactory().getExecutionFactory();
0267: final int columnCount = getMetaData().getColumnCount();
0268: this .currentRow = factory.getValueRow(columnCount);
0269: this .columnNameMap = null;
0270: currentRow.setRowArray(null);
0271:
0272: // Only incur the cost of allocating and maintaining
0273: // updated column information if the columns can be updated.
0274: if (concurrencyOfThisResultSet == JDBC20Translation.CONCUR_UPDATABLE) {
0275: //initialize arrays related to updateRow implementation
0276: columnGotUpdated = new boolean[columnCount];
0277: updateRow = factory.getValueRow(columnCount);
0278: for (int i = 1; i <= columnCount; i++) {
0279: updateRow.setColumn(i, resultDescription
0280: .getColumnDescriptor(i).getType().getNull());
0281: }
0282: initializeUpdateRowModifiers();
0283: } else {
0284: updateRow = null;
0285: }
0286:
0287: // assign the max rows and maxfiled size limit for this result set
0288: if (stmt != null) {
0289: // At connectivity level we handle only for forward only cursor
0290: if (stmt.resultSetType == JDBC20Translation.TYPE_FORWARD_ONLY)
0291: maxRows = stmt.maxRows;
0292:
0293: maxFieldSize = stmt.MaxFieldSize;
0294: } else
0295: maxFieldSize = 0;
0296:
0297: order = conn.getResultSetOrderId();
0298: }
0299:
0300: /**
0301: JDBC states that a ResultSet is closed when garbage collected.
0302: We simply mark the activation as unused. Some later use
0303: of the connection will clean everything up.
0304:
0305: @exception Throwable Allows any exception to be thrown during finalize
0306: */
0307: protected void finalize() throws Throwable {
0308: super .finalize();
0309:
0310: if (singleUseActivation != null) {
0311: singleUseActivation.markUnused();
0312: }
0313: }
0314:
0315: private void checkNotOnInsertRow() throws SQLException {
0316: if (isOnInsertRow) {
0317: throw newSQLException(SQLState.NO_CURRENT_ROW);
0318: }
0319: }
0320:
0321: // checkOnRow protects us from making requests of
0322: // resultSet that would fail with NullPointerExceptions
0323: // or milder problems due to not having a row.
0324: protected final void checkOnRow() throws SQLException {
0325: if (currentRow.getRowArray() == null) {
0326: throw newSQLException(SQLState.NO_CURRENT_ROW);
0327: }
0328: }
0329:
0330: /**
0331: * Initializes the currentRowHasBeenUpdated and columnGotUpdated fields
0332: */
0333: private void initializeUpdateRowModifiers() {
0334: currentRowHasBeenUpdated = false;
0335: Arrays.fill(columnGotUpdated, false);
0336: }
0337:
0338: /**
0339: Check the column is in range *and* return the JDBC type of the column.
0340:
0341: @exception SQLException ResultSet is not on a row or columnIndex is out of range.
0342: */
0343: final int getColumnType(int columnIndex) throws SQLException {
0344: if (!isOnInsertRow)
0345: checkOnRow(); // first make sure there's a row
0346:
0347: if (columnIndex < 1
0348: || columnIndex > resultDescription.getColumnCount())
0349: throw newSQLException(SQLState.COLUMN_NOT_FOUND,
0350: new Integer(columnIndex));
0351:
0352: return resultDescription.getColumnDescriptor(columnIndex)
0353: .getType().getJDBCTypeId();
0354: }
0355:
0356: /*
0357: * java.sql.ResultSet interface
0358: */
0359: /**
0360: * A ResultSet is initially positioned before its first row; the
0361: * first call to next makes the first row the current row; the
0362: * second call makes the second row the current row, etc.
0363: *
0364: * <P>If an input stream from the previous row is open, it is
0365: * implicitly closed. The ResultSet's warning chain is cleared
0366: * when a new row is read.
0367: *
0368: * @return true if the new current row is valid; false if there
0369: * are no more rows
0370: * @exception SQLException thrown on failure.
0371: */
0372: public boolean next() throws SQLException {
0373: // we seem to have some trigger paths which don't have
0374: // statement initialized, may not need this check in those cases
0375: if (maxRows != 0) {
0376: NumberofFetchedRows++;
0377: // check whether we hit the maxRows limit
0378: if (NumberofFetchedRows > maxRows) {
0379: //we return false for the next call when maxRows is hit
0380: closeCurrentStream();
0381: return false;
0382: }
0383: }
0384: return movePosition(NEXT, 0, "next");
0385: }
0386:
0387: protected boolean movePosition(int position, String positionText)
0388: throws SQLException {
0389: return movePosition(position, 0, positionText);
0390: }
0391:
0392: protected boolean movePosition(int position, int row,
0393: String positionText) throws SQLException {
0394: closeCurrentStream(); // closing currentStream does not depend on the
0395: // underlying connection. Do this outside of
0396: // the connection synchronization.
0397:
0398: checkExecIfClosed(positionText); // checking result set closure does not depend
0399: // on the underlying connection. Do this
0400: // outside of the connection synchronization.
0401:
0402: if (isOnInsertRow) {
0403: moveToCurrentRow();
0404: }
0405:
0406: synchronized (getConnectionSynchronization()) {
0407:
0408: setupContextStack();
0409: try {
0410: LanguageConnectionContext lcc = getEmbedConnection()
0411: .getLanguageConnection();
0412: final ExecRow newRow;
0413: try {
0414:
0415: /* Push and pop a StatementContext around a next call
0416: * so that the ResultSet will get correctly closed down
0417: * on an error.
0418: * (Cache the LanguageConnectionContext)
0419: */
0420: StatementContext statementContext = lcc
0421: .pushStatementContext(
0422: isAtomic,
0423: concurrencyOfThisResultSet == JDBC20Translation.CONCUR_READ_ONLY,
0424: getSQLText(),
0425: getParameterValueSet(), false,
0426: timeoutMillis);
0427:
0428: switch (position) {
0429: case BEFOREFIRST:
0430: newRow = theResults.setBeforeFirstRow();
0431: break;
0432:
0433: case FIRST:
0434: newRow = theResults.getFirstRow();
0435: break;
0436:
0437: case NEXT:
0438: newRow = theResults.getNextRow();
0439: break;
0440:
0441: case LAST:
0442: newRow = theResults.getLastRow();
0443: break;
0444:
0445: case AFTERLAST:
0446: newRow = theResults.setAfterLastRow();
0447: break;
0448:
0449: case PREVIOUS:
0450: newRow = theResults.getPreviousRow();
0451: break;
0452:
0453: case ABSOLUTE:
0454: newRow = theResults.getAbsoluteRow(row);
0455: break;
0456:
0457: case RELATIVE:
0458: newRow = theResults.getRelativeRow(row);
0459: break;
0460:
0461: default:
0462: newRow = null;
0463: if (SanityManager.DEBUG) {
0464: SanityManager
0465: .THROWASSERT("Unexpected value for position - "
0466: + position);
0467: }
0468: }
0469:
0470: lcc.popStatementContext(statementContext, null);
0471:
0472: } catch (Throwable t) {
0473: /*
0474: * Need to close the result set here because the error might
0475: * cause us to lose the current connection if this is an XA
0476: * connection and we won't be able to do the close later
0477: */
0478: throw closeOnTransactionError(t);
0479: }
0480:
0481: SQLWarning w = theResults.getWarnings();
0482: if (w != null) {
0483: if (topWarning == null)
0484: topWarning = w;
0485: else
0486: topWarning.setNextWarning(w);
0487: }
0488:
0489: boolean onRow = (newRow != null);
0490: if (onRow) {
0491: currentRow.setRowArray(newRow.getRowArray());
0492: } else {
0493: currentRow.setRowArray(null);
0494: }
0495:
0496: //if (onRow && !(currentRow instanceof org.apache.derby.impl.sql.execute.ValueRow))
0497: // System.out.println(currentRow.getClass());
0498:
0499: // The ResultSet may implicitly close when when the ResultSet type
0500: // is TYPE_FORWARD_ONLY and the next method of ResultSet returns
0501: // false. This will cause a commit if autocommit = true.
0502: if (!onRow && (position == NEXT)) {
0503:
0504: // In case of resultset for MetaData, we will only commit
0505: // if we are the only statement currently opened for this
0506: // connection; otherwise we don't want to affect other
0507: // resultSet's by committing the MetaData one.
0508: // There is no internal xact (xact isolation) for MetaData type
0509: // of resultSet; therefore committing (to release locks) would end
0510: // up committing all the other resultSet for this connection.
0511: //
0512: // We do synchronize on the connection, therefore Activation count
0513: // should be valid and protected.
0514: //
0515: //LanguageConnectionContext lcc = getEmbedConnection().getLanguageConnection();
0516: if (forMetaData && (lcc.getActivationCount() > 1)) {
0517: // we do not want to commit here as there seems to be other
0518: // statements/resultSets currently opened for this connection.
0519: } else if (owningStmt != null
0520: && owningStmt.getResultSetType() == TYPE_FORWARD_ONLY) {
0521: // allow the satement to commit if required.
0522: owningStmt.resultSetClosing(this );
0523: }
0524: }
0525:
0526: // Clear the indication of which columns were fetched as streams.
0527: if (streamUsedFlags != null)
0528: Arrays.fill(streamUsedFlags, false);
0529: if (columnGotUpdated != null
0530: && currentRowHasBeenUpdated) {
0531: initializeUpdateRowModifiers();
0532: }
0533:
0534: return onRow;
0535: } finally {
0536: restoreContextStack();
0537: }
0538: }
0539:
0540: }
0541:
0542: /**
0543: * In some cases, it is desirable to immediately release a
0544: * ResultSet's database and JDBC resources instead of waiting for
0545: * this to happen when it is automatically closed; the close
0546: * method provides this immediate release.
0547: *
0548: * <P><B>Note:</B> A ResultSet is automatically closed by the
0549: * Statement that generated it when that Statement is closed,
0550: * re-executed, or is used to retrieve the next result from a
0551: * sequence of multiple results. A ResultSet is also automatically
0552: * closed when it is garbage collected.
0553: * @exception SQLException thrown on failure.
0554: */
0555: public void close() throws SQLException {
0556:
0557: /* if this result is already closed, don't try to close again
0558: * we may have closed it earlier because of an error and trying
0559: * to close again will cause a different problem if the connection
0560: * has been closed as in XA error handling
0561: */
0562: if (isClosed)
0563: return;
0564:
0565: closeCurrentStream(); // closing currentStream does not depend on the
0566: // underlying connection. Do this outside of
0567: // the connection synchronization.
0568: // Would like to throw an exception if already closed, but
0569: // some code assumes you can close a ResultSet more than once.
0570: // checkIfClosed("close");
0571:
0572: // synchronize out here so the close and the autocommit are
0573: // both in the same sync block.
0574: synchronized (getConnectionSynchronization()) {
0575:
0576: try {
0577: setupContextStack(); // make sure there's context
0578: } catch (SQLException se) {
0579: // we may get an exception here if this is part of an XA transaction
0580: // and the transaction has been committed
0581: // just give up and return
0582: return;
0583: }
0584:
0585: try {
0586: try {
0587: theResults.finish(); // release the result set, don't just close it
0588:
0589: if (this .singleUseActivation != null) {
0590: this .singleUseActivation.close();
0591: this .singleUseActivation = null;
0592: }
0593:
0594: } catch (Throwable t) {
0595: throw handleException(t);
0596: }
0597:
0598: // In case of resultset for MetaData, we will only commit
0599: // if we are the only statement currently opened for this
0600: // connection; otherwise we don't want to affect other
0601: // resultSet's by committing the MetaData one.
0602: // There is no internal xact (xact isolation) for MetaData type
0603: // of resultSet; therefore committing (to release locks) would end
0604: // up committing all the other resultSet for this connection.
0605: //
0606: // We do synchronize on the connection, therefore Activation count
0607: // should be valid and protected.
0608: //
0609: if (forMetaData) {
0610:
0611: LanguageConnectionContext lcc = getEmbedConnection()
0612: .getLanguageConnection();
0613: if (lcc.getActivationCount() > 1) {
0614: // we do not want to commit here as there seems to be other
0615: // statements/resultSets currently opened for this connection.
0616: } else if (owningStmt != null)
0617: // allow the satement to commit if required.
0618: owningStmt.resultSetClosing(this );
0619:
0620: } else if (owningStmt != null) {
0621: // allow the satement to commit if required.
0622: owningStmt.resultSetClosing(this );
0623: }
0624:
0625: } finally {
0626: isClosed = true;
0627: restoreContextStack();
0628: }
0629:
0630: // the idea is to release resources, so:
0631: currentRow.setRowArray(null);
0632: rMetaData = null; // let it go, we can make a new one
0633:
0634: // we hang on to theResults and messenger
0635: // in case more calls come in on this resultSet
0636: }
0637:
0638: }
0639:
0640: /**
0641: * A column may have the value of SQL NULL; wasNull reports whether
0642: * the last column read had this special value.
0643: * Note that you must first call getXXX on a column to try to read
0644: * its value and then call wasNull() to find if the value was
0645: * the SQL NULL.
0646: *
0647: * <p> we take the least exception approach and simply return false
0648: * if no column has been read yet.
0649: *
0650: * @return true if last column read was SQL NULL
0651: *
0652: * @exception SQLException Thrown if this ResultSet is closed
0653: */
0654: public final boolean wasNull() throws SQLException {
0655: checkIfClosed("wasNull");
0656: return wasNull;
0657: }
0658:
0659: //======================================================================
0660: // Methods for accessing results by column index
0661: //======================================================================
0662:
0663: /**
0664: * Get the value of a column in the current row as a Java String.
0665: *
0666: * @param columnIndex the first column is 1, the second is 2, ...
0667: * @return the column value; if the value is SQL NULL, the result is null
0668: * @exception SQLException thrown on failure.
0669: */
0670: public final String getString(int columnIndex) throws SQLException {
0671: checkIfClosed("getString");
0672:
0673: try {
0674:
0675: DataValueDescriptor dvd = getColumn(columnIndex);
0676:
0677: if (wasNull = dvd.isNull())
0678: return null;
0679:
0680: String value = dvd.getString();
0681:
0682: // check for the max field size limit
0683: if (maxFieldSize > 0
0684: && isMaxFieldSizeType(getColumnType(columnIndex))) {
0685: if (value.length() > maxFieldSize) {
0686: value = value.substring(0, maxFieldSize);
0687: }
0688: }
0689:
0690: return value;
0691:
0692: } catch (Throwable t) {
0693: throw noStateChangeException(t);
0694: }
0695: }
0696:
0697: /**
0698: * Get the value of a column in the current row as a Java boolean.
0699: *
0700: * @param columnIndex the first column is 1, the second is 2, ...
0701: * @return the column value; if the value is SQL NULL, the result is false
0702: * @exception SQLException thrown on failure.
0703: */
0704: public final boolean getBoolean(int columnIndex)
0705: throws SQLException {
0706: checkIfClosed("getBoolean");
0707:
0708: try {
0709:
0710: DataValueDescriptor dvd = getColumn(columnIndex);
0711:
0712: if (wasNull = dvd.isNull())
0713: return false;
0714:
0715: return dvd.getBoolean();
0716:
0717: } catch (StandardException t) {
0718: throw noStateChangeException(t);
0719: }
0720: }
0721:
0722: /**
0723: * Get the value of a column in the current row as a Java byte.
0724: *
0725: * @param columnIndex the first column is 1, the second is 2, ...
0726: * @return the column value; if the value is SQL NULL, the result is 0
0727: * @exception SQLException thrown on failure.
0728: */
0729: public final byte getByte(int columnIndex) throws SQLException {
0730: checkIfClosed("getByte");
0731: try {
0732:
0733: DataValueDescriptor dvd = getColumn(columnIndex);
0734:
0735: if (wasNull = dvd.isNull())
0736: return 0;
0737:
0738: return dvd.getByte();
0739:
0740: } catch (StandardException t) {
0741: throw noStateChangeException(t);
0742: }
0743: }
0744:
0745: /**
0746: * Get the value of a column in the current row as a Java short.
0747: *
0748: * @param columnIndex the first column is 1, the second is 2, ...
0749: * @return the column value; if the value is SQL NULL, the result is 0
0750: * @exception SQLException thrown on failure.
0751: */
0752: public final short getShort(int columnIndex) throws SQLException {
0753: checkIfClosed("getShort");
0754:
0755: try {
0756:
0757: DataValueDescriptor dvd = getColumn(columnIndex);
0758:
0759: if (wasNull = dvd.isNull())
0760: return 0;
0761:
0762: return dvd.getShort();
0763:
0764: } catch (StandardException t) {
0765: throw noStateChangeException(t);
0766: }
0767: }
0768:
0769: /**
0770: * Get the value of a column in the current row as a Java int.
0771: *
0772: * @param columnIndex the first column is 1, the second is 2, ...
0773: * @return the column value; if the value is SQL NULL, the result is 0
0774: * @exception SQLException thrown on failure.
0775: */
0776: public final int getInt(int columnIndex) throws SQLException {
0777: checkIfClosed("getInt");
0778: try {
0779:
0780: DataValueDescriptor dvd = getColumn(columnIndex);
0781:
0782: if (wasNull = dvd.isNull())
0783: return 0;
0784:
0785: return dvd.getInt();
0786:
0787: } catch (StandardException t) {
0788: throw noStateChangeException(t);
0789: }
0790: }
0791:
0792: /**
0793: * Get the value of a column in the current row as a Java long.
0794: *
0795: * @param columnIndex the first column is 1, the second is 2, ...
0796: * @return the column value; if the value is SQL NULL, the result is 0
0797: * @exception SQLException thrown on failure.
0798: */
0799: public final long getLong(int columnIndex) throws SQLException {
0800: checkIfClosed("getLong");
0801: try {
0802:
0803: DataValueDescriptor dvd = getColumn(columnIndex);
0804:
0805: if (wasNull = dvd.isNull())
0806: return 0;
0807:
0808: return dvd.getLong();
0809:
0810: } catch (StandardException t) {
0811: throw noStateChangeException(t);
0812: }
0813: }
0814:
0815: /**
0816: * Get the value of a column in the current row as a Java float.
0817: *
0818: * @param columnIndex the first column is 1, the second is 2, ...
0819: * @return the column value; if the value is SQL NULL, the result is 0
0820: * @exception SQLException thrown on failure.
0821: */
0822: public final float getFloat(int columnIndex) throws SQLException {
0823: checkIfClosed("getFloat");
0824: try {
0825:
0826: DataValueDescriptor dvd = getColumn(columnIndex);
0827:
0828: if (wasNull = dvd.isNull())
0829: return 0.0F;
0830:
0831: return dvd.getFloat();
0832:
0833: } catch (StandardException t) {
0834: throw noStateChangeException(t);
0835: }
0836: }
0837:
0838: /**
0839: * Get the value of a column in the current row as a Java double.
0840: *
0841: * @param columnIndex the first column is 1, the second is 2, ...
0842: * @return the column value; if the value is SQL NULL, the result is 0
0843: * @exception SQLException thrown on failure.
0844: */
0845: public final double getDouble(int columnIndex) throws SQLException {
0846: checkIfClosed("getDouble");
0847: try {
0848:
0849: DataValueDescriptor dvd = getColumn(columnIndex);
0850:
0851: if (wasNull = dvd.isNull())
0852: return 0.0;
0853:
0854: return dvd.getDouble();
0855:
0856: } catch (StandardException t) {
0857: throw noStateChangeException(t);
0858: }
0859: }
0860:
0861: /**
0862: * Get the value of a column in the current row as a Java byte array.
0863: * The bytes represent the raw values returned by the driver.
0864: *
0865: * @param columnIndex the first column is 1, the second is 2, ...
0866: * @return the column value; if the value is SQL NULL, the result is null
0867: * @exception SQLException thrown on failure.
0868: */
0869: public final byte[] getBytes(int columnIndex) throws SQLException {
0870: checkIfClosed("getBytes");
0871: try {
0872:
0873: DataValueDescriptor dvd = getColumn(columnIndex);
0874:
0875: if (wasNull = dvd.isNull())
0876: return null;
0877:
0878: byte[] value = dvd.getBytes();
0879:
0880: // check for the max field size limit
0881: if (maxFieldSize > 0
0882: && isMaxFieldSizeType(getColumnType(columnIndex))) {
0883: if (value.length > maxFieldSize) {
0884: byte[] limited_value = new byte[maxFieldSize];
0885: System.arraycopy(value, 0, limited_value, 0,
0886: maxFieldSize);
0887: value = limited_value;
0888: }
0889: }
0890:
0891: return value;
0892:
0893: } catch (StandardException t) {
0894: throw noStateChangeException(t);
0895: }
0896: }
0897:
0898: /**
0899: * Get the value of a column in the current row as a java.sql.Date object.
0900: *
0901: * @param columnIndex the first column is 1, the second is 2, ...
0902: * @return the column value; if the value is SQL NULL, the result is null
0903: * @exception SQLException thrown on failure.
0904: */
0905: public final Date getDate(int columnIndex) throws SQLException {
0906: return getDate(columnIndex, (Calendar) null);
0907: }
0908:
0909: /**
0910: * Get the value of a column in the current row as a java.sql.Time object.
0911: *
0912: * @param columnIndex the first column is 1, the second is 2, ...
0913: * @return the column value; if the value is SQL NULL, the result is null
0914: * @exception SQLException thrown on failure.
0915: */
0916: public final Time getTime(int columnIndex) throws SQLException {
0917: return getTime(columnIndex, (Calendar) null);
0918: }
0919:
0920: /**
0921: * Get the value of a column in the current row as a java.sql.Timestamp object.
0922: *
0923: * @param columnIndex the first column is 1, the second is 2, ...
0924: * @return the column value; if the value is SQL NULL, the result is null
0925: * @exception SQLException thrown on failure.
0926: */
0927: public final Timestamp getTimestamp(int columnIndex)
0928: throws SQLException {
0929: return getTimestamp(columnIndex, (Calendar) null);
0930: }
0931:
0932: /**
0933: * JDBC 2.0
0934: *
0935: * Get the value of a column in the current row as a java.sql.Date
0936: * object. Use the calendar to construct an appropriate millisecond
0937: * value for the Date, if the underlying database doesn't store
0938: * timezone information.
0939: *
0940: * @param columnIndex the first column is 1, the second is 2, ...
0941: * @param cal the calendar to use in constructing the date
0942: * @return the column value; if the value is SQL NULL, the result is null
0943: * @exception SQLException if a database-access error occurs.
0944: */
0945: public java.sql.Date getDate(int columnIndex, Calendar cal)
0946: throws SQLException {
0947: checkIfClosed("getDate");
0948: try {
0949:
0950: DataValueDescriptor dvd = getColumn(columnIndex);
0951:
0952: if (wasNull = dvd.isNull())
0953: return null;
0954:
0955: if (cal == null)
0956: cal = getCal();
0957:
0958: return dvd.getDate(cal);
0959:
0960: } catch (StandardException t) {
0961: throw noStateChangeException(t);
0962: }
0963: }
0964:
0965: /**
0966: * JDBC 2.0
0967: *
0968: * Get the value of a column in the current row as a java.sql.Date
0969: * object. Use the calendar to construct an appropriate millisecond
0970: * value for the Date, if the underlying database doesn't store
0971: * timezone information.
0972: *
0973: * @param columnName is the SQL name of the column
0974: * @param cal the calendar to use in constructing the date
0975: * @return the column value; if the value is SQL NULL, the result is null
0976: * @exception SQLException if a database-access error occurs.
0977: */
0978: public java.sql.Date getDate(String columnName, Calendar cal)
0979: throws SQLException {
0980: checkIfClosed("getDate");
0981: return getDate(findColumnName(columnName), cal);
0982: }
0983:
0984: /**
0985: * JDBC 2.0
0986: *
0987: * Get the value of a column in the current row as a java.sql.Time
0988: * object. Use the calendar to construct an appropriate millisecond
0989: * value for the Time, if the underlying database doesn't store
0990: * timezone information.
0991: *
0992: * @param columnIndex the first column is 1, the second is 2, ...
0993: * @param cal the calendar to use in constructing the time
0994: * @return the column value; if the value is SQL NULL, the result is null
0995: * @exception SQLException if a database-access error occurs.
0996: */
0997: public java.sql.Time getTime(int columnIndex, Calendar cal)
0998: throws SQLException {
0999: checkIfClosed("getTime");
1000: try {
1001:
1002: DataValueDescriptor dvd = getColumn(columnIndex);
1003:
1004: if (wasNull = dvd.isNull())
1005: return null;
1006:
1007: if (cal == null)
1008: cal = getCal();
1009: return dvd.getTime(cal);
1010:
1011: } catch (StandardException t) {
1012: throw noStateChangeException(t);
1013: }
1014: }
1015:
1016: /**
1017: * JDBC 2.0
1018: *
1019: * Get the value of a column in the current row as a java.sql.Time
1020: * object. Use the calendar to construct an appropriate millisecond
1021: * value for the Time, if the underlying database doesn't store
1022: * timezone information.
1023: *
1024: * @param columnName is the SQL name of the column
1025: * @param cal the calendar to use in constructing the time
1026: * @return the column value; if the value is SQL NULL, the result is null
1027: * @exception SQLException if a database-access error occurs.
1028: */
1029: public java.sql.Time getTime(String columnName, Calendar cal)
1030: throws SQLException {
1031: checkIfClosed("getTime");
1032: return getTime(findColumnName(columnName), cal);
1033: }
1034:
1035: /**
1036: * JDBC 2.0
1037: *
1038: * Get the value of a column in the current row as a java.sql.Timestamp
1039: * object. Use the calendar to construct an appropriate millisecond
1040: * value for the Timestamp, if the underlying database doesn't store
1041: * timezone information.
1042: *
1043: * @param columnName is the SQL name of the column
1044: * @param cal the calendar to use in constructing the timestamp
1045: * @return the column value; if the value is SQL NULL, the result is null
1046: * @exception SQLException if a database-access error occurs.
1047: */
1048: public java.sql.Timestamp getTimestamp(String columnName,
1049: Calendar cal) throws SQLException {
1050: checkIfClosed("getTimestamp");
1051: return getTimestamp(findColumnName(columnName), cal);
1052: }
1053:
1054: /**
1055: * JDBC 2.0
1056: *
1057: * Get the value of a column in the current row as a java.sql.Timestamp
1058: * object. Use the calendar to construct an appropriate millisecond
1059: * value for the Timestamp, if the underlying database doesn't store
1060: * timezone information.
1061: *
1062: * @param columnIndex the first column is 1, the second is 2, ...
1063: * @param cal the calendar to use in constructing the timestamp
1064: * @return the column value; if the value is SQL NULL, the result is null
1065: * @exception SQLException if a database-access error occurs.
1066: */
1067: public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
1068: throws SQLException {
1069: checkIfClosed("getTimestamp");
1070: try {
1071:
1072: DataValueDescriptor dvd = getColumn(columnIndex);
1073:
1074: if (wasNull = dvd.isNull())
1075: return null;
1076:
1077: if (cal == null)
1078: cal = getCal();
1079: return dvd.getTimestamp(cal);
1080:
1081: } catch (StandardException t) {
1082: throw noStateChangeException(t);
1083: }
1084: }
1085:
1086: /**
1087: * JDBC 2.0
1088: *
1089: * <p>Get the value of a column in the current row as a java.io.Reader.
1090: *
1091: * @exception SQLException database error.
1092: */
1093: public final java.io.Reader getCharacterStream(int columnIndex)
1094: throws SQLException {
1095: checkIfClosed("getCharacterStream");
1096: int lmfs;
1097: int colType = getColumnType(columnIndex);
1098: switch (colType) {
1099: case Types.CHAR:
1100: case Types.VARCHAR:
1101: case Types.LONGVARCHAR:
1102: lmfs = maxFieldSize;
1103: break;
1104: case Types.CLOB: // Embedded and JCC extension - CLOB is not subject to max field size.
1105: lmfs = 0;
1106: break;
1107:
1108: // JDBC says to support these, but no defintion exists for the output.
1109: // match JCC which treats the bytes as a UTF16-BE stream
1110: case Types.BINARY:
1111: case Types.VARBINARY:
1112: case Types.LONGVARBINARY:
1113: case Types.BLOB:
1114: try {
1115: java.io.InputStream is = getBinaryStream(columnIndex);
1116: if (is == null)
1117: return null;
1118: java.io.Reader r = new java.io.InputStreamReader(is,
1119: "UTF-16BE");
1120: currentStream = r;
1121: return r;
1122: } catch (java.io.UnsupportedEncodingException uee) {
1123: throw new SQLException(uee.getMessage());
1124: }
1125: default:
1126: throw dataTypeConversion("java.io.Reader", columnIndex);
1127: }
1128:
1129: Object syncLock = getConnectionSynchronization();
1130:
1131: synchronized (syncLock) {
1132:
1133: boolean pushStack = false;
1134: try {
1135:
1136: useStream(columnIndex);
1137:
1138: DataValueDescriptor dvd = getColumn(columnIndex);
1139:
1140: if (wasNull = dvd.isNull()) {
1141: return null;
1142: }
1143:
1144: pushStack = true;
1145: setupContextStack();
1146:
1147: StreamStorable ss = (StreamStorable) dvd;
1148:
1149: InputStream stream = ss.returnStream();
1150:
1151: if (stream == null) {
1152:
1153: String val = dvd.getString();
1154: if (lmfs > 0) {
1155: if (val.length() > lmfs)
1156: val = val.substring(0, lmfs);
1157: }
1158: java.io.Reader ret = new java.io.StringReader(val);
1159: currentStream = ret;
1160: return ret;
1161: }
1162:
1163: java.io.Reader ret = new UTF8Reader(stream, lmfs, this ,
1164: syncLock);
1165: currentStream = ret;
1166: return ret;
1167:
1168: } catch (Throwable t) {
1169: throw noStateChangeException(t);
1170: } finally {
1171: if (pushStack) {
1172: restoreContextStack();
1173: }
1174: }
1175: }
1176: }
1177:
1178: /**
1179: Pushes a converter on top of getCharacterStream().
1180: *
1181: * @param columnIndex the first column is 1, the second is 2, ...
1182: * @return a Java input stream that delivers the database column value
1183: * as a stream of one byte ASCII characters. If the value is SQL NULL
1184: * then the result is null.
1185: * @exception SQLException thrown on failure.
1186: */
1187: public final InputStream getAsciiStream(int columnIndex)
1188: throws SQLException {
1189: checkIfClosed("getAsciiStream");
1190: int colType = getColumnType(columnIndex);
1191: switch (colType) {
1192: case Types.CHAR:
1193: case Types.VARCHAR:
1194: case Types.LONGVARCHAR:
1195: case Types.CLOB: // Embedded and JCC extension
1196: break;
1197:
1198: // JDBC says to support these, we match JCC by returning the raw bytes.
1199: case Types.BINARY:
1200: case Types.VARBINARY:
1201: case Types.LONGVARBINARY:
1202: case Types.BLOB:
1203: return getBinaryStream(columnIndex);
1204:
1205: default:
1206: throw dataTypeConversion("java.io.InputStream(ASCII)",
1207: columnIndex);
1208: }
1209:
1210: java.io.Reader reader = getCharacterStream(columnIndex);
1211: if (reader == null)
1212: return null;
1213:
1214: return new ReaderToAscii(reader);
1215: }
1216:
1217: /**
1218: * Get the column as an InputStream. If the column is already of type
1219: InputStream then just return it, otherwise convert the column to a set
1220: of bytes and create a stream out of the bytes.
1221: *
1222: * @param columnIndex the first column is 1, the second is 2, ...
1223: * @return a Java input stream that delivers the database column value
1224: * as a stream of uninterpreted bytes. If the value is SQL NULL
1225: * then the result is null.
1226: * @exception SQLException thrown on failure.
1227: */
1228: public final InputStream getBinaryStream(int columnIndex)
1229: throws SQLException {
1230: checkIfClosed("getBinaryStream");
1231: int lmfs;
1232: int colType = getColumnType(columnIndex);
1233: switch (colType) {
1234: case Types.BINARY:
1235: case Types.VARBINARY:
1236: case Types.LONGVARBINARY:
1237: lmfs = maxFieldSize;
1238: break;
1239: case Types.BLOB:
1240: lmfs = 0;
1241: break;
1242:
1243: default:
1244: throw dataTypeConversion("java.io.InputStream", columnIndex);
1245: }
1246:
1247: Object syncLock = getConnectionSynchronization();
1248:
1249: synchronized (syncLock) {
1250:
1251: boolean pushStack = false;
1252: try {
1253:
1254: useStream(columnIndex);
1255:
1256: DataValueDescriptor dvd = getColumn(columnIndex);
1257:
1258: if (wasNull = dvd.isNull()) {
1259: return null;
1260: }
1261:
1262: pushStack = true;
1263: setupContextStack();
1264:
1265: StreamStorable ss = (StreamStorable) dvd;
1266:
1267: InputStream stream = ss.returnStream();
1268:
1269: if (stream == null) {
1270: stream = new NewByteArrayInputStream(dvd.getBytes());
1271: } else {
1272: stream = new BinaryToRawStream(stream, dvd);
1273: }
1274:
1275: if (lmfs > 0) {
1276: // Just wrap the InputStream with a LimitInputStream class
1277: LimitInputStream limitResultIn = new LimitInputStream(
1278: stream);
1279: limitResultIn.setLimit(lmfs);
1280: stream = limitResultIn;
1281: }
1282: currentStream = stream;
1283: return stream;
1284:
1285: } catch (Throwable t) {
1286: throw noStateChangeException(t);
1287: } finally {
1288: if (pushStack) {
1289: restoreContextStack();
1290: }
1291: }
1292: }
1293: }
1294:
1295: //======================================================================
1296: // Methods for accessing results by column name
1297: //======================================================================
1298:
1299: /**
1300: * Get the value of a column in the current row as a Java String.
1301: *
1302: * @param columnName is the SQL name of the column
1303: * @return the column value; if the value is SQL NULL, the result is null
1304: * @exception SQLException thrown on failure.
1305: */
1306: public final String getString(String columnName)
1307: throws SQLException {
1308: checkIfClosed("getString");
1309: return (getString(findColumnName(columnName)));
1310: }
1311:
1312: /**
1313: * Get the value of a column in the current row as a Java boolean.
1314: *
1315: * @param columnName is the SQL name of the column
1316: * @return the column value; if the value is SQL NULL, the result is false
1317: * @exception SQLException thrown on failure.
1318: */
1319: public final boolean getBoolean(String columnName)
1320: throws SQLException {
1321: checkIfClosed("getBoolean");
1322: return (getBoolean(findColumnName(columnName)));
1323: }
1324:
1325: /**
1326: * Get the value of a column in the current row as a Java byte.
1327: *
1328: * @param columnName is the SQL name of the column
1329: * @return the column value; if the value is SQL NULL, the result is 0
1330: * @exception SQLException thrown on failure.
1331: */
1332: public final byte getByte(String columnName) throws SQLException {
1333: checkIfClosed("getByte");
1334: return (getByte(findColumnName(columnName)));
1335: }
1336:
1337: /**
1338: * Get the value of a column in the current row as a Java short.
1339: *
1340: * @param columnName is the SQL name of the column
1341: * @return the column value; if the value is SQL NULL, the result is 0
1342: * @exception SQLException thrown on failure.
1343: */
1344: public final short getShort(String columnName) throws SQLException {
1345: checkIfClosed("getShort");
1346: return (getShort(findColumnName(columnName)));
1347: }
1348:
1349: /**
1350: * Get the value of a column in the current row as a Java int.
1351: *
1352: * @param columnName is the SQL name of the column
1353: * @return the column value; if the value is SQL NULL, the result is 0
1354: * @exception SQLException thrown on failure.
1355: */
1356: public final int getInt(String columnName) throws SQLException {
1357: checkIfClosed("getInt");
1358: return (getInt(findColumnName(columnName)));
1359: }
1360:
1361: /**
1362: * Get the value of a column in the current row as a Java long.
1363: *
1364: * @param columnName is the SQL name of the column
1365: * @return the column value; if the value is SQL NULL, the result is 0
1366: * @exception SQLException thrown on failure.
1367: */
1368: public final long getLong(String columnName) throws SQLException {
1369: checkIfClosed("getLong");
1370: return (getLong(findColumnName(columnName)));
1371: }
1372:
1373: /**
1374: * Get the value of a column in the current row as a Java float.
1375: *
1376: * @param columnName is the SQL name of the column
1377: * @return the column value; if the value is SQL NULL, the result is 0
1378: * @exception SQLException thrown on failure.
1379: */
1380: public final float getFloat(String columnName) throws SQLException {
1381: checkIfClosed("getFloat");
1382: return (getFloat(findColumnName(columnName)));
1383: }
1384:
1385: /**
1386: * Get the value of a column in the current row as a Java double.
1387: *
1388: * @param columnName is the SQL name of the column
1389: * @return the column value; if the value is SQL NULL, the result is 0
1390: * @exception SQLException thrown on failure.
1391: */
1392: public final double getDouble(String columnName)
1393: throws SQLException {
1394: checkIfClosed("getDouble");
1395: return (getDouble(findColumnName(columnName)));
1396: }
1397:
1398: /**
1399: * Get the value of a column in the current row as a Java byte array.
1400: * The bytes represent the raw values returned by the driver.
1401: *
1402: * @param columnName is the SQL name of the column
1403: * @return the column value; if the value is SQL NULL, the result is null
1404: * @exception SQLException thrown on failure.
1405: */
1406: public final byte[] getBytes(String columnName) throws SQLException {
1407: checkIfClosed("getBytes");
1408: return (getBytes(findColumnName(columnName)));
1409: }
1410:
1411: /**
1412: * Get the value of a column in the current row as a java.sql.Date object.
1413: *
1414: * @param columnName is the SQL name of the column
1415: * @return the column value; if the value is SQL NULL, the result is null
1416: * @exception SQLException thrown on failure.
1417: */
1418: public final Date getDate(String columnName) throws SQLException {
1419: checkIfClosed("getDate");
1420: return (getDate(findColumnName(columnName)));
1421: }
1422:
1423: /**
1424: * Get the value of a column in the current row as a java.sql.Time object.
1425: *
1426: * @param columnName is the SQL name of the column
1427: * @return the column value; if the value is SQL NULL, the result is null
1428: * @exception SQLException thrown on failure.
1429: */
1430: public final Time getTime(String columnName) throws SQLException {
1431: checkIfClosed("getTime");
1432: return (getTime(findColumnName(columnName)));
1433: }
1434:
1435: /**
1436: * Get the value of a column in the current row as a java.sql.Timestamp object.
1437: *
1438: * @param columnName is the SQL name of the column
1439: * @return the column value; if the value is SQL NULL, the result is null
1440: * @exception SQLException thrown on failure.
1441: */
1442: public final Timestamp getTimestamp(String columnName)
1443: throws SQLException {
1444: checkIfClosed("getTimestamp");
1445: return (getTimestamp(findColumnName(columnName)));
1446: }
1447:
1448: /**
1449: * JDBC 2.0
1450: *
1451: * <p>Get the value of a column in the current row as a java.io.Reader.
1452: *
1453: * @exception SQLException Feature not implemented for now.
1454: */
1455: public final java.io.Reader getCharacterStream(String columnName)
1456: throws SQLException {
1457: checkIfClosed("getCharacterStream");
1458: return (getCharacterStream(findColumnName(columnName)));
1459: }
1460:
1461: /**
1462: * A column value can be retrieved as a stream of ASCII characters
1463: * and then read in chunks from the stream. This method is particularly
1464: * suitable for retrieving large LONGVARCHAR values. The JDBC driver will
1465: * do any necessary conversion from the database format into ASCII.
1466: *
1467: * <P><B>Note:</B> All the data in the returned stream must
1468: * be read prior to getting the value of any other column. The
1469: * next call to a get method implicitly closes the stream.
1470: *
1471: * @param columnName is the SQL name of the column
1472: * @return a Java input stream that delivers the database column value
1473: * as a stream of one byte ASCII characters. If the value is SQL NULL
1474: * then the result is null.
1475: * @exception SQLException thrown on failure.
1476: */
1477: public final InputStream getAsciiStream(String columnName)
1478: throws SQLException {
1479: checkIfClosed("getAsciiStream");
1480: return (getAsciiStream(findColumnName(columnName)));
1481: }
1482:
1483: /**
1484: * A column value can be retrieved as a stream of uninterpreted bytes
1485: * and then read in chunks from the stream. This method is particularly
1486: * suitable for retrieving large LONGVARBINARY values.
1487: *
1488: * <P><B>Note:</B> All the data in the returned stream must
1489: * be read prior to getting the value of any other column. The
1490: * next call to a get method implicitly closes the stream.
1491: *
1492: * @param columnName is the SQL name of the column
1493: * @return a Java input stream that delivers the database column value
1494: * as a stream of uninterpreted bytes. If the value is SQL NULL
1495: * then the result is null.
1496: * @exception SQLException thrown on failure.
1497: */
1498: public final InputStream getBinaryStream(String columnName)
1499: throws SQLException {
1500: checkIfClosed("getBinaryStream");
1501: return (getBinaryStream(findColumnName(columnName)));
1502: }
1503:
1504: /**
1505: * JDBC 3.0
1506: *
1507: * Retrieves the value of the designated column in the current row of this
1508: * ResultSet object as a java.net.URL object in the Java programming
1509: * language.
1510: *
1511: * @param columnIndex -
1512: * the first column is 1, the second is 2
1513: * @return the column value as a java.net.URL object, if the value is SQL
1514: * NULL, the value returned is null in the Java programming language
1515: * @exception SQLException
1516: * Feature not implemented for now.
1517: */
1518: public URL getURL(int columnIndex) throws SQLException {
1519: throw Util.notImplemented();
1520: }
1521:
1522: /**
1523: * JDBC 3.0
1524: *
1525: * Retrieves the value of the designated column in the current row of this
1526: * ResultSet object as a java.net.URL object in the Java programming
1527: * language.
1528: *
1529: * @param columnName -
1530: * the SQL name of the column
1531: * @return the column value as a java.net.URL object, if the value is SQL
1532: * NULL, the value returned is null in the Java programming language
1533: * @exception SQLException
1534: * Feature not implemented for now.
1535: */
1536: public URL getURL(String columnName) throws SQLException {
1537: throw Util.notImplemented();
1538: }
1539:
1540: //=====================================================================
1541: // Advanced features:
1542: //=====================================================================
1543:
1544: /**
1545: * <p>The first warning reported by calls on this ResultSet is
1546: * returned. Subsequent ResultSet warnings will be chained to this
1547: * SQLWarning.
1548: *
1549: * <P>The warning chain is automatically cleared each time a new
1550: * row is read.
1551: *
1552: * <P><B>Note:</B> This warning chain only covers warnings caused
1553: * by ResultSet methods. Any warning caused by statement methods
1554: * (such as reading OUT parameters) will be chained on the
1555: * Statement object.
1556: *
1557: * @return the first SQLWarning or null
1558: *
1559: * @exception SQLException Thrown if this ResultSet is closed
1560: */
1561: public final SQLWarning getWarnings() throws SQLException {
1562: checkIfClosed("getWarnings");
1563: return topWarning;
1564: }
1565:
1566: /**
1567: * After this call getWarnings returns null until a new warning is
1568: * reported for this ResultSet.
1569: *
1570: * @exception SQLException Thrown if this ResultSet is closed
1571: */
1572: public final void clearWarnings() throws SQLException {
1573: checkIfClosed("clearWarnings");
1574: topWarning = null;
1575: }
1576:
1577: /**
1578: * Get the name of the SQL cursor used by this ResultSet.
1579: *
1580: * <P>In SQL, a result table is retrieved through a cursor that is
1581: * named. The current row of a result can be updated or deleted
1582: * using a positioned update/delete statement that references the
1583: * cursor name.
1584: *
1585: * <P>JDBC supports this SQL feature by providing the name of the
1586: * SQL cursor used by a ResultSet. The current row of a ResultSet
1587: * is also the current row of this SQL cursor.
1588: *
1589: * <P><B>Note:</B> If positioned update is not supported a
1590: * SQLException is thrown
1591: *
1592: * @return the ResultSet's SQL cursor name
1593: * @exception SQLException thrown on failure.
1594: */
1595: public final String getCursorName() throws SQLException {
1596:
1597: checkIfClosed("getCursorName"); // checking result set closure does not depend
1598: // on the underlying connection. Do this
1599: // outside of the connection synchronization.
1600:
1601: return theResults.getCursorName();
1602: }
1603:
1604: /**
1605: * The number, types and properties of a ResultSet's columns
1606: * are provided by the getMetaData method.
1607: *
1608: * @return the description of a ResultSet's columns
1609: * @exception SQLException thrown on failure.
1610: */
1611: public ResultSetMetaData getMetaData() throws SQLException {
1612:
1613: checkIfClosed("getMetaData"); // checking result set closure does not depend
1614: // on the underlying connection. Do this
1615: // outside of the connection synchronization.
1616:
1617: synchronized (getConnectionSynchronization()) {
1618:
1619: if (rMetaData == null) {
1620: // cache this object and keep returning it
1621: rMetaData = newEmbedResultSetMetaData(resultDescription);
1622: }
1623: return rMetaData;
1624: }
1625: }
1626:
1627: /**
1628: * JDBC 4.0
1629: *
1630: * <p>
1631: * Retrieves the holdability for this <code>ResultSet</code>
1632: * object.
1633: *
1634: * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
1635: * or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
1636: * @exception SQLException
1637: * if a database error occurs
1638: */
1639: public final int getHoldability() throws SQLException {
1640: checkIfClosed("getHoldability");
1641: if (theResults.getActivation().getResultSetHoldability()) {
1642: return JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
1643: }
1644: return JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
1645: }
1646:
1647: /**
1648: * <p>Get the value of a column in the current row as a Java object.
1649: *
1650: * <p>This method will return the value of the given column as a
1651: * Java object. The type of the Java object will be the default
1652: * Java Object type corresponding to the column's SQL type,
1653: * following the mapping specified in the JDBC spec.
1654: *
1655: * <p>This method may also be used to read datatabase specific abstract
1656: * data types.
1657: *
1658: * JDBC 2.0
1659: *
1660: * New behavior for getObject().
1661: * The behavior of method getObject() is extended to materialize
1662: * data of SQL user-defined types. When the column @columnIndex is
1663: * a structured or distinct value, the behavior of this method is as
1664: * if it were a call to: getObject(columnIndex,
1665: * this.getStatement().getConnection().getTypeMap()).
1666: *
1667: * @param columnIndex the first column is 1, the second is 2, ...
1668: * @return A java.lang.Object holding the column value.
1669: * @exception SQLException thrown on failure.
1670: */
1671: public final Object getObject(int columnIndex) throws SQLException {
1672: checkIfClosed("getObject");
1673:
1674: // need special handling for some types.
1675: int colType = getColumnType(columnIndex);
1676: switch (colType) {
1677: case Types.CHAR:
1678: case Types.VARCHAR:
1679: case Types.LONGVARCHAR:
1680: // handles maxfield size correctly
1681: return getString(columnIndex);
1682:
1683: case Types.CLOB:
1684: return getClob(columnIndex);
1685:
1686: case Types.BINARY:
1687: case Types.VARBINARY:
1688: case Types.LONGVARBINARY:
1689: // handles maxfield size correctly
1690: return getBytes(columnIndex);
1691:
1692: case Types.BLOB:
1693: return getBlob(columnIndex);
1694:
1695: default:
1696: break;
1697: }
1698:
1699: try {
1700:
1701: DataValueDescriptor dvd = getColumn(columnIndex);
1702: if (wasNull = dvd.isNull())
1703: return null;
1704:
1705: return dvd.getObject();
1706:
1707: } catch (StandardException t) {
1708: throw noStateChangeException(t);
1709: }
1710: }
1711:
1712: /**
1713: * <p>Get the value of a column in the current row as a Java object.
1714: *
1715: * <p>This method will return the value of the given column as a
1716: * Java object. The type of the Java object will be the default
1717: * Java Object type corresponding to the column's SQL type,
1718: * following the mapping specified in the JDBC spec.
1719: *
1720: * <p>This method may also be used to read datatabase specific abstract
1721: * data types.
1722: *
1723: * JDBC 2.0
1724: *
1725: * New behavior for getObject().
1726: * The behavior of method getObject() is extended to materialize
1727: * data of SQL user-defined types. When the column @columnName is
1728: * a structured or distinct value, the behavior of this method is as
1729: * if it were a call to: getObject(columnName,
1730: * this.getStatement().getConnection().getTypeMap()).
1731: *
1732: * @param columnName is the SQL name of the column
1733: * @return A java.lang.Object holding the column value.
1734: * @exception SQLException thrown on failure.
1735: */
1736: public final Object getObject(String columnName)
1737: throws SQLException {
1738: checkIfClosed("getObject");
1739: return (getObject(findColumnName(columnName)));
1740: }
1741:
1742: //----------------------------------------------------------------
1743:
1744: /**
1745: * Map a Resultset column name to a ResultSet column index.
1746: *
1747: * @param columnName the name of the column
1748: * @return the column index
1749: * @exception SQLException thrown on failure.
1750: */
1751: public final int findColumn(String columnName) throws SQLException {
1752: checkIfClosed("findColumn");
1753: return findColumnName(columnName);
1754: }
1755:
1756: /////////////////////////////////////////////////////////////////////////
1757: //
1758: // JDBC 2.0 - New public methods
1759: //
1760: /////////////////////////////////////////////////////////////////////////
1761:
1762: //---------------------------------------------------------------------
1763: // Getter's and Setter's
1764: //---------------------------------------------------------------------
1765:
1766: /**
1767: * JDBC 2.0
1768: *
1769: * Return the Statement that produced the ResultSet.
1770: *
1771: * @return the Statment that produced the result set, or null if the result
1772: * was produced some other way.
1773: * @exception SQLException if a database error occurs or the
1774: * result set is closed
1775: */
1776: public final Statement getStatement() throws SQLException {
1777: checkIfClosed("getStatement");
1778: return applicationStmt;
1779: }
1780:
1781: /**
1782: * Set the application Statement object that created this ResultSet.
1783: * Used when the Statement objects returned to the application
1784: * are wrapped for XA.
1785: */
1786: public final void setApplicationStatement(Statement applicationStmt) {
1787: this .applicationStmt = applicationStmt;
1788: }
1789:
1790: //---------------------------------------------------------------------
1791: // Traversal/Positioning
1792: //---------------------------------------------------------------------
1793:
1794: /**
1795: * JDBC 2.0
1796: *
1797: * <p>
1798: * Determine if the cursor is before the first row in the result set.
1799: *
1800: * @return true if before the first row, false otherwise. Returns false when
1801: * the result set contains no rows.
1802: * @exception SQLException
1803: * Thrown on error.
1804: */
1805: public boolean isBeforeFirst() throws SQLException {
1806: return checkRowPosition(ResultSet.ISBEFOREFIRST,
1807: "isBeforeFirst");
1808: }
1809:
1810: /**
1811: * JDBC 2.0
1812: *
1813: * <p>
1814: * Determine if the cursor is after the last row in the result set.
1815: *
1816: * @return true if after the last row, false otherwise. Returns false when
1817: * the result set contains no rows.
1818: * @exception SQLException
1819: * Thrown on error.
1820: */
1821: public boolean isAfterLast() throws SQLException {
1822: return checkRowPosition(ResultSet.ISAFTERLAST, "isAfterLast");
1823: }
1824:
1825: /**
1826: * JDBC 2.0
1827: *
1828: * <p>
1829: * Determine if the cursor is on the first row of the result set.
1830: *
1831: * @return true if on the first row, false otherwise.
1832: * @exception SQLException
1833: * Thrown on error.
1834: */
1835: public boolean isFirst() throws SQLException {
1836: return checkRowPosition(ResultSet.ISFIRST, "isFirst");
1837: }
1838:
1839: /**
1840: * JDBC 2.0
1841: *
1842: * <p>
1843: * Determine if the cursor is on the last row of the result set. Note:
1844: * Calling isLast() may be expensive since the JDBC driver might need to
1845: * fetch ahead one row in order to determine whether the current row is the
1846: * last row in the result set.
1847: *
1848: * @return true if on the last row, false otherwise.
1849: * @exception SQLException
1850: * Thrown on error.
1851: */
1852: public boolean isLast() throws SQLException {
1853: return checkRowPosition(ResultSet.ISLAST, "isLast");
1854: }
1855:
1856: /**
1857: * JDBC 2.0
1858: *
1859: * <p>
1860: * Moves to the front of the result set, just before the first row. Has no
1861: * effect if the result set contains no rows.
1862: *
1863: * @exception SQLException
1864: * if a database-access error occurs, or result set type is
1865: * TYPE_FORWARD_ONLY
1866: */
1867: public void beforeFirst() throws SQLException {
1868: // beforeFirst is only allowed on scroll cursors
1869: checkScrollCursor("beforeFirst()");
1870: movePosition(BEFOREFIRST, "beforeFirst");
1871: }
1872:
1873: /**
1874: * JDBC 2.0
1875: *
1876: * <p>
1877: * Moves to the end of the result set, just after the last row. Has no
1878: * effect if the result set contains no rows.
1879: *
1880: * @exception SQLException
1881: * if a database-access error occurs, or result set type is
1882: * TYPE_FORWARD_ONLY.
1883: */
1884: public void afterLast() throws SQLException {
1885: // afterLast is only allowed on scroll cursors
1886: checkScrollCursor("afterLast()");
1887: movePosition(AFTERLAST, "afterLast");
1888: }
1889:
1890: /**
1891: * JDBC 2.0
1892: *
1893: * <p>
1894: * Moves to the first row in the result set.
1895: *
1896: * @return true if on a valid row, false if no rows in the result set.
1897: * @exception SQLException
1898: * if a database-access error occurs, or result set type is
1899: * TYPE_FORWARD_ONLY.
1900: */
1901: public boolean first() throws SQLException {
1902: // first is only allowed on scroll cursors
1903: checkScrollCursor("first()");
1904: return movePosition(FIRST, "first");
1905: }
1906:
1907: /**
1908: * JDBC 2.0
1909: *
1910: * <p>
1911: * Moves to the last row in the result set.
1912: *
1913: * @return true if on a valid row, false if no rows in the result set.
1914: * @exception SQLException
1915: * if a database-access error occurs, or result set type is
1916: * TYPE_FORWARD_ONLY.
1917: */
1918: public boolean last() throws SQLException {
1919: // last is only allowed on scroll cursors
1920: checkScrollCursor("last()");
1921: return movePosition(LAST, "last");
1922: }
1923:
1924: /**
1925: * JDBC 2.0
1926: *
1927: * <p>
1928: * Determine the current row number. The first row is number 1, the second
1929: * number 2, etc.
1930: *
1931: * @return the current row number, else return 0 if there is no current row
1932: * @exception SQLException
1933: * if a database-access error occurs.
1934: */
1935: public int getRow() throws SQLException {
1936: // getRow() is only allowed on scroll cursors
1937: checkScrollCursor("getRow()");
1938:
1939: /*
1940: * * We probably needn't bother getting the text of * the underlying
1941: * statement but it is better to be * consistent and we aren't
1942: * particularly worried * about performance of getRow().
1943: */
1944: return theResults.getRowNumber();
1945: }
1946:
1947: /**
1948: * JDBC 2.0
1949: *
1950: * <p>
1951: * Move to an absolute row number in the result set.
1952: *
1953: * <p>
1954: * If row is positive, moves to an absolute row with respect to the
1955: * beginning of the result set. The first row is row 1, the second is row 2,
1956: * etc.
1957: *
1958: * <p>
1959: * If row is negative, moves to an absolute row position with respect to the
1960: * end of result set. For example, calling absolute(-1) positions the cursor
1961: * on the last row, absolute(-2) indicates the next-to-last row, etc.
1962: *
1963: * <p>
1964: * An attempt to position the cursor beyond the first/last row in the result
1965: * set, leaves the cursor before/after the first/last row, respectively.
1966: *
1967: * <p>
1968: * Note: Calling absolute(1) is the same as calling first(). Calling
1969: * absolute(-1) is the same as calling last().
1970: *
1971: * @return true if on the result set, false if off.
1972: * @exception SQLException
1973: * if a database-access error occurs, or row is 0, or result
1974: * set type is TYPE_FORWARD_ONLY.
1975: */
1976: public boolean absolute(int row) throws SQLException {
1977: // absolute is only allowed on scroll cursors
1978: checkScrollCursor("absolute()");
1979: return movePosition(ABSOLUTE, row, "absolute");
1980: }
1981:
1982: /**
1983: * JDBC 2.0
1984: *
1985: * <p>
1986: * Moves a relative number of rows, either positive or negative. Attempting
1987: * to move beyond the first/last row in the result set positions the cursor
1988: * before/after the the first/last row. Calling relative(0) is valid, but
1989: * does not change the cursor position.
1990: *
1991: * <p>
1992: * Note: Calling relative(1) is different than calling next() since is makes
1993: * sense to call next() when there is no current row, for example, when the
1994: * cursor is positioned before the first row or after the last row of the
1995: * result set.
1996: *
1997: * @return true if on a row, false otherwise.
1998: * @exception SQLException
1999: * if a database-access error occurs, or there is no current
2000: * row, or result set type is TYPE_FORWARD_ONLY.
2001: */
2002: public boolean relative(int row) throws SQLException {
2003: // absolute is only allowed on scroll cursors
2004: checkScrollCursor("relative()");
2005: return movePosition(RELATIVE, row, "relative");
2006: }
2007:
2008: /**
2009: * JDBC 2.0
2010: *
2011: * <p>
2012: * Moves to the previous row in the result set.
2013: *
2014: * <p>
2015: * Note: previous() is not the same as relative(-1) since it makes sense to
2016: * call previous() when there is no current row.
2017: *
2018: * @return true if on a valid row, false if off the result set.
2019: * @exception SQLException
2020: * if a database-access error occurs, or result set type is
2021: * TYPE_FORWAR_DONLY.
2022: */
2023: public boolean previous() throws SQLException {
2024: // previous is only allowed on scroll cursors
2025: checkScrollCursor("previous()");
2026: return movePosition(PREVIOUS, "previous");
2027: }
2028:
2029: //---------------------------------------------------------------------
2030: // Properties
2031: //---------------------------------------------------------------------
2032:
2033: /**
2034: * JDBC 2.0
2035: *
2036: * Give a hint as to the direction in which the rows in this result set will
2037: * be processed. The initial value is determined by the statement that
2038: * produced the result set. The fetch direction may be changed at any time.
2039: *
2040: * @exception SQLException
2041: * if a database-access error occurs, or the result set type
2042: * is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
2043: */
2044: public void setFetchDirection(int direction) throws SQLException {
2045: checkScrollCursor("setFetchDirection()");
2046: /*
2047: * FetchDirection is meaningless to us. We just save it off and return
2048: * the current value if asked.
2049: */
2050: fetchDirection = direction;
2051: }
2052:
2053: /**
2054: * JDBC 2.0
2055: *
2056: * Return the fetch direction for this result set.
2057: *
2058: * @exception SQLException
2059: * if a database-access error occurs
2060: */
2061: public int getFetchDirection() throws SQLException {
2062: checkIfClosed("getFetchDirection");
2063: if (fetchDirection == 0) {
2064: // value is not set at the result set level
2065: // get it from the statement level
2066: return stmt.getFetchDirection();
2067: } else
2068: return fetchDirection;
2069: }
2070:
2071: /**
2072: * JDBC 2.0
2073: *
2074: * Give the JDBC driver a hint as to the number of rows that should be
2075: * fetched from the database when more rows are needed for this result set.
2076: * If the fetch size specified is zero, then the JDBC driver ignores the
2077: * value, and is free to make its own best guess as to what the fetch size
2078: * should be. The default value is set by the statement that creates the
2079: * result set. The fetch size may be changed at any time.
2080: *
2081: * @param rows
2082: * the number of rows to fetch
2083: * @exception SQLException
2084: * if a database-access error occurs, or the condition 0 <=
2085: * rows <= this.getMaxRows() is not satisfied.
2086: */
2087: public void setFetchSize(int rows) throws SQLException {
2088: checkIfClosed("setFetchSize");
2089: if (rows < 0
2090: || (stmt.getMaxRows() != 0 && rows > stmt.getMaxRows())) {
2091: throw Util.generateCsSQLException(
2092: SQLState.INVALID_FETCH_SIZE, new Integer(rows));
2093: } else if (rows > 0) // if it is zero ignore the call
2094: {
2095: fetchSize = rows;
2096: }
2097: }
2098:
2099: /**
2100: * JDBC 2.0
2101: *
2102: * Return the fetch size for this result set.
2103: *
2104: * @exception SQLException
2105: * if a database-access error occurs
2106: */
2107: public int getFetchSize() throws SQLException {
2108: checkIfClosed("getFetchSize");
2109: if (fetchSize == 0) {
2110: // value is not set at the result set level
2111: // get the default value from the statement
2112: return stmt.getFetchSize();
2113: } else
2114: return fetchSize;
2115: }
2116:
2117: /**
2118: * JDBC 2.0
2119: *
2120: * Return the type of this result set. The type is determined based on the
2121: * statement that created the result set.
2122: *
2123: * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
2124: * TYPE_SCROLL_SENSITIVE
2125: * @exception SQLException
2126: * if a database-access error occurs
2127: */
2128: public int getType() throws SQLException {
2129: checkIfClosed("getType");
2130: return stmt.getResultSetType();
2131: }
2132:
2133: /**
2134: * JDBC 2.0
2135: *
2136: * Return the concurrency of this result set. The concurrency is determined
2137: * as follows If Statement object has CONCUR_READ_ONLY concurrency, then
2138: * ResultSet object will also have the CONCUR_READ_ONLY concurrency. But if
2139: * Statement object has CONCUR_UPDATABLE concurrency, then the concurrency
2140: * of ResultSet object depends on whether the underlying language resultset
2141: * is updatable or not. If the language resultset is updatable, then JDBC
2142: * ResultSet object will also have the CONCUR_UPDATABLE concurrency. If
2143: * lanugage resultset is not updatable, then JDBC ResultSet object
2144: * concurrency will be set to CONCUR_READ_ONLY.
2145: *
2146: * @return the concurrency type, CONCUR_READ_ONLY, etc.
2147: * @exception SQLException
2148: * if a database-access error occurs
2149: */
2150: public int getConcurrency() throws SQLException {
2151: checkIfClosed("getConcurrency");
2152: return concurrencyOfThisResultSet;
2153: }
2154:
2155: //---------------------------------------------------------------------
2156: // Updates
2157: //---------------------------------------------------------------------
2158:
2159: /**
2160: * JDBC 2.0
2161: *
2162: * Determine if the current row has been updated. The value returned depends
2163: * on whether or not the result set can detect updates.
2164: *
2165: * @return true if the row has been visibly updated by the owner or another,
2166: * and updates are detected
2167: * @exception SQLException
2168: * if a database-access error occurs
2169: *
2170: * @see EmbedDatabaseMetaData#updatesAreDetected
2171: */
2172: public boolean rowUpdated() throws SQLException {
2173: checkIfClosed("rowUpdated");
2174: checkNotOnInsertRow();
2175: checkOnRow();
2176:
2177: boolean rvalue = false;
2178:
2179: try {
2180: if (isForUpdate()
2181: && getType() == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE) {
2182: rvalue = ((ScrollInsensitiveResultSet) theResults)
2183: .isUpdated();
2184: }
2185: } catch (Throwable t) {
2186: handleException(t);
2187: }
2188: return rvalue;
2189: }
2190:
2191: /**
2192: * JDBC 2.0
2193: *
2194: * Determine if the current row has been inserted. The value returned
2195: * depends on whether or not the result set can detect visible inserts.
2196: *
2197: * @return true if inserted and inserts are detected
2198: * @exception SQLException
2199: * if a database-access error occurs
2200: *
2201: * @see EmbedDatabaseMetaData#insertsAreDetected
2202: */
2203: public boolean rowInserted() throws SQLException {
2204: checkIfClosed("rowInserted");
2205: checkNotOnInsertRow();
2206: checkOnRow();
2207:
2208: return false;
2209: }
2210:
2211: /**
2212: * JDBC 2.0
2213: *
2214: * Determine if this row has been deleted. A deleted row may leave a visible
2215: * "hole" in a result set. This method can be used to detect holes in a
2216: * result set. The value returned depends on whether or not the result set
2217: * can detect deletions.
2218: *
2219: * @return true if deleted and deletes are detected
2220: * @exception SQLException
2221: * if a database-access error occurs
2222: *
2223: * @see EmbedDatabaseMetaData#deletesAreDetected
2224: */
2225: public boolean rowDeleted() throws SQLException {
2226: checkIfClosed("rowUpdated");
2227: checkNotOnInsertRow();
2228: checkOnRow();
2229:
2230: boolean rvalue = false;
2231:
2232: try {
2233: if (isForUpdate()
2234: && getType() == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE) {
2235: rvalue = ((ScrollInsensitiveResultSet) theResults)
2236: .isDeleted();
2237: }
2238: } catch (Throwable t) {
2239: handleException(t);
2240: }
2241: return rvalue;
2242: }
2243:
2244: //do following few checks before accepting updateXXX resultset api
2245: protected void checksBeforeUpdateXXX(String methodName,
2246: int columnIndex) throws SQLException {
2247: checksBeforeUpdateOrDelete(methodName, columnIndex);
2248:
2249: //1)Make sure for updateXXX methods, the column position is not out of range
2250: ResultDescription rd = theResults.getResultDescription();
2251: if (columnIndex < 1 || columnIndex > rd.getColumnCount())
2252: throw Util.generateCsSQLException(
2253: SQLState.LANG_INVALID_COLUMN_POSITION, new Integer(
2254: columnIndex), String.valueOf(rd
2255: .getColumnCount()));
2256:
2257: //2)Make sure the column corresponds to a column in the base table and it is not a derived column
2258: if (rd.getColumnDescriptor(columnIndex).getSourceTableName() == null)
2259: throw Util.generateCsSQLException(
2260: SQLState.COLUMN_NOT_FROM_BASE_TABLE, methodName);
2261:
2262: //3)If column not updatable then throw an exception
2263: if (!getMetaData().isWritable(columnIndex))
2264: throw Util
2265: .generateCsSQLException(
2266: SQLState.LANG_COLUMN_NOT_UPDATABLE_IN_CURSOR,
2267: theResults.getResultDescription()
2268: .getColumnDescriptor(columnIndex)
2269: .getName(), getCursorName());
2270: }
2271:
2272: //do following few checks before accepting updateRow or deleteRow
2273: //1)Make sure JDBC ResultSet is not closed
2274: //2)Make sure this is an updatable ResultSet
2275: //3)Make sure JDBC ResultSet is positioned on a row
2276: //4)Make sure underneath language resultset is not closed
2277: protected void checksBeforeUpdateOrDelete(String methodName,
2278: int columnIndex) throws SQLException {
2279:
2280: //1)Make sure JDBC ResultSet is not closed
2281: checkIfClosed(methodName);
2282:
2283: //2)Make sure this is an updatable ResultSet
2284: checkUpdatableCursor(methodName);
2285:
2286: //3)Make sure JDBC ResultSet is positioned on a row
2287: if (!isOnInsertRow)
2288: checkOnRow(); // make sure there's a current row
2289: //in case of autocommit on, if there was an exception which caused runtime rollback in this transaction prior to this call,
2290: //the rollback code will mark the language resultset closed (it doesn't mark the JDBC ResultSet closed).
2291: //That is why alongwith the earlier checkIfClosed call in this method, there is a check for language resultset close as well.
2292:
2293: //4)Make sure underneath language resultset is not closed
2294: if (theResults.isClosed())
2295: throw Util.generateCsSQLException(
2296: SQLState.LANG_RESULT_SET_NOT_OPEN, methodName);
2297: }
2298:
2299: //mark the column as updated and return DataValueDescriptor for it. It will be used by updateXXX methods to put new values
2300: protected DataValueDescriptor getDVDforColumnToBeUpdated(
2301: int columnIndex, String updateMethodName)
2302: throws StandardException, SQLException {
2303: checksBeforeUpdateXXX(updateMethodName, columnIndex);
2304: columnGotUpdated[columnIndex - 1] = true;
2305: currentRowHasBeenUpdated = true;
2306:
2307: return updateRow.getColumn(columnIndex);
2308: }
2309:
2310: /* do following few checks before accepting insertRow
2311: * 1) Make sure JDBC ResultSet is not closed
2312: * 2) Make sure this is an updatable ResultSet
2313: * 3) Make sure JDBC ResultSet is positioned on insertRow
2314: * 4) Make sure underneath language resultset is not closed
2315: */
2316: protected void checksBeforeInsert() throws SQLException {
2317: // 1)Make sure JDBC ResultSet is not closed
2318: checkIfClosed("insertRow");
2319:
2320: // 2)Make sure this is an updatable ResultSet
2321: // if not updatable resultset, then throw exception
2322: checkUpdatableCursor("insertRow");
2323:
2324: // 3)Make sure JDBC ResultSet is positioned on insertRow
2325: if (!isOnInsertRow) {
2326: throw newSQLException(SQLState.CURSOR_NOT_POSITIONED_ON_INSERT_ROW);
2327: }
2328:
2329: // 4)Make sure underneath language resultset is not closed
2330: if (theResults.isClosed()) {
2331: throw Util.generateCsSQLException(
2332: SQLState.LANG_RESULT_SET_NOT_OPEN, "insertRow");
2333: }
2334: }
2335:
2336: /**
2337: * Check whether it is OK to update a column using
2338: * <code>updateAsciiStream()</code>.
2339: *
2340: * @param columnIndex the column index (first column is 1)
2341: * @exception SQLException if the column could not be updated with
2342: * <code>updateAsciiStream()</code>
2343: */
2344: private void checksBeforeUpdateAsciiStream(int columnIndex)
2345: throws SQLException {
2346: checksBeforeUpdateXXX("updateAsciiStream", columnIndex);
2347: int colType = getColumnType(columnIndex);
2348: if (!DataTypeDescriptor.isAsciiStreamAssignable(colType)) {
2349: throw dataTypeConversion(columnIndex, "java.io.InputStream");
2350: }
2351: }
2352:
2353: /**
2354: * Check whether it is OK to update a column using
2355: * <code>updateBinaryStream()</code>.
2356: *
2357: * @param columnIndex the column index (first column is 1)
2358: * @exception SQLException if the column could not be updated with
2359: * <code>updateBinaryStream()</code>
2360: */
2361: private void checksBeforeUpdateBinaryStream(int columnIndex)
2362: throws SQLException {
2363: checksBeforeUpdateXXX("updateBinaryStream", columnIndex);
2364: int colType = getColumnType(columnIndex);
2365: if (!DataTypeDescriptor.isBinaryStreamAssignable(colType)) {
2366: throw dataTypeConversion(columnIndex, "java.io.InputStream");
2367: }
2368: }
2369:
2370: /**
2371: * Check whether it is OK to update a column using
2372: * <code>updateCharacterStream()</code>.
2373: *
2374: * @param columnIndex the column index (first column is 1)
2375: * @exception SQLException if the column could not be updated with
2376: * <code>updateCharacterStream()</code>
2377: */
2378: private void checksBeforeUpdateCharacterStream(int columnIndex)
2379: throws SQLException {
2380: checksBeforeUpdateXXX("updateCharacterStream", columnIndex);
2381: int colType = getColumnType(columnIndex);
2382: if (!DataTypeDescriptor.isCharacterStreamAssignable(colType)) {
2383: throw dataTypeConversion(columnIndex, "java.io.Reader");
2384: }
2385: }
2386:
2387: /**
2388: * JDBC 2.0
2389: *
2390: * Give a nullable column a null value.
2391: *
2392: * The updateXXX() methods are used to update column values in the current
2393: * row, or the insert row. The updateXXX() methods do not update the
2394: * underlying database, instead the updateRow() or insertRow() methods are
2395: * called to update the database.
2396: *
2397: * @param columnIndex
2398: * the first column is 1, the second is 2, ...
2399: * @exception SQLException
2400: * if a database-access error occurs
2401: */
2402: public void updateNull(int columnIndex) throws SQLException {
2403: try {
2404: getDVDforColumnToBeUpdated(columnIndex, "updateNull")
2405: .setToNull();
2406: } catch (StandardException t) {
2407: throw noStateChangeException(t);
2408: }
2409: }
2410:
2411: /**
2412: * JDBC 2.0
2413: *
2414: * Update a column with a boolean value.
2415: *
2416: * The updateXXX() methods are used to update column values in the current
2417: * row, or the insert row. The updateXXX() methods do not update the
2418: * underlying database, instead the updateRow() or insertRow() methods are
2419: * called to update the database.
2420: *
2421: * @param columnIndex
2422: * the first column is 1, the second is 2, ...
2423: * @param x
2424: * the new column value
2425: * @exception SQLException
2426: * if a database-access error occurs
2427: */
2428: public void updateBoolean(int columnIndex, boolean x)
2429: throws SQLException {
2430: try {
2431: getDVDforColumnToBeUpdated(columnIndex, "updateBoolean")
2432: .setValue(x);
2433: } catch (StandardException t) {
2434: throw noStateChangeException(t);
2435: }
2436: }
2437:
2438: /**
2439: * JDBC 2.0
2440: *
2441: * Update a column with a byte value.
2442: *
2443: * The updateXXX() methods are used to update column values in the current
2444: * row, or the insert row. The updateXXX() methods do not update the
2445: * underlying database, instead the updateRow() or insertRow() methods are
2446: * called to update the database.
2447: *
2448: * @param columnIndex
2449: * the first column is 1, the second is 2, ...
2450: * @param x
2451: * the new column value
2452: * @exception SQLException
2453: * if a database-access error occurs
2454: */
2455: public void updateByte(int columnIndex, byte x) throws SQLException {
2456: try {
2457: getDVDforColumnToBeUpdated(columnIndex, "updateByte")
2458: .setValue(x);
2459: } catch (StandardException t) {
2460: throw noStateChangeException(t);
2461: }
2462: }
2463:
2464: /**
2465: * JDBC 2.0
2466: *
2467: * Update a column with a short value.
2468: *
2469: * The updateXXX() methods are used to update column values in the current
2470: * row, or the insert row. The updateXXX() methods do not update the
2471: * underlying database, instead the updateRow() or insertRow() methods are
2472: * called to update the database.
2473: *
2474: * @param columnIndex
2475: * the first column is 1, the second is 2, ...
2476: * @param x
2477: * the new column value
2478: * @exception SQLException
2479: * if a database-access error occurs
2480: */
2481: public void updateShort(int columnIndex, short x)
2482: throws SQLException {
2483: try {
2484: getDVDforColumnToBeUpdated(columnIndex, "updateShort")
2485: .setValue(x);
2486: } catch (StandardException t) {
2487: throw noStateChangeException(t);
2488: }
2489: }
2490:
2491: /**
2492: * JDBC 2.0
2493: *
2494: * Update a column with an integer value.
2495: *
2496: * The updateXXX() methods are used to update column values in the current
2497: * row, or the insert row. The updateXXX() methods do not update the
2498: * underlying database, instead the updateRow() or insertRow() methods are
2499: * called to update the database.
2500: *
2501: * @param columnIndex
2502: * the first column is 1, the second is 2, ...
2503: * @param x
2504: * the new column value
2505: * @exception SQLException
2506: * if a database-access error occurs
2507: */
2508: public void updateInt(int columnIndex, int x) throws SQLException {
2509: try {
2510: getDVDforColumnToBeUpdated(columnIndex, "updateInt")
2511: .setValue(x);
2512: } catch (StandardException t) {
2513: throw noStateChangeException(t);
2514: }
2515: }
2516:
2517: /**
2518: * JDBC 2.0
2519: *
2520: * Update a column with a long value.
2521: *
2522: * The updateXXX() methods are used to update column values in the current
2523: * row, or the insert row. The updateXXX() methods do not update the
2524: * underlying database, instead the updateRow() or insertRow() methods are
2525: * called to update the database.
2526: *
2527: * @param columnIndex
2528: * the first column is 1, the second is 2, ...
2529: * @param x
2530: * the new column value
2531: * @exception SQLException
2532: * if a database-access error occurs
2533: */
2534: public void updateLong(int columnIndex, long x) throws SQLException {
2535: try {
2536: getDVDforColumnToBeUpdated(columnIndex, "updateLong")
2537: .setValue(x);
2538: } catch (StandardException t) {
2539: throw noStateChangeException(t);
2540: }
2541: }
2542:
2543: /**
2544: * JDBC 2.0
2545: *
2546: * Update a column with a float value.
2547: *
2548: * The updateXXX() methods are used to update column values in the current
2549: * row, or the insert row. The updateXXX() methods do not update the
2550: * underlying database, instead the updateRow() or insertRow() methods are
2551: * called to update the database.
2552: *
2553: * @param columnIndex
2554: * the first column is 1, the second is 2, ...
2555: * @param x
2556: * the new column value
2557: * @exception SQLException
2558: * if a database-access error occurs
2559: */
2560: public void updateFloat(int columnIndex, float x)
2561: throws SQLException {
2562: try {
2563: getDVDforColumnToBeUpdated(columnIndex, "updateFloat")
2564: .setValue(x);
2565: } catch (StandardException t) {
2566: throw noStateChangeException(t);
2567: }
2568: }
2569:
2570: /**
2571: * JDBC 2.0
2572: *
2573: * Update a column with a Double value.
2574: *
2575: * The updateXXX() methods are used to update column values in the current
2576: * row, or the insert row. The updateXXX() methods do not update the
2577: * underlying database, instead the updateRow() or insertRow() methods are
2578: * called to update the database.
2579: *
2580: * @param columnIndex
2581: * the first column is 1, the second is 2, ...
2582: * @param x
2583: * the new column value
2584: * @exception SQLException
2585: * if a database-access error occurs
2586: */
2587: public void updateDouble(int columnIndex, double x)
2588: throws SQLException {
2589: try {
2590: getDVDforColumnToBeUpdated(columnIndex, "updateDouble")
2591: .setValue(x);
2592: } catch (StandardException t) {
2593: throw noStateChangeException(t);
2594: }
2595: }
2596:
2597: /**
2598: * JDBC 2.0
2599: *
2600: * Update a column with a String value.
2601: *
2602: * The updateXXX() methods are used to update column values in the current
2603: * row, or the insert row. The updateXXX() methods do not update the
2604: * underlying database, instead the updateRow() or insertRow() methods are
2605: * called to update the database.
2606: *
2607: * @param columnIndex
2608: * the first column is 1, the second is 2, ...
2609: * @param x
2610: * the new column value
2611: * @exception SQLException
2612: * if a database-access error occurs
2613: */
2614: public void updateString(int columnIndex, String x)
2615: throws SQLException {
2616: try {
2617: getDVDforColumnToBeUpdated(columnIndex, "updateString")
2618: .setValue(x);
2619: } catch (StandardException t) {
2620: throw noStateChangeException(t);
2621: }
2622: }
2623:
2624: /**
2625: * JDBC 2.0
2626: *
2627: * Update a column with a byte array value.
2628: *
2629: * The updateXXX() methods are used to update column values in the current
2630: * row, or the insert row. The updateXXX() methods do not update the
2631: * underlying database, instead the updateRow() or insertRow() methods are
2632: * called to update the database.
2633: *
2634: * @param columnIndex
2635: * the first column is 1, the second is 2, ...
2636: * @param x
2637: * the new column value
2638: * @exception SQLException
2639: * if a database-access error occurs
2640: */
2641: public void updateBytes(int columnIndex, byte x[])
2642: throws SQLException {
2643: try {
2644: getDVDforColumnToBeUpdated(columnIndex, "updateBytes")
2645: .setValue(x);
2646: } catch (StandardException t) {
2647: throw noStateChangeException(t);
2648: }
2649: }
2650:
2651: /**
2652: * JDBC 2.0
2653: *
2654: * Update a column with a Date value.
2655: *
2656: * The updateXXX() methods are used to update column values in the current
2657: * row, or the insert row. The updateXXX() methods do not update the
2658: * underlying database, instead the updateRow() or insertRow() methods are
2659: * called to update the database.
2660: *
2661: * @param columnIndex
2662: * the first column is 1, the second is 2, ...
2663: * @param x
2664: * the new column value
2665: * @exception SQLException
2666: * if a database-access error occurs
2667: */
2668: public void updateDate(int columnIndex, java.sql.Date x)
2669: throws SQLException {
2670: try {
2671: getDVDforColumnToBeUpdated(columnIndex, "updateDate")
2672: .setValue(x);
2673: } catch (StandardException t) {
2674: throw noStateChangeException(t);
2675: }
2676: }
2677:
2678: /**
2679: * JDBC 2.0
2680: *
2681: * Update a column with a Time value.
2682: *
2683: * The updateXXX() methods are used to update column values in the current
2684: * row, or the insert row. The updateXXX() methods do not update the
2685: * underlying database, instead the updateRow() or insertRow() methods are
2686: * called to update the database.
2687: *
2688: * @param columnIndex
2689: * the first column is 1, the second is 2, ...
2690: * @param x
2691: * the new column value
2692: * @exception SQLException
2693: * if a database-access error occurs
2694: */
2695: public void updateTime(int columnIndex, java.sql.Time x)
2696: throws SQLException {
2697: try {
2698: getDVDforColumnToBeUpdated(columnIndex, "updateTime")
2699: .setValue(x);
2700: } catch (StandardException t) {
2701: throw noStateChangeException(t);
2702: }
2703: }
2704:
2705: /**
2706: * JDBC 2.0
2707: *
2708: * Update a column with a Timestamp value.
2709: *
2710: * The updateXXX() methods are used to update column values in the current
2711: * row, or the insert row. The updateXXX() methods do not update the
2712: * underlying database, instead the updateRow() or insertRow() methods are
2713: * called to update the database.
2714: *
2715: * @param columnIndex
2716: * the first column is 1, the second is 2, ...
2717: * @param x
2718: * the new column value
2719: * @exception SQLException
2720: * if a database-access error occurs
2721: */
2722: public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
2723: throws SQLException {
2724: try {
2725: getDVDforColumnToBeUpdated(columnIndex, "updateTimestamp")
2726: .setValue(x);
2727: } catch (StandardException t) {
2728: throw noStateChangeException(t);
2729: }
2730: }
2731:
2732: /**
2733: *
2734: * Update a column with an ascii stream value.
2735: *
2736: * The updateXXX() methods are used to update column values in the current
2737: * row, or the insert row. The updateXXX() methods do not update the
2738: * underlying database, instead the updateRow() or insertRow() methods are
2739: * called to update the database.
2740: *
2741: * @param columnIndex
2742: * the first column is 1, the second is 2, ...
2743: * @param x
2744: * the new column value
2745: * @param length
2746: * the length of the stream
2747: * @exception SQLException
2748: * if a database-access error occurs
2749: */
2750: public void updateAsciiStream(int columnIndex,
2751: java.io.InputStream x, long length) throws SQLException {
2752: checksBeforeUpdateAsciiStream(columnIndex);
2753:
2754: java.io.Reader r = null;
2755: if (x != null) {
2756: try {
2757: r = new java.io.InputStreamReader(x, "ISO-8859-1");
2758: } catch (java.io.UnsupportedEncodingException uee) {
2759: throw new SQLException(uee.getMessage());
2760: }
2761: }
2762: updateCharacterStreamInternal(columnIndex, r, false, length,
2763: "updateAsciiStream");
2764: }
2765:
2766: /**
2767: * Updates the designated column with a character stream value.
2768: * The data will be read from the stream as needed until end-of-stream is
2769: * reached.
2770: *
2771: * The updater methods are used to update column values in the current row
2772: * or the insert row. The updater methods do not update the underlying
2773: * database; instead the <code>updateRow</code> or </code>insertRow</code>
2774: * methods are called to update the database.
2775: *
2776: * @param columnIndex the first column is 1, the second is 2, ...
2777: * @param x the new column value
2778: * @throws SQLException if the columnIndex is not valid; if a database
2779: * access error occurs; the result set concurrency is
2780: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
2781: * result set
2782: */
2783: public void updateAsciiStream(int columnIndex, InputStream x)
2784: throws SQLException {
2785: checksBeforeUpdateAsciiStream(columnIndex);
2786:
2787: java.io.Reader r = null;
2788: if (x != null) {
2789: try {
2790: r = new java.io.InputStreamReader(x, "ISO-8859-1");
2791: } catch (java.io.UnsupportedEncodingException uee) {
2792: throw new SQLException(uee.getMessage());
2793: }
2794: }
2795: updateCharacterStreamInternal(columnIndex, r, true, -1,
2796: "updateAsciiStream");
2797: }
2798:
2799: /**
2800: *
2801: * Update a column with a binary stream value.
2802: *
2803: * The updateXXX() methods are used to update column values in the current
2804: * row, or the insert row. The updateXXX() methods do not update the
2805: * underlying database, instead the updateRow() or insertRow() methods are
2806: * called to update the database.
2807: *
2808: * @param columnIndex
2809: * the first column is 1, the second is 2, ...
2810: * @param x
2811: * the new column value
2812: * @param length
2813: * the length of the stream
2814: * @exception SQLException
2815: * if a database-access error occurs
2816: */
2817: public void updateBinaryStream(int columnIndex,
2818: java.io.InputStream x, long length) throws SQLException {
2819: checksBeforeUpdateBinaryStream(columnIndex);
2820:
2821: if (x == null) {
2822: updateNull(columnIndex);
2823: return;
2824: }
2825:
2826: updateBinaryStreamInternal(columnIndex, x, false, length,
2827: "updateBinaryStream");
2828: }
2829:
2830: /**
2831: * Updates the designated column with a binary stream value.
2832: * The data will be read from the stream as needed until end-of-stream is
2833: * reached.
2834: *
2835: * The updater methods are used to update column values in the current row
2836: * or the insert row. The updater methods do not update the underlying
2837: * database; instead the <code>updateRow</code> or <code>insertRow</code>
2838: * methods are called to update the database.
2839: *
2840: * @param columnIndex the first column is 1, the second is 2, ...
2841: * @param x the new column value
2842: * @throws SQLException if the columnLabel is not valid; if a database
2843: * access error occurs; the result set concurrency is
2844: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
2845: * result set
2846: */
2847: public void updateBinaryStream(int columnIndex, InputStream x)
2848: throws SQLException {
2849: checksBeforeUpdateBinaryStream(columnIndex);
2850: updateBinaryStreamInternal(columnIndex, x, true, -1,
2851: "updateBinaryStream");
2852: }
2853:
2854: /**
2855: * Set the given binary stream for the specified parameter.
2856: *
2857: * If <code>lengthLess</code> is <code>true</code>, the following
2858: * conditions are either not checked or verified at the execution time
2859: * of <code>updateRow</code>/<code>insertRow</code>:
2860: * <ol><li>If the stream length is negative.
2861: * <li>If the stream's actual length equals the specified length.</ol>
2862: * The <code>lengthLess</code> variable was added to differentiate between
2863: * streams with invalid lengths and streams without known lengths.
2864: *
2865: * @param columnIndex the 1-based index of the parameter to set.
2866: * @param x the data.
2867: * @param lengthLess tells whether we know the length of the data or not.
2868: * @param length the length of the data. Ignored if <code>lengthLess</code>
2869: * is <code>true</code>.
2870: * @param updateMethodName the name of the method calling us. Used in
2871: * error messages.
2872: * @throws SQLException if reading the data fails, or one of the data
2873: * checks fails.
2874: */
2875: private void updateBinaryStreamInternal(int columnIndex,
2876: InputStream x, final boolean lengthLess, long length,
2877: String updateMethodName) throws SQLException {
2878: RawToBinaryFormatStream rawStream;
2879: if (!lengthLess) {
2880: if (length < 0)
2881: throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
2882:
2883: // max number of bytes that can be set to be inserted
2884: // in Derby is 2Gb-1 (ie Integer.MAX_VALUE).
2885: // (e.g into a blob column).
2886: if (length > Integer.MAX_VALUE) {
2887: throw newSQLException(
2888: SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
2889: getColumnSQLType(columnIndex));
2890: }
2891: rawStream = new RawToBinaryFormatStream(x, (int) length);
2892: } else {
2893: // Force length to -1 if stream is length less.
2894: length = -1;
2895: rawStream = new RawToBinaryFormatStream(x,
2896: getMaxColumnWidth(columnIndex),
2897: getColumnSQLType(columnIndex));
2898: }
2899:
2900: try {
2901: getDVDforColumnToBeUpdated(columnIndex, updateMethodName)
2902: .setValue(rawStream, (int) length);
2903: } catch (StandardException t) {
2904: throw noStateChangeException(t);
2905: }
2906: }
2907:
2908: /**
2909: * JDBC 4.0
2910: *
2911: * Update a column with a character stream value.
2912: *
2913: * The updateXXX() methods are used to update column values in the current
2914: * row, or the insert row. The updateXXX() methods do not update the
2915: * underlying database, instead the updateRow() or insertRow() methods are
2916: * called to update the database.
2917: *
2918: * @param columnIndex
2919: * the first column is 1, the second is 2, ...
2920: * @param x
2921: * the new column value
2922: * @param length
2923: * the length of the stream
2924: * @exception SQLException
2925: * if a database-access error occurs
2926: */
2927: public void updateCharacterStream(int columnIndex,
2928: java.io.Reader x, long length) throws SQLException {
2929: checksBeforeUpdateCharacterStream(columnIndex);
2930: updateCharacterStreamInternal(columnIndex, x, false, length,
2931: "updateCharacterStream");
2932: }
2933:
2934: /**
2935: * Updates the designated column with a character stream value.
2936: * The data will be read from the stream as needed until end-of-stream is
2937: * reached.
2938: *
2939: * The updater methods are used to update column values in the current row
2940: * or the insert row. The updater methods do not update the underlying
2941: * database; instead the <code>updateRow</code> or </code>insertRow</code>
2942: * methods are called to update the database.
2943: *
2944: * @param columnIndex the first column is 1, the second is 2, ...
2945: * @param x the new column value
2946: * @throws SQLException if the columnIndex is not valid; if a database
2947: * access error occurs; the result set concurrency is
2948: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
2949: * result set
2950: */
2951: public void updateCharacterStream(int columnIndex, Reader x)
2952: throws SQLException {
2953: checksBeforeUpdateCharacterStream(columnIndex);
2954: updateCharacterStreamInternal(columnIndex, x, true, -1,
2955: "updateCharacterStream");
2956: }
2957:
2958: /**
2959: * Set the given character stream for the specified parameter.
2960: *
2961: * If <code>lengthLess</code> is <code>true</code>, the following
2962: * conditions are either not checked or verified at the execution time
2963: * of the prepared statement:
2964: * <ol><li>If the stream length is negative.
2965: * <li>If the stream's actual length equals the specified length.</ol>
2966: * The <code>lengthLess</code> variable was added to differentiate between
2967: * streams with invalid lengths and streams without known lengths.
2968: *
2969: * @param columnIndex the 1-based index of the parameter to set.
2970: * @param reader the data.
2971: * @param lengthLess tells whether we know the length of the data or not.
2972: * @param length the length of the data. Ignored if <code>lengthLess</code>
2973: * is <code>true</code>.
2974: * @throws SQLException if reading the data fails, or one of the data
2975: * checks fails.
2976: */
2977: private void updateCharacterStreamInternal(int columnIndex,
2978: Reader reader, final boolean lengthLess, long length,
2979: String updateMethodName) throws SQLException {
2980: try {
2981:
2982: if (reader == null) {
2983: updateNull(columnIndex);
2984: return;
2985: }
2986:
2987: ReaderToUTF8Stream utfIn;
2988: int usableLength = -1;
2989: if (!lengthLess) {
2990: // check for -ve length here
2991: if (length < 0)
2992: throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
2993:
2994: // max number of characters that can be set to be inserted
2995: // in Derby is 2Gb-1 (ie Integer.MAX_VALUE).
2996: // (e.g into a CLOB column).
2997: if (length > Integer.MAX_VALUE) {
2998: throw newSQLException(
2999: SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
3000: getColumnSQLType(columnIndex));
3001: }
3002:
3003: // length is +ve. at this point, all checks for negative
3004: // length has already been done
3005: usableLength = (int) length;
3006: int truncationLength = 0;
3007:
3008: // Currently long varchar does not allow for truncation of
3009: // trailing blanks. For char and varchar types, current
3010: // mechanism of materializing when using streams seems fine
3011: // given their max limits. This change is fix for DERBY-352:
3012: // Insert of clobs using streams should not materialize the
3013: // entire stream into memory
3014: // In case of clobs, the truncation of trailing blanks is
3015: // factored in when reading from the stream without
3016: // materializing the entire stream, and so the special casing
3017: // for clob below.
3018: if (getColumnType(columnIndex) == Types.CLOB) {
3019: // Need column width to figure out if truncation is
3020: // needed
3021: int colWidth = getMaxColumnWidth(columnIndex);
3022:
3023: // It is possible that the length of the stream passed in
3024: // is greater than the column width, in which case the data
3025: // from the stream needs to be truncated.
3026: // usableLength is the length of the data from stream
3027: // that can be used which is min(colWidth,length) provided
3028: // length - colWidth has trailing blanks only
3029: if (usableLength > colWidth) {
3030: truncationLength = usableLength - colWidth;
3031: usableLength = colWidth;
3032: }
3033: }
3034:
3035: utfIn = new ReaderToUTF8Stream(reader, usableLength,
3036: truncationLength, getColumnSQLType(columnIndex));
3037: } else {
3038: int colWidth = getMaxColumnWidth(columnIndex);
3039: utfIn = new ReaderToUTF8Stream(reader, colWidth,
3040: getColumnSQLType(columnIndex));
3041: }
3042:
3043: // NOTE: The length argument to setValue is not used. If that
3044: // changes, the value might also have to change.
3045: getDVDforColumnToBeUpdated(columnIndex, updateMethodName)
3046: .setValue(utfIn, (int) usableLength);
3047: } catch (StandardException t) {
3048: throw noStateChangeException(t);
3049: }
3050: }
3051:
3052: /**
3053: * JDBC 2.0
3054: *
3055: * Update a column with an Object value.
3056: *
3057: * The updateXXX() methods are used to update column values in the current
3058: * row, or the insert row. The updateXXX() methods do not update the
3059: * underlying database, instead the updateRow() or insertRow() methods are
3060: * called to update the database.
3061: *
3062: * @param columnIndex
3063: * the first column is 1, the second is 2, ...
3064: * @param x
3065: * the new column value
3066: * @param scale
3067: * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
3068: * this is the number of digits after the decimal. For all other
3069: * types this value will be ignored.
3070: * @exception SQLException
3071: * if a database-access error occurs
3072: */
3073: public void updateObject(int columnIndex, Object x, int scale)
3074: throws SQLException {
3075: updateObject(columnIndex, x);
3076: /*
3077: * If the parameter type is DECIMAL or NUMERIC, then
3078: * we need to set them to the passed scale.
3079: */
3080: int colType = getColumnType(columnIndex);
3081: if ((colType == Types.DECIMAL) || (colType == Types.NUMERIC)) {
3082: if (scale < 0)
3083: throw newSQLException(SQLState.BAD_SCALE_VALUE,
3084: new Integer(scale));
3085:
3086: try {
3087: DataValueDescriptor value = updateRow
3088: .getColumn(columnIndex);
3089:
3090: int origvaluelen = value.getLength();
3091: ((VariableSizeDataValue) value).setWidth(
3092: VariableSizeDataValue.IGNORE_PRECISION, scale,
3093: false);
3094:
3095: } catch (StandardException t) {
3096: throw EmbedResultSet.noStateChangeException(t);
3097: }
3098: }
3099: }
3100:
3101: /**
3102: * JDBC 2.0
3103: *
3104: * Update a column with an Object value.
3105: *
3106: * The updateXXX() methods are used to update column values in the current
3107: * row, or the insert row. The updateXXX() methods do not update the
3108: * underlying database, instead the updateRow() or insertRow() methods are
3109: * called to update the database.
3110: *
3111: * @param columnIndex
3112: * the first column is 1, the second is 2, ...
3113: * @param x
3114: * the new column value
3115: * @exception SQLException
3116: * if a database-access error occurs
3117: */
3118: public void updateObject(int columnIndex, Object x)
3119: throws SQLException {
3120: checksBeforeUpdateXXX("updateObject", columnIndex);
3121: int colType = getColumnType(columnIndex);
3122: if (colType == org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT) {
3123: try {
3124: ((UserDataValue) getDVDforColumnToBeUpdated(
3125: columnIndex, "updateObject")).setValue(x);
3126: return;
3127: } catch (StandardException t) {
3128: throw noStateChangeException(t);
3129: }
3130: }
3131:
3132: if (x == null) {
3133: updateNull(columnIndex);
3134: return;
3135: }
3136:
3137: if (x instanceof String) {
3138: updateString(columnIndex, (String) x);
3139: return;
3140: }
3141:
3142: if (x instanceof Boolean) {
3143: updateBoolean(columnIndex, ((Boolean) x).booleanValue());
3144: return;
3145: }
3146:
3147: if (x instanceof Short) {
3148: updateShort(columnIndex, ((Short) x).shortValue());
3149: return;
3150: }
3151:
3152: if (x instanceof Integer) {
3153: updateInt(columnIndex, ((Integer) x).intValue());
3154: return;
3155: }
3156:
3157: if (x instanceof Long) {
3158: updateLong(columnIndex, ((Long) x).longValue());
3159: return;
3160: }
3161:
3162: if (x instanceof Float) {
3163: updateFloat(columnIndex, ((Float) x).floatValue());
3164: return;
3165: }
3166:
3167: if (x instanceof Double) {
3168: updateDouble(columnIndex, ((Double) x).doubleValue());
3169: return;
3170: }
3171:
3172: if (x instanceof byte[]) {
3173: updateBytes(columnIndex, (byte[]) x);
3174: return;
3175: }
3176:
3177: if (x instanceof Date) {
3178: updateDate(columnIndex, (Date) x);
3179: return;
3180: }
3181:
3182: if (x instanceof Time) {
3183: updateTime(columnIndex, (Time) x);
3184: return;
3185: }
3186:
3187: if (x instanceof Timestamp) {
3188: updateTimestamp(columnIndex, (Timestamp) x);
3189: return;
3190: }
3191:
3192: if (x instanceof Blob) {
3193: updateBlob(columnIndex, (Blob) x);
3194: return;
3195: }
3196:
3197: if (x instanceof Clob) {
3198: updateClob(columnIndex, (Clob) x);
3199: return;
3200: }
3201:
3202: throw dataTypeConversion(columnIndex, x.getClass().getName());
3203: }
3204:
3205: /**
3206: * JDBC 2.0
3207: *
3208: * Update a column with a null value.
3209: *
3210: * The updateXXX() methods are used to update column values in the current
3211: * row, or the insert row. The updateXXX() methods do not update the
3212: * underlying database, instead the updateRow() or insertRow() methods are
3213: * called to update the database.
3214: *
3215: * @param columnName
3216: * the name of the column
3217: * @exception SQLException
3218: * if a database-access error occurs
3219: */
3220: public void updateNull(String columnName) throws SQLException {
3221: checkIfClosed("updateNull");
3222: updateNull(findColumnName(columnName));
3223: }
3224:
3225: /**
3226: * JDBC 2.0
3227: *
3228: * Update a column with a boolean value.
3229: *
3230: * The updateXXX() methods are used to update column values in the current
3231: * row, or the insert row. The updateXXX() methods do not update the
3232: * underlying database, instead the updateRow() or insertRow() methods are
3233: * called to update the database.
3234: *
3235: * @param columnName
3236: * the name of the column
3237: * @param x
3238: * the new column value
3239: * @exception SQLException
3240: * if a database-access error occurs
3241: */
3242: public void updateBoolean(String columnName, boolean x)
3243: throws SQLException {
3244: checkIfClosed("updateBoolean");
3245: updateBoolean(findColumnName(columnName), x);
3246: }
3247:
3248: /**
3249: * JDBC 2.0
3250: *
3251: * Update a column with a byte value.
3252: *
3253: * The updateXXX() methods are used to update column values in the current
3254: * row, or the insert row. The updateXXX() methods do not update the
3255: * underlying database, instead the updateRow() or insertRow() methods are
3256: * called to update the database.
3257: *
3258: * @param columnName
3259: * the name of the column
3260: * @param x
3261: * the new column value
3262: * @exception SQLException
3263: * if a database-access error occurs
3264: */
3265: public void updateByte(String columnName, byte x)
3266: throws SQLException {
3267: checkIfClosed("updateByte");
3268: updateByte(findColumnName(columnName), x);
3269: }
3270:
3271: /**
3272: * JDBC 2.0
3273: *
3274: * Update a column with a short value.
3275: *
3276: * The updateXXX() methods are used to update column values in the current
3277: * row, or the insert row. The updateXXX() methods do not update the
3278: * underlying database, instead the updateRow() or insertRow() methods are
3279: * called to update the database.
3280: *
3281: * @param columnName
3282: * the name of the column
3283: * @param x
3284: * the new column value
3285: * @exception SQLException
3286: * if a database-access error occurs
3287: */
3288: public void updateShort(String columnName, short x)
3289: throws SQLException {
3290: checkIfClosed("updateShort");
3291: updateShort(findColumnName(columnName), x);
3292: }
3293:
3294: /**
3295: * JDBC 2.0
3296: *
3297: * Update a column with an integer value.
3298: *
3299: * The updateXXX() methods are used to update column values in the current
3300: * row, or the insert row. The updateXXX() methods do not update the
3301: * underlying database, instead the updateRow() or insertRow() methods are
3302: * called to update the database.
3303: *
3304: * @param columnName
3305: * the name of the column
3306: * @param x
3307: * the new column value
3308: * @exception SQLException
3309: * if a database-access error occurs
3310: */
3311: public void updateInt(String columnName, int x) throws SQLException {
3312: checkIfClosed("updateInt");
3313: updateInt(findColumnName(columnName), x);
3314: }
3315:
3316: /**
3317: * JDBC 2.0
3318: *
3319: * Update a column with a long value.
3320: *
3321: * The updateXXX() methods are used to update column values in the current
3322: * row, or the insert row. The updateXXX() methods do not update the
3323: * underlying database, instead the updateRow() or insertRow() methods are
3324: * called to update the database.
3325: *
3326: * @param columnName
3327: * the name of the column
3328: * @param x
3329: * the new column value
3330: * @exception SQLException
3331: * if a database-access error occurs
3332: */
3333: public void updateLong(String columnName, long x)
3334: throws SQLException {
3335: checkIfClosed("updateLong");
3336: updateLong(findColumnName(columnName), x);
3337: }
3338:
3339: /**
3340: * JDBC 2.0
3341: *
3342: * Update a column with a float value.
3343: *
3344: * The updateXXX() methods are used to update column values in the current
3345: * row, or the insert row. The updateXXX() methods do not update the
3346: * underlying database, instead the updateRow() or insertRow() methods are
3347: * called to update the database.
3348: *
3349: * @param columnName
3350: * the name of the column
3351: * @param x
3352: * the new column value
3353: * @exception SQLException
3354: * if a database-access error occurs
3355: */
3356: public void updateFloat(String columnName, float x)
3357: throws SQLException {
3358: checkIfClosed("updateFloat");
3359: updateFloat(findColumnName(columnName), x);
3360: }
3361:
3362: /**
3363: * JDBC 2.0
3364: *
3365: * Update a column with a double value.
3366: *
3367: * The updateXXX() methods are used to update column values in the current
3368: * row, or the insert row. The updateXXX() methods do not update the
3369: * underlying database, instead the updateRow() or insertRow() methods are
3370: * called to update the database.
3371: *
3372: * @param columnName
3373: * the name of the column
3374: * @param x
3375: * the new column value
3376: * @exception SQLException
3377: * if a database-access error occurs
3378: */
3379: public void updateDouble(String columnName, double x)
3380: throws SQLException {
3381: checkIfClosed("updateDouble");
3382: updateDouble(findColumnName(columnName), x);
3383: }
3384:
3385: /**
3386: * JDBC 2.0
3387: *
3388: * Update a column with a String value.
3389: *
3390: * The updateXXX() methods are used to update column values in the current
3391: * row, or the insert row. The updateXXX() methods do not update the
3392: * underlying database, instead the updateRow() or insertRow() methods are
3393: * called to update the database.
3394: *
3395: * @param columnName
3396: * the name of the column
3397: * @param x
3398: * the new column value
3399: * @exception SQLException
3400: * if a database-access error occurs
3401: */
3402: public void updateString(String columnName, String x)
3403: throws SQLException {
3404: checkIfClosed("updateString");
3405: updateString(findColumnName(columnName), x);
3406: }
3407:
3408: /**
3409: * JDBC 2.0
3410: *
3411: * Update a column with a byte array value.
3412: *
3413: * The updateXXX() methods are used to update column values in the current
3414: * row, or the insert row. The updateXXX() methods do not update the
3415: * underlying database, instead the updateRow() or insertRow() methods are
3416: * called to update the database.
3417: *
3418: * @param columnName
3419: * the name of the column
3420: * @param x
3421: * the new column value
3422: * @exception SQLException
3423: * if a database-access error occurs
3424: */
3425: public void updateBytes(String columnName, byte x[])
3426: throws SQLException {
3427: checkIfClosed("updateBytes");
3428: updateBytes(findColumnName(columnName), x);
3429: }
3430:
3431: /**
3432: * JDBC 2.0
3433: *
3434: * Update a column with a Date value.
3435: *
3436: * The updateXXX() methods are used to update column values in the current
3437: * row, or the insert row. The updateXXX() methods do not update the
3438: * underlying database, instead the updateRow() or insertRow() methods are
3439: * called to update the database.
3440: *
3441: * @param columnName
3442: * the name of the column
3443: * @param x
3444: * the new column value
3445: * @exception SQLException
3446: * if a database-access error occurs
3447: */
3448: public void updateDate(String columnName, java.sql.Date x)
3449: throws SQLException {
3450: checkIfClosed("updateDate");
3451: updateDate(findColumnName(columnName), x);
3452: }
3453:
3454: /**
3455: * JDBC 2.0
3456: *
3457: * Update a column with a Time value.
3458: *
3459: * The updateXXX() methods are used to update column values in the current
3460: * row, or the insert row. The updateXXX() methods do not update the
3461: * underlying database, instead the updateRow() or insertRow() methods are
3462: * called to update the database.
3463: *
3464: * @param columnName
3465: * the name of the column
3466: * @param x
3467: * the new column value
3468: * @exception SQLException
3469: * if a database-access error occurs
3470: */
3471: public void updateTime(String columnName, java.sql.Time x)
3472: throws SQLException {
3473: checkIfClosed("updateTime");
3474: updateTime(findColumnName(columnName), x);
3475: }
3476:
3477: /**
3478: * JDBC 2.0
3479: *
3480: * Update a column with a Timestamp value.
3481: *
3482: * The updateXXX() methods are used to update column values in the current
3483: * row, or the insert row. The updateXXX() methods do not update the
3484: * underlying database, instead the updateRow() or insertRow() methods are
3485: * called to update the database.
3486: *
3487: * @param columnName
3488: * the name of the column
3489: * @param x
3490: * the new column value
3491: * @exception SQLException
3492: * if a database-access error occurs
3493: */
3494: public void updateTimestamp(String columnName, java.sql.Timestamp x)
3495: throws SQLException {
3496: checkIfClosed("updateTimestamp");
3497: updateTimestamp(findColumnName(columnName), x);
3498: }
3499:
3500: /**
3501: * JDBC 2.0
3502: *
3503: * Update a column with an ascii stream value.
3504: *
3505: * The updateXXX() methods are used to update column values in the current
3506: * row, or the insert row. The updateXXX() methods do not update the
3507: * underlying database, instead the updateRow() or insertRow() methods are
3508: * called to update the database.
3509: *
3510: * @param columnName
3511: * the name of the column
3512: * @param x
3513: * the new column value
3514: * @param length
3515: * of the stream
3516: * @exception SQLException
3517: * if a database-access error occurs
3518: */
3519: public void updateAsciiStream(String columnName,
3520: java.io.InputStream x, int length) throws SQLException {
3521: checkIfClosed("updateAsciiStream");
3522: updateAsciiStream(findColumnName(columnName), x, length);
3523: }
3524:
3525: /**
3526: * JDBC 2.0
3527: *
3528: * Update a column with a binary stream value.
3529: *
3530: * The updateXXX() methods are used to update column values in the current
3531: * row, or the insert row. The updateXXX() methods do not update the
3532: * underlying database, instead the updateRow() or insertRow() methods are
3533: * called to update the database.
3534: *
3535: * @param columnName
3536: * the name of the column
3537: * @param x
3538: * the new column value
3539: * @param length
3540: * of the stream
3541: * @exception SQLException
3542: * if a database-access error occurs
3543: */
3544: public void updateBinaryStream(String columnName,
3545: java.io.InputStream x, int length) throws SQLException {
3546: checkIfClosed("updateBinaryStream");
3547: updateBinaryStream(findColumnName(columnName), x, length);
3548: }
3549:
3550: /**
3551: * JDBC 2.0
3552: *
3553: * Update a column with a character stream value.
3554: *
3555: * The updateXXX() methods are used to update column values in the current
3556: * row, or the insert row. The updateXXX() methods do not update the
3557: * underlying database, instead the updateRow() or insertRow() methods are
3558: * called to update the database.
3559: *
3560: * @param columnName
3561: * the name of the column
3562: * @param reader
3563: * the new column value
3564: * @param length
3565: * length of the stream
3566: * @exception SQLException
3567: * if a database-access error occurs
3568: */
3569: public void updateCharacterStream(String columnName,
3570: java.io.Reader reader, int length) throws SQLException {
3571: checkIfClosed("updateCharacterStream");
3572: updateCharacterStream(findColumnName(columnName), reader,
3573: length);
3574: }
3575:
3576: /**
3577: * JDBC 2.0
3578: *
3579: * Update a column with an Object value.
3580: *
3581: * The updateXXX() methods are used to update column values in the
3582: * current row, or the insert row. The updateXXX() methods do not
3583: * update the underlying database, instead the updateRow() or insertRow()
3584: * methods are called to update the database.
3585: *
3586: * @param columnName the name of the column
3587: * @param x the new column value
3588: * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
3589: * this is the number of digits after the decimal. For all other
3590: * types this value will be ignored.
3591: * @exception SQLException if a database-access error occurs
3592: */
3593: public void updateObject(String columnName, Object x, int scale)
3594: throws SQLException {
3595: checkIfClosed("updateObject");
3596: updateObject(findColumnName(columnName), x, scale);
3597: }
3598:
3599: /**
3600: * JDBC 2.0
3601: *
3602: * Update a column with an Object value.
3603: *
3604: * The updateXXX() methods are used to update column values in the current
3605: * row, or the insert row. The updateXXX() methods do not update the
3606: * underlying database, instead the updateRow() or insertRow() methods are
3607: * called to update the database.
3608: *
3609: * @param columnName
3610: * the name of the column
3611: * @param x
3612: * the new column value
3613: * @exception SQLException
3614: * if a database-access error occurs
3615: */
3616: public void updateObject(String columnName, Object x)
3617: throws SQLException {
3618: checkIfClosed("updateObject");
3619: updateObject(findColumnName(columnName), x);
3620: }
3621:
3622: /**
3623: * JDBC 2.0
3624: *
3625: * Insert the contents of the insert row into the result set and the
3626: * database. Must be on the insert row when this method is called.
3627: *
3628: * @exception SQLException
3629: * if a database-access error occurs, if called when not on
3630: * the insert row, or if all non-nullable columns in the
3631: * insert row have not been given a value
3632: */
3633: public void insertRow() throws SQLException {
3634: synchronized (getConnectionSynchronization()) {
3635: checksBeforeInsert();
3636: setupContextStack();
3637: LanguageConnectionContext lcc = null;
3638: StatementContext statementContext = null;
3639: try {
3640: /*
3641: * construct the insert statement
3642: *
3643: * If no values have been supplied for a column, it will be set
3644: * to the column's default value, if any.
3645: * If no default value had been defined, the default value of a
3646: * nullable column is set to NULL.
3647: */
3648:
3649: boolean foundOneColumnAlready = false;
3650: StringBuffer insertSQL = new StringBuffer(
3651: "INSERT INTO ");
3652: StringBuffer valuesSQL = new StringBuffer("VALUES (");
3653: CursorActivation activation = getEmbedConnection()
3654: .getLanguageConnection()
3655: .lookupCursorActivation(getCursorName());
3656:
3657: ExecCursorTableReference targetTable = activation
3658: .getPreparedStatement().getTargetTable();
3659: // got the underlying (schema.)table name
3660: insertSQL.append(getFullBaseTableName(targetTable));
3661: ResultDescription rd = theResults
3662: .getResultDescription();
3663:
3664: insertSQL.append(" (");
3665: // in this for loop we are constructing list of column-names
3666: // and values (?) ,... part of the insert sql
3667: for (int i = 1; i <= rd.getColumnCount(); i++) {
3668: if (foundOneColumnAlready) {
3669: insertSQL.append(",");
3670: valuesSQL.append(",");
3671: }
3672: // using quotes around the column name
3673: // to preserve case sensitivity
3674: insertSQL.append(quoteSqlIdentifier(rd
3675: .getColumnDescriptor(i).getName()));
3676: if (columnGotUpdated[i - 1]) {
3677: valuesSQL.append("?");
3678: } else {
3679: valuesSQL.append("DEFAULT");
3680: }
3681: foundOneColumnAlready = true;
3682: }
3683: insertSQL.append(") ");
3684: valuesSQL.append(") ");
3685: insertSQL.append(valuesSQL);
3686:
3687: lcc = getEmbedConnection().getLanguageConnection();
3688:
3689: // Context used for preparing, don't set any timeout (use 0)
3690: statementContext = lcc.pushStatementContext(isAtomic,
3691: false, insertSQL.toString(), null, false, 0L);
3692: org.apache.derby.iapi.sql.PreparedStatement ps = lcc
3693: .prepareInternalStatement(insertSQL.toString());
3694: Activation act = ps.getActivation(lcc, false);
3695:
3696: // in this for loop we are assigning values for parameters
3697: //in sql constructed earlier VALUES (?, ..)
3698: for (int i = 1, paramPosition = 0; i <= rd
3699: .getColumnCount(); i++) {
3700: // if the column got updated, do following
3701: if (columnGotUpdated[i - 1]) {
3702: act.getParameterValueSet().getParameterForSet(
3703: paramPosition++).setValue(
3704: updateRow.getColumn(i));
3705: }
3706: }
3707: // Don't see any timeout when inserting rows (use 0)
3708: //execute the insert
3709: org.apache.derby.iapi.sql.ResultSet rs = ps.execute(
3710: act, true, 0L);
3711: rs.close();
3712: rs.finish();
3713:
3714: lcc.popStatementContext(statementContext, null);
3715: } catch (StandardException t) {
3716: throw closeOnTransactionError(t);
3717: } finally {
3718: if (statementContext != null)
3719: lcc.popStatementContext(statementContext, null);
3720: restoreContextStack();
3721: }
3722: }
3723: }
3724:
3725: /**
3726: * JDBC 2.0
3727: *
3728: * Update the underlying database with the new contents of the
3729: * current row. Cannot be called when on the insert row.
3730: *
3731: * @exception SQLException if a database-access error occurs, or
3732: * if called when on the insert row
3733: */
3734: public void updateRow() throws SQLException {
3735: synchronized (getConnectionSynchronization()) {
3736: checksBeforeUpdateOrDelete("updateRow", -1);
3737:
3738: // Check that the cursor is not positioned on insertRow
3739: checkNotOnInsertRow();
3740:
3741: setupContextStack();
3742: LanguageConnectionContext lcc = null;
3743: StatementContext statementContext = null;
3744: try {
3745: if (currentRowHasBeenUpdated == false) //nothing got updated on this row
3746: return; //nothing to do since no updates were made to this row
3747:
3748: //now construct the update where current of sql
3749: boolean foundOneColumnAlready = false;
3750: StringBuffer updateWhereCurrentOfSQL = new StringBuffer(
3751: "UPDATE ");
3752: CursorActivation activation = getEmbedConnection()
3753: .getLanguageConnection()
3754: .lookupCursorActivation(getCursorName());
3755:
3756: ExecCursorTableReference targetTable = activation
3757: .getPreparedStatement().getTargetTable();
3758: updateWhereCurrentOfSQL
3759: .append(getFullBaseTableName(targetTable));//got the underlying (schema.)table name
3760: updateWhereCurrentOfSQL.append(" SET ");
3761: ResultDescription rd = theResults
3762: .getResultDescription();
3763:
3764: for (int i = 1; i <= rd.getColumnCount(); i++) { //in this for loop we are constructing columnname=?,... part of the update sql
3765: if (columnGotUpdated[i - 1]) { //if the column got updated, do following
3766: if (foundOneColumnAlready)
3767: updateWhereCurrentOfSQL.append(",");
3768: //using quotes around the column name to preserve case sensitivity
3769: updateWhereCurrentOfSQL
3770: .append(quoteSqlIdentifier(rd
3771: .getColumnDescriptor(i)
3772: .getName())
3773: + "=?");
3774: foundOneColumnAlready = true;
3775: }
3776: }
3777: //using quotes around the cursor name to preserve case sensitivity
3778: updateWhereCurrentOfSQL.append(" WHERE CURRENT OF "
3779: + quoteSqlIdentifier(getCursorName()));
3780: lcc = getEmbedConnection().getLanguageConnection();
3781:
3782: // Context used for preparing, don't set any timeout (use 0)
3783: statementContext = lcc.pushStatementContext(isAtomic,
3784: false, updateWhereCurrentOfSQL.toString(),
3785: null, false, 0L);
3786: org.apache.derby.iapi.sql.PreparedStatement ps = lcc
3787: .prepareInternalStatement(updateWhereCurrentOfSQL
3788: .toString());
3789: Activation act = ps.getActivation(lcc, false);
3790:
3791: //in this for loop we are assigning values for parameters in sql constructed earlier with columnname=?,...
3792: for (int i = 1, paramPosition = 0; i <= rd
3793: .getColumnCount(); i++) {
3794: if (columnGotUpdated[i - 1]) //if the column got updated, do following
3795: act.getParameterValueSet().getParameterForSet(
3796: paramPosition++).setValue(
3797: updateRow.getColumn(i));
3798: }
3799: // Don't set any timeout when updating rows (use 0)
3800: // Execute the update where current of sql.
3801: org.apache.derby.iapi.sql.ResultSet rs = ps.execute(
3802: act, true, 0L);
3803: SQLWarning w = act.getWarnings();
3804: if (w != null) {
3805: addWarning(w);
3806: }
3807: rs.close();
3808: rs.finish();
3809: //For forward only resultsets, after a update, the ResultSet will be positioned right before the next row.
3810: if (getType() == TYPE_FORWARD_ONLY) {
3811: currentRow.setRowArray(null);
3812: } else {
3813: movePosition(RELATIVE, 0, "relative");
3814: }
3815: lcc.popStatementContext(statementContext, null);
3816: } catch (StandardException t) {
3817: throw closeOnTransactionError(t);
3818: } finally {
3819: if (statementContext != null)
3820: lcc.popStatementContext(statementContext, null);
3821: restoreContextStack();
3822: initializeUpdateRowModifiers();
3823: }
3824: }
3825: }
3826:
3827: /**
3828: * JDBC 2.0
3829: *
3830: * Delete the current row from the result set and the underlying
3831: * database. Cannot be called when on the insert row.
3832: *
3833: * @exception SQLException if a database-access error occurs, or if
3834: * called when on the insert row.
3835: */
3836: public void deleteRow() throws SQLException {
3837: synchronized (getConnectionSynchronization()) {
3838: checksBeforeUpdateOrDelete("deleteRow", -1);
3839:
3840: // Check that the cursor is not positioned on insertRow
3841: checkNotOnInsertRow();
3842:
3843: setupContextStack();
3844:
3845: LanguageConnectionContext lcc = null;
3846: StatementContext statementContext = null;
3847:
3848: //now construct the delete where current of sql
3849: try {
3850: StringBuffer deleteWhereCurrentOfSQL = new StringBuffer(
3851: "DELETE FROM ");
3852: CursorActivation activation = getEmbedConnection()
3853: .getLanguageConnection()
3854: .lookupCursorActivation(getCursorName());
3855: deleteWhereCurrentOfSQL
3856: .append(getFullBaseTableName(activation
3857: .getPreparedStatement()
3858: .getTargetTable()));//get the underlying (schema.)table name
3859: //using quotes around the cursor name to preserve case sensitivity
3860: deleteWhereCurrentOfSQL.append(" WHERE CURRENT OF "
3861: + quoteSqlIdentifier(getCursorName()));
3862:
3863: lcc = getEmbedConnection().getLanguageConnection();
3864:
3865: // Context used for preparing, don't set any timeout (use 0)
3866: statementContext = lcc.pushStatementContext(isAtomic,
3867: false, deleteWhereCurrentOfSQL.toString(),
3868: null, false, 0L);
3869: org.apache.derby.iapi.sql.PreparedStatement ps = lcc
3870: .prepareInternalStatement(deleteWhereCurrentOfSQL
3871: .toString());
3872: // Get activation, so that we can get the warning from it
3873: Activation act = ps.getActivation(lcc, false);
3874: // Don't set any timeout when deleting rows (use 0)
3875: //execute delete where current of sql
3876: org.apache.derby.iapi.sql.ResultSet rs = ps.execute(
3877: act, true, 0L);
3878: SQLWarning w = act.getWarnings();
3879: if (w != null) {
3880: addWarning(w);
3881: }
3882: rs.close();
3883: rs.finish();
3884: //After a delete, the ResultSet will be positioned right before
3885: //the next row.
3886: currentRow.setRowArray(null);
3887: lcc.popStatementContext(statementContext, null);
3888: } catch (StandardException t) {
3889: throw closeOnTransactionError(t);
3890: } finally {
3891: if (statementContext != null)
3892: lcc.popStatementContext(statementContext, null);
3893: restoreContextStack();
3894: initializeUpdateRowModifiers();
3895: }
3896: }
3897: }
3898:
3899: private String getFullBaseTableName(
3900: ExecCursorTableReference targetTable) {
3901: //using quotes to preserve case sensitivity
3902: if (targetTable.getSchemaName() != null)
3903: return quoteSqlIdentifier(targetTable.getSchemaName())
3904: + "."
3905: + quoteSqlIdentifier(targetTable.getBaseName());
3906: else
3907: return quoteSqlIdentifier(targetTable.getBaseName());
3908: }
3909:
3910: private String quoteSqlIdentifier(String orgValue) {
3911: int i = 0, start = 0;
3912: String retValue = "";
3913: while ((i = orgValue.indexOf("\"", start) + 1) > 0) {
3914: retValue += orgValue.substring(start, i) + "\"";
3915: start = i;
3916: }
3917: retValue += orgValue.substring(start, orgValue.length());
3918: return "\"" + retValue + "\"";
3919: }
3920:
3921: /**
3922: * JDBC 2.0
3923: *
3924: * Refresh the value of the current row with its current value in the
3925: * database. Cannot be called when on the insert row.
3926: *
3927: * The refreshRow() method provides a way for an application to explicitly
3928: * tell the JDBC driver to refetch a row(s) from the database. An
3929: * application may want to call refreshRow() when caching or prefetching is
3930: * being done by the JDBC driver to fetch the latest value of a row from the
3931: * database. The JDBC driver may actually refresh multiple rows at once if
3932: * the fetch size is greater than one.
3933: *
3934: * All values are refetched subject to the transaction isolation level and
3935: * cursor sensitivity. If refreshRow() is called after calling updateXXX(),
3936: * but before calling updateRow() then the updates made to the row are lost.
3937: * Calling refreshRow() frequently will likely slow performance.
3938: *
3939: * @exception SQLException
3940: * if a database-access error occurs, or if called when on
3941: * the insert row.
3942: */
3943: public void refreshRow() throws SQLException {
3944: throw Util.notImplemented();
3945: }
3946:
3947: /**
3948: * JDBC 2.0
3949: *
3950: * The cancelRowUpdates() method may be called after calling an
3951: * updateXXX() method(s) and before calling updateRow() to rollback
3952: * the updates made to a row. If no updates have been made or
3953: * updateRow() has already been called, then this method has no
3954: * effect.
3955: *
3956: * @exception SQLException if a database-access error occurs, or if
3957: * called when on the insert row.
3958: *
3959: */
3960: public void cancelRowUpdates() throws SQLException {
3961: checksBeforeUpdateOrDelete("cancelRowUpdates", -1);
3962:
3963: checkNotOnInsertRow();
3964:
3965: initializeUpdateRowModifiers();
3966: }
3967:
3968: /**
3969: * JDBC 2.0
3970: *
3971: * Move to the insert row. The current cursor position is remembered while
3972: * the cursor is positioned on the insert row.
3973: *
3974: * The insert row is a special row associated with an updatable result set.
3975: * It is essentially a buffer where a new row may be constructed by calling
3976: * the updateXXX() methods prior to inserting the row into the result set.
3977: *
3978: * Only the updateXXX(), getXXX(), and insertRow() methods may be called
3979: * when the cursor is on the insert row. All of the columns in a result set
3980: * must be given a value each time this method is called before calling
3981: * insertRow(). UpdateXXX()must be called before getXXX() on a column.
3982: *
3983: * @exception SQLException
3984: * if a database-access error occurs, or the result set is
3985: * not updatable
3986: */
3987: public void moveToInsertRow() throws SQLException {
3988: checkExecIfClosed("moveToInsertRow");
3989:
3990: // if not updatable resultset, then throw exception
3991: checkUpdatableCursor("moveToInsertRow");
3992:
3993: synchronized (getConnectionSynchronization()) {
3994: try {
3995: // initialize state corresponding to insertRow/updateRow impl.
3996: initializeUpdateRowModifiers();
3997: isOnInsertRow = true;
3998:
3999: for (int i = 1; i <= columnGotUpdated.length; i++) {
4000: updateRow
4001: .setColumn(i, resultDescription
4002: .getColumnDescriptor(i).getType()
4003: .getNull());
4004: }
4005: } catch (Throwable ex) {
4006: handleException(ex);
4007: }
4008: }
4009: }
4010:
4011: /**
4012: * JDBC 2.0
4013: *
4014: * Move the cursor to the remembered cursor position, usually the current
4015: * row. Has no effect unless the cursor is on the insert row.
4016: *
4017: * @exception SQLException
4018: * if a database-access error occurs, or the result set is
4019: * not updatable
4020: */
4021: public void moveToCurrentRow() throws SQLException {
4022: checkExecIfClosed("moveToCurrentRow");
4023:
4024: // if not updatable resultset, then throw exception
4025: checkUpdatableCursor("moveToCurrentRow");
4026:
4027: synchronized (getConnectionSynchronization()) {
4028: try {
4029:
4030: if (isOnInsertRow) {
4031: // initialize state corresponding to insertRow/updateRow impl.
4032: initializeUpdateRowModifiers();
4033:
4034: isOnInsertRow = false;
4035: }
4036: } catch (Throwable ex) {
4037: handleException(ex);
4038: }
4039: }
4040: }
4041:
4042: /**
4043: * JDBC 2.0
4044: *
4045: * Get a BLOB column.
4046: *
4047: * @param columnIndex the first column is 1, the second is 2, ...
4048: * @return an object representing a BLOB
4049: */
4050: public Blob getBlob(int columnIndex) throws SQLException {
4051:
4052: closeCurrentStream(); // closing currentStream does not depend on the
4053: // underlying connection. Do this outside of
4054: // the connection synchronization.
4055:
4056: checkIfClosed("getBlob"); // checking result set closure does not depend
4057: // on the underlying connection. Do this
4058: // outside of the connection synchronization.
4059:
4060: synchronized (getConnectionSynchronization()) {
4061: int colType = getColumnType(columnIndex);
4062:
4063: // DB2, only allow getBlob on a BLOB column.
4064: if (colType != Types.BLOB)
4065: throw dataTypeConversion("java.sql.Blob", columnIndex);
4066:
4067: boolean pushStack = false;
4068: try {
4069: DataValueDescriptor dvd = getColumn(columnIndex);
4070:
4071: if (wasNull = dvd.isNull())
4072: return null;
4073:
4074: // should set up a context stack if we have a long column,
4075: // since a blob may keep a pointer to a long column in the
4076: // database
4077: if (dvd.getStream() != null)
4078: pushStack = true;
4079:
4080: if (pushStack)
4081: setupContextStack();
4082:
4083: return new EmbedBlob(dvd, getEmbedConnection());
4084: } catch (Throwable t) {
4085: throw handleException(t);
4086: } finally {
4087: if (pushStack)
4088: restoreContextStack();
4089: }
4090: }
4091: }
4092:
4093: /**
4094: * JDBC 2.0
4095: *
4096: * Get a CLOB column.
4097: *
4098: * @param columnIndex the first column is 1, the second is 2, ...
4099: * @return an object representing a CLOB
4100: */
4101: public final Clob getClob(int columnIndex) throws SQLException {
4102:
4103: closeCurrentStream(); // closing currentStream does not depend on the
4104: // underlying connection. Do this outside of
4105: // the connection synchronization.
4106:
4107: checkIfClosed("getClob"); // checking result set closure does not depend
4108: // on the underlying connection. Do this
4109: // outside of the connection synchronization.
4110:
4111: synchronized (getConnectionSynchronization()) {
4112: int colType = getColumnType(columnIndex);
4113:
4114: // DB2:, only allow getClob on a CLOB column.
4115: if (colType != Types.CLOB)
4116: throw dataTypeConversion("java.sql.Clob", columnIndex);
4117:
4118: boolean pushStack = false;
4119: try {
4120:
4121: DataValueDescriptor dvd = getColumn(columnIndex);
4122:
4123: if (wasNull = dvd.isNull())
4124: return null;
4125:
4126: // should set up a context stack if we have a long column,
4127: // since a blob may keep a pointer to a long column in the
4128: // database
4129: if (dvd.getStream() != null)
4130: pushStack = true;
4131:
4132: if (pushStack)
4133: setupContextStack();
4134:
4135: return new EmbedClob(dvd, getEmbedConnection());
4136: } catch (Throwable t) {
4137: throw handleException(t);
4138: } finally {
4139: if (pushStack)
4140: restoreContextStack();
4141: }
4142: }
4143: }
4144:
4145: /**
4146: * JDBC 2.0
4147: *
4148: * Get a BLOB column.
4149: *
4150: * @param columnName the column name
4151: * @return an object representing a BLOB
4152: */
4153: public final Blob getBlob(String columnName) throws SQLException {
4154: checkIfClosed("getBlob");
4155: return (getBlob(findColumnName(columnName)));
4156: }
4157:
4158: /**
4159: * JDBC 2.0
4160: *
4161: * Get a CLOB column.
4162: *
4163: * @param columnName the column name
4164: * @return an object representing a CLOB
4165: * @exception SQLException
4166: * Feature not implemented for now.
4167: */
4168: public final Clob getClob(String columnName) throws SQLException {
4169: checkIfClosed("getClob");
4170: return (getClob(findColumnName(columnName)));
4171: }
4172:
4173: /**
4174: * JDBC 3.0
4175: *
4176: * Updates the designated column with a java.sql.Blob value. The updater
4177: * methods are used to update column values in the current row or the insert
4178: * row. The updater methods do not update the underlying database; instead
4179: * the updateRow or insertRow methods are called to update the database.
4180: *
4181: * @param columnIndex -
4182: * the first column is 1, the second is 2
4183: * @param x -
4184: * the new column value
4185: * @exception SQLException
4186: * Feature not implemented for now.
4187: */
4188: public void updateBlob(int columnIndex, Blob x) throws SQLException {
4189: checksBeforeUpdateXXX("updateBlob", columnIndex);
4190: int colType = getColumnType(columnIndex);
4191: if (colType != Types.BLOB)
4192: throw dataTypeConversion(columnIndex, "java.sql.Blob");
4193:
4194: if (x == null)
4195: updateNull(columnIndex);
4196: else {
4197: long length = x.length();
4198: updateBinaryStreamInternal(columnIndex,
4199: x.getBinaryStream(), false, length, "updateBlob");
4200: }
4201: }
4202:
4203: /**
4204: * JDBC 3.0
4205: *
4206: * Updates the designated column with a java.sql.Blob value. The updater
4207: * methods are used to update column values in the current row or the insert
4208: * row. The updater methods do not update the underlying database; instead
4209: * the updateRow or insertRow methods are called to update the database.
4210: *
4211: * @param columnName -
4212: * the SQL name of the column
4213: * @param x -
4214: * the new column value
4215: * @exception SQLException
4216: * Feature not implemented for now.
4217: */
4218: public void updateBlob(String columnName, Blob x)
4219: throws SQLException {
4220: checkIfClosed("updateBlob");
4221: updateBlob(findColumnName(columnName), x);
4222: }
4223:
4224: /**
4225: * JDBC 3.0
4226: *
4227: * Updates the designated column with a java.sql.Clob value. The updater
4228: * methods are used to update column values in the current row or the insert
4229: * row. The updater methods do not update the underlying database; instead
4230: * the updateRow or insertRow methods are called to update the database.
4231: *
4232: * @param columnIndex -
4233: * the first column is 1, the second is 2
4234: * @param x -
4235: * the new column value
4236: * @exception SQLException
4237: * Feature not implemented for now.
4238: */
4239: public void updateClob(int columnIndex, Clob x) throws SQLException {
4240: checksBeforeUpdateXXX("updateClob", columnIndex);
4241: int colType = getColumnType(columnIndex);
4242: if (colType != Types.CLOB)
4243: throw dataTypeConversion(columnIndex, "java.sql.Clob");
4244:
4245: if (x == null) {
4246: updateNull(columnIndex);
4247: } else {
4248:
4249: long length = x.length();
4250:
4251: updateCharacterStreamInternal(columnIndex, x
4252: .getCharacterStream(), false, length, "updateClob");
4253: }
4254: }
4255:
4256: /**
4257: * JDBC 3.0
4258: *
4259: * Updates the designated column with a java.sql.Clob value. The updater
4260: * methods are used to update column values in the current row or the insert
4261: * row. The updater methods do not update the underlying database; instead
4262: * the updateRow or insertRow methods are called to update the database.
4263: *
4264: * @param columnName -
4265: * the SQL name of the column
4266: * @param x -
4267: * the new column value
4268: * @exception SQLException
4269: * Feature not implemented for now.
4270: */
4271: public void updateClob(String columnName, Clob x)
4272: throws SQLException {
4273: checkIfClosed("updateClob");
4274: updateClob(findColumnName(columnName), x);
4275: }
4276:
4277: /*
4278: * * End of JDBC public methods.
4279: */
4280:
4281: /**
4282: * Map a Resultset column name to a ResultSet column index.
4283: *
4284: * @param columnName
4285: * the name of the column
4286: * @return the column index
4287: * @exception SQLException
4288: * thrown on failure.
4289: */
4290: protected int findColumnName(String columnName) throws SQLException {
4291: // n.b. if we went through the JDBC interface,
4292: // there is a caching implementation in the JDBC doc
4293: // (appendix C). But we go through our own info, for now.
4294:
4295: if (columnName == null)
4296: throw newSQLException(SQLState.NULL_COLUMN_NAME);
4297:
4298: final Map workMap;
4299:
4300: synchronized (this ) {
4301: if (columnNameMap == null) {
4302: // updateXXX and getXXX methods are case insensitive and the
4303: // first column should be returned. The loop goes backward to
4304: // create a map which preserves this property.
4305: columnNameMap = new HashMap();
4306: for (int i = resultDescription.getColumnCount(); i >= 1; i--) {
4307:
4308: final String key = StringUtil
4309: .SQLToUpperCase(resultDescription
4310: .getColumnDescriptor(i).getName());
4311:
4312: final Integer value = ReuseFactory.getInteger(i);
4313:
4314: columnNameMap.put(key, value);
4315: }
4316: }
4317: workMap = columnNameMap;
4318: }
4319:
4320: Integer val = (Integer) workMap.get(columnName);
4321: if (val == null) {
4322: val = (Integer) workMap.get(StringUtil
4323: .SQLToUpperCase(columnName));
4324: }
4325: if (val == null) {
4326: throw newSQLException(SQLState.COLUMN_NOT_FOUND, columnName);
4327: } else {
4328: return val.intValue();
4329: }
4330: }
4331:
4332: //
4333: // methods to be overridden in subimplementations
4334: // that want to stay within their subimplementation.
4335: //
4336: protected EmbedResultSetMetaData newEmbedResultSetMetaData(
4337: ResultDescription resultDesc) {
4338: return factory.newEmbedResultSetMetaData(resultDesc
4339: .getColumnInfo());
4340: }
4341:
4342: /**
4343: * Documented behaviour for streams is that they are implicitly closed on
4344: * the next get*() method call.
4345: */
4346: private final void closeCurrentStream() {
4347:
4348: if (currentStream != null) {
4349: try {
4350: // 99% of the time, the stream is already closed.
4351: synchronized (this ) {
4352: if (currentStream != null) {
4353: if (currentStream instanceof java.io.Reader)
4354: ((java.io.Reader) currentStream).close();
4355: else
4356: ((java.io.InputStream) currentStream)
4357: .close();
4358: }
4359: }
4360: } catch (IOException ioe) {
4361: // just ignore, caller has already read the data they require
4362: } finally {
4363: currentStream = null;
4364: }
4365: }
4366: }
4367:
4368: /**
4369: * Throw an exception if this ResultSet is closed.
4370: *
4371: * @param operation The operation the caller is trying to perform
4372: *
4373: * @exception SQLException Thrown if this ResultSet is closed.
4374: */
4375: final void checkIfClosed(String operation) throws SQLException {
4376: if (isClosed) {
4377: throw newSQLException(SQLState.LANG_RESULT_SET_NOT_OPEN,
4378: operation);
4379: }
4380: }
4381:
4382: /**
4383: * Throw an exception if this ResultSet is closed or its
4384: * Connection has been closed. If the ResultSet has not
4385: * been explictly closed but the Connection is closed,
4386: * then this ResultSet will be marked as closed.
4387: */
4388: final void checkExecIfClosed(String operation) throws SQLException {
4389:
4390: checkIfClosed(operation);
4391:
4392: java.sql.Connection appConn = getEmbedConnection()
4393: .getApplicationConnection();
4394:
4395: // Currently disconnected, i.e. a detached gobal transaction
4396: if (appConn == null)
4397: throw Util.noCurrentConnection();
4398:
4399: if (appConn.isClosed()) {
4400: closeCurrentStream();
4401: isClosed = true;
4402: throw Util.noCurrentConnection();
4403: }
4404: }
4405:
4406: /**
4407: * Try to see if we can fish the SQL Statement out of the local statement.
4408: * @return null if we cannot figure out what SQL Statement is currently
4409: * executing
4410: */
4411: protected String getSQLText() {
4412: if (stmt == null)
4413: return null;
4414:
4415: return stmt.getSQLText();
4416: }
4417:
4418: /**
4419: * Try to see if we can fish the pvs out of the local statement.
4420: * @return null if we cannot figure out what parameter value set is currently
4421: * using
4422: */
4423: protected ParameterValueSet getParameterValueSet() {
4424: if (stmt == null)
4425: return null;
4426:
4427: return stmt.getParameterValueSet();
4428: }
4429:
4430: private static boolean isMaxFieldSizeType(int colType) {
4431: return (colType == Types.BINARY || colType == Types.VARBINARY
4432: || colType == Types.LONGVARBINARY
4433: || colType == Types.CHAR || colType == Types.VARCHAR || colType == Types.LONGVARCHAR);
4434: }
4435:
4436: /*
4437: * close result set if we have a transaction level error
4438: */
4439: final SQLException closeOnTransactionError(Throwable thrownException)
4440: throws SQLException {
4441: SQLException sqle = handleException(thrownException);
4442: if (thrownException instanceof StandardException) {
4443: StandardException se = (StandardException) thrownException;
4444: int severity = se.getSeverity();
4445: if (severity == ExceptionSeverity.TRANSACTION_SEVERITY) {
4446: try {
4447: close();
4448: } catch (Throwable t) {
4449: SQLException top = handleException(t);
4450: top.setNextException(sqle);
4451: sqle = top;
4452: }
4453: }
4454: }
4455:
4456: return sqle;
4457: }
4458:
4459: /**
4460: Get the column value for a getXXX() call.
4461: This method:
4462: <UL>
4463: <LI> Closes the current stream (as per JDBC)
4464: <LI> Throws a SQLException if the result set is closed
4465: <LI> Throws a SQLException if the ResultSet is not on a row
4466: <LI> Throws a SQLException if the columnIndex is out of range
4467: <LI> Returns the DataValueDescriptor for the column.
4468: </UL>
4469: */
4470: protected final DataValueDescriptor getColumn(int columnIndex)
4471: throws SQLException, StandardException {
4472:
4473: closeCurrentStream();
4474:
4475: if (columnIndex < 1 || columnIndex > currentRow.nColumns()) {
4476: throw newSQLException(SQLState.COLUMN_NOT_FOUND,
4477: new Integer(columnIndex));
4478: }
4479: if (isOnInsertRow || currentRowHasBeenUpdated
4480: && columnGotUpdated[columnIndex - 1]) {
4481: return updateRow.getColumn(columnIndex);
4482: } else {
4483: checkOnRow(); // make sure there's a row
4484: return currentRow.getColumn(columnIndex);
4485: }
4486: }
4487:
4488: /**
4489: An exception on many method calls to JDBC objects does not change the state
4490: of the transaction or statement, or even the underlying object. This method
4491: simply wraps the excecption in a SQLException. Examples are:
4492: <UL>
4493: <LI> getXXX() calls on ResultSet - ResultSet is not closed.
4494: <LI> setXXX() calls on PreparedStatement - ResultSet is not closed.
4495: </UL>
4496: In addition these exceptions must not call higher level objects to
4497: be closed (e.g. when executing a server side Java procedure). See bug 4397
4498:
4499: */
4500: static final SQLException noStateChangeException(
4501: Throwable thrownException) {
4502:
4503: // Any exception on a setXXX/getXXX method does not close
4504: // the ResultSet or the Statement. So we only need
4505: // to convert the exception to a SQLException.
4506:
4507: return TransactionResourceImpl.wrapInSQLException(
4508: (SQLException) null, thrownException);
4509:
4510: }
4511:
4512: /**
4513: A dynamic result set was created in a procedure by a nested connection.
4514: Once the procedure returns, there is a good chance that connection is closed,
4515: so we re-attach the result set to the connection of the statement the called
4516: the procedure, which will be still open.
4517: */
4518: void setDynamicResultSet(EmbedStatement owningStmt) {
4519:
4520: this .owningStmt = owningStmt;
4521: this .localConn = owningStmt.getEmbedConnection();
4522: }
4523:
4524: /*
4525: ** Comparable (for ordering dynamic result sets from procedures)
4526: */
4527:
4528: public final int compareTo(Object other) {
4529:
4530: EmbedResultSet olrs = (EmbedResultSet) other;
4531:
4532: return order - olrs.order;
4533:
4534: }
4535:
4536: /**
4537: * Checks if the result set has a scrollable cursor.
4538: *
4539: * @param methodName name of the method which requests the check
4540: * @exception SQLException if the result set is closed or its type
4541: * is <code>TYPE_FORWARD_ONLY</code>
4542: */
4543: private void checkScrollCursor(String methodName)
4544: throws SQLException {
4545: checkIfClosed(methodName);
4546: if (stmt.getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY)
4547: throw Util
4548: .newEmbedSQLException(
4549: SQLState.NOT_ON_FORWARD_ONLY_CURSOR,
4550: new Object[] { methodName },
4551: StandardException
4552: .getSeverityFromIdentifier(SQLState.NOT_ON_FORWARD_ONLY_CURSOR));
4553: }
4554:
4555: private void checkUpdatableCursor(String operation)
4556: throws SQLException {
4557: if (getConcurrency() != JDBC20Translation.CONCUR_UPDATABLE) {
4558: throw Util.generateCsSQLException(
4559: SQLState.UPDATABLE_RESULTSET_API_DISALLOWED,
4560: operation);
4561: }
4562: }
4563:
4564: private boolean checkRowPosition(int position, String positionText)
4565: throws SQLException {
4566: // beforeFirst is only allowed on scroll cursors
4567: checkScrollCursor(positionText);
4568:
4569: synchronized (getConnectionSynchronization()) {
4570: setupContextStack();
4571: try {
4572: try {
4573:
4574: /*
4575: * Push and pop a StatementContext around a next call so
4576: * that the ResultSet will get correctly closed down on an
4577: * error. (Cache the LanguageConnectionContext)
4578: */
4579: LanguageConnectionContext lcc = getEmbedConnection()
4580: .getLanguageConnection();
4581: // No timeout for this operation (use 0)
4582: StatementContext statementContext = lcc
4583: .pushStatementContext(
4584: isAtomic,
4585: concurrencyOfThisResultSet == JDBC20Translation.CONCUR_READ_ONLY,
4586: getSQLText(),
4587: getParameterValueSet(), false, 0L);
4588:
4589: boolean result = theResults
4590: .checkRowPosition(position);
4591:
4592: lcc.popStatementContext(statementContext, null);
4593:
4594: return result;
4595:
4596: } catch (Throwable t) {
4597: /*
4598: * Need to close the result set here because the error might
4599: * cause us to lose the current connection if this is an XA
4600: * connection and we won't be able to do the close later
4601: */
4602: throw closeOnTransactionError(t);
4603: }
4604:
4605: } finally {
4606: restoreContextStack();
4607: }
4608: }
4609: }
4610:
4611: /**
4612: * * Is this result set from a select for update statement?
4613: */
4614: public final boolean isForUpdate() {
4615: if (theResults instanceof NoPutResultSet)
4616: return ((NoPutResultSet) theResults).isForUpdate();
4617: return false;
4618: }
4619:
4620: final String getColumnSQLType(int column) {
4621: return resultDescription.getColumnDescriptor(column).getType()
4622: .getTypeId().getSQLTypeName();
4623: }
4624:
4625: /**
4626: * Return the user-defined maximum size of the column.
4627: *
4628: * Note that this may be different from the maximum column size Derby is
4629: * able, or allowed, to handle (called 'maximum maximum length').
4630: *
4631: * @param columnIndex the 1-based index of the column
4632: * @return the maximum length of the column
4633: */
4634: private final int getMaxColumnWidth(int columnIndex) {
4635: return resultDescription.getColumnDescriptor(columnIndex)
4636: .getType().getMaximumWidth();
4637: }
4638:
4639: private final SQLException dataTypeConversion(String targetType,
4640: int column) {
4641: return newSQLException(SQLState.LANG_DATA_TYPE_GET_MISMATCH,
4642: targetType, getColumnSQLType(column));
4643: }
4644:
4645: private final SQLException dataTypeConversion(int column,
4646: String targetType) {
4647: return newSQLException(SQLState.LANG_DATA_TYPE_GET_MISMATCH,
4648: getColumnSQLType(column), targetType);
4649: }
4650:
4651: /**
4652: * Mark a column as already having a stream accessed from it.
4653: * If the stream was already accessed, then throw an exception.
4654: * @param columnIndex
4655: * @throws SQLException
4656: */
4657: final void useStream(int columnIndex) throws SQLException {
4658:
4659: if (streamUsedFlags == null)
4660: streamUsedFlags = new boolean[getMetaData()
4661: .getColumnCount()];
4662:
4663: else if (streamUsedFlags[columnIndex - 1])
4664: throw newSQLException(SQLState.LANG_STREAM_RETRIEVED_ALREADY);
4665:
4666: streamUsedFlags[columnIndex - 1] = true;
4667: }
4668:
4669: /**
4670: * JDBC 4.0
4671: *
4672: * <p>
4673: * Checks whether this <code>ResultSet</code> object has been
4674: * closed, either automatically or because <code>close()</code>
4675: * has been called.
4676: *
4677: * @return <code>true</code> if the <code>ResultSet</code> is
4678: * closed, <code>false</code> otherwise
4679: * @exception SQLException if a database error occurs
4680: */
4681: public final boolean isClosed() throws SQLException {
4682: if (isClosed)
4683: return true;
4684: try {
4685: // isClosed is not updated when EmbedConnection.close() is
4686: // called, so we need to check the status of the
4687: // connection
4688: checkExecIfClosed("");
4689: return false;
4690: } catch (SQLException sqle) {
4691: return isClosed;
4692: }
4693: }
4694:
4695: /**
4696: * Adds a warning to the end of the warning chain.
4697: *
4698: * @param w The warning to add to the warning chain.
4699: */
4700: private void addWarning(SQLWarning w) {
4701: if (topWarning == null) {
4702: topWarning = w;
4703: } else {
4704: topWarning.setNextWarning(w);
4705: }
4706: }
4707:
4708: /**
4709: *
4710: * JDBC 2.0
4711: *
4712: * Update a column with an ascii stream value.
4713: *
4714: * The updateXXX() methods are used to update column values in the current
4715: * row, or the insert row. The updateXXX() methods do not update the
4716: * underlying database, instead the updateRow() or insertRow() methods are
4717: * called to update the database.
4718: *
4719: * @param columnIndex
4720: * the first column is 1, the second is 2, ...
4721: * @param x
4722: * the new column value
4723: * @param length
4724: * the length of the stream
4725: * @exception SQLException
4726: * if a database-access error occurs
4727: */
4728: public void updateAsciiStream(int columnIndex,
4729: java.io.InputStream x, int length) throws SQLException {
4730: checkIfClosed("updateAsciiStream");
4731: updateAsciiStream(columnIndex, x, (long) length);
4732: }
4733:
4734: /**
4735: *
4736: * JDBC 2.0
4737: *
4738: * Update a column with a binary stream value.
4739: *
4740: * The updateXXX() methods are used to update column values in the current
4741: * row, or the insert row. The updateXXX() methods do not update the
4742: * underlying database, instead the updateRow() or insertRow() methods are
4743: * called to update the database.
4744: *
4745: * @param columnIndex
4746: * the first column is 1, the second is 2, ...
4747: * @param x
4748: * the new column value
4749: * @param length
4750: * the length of the stream
4751: * @exception SQLException
4752: * if a database-access error occurs
4753: */
4754: public void updateBinaryStream(int columnIndex,
4755: java.io.InputStream x, int length) throws SQLException {
4756: checkIfClosed("updateBinaryStream");
4757: updateBinaryStream(columnIndex, x, (long) length);
4758: }
4759:
4760: /**
4761: *
4762: * JDBC 2.0
4763: *
4764: * Update a column with a character stream value.
4765: *
4766: * The updateXXX() methods are used to update column values in the current
4767: * row, or the insert row. The updateXXX() methods do not update the
4768: * underlying database, instead the updateRow() or insertRow() methods are
4769: * called to update the database.
4770: *
4771: * @param columnIndex
4772: * the first column is 1, the second is 2, ...
4773: * @param x
4774: * the new column value
4775: * @param length
4776: * the length of the stream
4777: * @exception SQLException
4778: * if a database-access error occurs
4779: */
4780: public void updateCharacterStream(int columnIndex,
4781: java.io.Reader x, int length) throws SQLException {
4782: checkIfClosed("updateCharacterStream");
4783: updateCharacterStream(columnIndex, x, (long) length);
4784: }
4785:
4786: /**
4787: *
4788: * JDBC 4.0
4789: *
4790: * Update a column with an ascii stream value.
4791: *
4792: * The updateXXX() methods are used to update column values in the current
4793: * row, or the insert row. The updateXXX() methods do not update the
4794: * underlying database, instead the updateRow() or insertRow() methods are
4795: * called to update the database.
4796: *
4797: * @param columnName
4798: * the name of the column
4799: * @param x
4800: * the new column value
4801: * @param length
4802: * of the stream
4803: * @exception SQLException
4804: * if a database-access error occurs
4805: */
4806: public void updateAsciiStream(String columnName,
4807: java.io.InputStream x, long length) throws SQLException {
4808: checkIfClosed("updateAsciiStream");
4809: updateAsciiStream(findColumnName(columnName), x, length);
4810: }
4811:
4812: /**
4813: * Updates the designated column with a character stream value.
4814: * The data will be read from the stream as needed until end-of-stream is
4815: * reached.
4816: *
4817: * The updater methods are used to update column values in the current row
4818: * or the insert row. The updater methods do not update the underlying
4819: * database; instead the <code>updateRow</code> or </code>insertRow</code>
4820: * methods are called to update the database.
4821: *
4822: * @param columnName the label for the column specified with the SQL AS
4823: * clause. If the SQL AS clause was not specified, then the label is
4824: * the name of the column
4825: * @param x the new column value
4826: * @throws SQLException if the columnIndex is not valid; if a database
4827: * access error occurs; the result set concurrency is
4828: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
4829: * result set
4830: */
4831: public void updateAsciiStream(String columnName, InputStream x)
4832: throws SQLException {
4833: checkIfClosed("updateAsciiStream");
4834: updateAsciiStream(findColumnName(columnName), x);
4835: }
4836:
4837: /**
4838: *
4839: * JDBC 4.0
4840: *
4841: * Update a column with a binary stream value.
4842: *
4843: * The updateXXX() methods are used to update column values in the current
4844: * row, or the insert row. The updateXXX() methods do not update the
4845: * underlying database, instead the updateRow() or insertRow() methods are
4846: * called to update the database.
4847: *
4848: * @param columnName
4849: * the name of the column
4850: * @param x
4851: * the new column value
4852: * @param length
4853: * of the stream
4854: * @exception SQLException
4855: * if a database-access error occurs
4856: */
4857:
4858: public void updateBinaryStream(String columnName,
4859: java.io.InputStream x, long length) throws SQLException {
4860: checkIfClosed("updateBinaryStream");
4861: updateBinaryStream(findColumnName(columnName), x, length);
4862: }
4863:
4864: /**
4865: * Updates the designated column with a binary stream value.
4866: * The data will be read from the stream as needed until end-of-stream is
4867: * reached.
4868: *
4869: * The updater methods are used to update column values in the current row
4870: * or the insert row. The updater methods do not update the underlying
4871: * database; instead the <code>updateRow</code> or <code>insertRow</code>
4872: * methods are called to update the database.
4873: *
4874: * @param columnName the label for the column specified with the SQL AS
4875: * clause. If the SQL AS clause was not specified, then the label is
4876: * the name of the column
4877: * @param x the new column value
4878: * @throws SQLException if the columnLabel is not valid; if a database
4879: * access error occurs; the result set concurrency is
4880: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
4881: * result set
4882: */
4883: public void updateBinaryStream(String columnName, InputStream x)
4884: throws SQLException {
4885: checkIfClosed("updateBinaryStream");
4886: updateBinaryStream(findColumnName(columnName), x);
4887: }
4888:
4889: /**
4890: * JDBC 4.0
4891: *
4892: * Update a column with a character stream value.
4893: *
4894: * The updateXXX() methods are used to update column values in the current
4895: * row, or the insert row. The updateXXX() methods do not update the
4896: * underlying database, instead the updateRow() or insertRow() methods are
4897: * called to update the database.
4898: *
4899: * @param columnName
4900: * the name of the column
4901: * @param reader
4902: * the new column value
4903: * @param length
4904: * length of the stream
4905: * @exception SQLException
4906: * if a database-access error occurs
4907: */
4908: public void updateCharacterStream(String columnName,
4909: java.io.Reader reader, long length) throws SQLException {
4910: checkIfClosed("updateCharacterStream");
4911: updateCharacterStream(findColumnName(columnName), reader,
4912: length);
4913: }
4914:
4915: /**
4916: * Updates the designated column with a character stream value.
4917: * The data will be read from the stream as needed until end-of-stream is
4918: * reached.
4919: *
4920: * The updater methods are used to update column values in the current row
4921: * or the insert row. The updater methods do not update the underlying
4922: * database; instead the <code>updateRow</code> or </code>insertRow</code>
4923: * methods are called to update the database.
4924: *
4925: * @param columnName the label for the column specified with the SQL AS
4926: * clause. If the SQL AS clause was not specified, then the label is
4927: * the name of the column
4928: * @param reader the new column value
4929: * @throws SQLException if the columnIndex is not valid; if a database
4930: * access error occurs; the result set concurrency is
4931: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
4932: * result set
4933: */
4934: public void updateCharacterStream(String columnName, Reader reader)
4935: throws SQLException {
4936: checkIfClosed("updateCharacterStream");
4937: updateCharacterStream(findColumnName(columnName), reader);
4938: }
4939:
4940: /**
4941: *
4942: * JDBC 4.0
4943: *
4944: * Updates the designated column with a java.sql.Blob value. The updater
4945: * methods are used to update column values in the current row or the insert
4946: * row. The updater methods do not update the underlying database; instead
4947: * the updateRow or insertRow methods are called to update the database.
4948: *
4949: * @param columnIndex -
4950: * the first column is 1, the second is 2
4951: * @param x -
4952: * the new column value
4953: * @param length -
4954: * the length of the Blob datatype
4955: * @exception SQLException
4956: *
4957: */
4958: public void updateBlob(int columnIndex, InputStream x, long length)
4959: throws SQLException {
4960: checksBeforeUpdateXXX("updateBlob", columnIndex);
4961: int colType = getColumnType(columnIndex);
4962: if (colType != Types.BLOB)
4963: throw dataTypeConversion(columnIndex, "java.sql.Blob");
4964:
4965: if (x == null)
4966: updateNull(columnIndex);
4967: else {
4968: updateBinaryStreamInternal(columnIndex, x, false, length,
4969: "updateBlob");
4970: }
4971: }
4972:
4973: /**
4974: * Updates the designated column using the given input stream.
4975: * The data will be read from the stream as needed until end-of-stream is reached.
4976: *
4977: * The updater methods are used to update column values in the current row
4978: * or the insert row. The updater methods do not update the underlying
4979: * database; instead the updateRow or insertRow methods are called to
4980: * update the database.
4981: *
4982: * @param columnIndex the first column is 1, the second is 2, ...
4983: * @param x an object that contains the data to set the
4984: * parameter value to.
4985: * @throws SQLException if the columnIndex is not valid; if a database
4986: * access error occurs; the result set concurrency is
4987: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
4988: * result set
4989: */
4990: public void updateBlob(int columnIndex, InputStream x)
4991: throws SQLException {
4992: checksBeforeUpdateXXX("updateBlob", columnIndex);
4993: int colType = getColumnType(columnIndex);
4994: if (colType != Types.BLOB) {
4995: throw dataTypeConversion(columnIndex, "java.sql.Blob");
4996: }
4997: updateBinaryStreamInternal(columnIndex, x, true, -1,
4998: "updateBlob");
4999: }
5000:
5001: /**
5002: *
5003: * JDBC 4.0
5004: *
5005: * Updates the designated column with a java.sql.Blob value. The updater
5006: * methods are used to update column values in the current row or the insert
5007: * row. The updater methods do not update the underlying database; instead
5008: * the updateRow or insertRow methods are called to update the database.
5009: *
5010: * @param columnName -
5011: * the name of the column to be updated
5012: * @param x -
5013: * the new column value
5014: * @param length -
5015: * the length of the Blob datatype
5016: * @exception SQLException
5017: *
5018: */
5019:
5020: public void updateBlob(String columnName, InputStream x, long length)
5021: throws SQLException {
5022: checkIfClosed("updateBlob");
5023: updateBlob(findColumnName(columnName), x, length);
5024: }
5025:
5026: /**
5027: * Updates the designated column using the given input stream.
5028: * The data will be read from the stream as needed until end-of-stream is reached.
5029: *
5030: * The updater methods are used to update column values in the current row
5031: * or the insert row. The updater methods do not update the underlying
5032: * database; instead the updateRow or insertRow methods are called to
5033: * update the database.
5034: *
5035: * @param columnName the label for the column specified with the SQL AS
5036: * clause. If the SQL AS clause was not specified, then the label is
5037: * the name of the column
5038: * @param x an object that contains the data to set the
5039: * parameter value to.
5040: * @throws SQLException if the columnIndex is not valid; if a database
5041: * access error occurs; the result set concurrency is
5042: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5043: * result set
5044: */
5045: public void updateBlob(String columnName, InputStream x)
5046: throws SQLException {
5047: checkIfClosed("updateBlob");
5048: updateBlob(findColumnName(columnName), x);
5049: }
5050:
5051: /**
5052: *
5053: * JDBC 4.0
5054: *
5055: * Updates the designated column with a java.sql.Clob value. The updater
5056: * methods are used to update column values in the current row or the insert
5057: * row. The updater methods do not update the underlying database; instead
5058: * the updateRow or insertRow methods are called to update the database.
5059: *
5060: * @param columnIndex -
5061: * the first column is 1, the second is 2
5062: * @param x -
5063: * the new column value
5064: * @exception SQLException
5065: * Feature not implemented for now.
5066: */
5067: public void updateClob(int columnIndex, Reader x, long length)
5068: throws SQLException {
5069: checksBeforeUpdateXXX("updateClob", columnIndex);
5070: int colType = getColumnType(columnIndex);
5071: if (colType != Types.CLOB)
5072: throw dataTypeConversion(columnIndex, "java.sql.Clob");
5073:
5074: if (x == null) {
5075: updateNull(columnIndex);
5076: } else {
5077: updateCharacterStreamInternal(columnIndex, x, false,
5078: length, "updateClob");
5079: }
5080: }
5081:
5082: /**
5083: * Updates the designated column using the given <code>Reader</code>
5084: * object.
5085: *
5086: * The data will be read from the stream as needed until end-of-stream is
5087: * reached. The JDBC driver will do any necessary conversion from
5088: * <code>UNICODE</code> to the database char format.
5089: *
5090: * The updater methods are used to update column values in the current row
5091: * or the insert row. The updater methods do not update the underlying
5092: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5093: * methods are called to update the database.
5094: *
5095: * @param columnIndex the first column is 1, the second is 2, ...
5096: * @param x an object that contains the data to set the parameter
5097: * value to
5098: * @throws SQLException if the columnIndex is not valid; if a database
5099: * access error occurs; the result set concurrency is
5100: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5101: * result set
5102: */
5103: public void updateClob(int columnIndex, Reader x)
5104: throws SQLException {
5105: checksBeforeUpdateXXX("updateClob", columnIndex);
5106: int colType = getColumnType(columnIndex);
5107: if (colType != Types.CLOB) {
5108: throw dataTypeConversion(columnIndex, "java.sql.Clob");
5109: }
5110: updateCharacterStreamInternal(columnIndex, x, true, -1,
5111: "updateClob");
5112: }
5113:
5114: /**
5115: *
5116: * JDBC 4.0
5117: *
5118: * Updates the designated column with a java.sql.Clob value. The updater
5119: * methods are used to update column values in the current row or the insert
5120: * row. The updater methods do not update the underlying database; instead
5121: * the updateRow or insertRow methods are called to update the database.
5122: *
5123: * @param columnName -
5124: * the name of the Clob column
5125: * @param x -
5126: * the new column value
5127: * @exception SQLException
5128: * Feature not implemented for now.
5129: */
5130:
5131: public void updateClob(String columnName, Reader x, long length)
5132: throws SQLException {
5133: checkIfClosed("updateClob");
5134: updateClob(findColumnName(columnName), x, length);
5135: }
5136:
5137: /**
5138: * Updates the designated column using the given <code>Reader</code>
5139: * object.
5140: *
5141: * The data will be read from the stream as needed until end-of-stream is
5142: * reached. The JDBC driver will do any necessary conversion from
5143: * <code>UNICODE</code> to the database char format.
5144: *
5145: * The updater methods are used to update column values in the current row
5146: * or the insert row. The updater methods do not update the underlying
5147: * database; instead the <code>updateRow</code> or <code>insertRow</code>
5148: * methods are called to update the database.
5149: *
5150: * @param columnName the label for the column specified with the SQL AS
5151: * clause. If the SQL AS clause was not specified, then the label is
5152: * the name of the column
5153: * @param x an object that contains the data to set the parameter
5154: * value to
5155: * @throws SQLException if the columnIndex is not valid; if a database
5156: * access error occurs; the result set concurrency is
5157: * <code>CONCUR_READ_ONLY</code> or this method is called on a closed
5158: * result set
5159: */
5160: public void updateClob(String columnName, Reader x)
5161: throws SQLException {
5162: checkIfClosed("updateClob");
5163: updateClob(findColumnName(columnName), x);
5164: }
5165: }
|