Logo Search packages:      
Sourcecode: mysql-connector-java version File versions  Download package

RowDataDynamic.java

/*
 Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 

  The MySQL Connector/J is licensed under the terms of the GPLv2
  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
  There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
  this software, see the FLOSS License Exception
  <http://www.mysql.com/about/legal/licensing/foss-exception.html>.

  This program is free software; you can redistribute it and/or modify it under the terms
  of the GNU General Public License as published by the Free Software Foundation; version 2
  of the License.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this
  program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
  Floor, Boston, MA 02110-1301  USA



 */
package com.mysql.jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.mysql.jdbc.profiler.ProfilerEvent;
import com.mysql.jdbc.profiler.ProfilerEventHandler;

/**
 * Allows streaming of MySQL data.
 * 
 * @author dgan
 * @version $Id$
 */
00041 public class RowDataDynamic implements RowData {

00043       class OperationNotSupportedException extends SQLException {
            OperationNotSupportedException() {
                  super(
                              Messages.getString("RowDataDynamic.10"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
            }
      }

      private int columnCount;

      private Field[] metadata;

      private int index = -1;

      private MysqlIO io;

      private boolean isAfterEnd = false;

      private boolean noMoreRows = false;

      private boolean isBinaryEncoded = false;

      private ResultSetRow nextRow;

      private ResultSetImpl owner;

      private boolean streamerClosed = false;
      
      private boolean wasEmpty = false; // we don't know until we attempt to traverse

      private boolean useBufferRowExplicit;

      private boolean moreResultsExisted;

      private ExceptionInterceptor exceptionInterceptor;
      
      /**
       * Creates a new RowDataDynamic object.
       * 
       * @param io
       *            the connection to MySQL that this data is coming from
       * @param metadata
       *            the metadata that describe this data
       * @param isBinaryEncoded
       *            is this data in native format?
       * @param colCount
       *            the number of columns
       * @throws SQLException
       *             if the next record can not be found
       */
00092       public RowDataDynamic(MysqlIO io, int colCount, Field[] fields,
                  boolean isBinaryEncoded) throws SQLException {
            this.io = io;
            this.columnCount = colCount;
            this.isBinaryEncoded = isBinaryEncoded;
            this.metadata = fields;
            this.exceptionInterceptor = this.io.getExceptionInterceptor();
            this.useBufferRowExplicit = MysqlIO.useBufferRowExplicit(this.metadata);
      }

      /**
       * Adds a row to this row data.
       * 
       * @param row
       *            the row to add
       * @throws SQLException
       *             if a database error occurs
       */
00110       public void addRow(ResultSetRow row) throws SQLException {
            notSupported();
      }

      /**
       * Moves to after last.
       * 
       * @throws SQLException
       *             if a database error occurs
       */
00120       public void afterLast() throws SQLException {
            notSupported();
      }

      /**
       * Moves to before first.
       * 
       * @throws SQLException
       *             if a database error occurs
       */
00130       public void beforeFirst() throws SQLException {
            notSupported();
      }

      /**
       * Moves to before last so next el is the last el.
       * 
       * @throws SQLException
       *             if a database error occurs
       */
00140       public void beforeLast() throws SQLException {
            notSupported();
      }

      /**
       * We're done.
       * 
       * @throws SQLException
       *             if a database error occurs
       */
00150       public void close() throws SQLException {
            // Belt and suspenders here - if we don't
            // have a reference to the connection
            // it's more than likely dead/gone and we
            // won't be able to consume rows anyway

            Object mutex = this;

            MySQLConnection conn = null;

            if (this.owner != null) {
                  conn = this.owner.connection;

                  if (conn != null) {
                        mutex = conn;
                  }
            }

            boolean hadMore = false;
            int howMuchMore = 0;

            synchronized (mutex) {
                  // drain the rest of the records.
                  while (next() != null) {
                        hadMore = true;
                        howMuchMore++;

                        if (howMuchMore % 100 == 0) {
                              Thread.yield();
                        }
                  }

                  if (conn != null) {
                        if (!conn.getClobberStreamingResults() && 
                                    conn.getNetTimeoutForStreamingResults() > 0) {
                              String oldValue = conn
                              .getServerVariable("net_write_timeout");

                              if (oldValue == null || oldValue.length() == 0) {
                                    oldValue = "60"; // the current default
                              }

                              this.io.clearInputStream();
                              
                              java.sql.Statement stmt = null;
                              
                              try {
                                    stmt = conn.createStatement();
                                    ((com.mysql.jdbc.StatementImpl)stmt).executeSimpleNonQuery(conn, "SET net_write_timeout=" + oldValue);
                              } finally {
                                    if (stmt != null) {
                                          stmt.close();
                                    }
                              }
                        }
                        
                        if (conn.getUseUsageAdvisor()) {
                              if (hadMore) {

                                    ProfilerEventHandler eventSink = ProfilerEventHandlerFactory
                                    .getInstance(conn);

                                    eventSink
                                    .consumeEvent(new ProfilerEvent(
                                                ProfilerEvent.TYPE_WARN,
                                                "", //$NON-NLS-1$
                                                this.owner.owningStatement == null ? "N/A" : this.owner.owningStatement.currentCatalog, //$NON-NLS-1$
                                                this.owner.connectionId,
                                                this.owner.owningStatement == null ? -1
                                                            : this.owner.owningStatement
                                                                        .getId(),
                                                -1,
                                                System.currentTimeMillis(),
                                                0,
                                                Constants.MILLIS_I18N,
                                                null,
                                                null,
                                                Messages.getString("RowDataDynamic.2") //$NON-NLS-1$
                                                            + howMuchMore
                                                            + Messages
                                                                        .getString("RowDataDynamic.3") //$NON-NLS-1$
                                                            + Messages
                                                                        .getString("RowDataDynamic.4") //$NON-NLS-1$
                                                            + Messages
                                                                        .getString("RowDataDynamic.5") //$NON-NLS-1$
                                                            + Messages
                                                                        .getString("RowDataDynamic.6") //$NON-NLS-1$
                                                            + this.owner.pointOfOrigin));
                              }
                        }
                  }
            }

            this.metadata = null;
            this.owner = null;
      }

      /**
       * Only works on non dynamic result sets.
       * 
       * @param index
       *            row number to get at
       * @return row data at index
       * @throws SQLException
       *             if a database error occurs
       */
00256       public ResultSetRow getAt(int ind) throws SQLException {
            notSupported();

            return null;
      }

      /**
       * Returns the current position in the result set as a row number.
       * 
       * @return the current row number
       * @throws SQLException
       *             if a database error occurs
       */
00269       public int getCurrentRowNumber() throws SQLException {
            notSupported();

            return -1;
      }

      /**
       * @see com.mysql.jdbc.RowData#getOwner()
       */
00278       public ResultSetInternalMethods getOwner() {
            return this.owner;
      }

      /**
       * Returns true if another row exsists.
       * 
       * @return true if more rows
       * @throws SQLException
       *             if a database error occurs
       */
00289       public boolean hasNext() throws SQLException {
            boolean hasNext = (this.nextRow != null);

            if (!hasNext && !this.streamerClosed) {
                  this.io.closeStreamer(this);
                  this.streamerClosed = true;
            }

            return hasNext;
      }

      /**
       * Returns true if we got the last element.
       * 
       * @return true if after last row
       * @throws SQLException
       *             if a database error occurs
       */
00307       public boolean isAfterLast() throws SQLException {
            return this.isAfterEnd;
      }

      /**
       * Returns if iteration has not occured yet.
       * 
       * @return true if before first row
       * @throws SQLException
       *             if a database error occurs
       */
00318       public boolean isBeforeFirst() throws SQLException {
            return this.index < 0;
      }

      /**
       * Returns true if the result set is dynamic.
       * 
       * This means that move back and move forward won't work because we do not
       * hold on to the records.
       * 
       * @return true if this result set is streaming from the server
       */
00330       public boolean isDynamic() {
            return true;
      }

      /**
       * Has no records.
       * 
       * @return true if no records
       * @throws SQLException
       *             if a database error occurs
       */
00341       public boolean isEmpty() throws SQLException {
            notSupported();

            return false;
      }

      /**
       * Are we on the first row of the result set?
       * 
       * @return true if on first row
       * @throws SQLException
       *             if a database error occurs
       */
00354       public boolean isFirst() throws SQLException {
            notSupported();

            return false;
      }

      /**
       * Are we on the last row of the result set?
       * 
       * @return true if on last row
       * @throws SQLException
       *             if a database error occurs
       */
00367       public boolean isLast() throws SQLException {
            notSupported();

            return false;
      }

      /**
       * Moves the current position relative 'rows' from the current position.
       * 
       * @param rows
       *            the relative number of rows to move
       * @throws SQLException
       *             if a database error occurs
       */
00381       public void moveRowRelative(int rows) throws SQLException {
            notSupported();
      }

      /**
       * Returns the next row.
       * 
       * @return the next row value
       * @throws SQLException
       *             if a database error occurs
       */
00392       public ResultSetRow next() throws SQLException {
            

            nextRecord();

            if (this.nextRow == null && !this.streamerClosed && !this.moreResultsExisted) {
                  this.io.closeStreamer(this);
                  this.streamerClosed = true;
            }
            
            if (this.nextRow != null) {
                  if (this.index != Integer.MAX_VALUE) {
                        this.index++;
                  }
            }
            
            return this.nextRow;
      }


      private void nextRecord() throws SQLException {

            try {
                  if (!this.noMoreRows) {                   
                        this.nextRow = this.io.nextRow(this.metadata, this.columnCount,
                                    this.isBinaryEncoded,
                                    java.sql.ResultSet.CONCUR_READ_ONLY, true, 
                                    this.useBufferRowExplicit, true, null);

                        if (this.nextRow == null) {
                              this.noMoreRows = true;
                              this.isAfterEnd = true;
                              this.moreResultsExisted = this.io.tackOnMoreStreamingResults(this.owner);

                              if (this.index == -1) {
                                    this.wasEmpty = true;
                              }
                        }
                  } else {
                        this.isAfterEnd = true;
                  }
            } catch (SQLException sqlEx) {
                  if (sqlEx instanceof StreamingNotifiable) {
                        ((StreamingNotifiable)sqlEx).setWasStreamingResults();
                  }
                  
                  // don't wrap SQLExceptions
                  throw sqlEx;
            } catch (Exception ex) {
                  String exceptionType = ex.getClass().getName();
                  String exceptionMessage = ex.getMessage();

                  exceptionMessage += Messages.getString("RowDataDynamic.7"); //$NON-NLS-1$
                  exceptionMessage += Util.stackTraceToString(ex);

                  SQLException sqlEx = SQLError.createSQLException(
                              Messages.getString("RowDataDynamic.8") //$NON-NLS-1$
                                          + exceptionType
                                          + Messages.getString("RowDataDynamic.9") + exceptionMessage, SQLError.SQL_STATE_GENERAL_ERROR, this.exceptionInterceptor); //$NON-NLS-1$
                  sqlEx.initCause(ex);
                  
                  throw sqlEx;
            }
      }

      private void notSupported() throws SQLException {
            throw new OperationNotSupportedException();
      }

      /**
       * Removes the row at the given index.
       * 
       * @param index
       *            the row to move to
       * @throws SQLException
       *             if a database error occurs
       */
00469       public void removeRow(int ind) throws SQLException {
            notSupported();
      }

      /**
       * Moves the current position in the result set to the given row number.
       * 
       * @param rowNumber
       *            row to move to
       * @throws SQLException
       *             if a database error occurs
       */
00481       public void setCurrentRow(int rowNumber) throws SQLException {
            notSupported();
      }

      /**
       * @see com.mysql.jdbc.RowData#setOwner(com.mysql.jdbc.ResultSetInternalMethods)
       */
00488       public void setOwner(ResultSetImpl rs) {
            this.owner = rs;
      }

      /**
       * Only works on non dynamic result sets.
       * 
       * @return the size of this row data
       */
00497       public int size() {
            return RESULT_SET_SIZE_UNKNOWN;
      }

00501       public boolean wasEmpty() {
            return this.wasEmpty;
      }

00505       public void setMetadata(Field[] metadata) {
            this.metadata = metadata;
      }
}

Generated by  Doxygen 1.6.0   Back to index