private IngresConnection _connection; // = null; /* * The constructors are marked as internal because an application * can't create an IngresDataReader directly. It is created only * by executing one of the reader methods in the IngresCommand. */ internal IngresDataReader( AdvanRslt resultset, IngresConnection connection, CommandBehavior commandBehavior, int recordsAffected, MetaData keyInfoMetaData) { if (resultset == null) // if no result set, build an empty one { resultset = connection.advanConnect.CreateEmptyResultSet(); } _resultset = resultset; _fieldCount = resultset.rsmd.getColumnCount(); _connection = connection; _valueList = new Object[_fieldCount]; _isOpen = true; _commandBehavior = commandBehavior; _recordsAffected = recordsAffected; _keyInfoMetaData = keyInfoMetaData; if (connection != null) connection.ActiveDataReader = this; // only one active DataReader allowed at a time FireInfoMessageEvent(); // call the delegates with any warning messages }
public void Close() #endif { _isOpen = false; if (_resultset != null && _fieldCount > 0) // if result present, close it { try { _resultset.close(); } catch( SqlEx ex ) { throw ex.createProviderException(); } FireInfoMessageEvent(); // call the delegates with any messages _resultset = null; } if (_connection != null) { _connection.ActiveDataReader = null; // If ExecuteReader(CommandBehavior.CloseConnection) was // specified then the associated Connection object is closed // when the DataReader object is closed. if ((_commandBehavior & CommandBehavior.CloseConnection) != 0) _connection.Close(); } }
/* ** Name: exec ** ** Description: ** Send SQL statement to server and process results. ** A cursor is opened when executing a SELECT and a ** result-set is generated. Non-SELECT statements ** are simply executed and the row count is updated. ** ** Input: ** text Statement text. ** mode Execute mode: QUERY, UPDATE, UNKNOWN. ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 26-Oct-99 (gordy) ** Extracted from interface methods. ** 15-Nov-99 (gordy) ** Pass max row count and column length to result set. ** 16-Nov-99 (gordy) ** Added query timeouts. ** 13-Dec-99 (gordy) ** Added fetch limit. ** 16-May-00 (gordy) ** Move SQL parsing back into individual query processing ** sections so that it occurs after parser.getCursonName(). ** 19-May-00 (gordy) ** If select loops have been enabled, and a cursor name has ** not been assigned, execute queries directly rather than ** opening a cursor. Locking had to be reorganized since ** select loops are not unlocked until the result set is ** closed. Also needed additional handling when executing ** (supposedly) non-queries and get a result set by mistake. ** 28-Mar-01 (gordy) ** Call result-set shut() to avoid top-level tracing. ** 20-Jun-01 (gordy) ** Pass cursor name to result-set according to spec: ** NULL if READONLY and not provided by application. ** 21-Jun-01 (gordy) ** Re-worked parsing to eliminate redundant code. Parser ** parameter replaced with simple query text string. Query ** parameter replaced with mode to convey caller intent. ** 20-Aug-01 (gordy) ** Use cursor type constants. Send READONLY flag to server. ** Warn if cursor mode changed to READONLY. ** 25-Oct-01 (gordy) ** Select loops are only supported at PROTO_2 and above. ** 31-Oct-01 (gordy) ** Timezone now passed to AdvanSQL. ** 31-Oct-02 (gordy) ** Adapted for generic GCF driver. ** 19-Feb-03 (gordy) ** Added method to calculate fetch size. ** 15-Apr-03 (gordy) ** Added connection timezones separate from date formatters. ** 7-Jul-03 (gordy) ** Added Ingres timezone config which affects date/time literals. ** 4-Aug-03 (gordy) ** Created neew result-set class for updatable cursors. ** 20-Aug-03 (gordy) ** Send AUTO_CLOSE flag for query statements. ** 12-Sep-03 (gordy) ** Timezone replaced by GMT indicator. ** 6-Oct-03 (gordy) ** Fetch first block of rows for select-loops and read-only cursors. ** 19-Jun-06 (gordy) ** I give up... GMT indicator replaced with connection. */ private void exec( String text, int mode ) { SqlParse parser = new SqlParse( text, conn ); int type = parser.getQueryType(); AdvanRSMD rsmd; String cursor = null; clearResults(); if ( mode == UNKNOWN ) mode = (type == SqlParse.QT_SELECT) ? QUERY : UPDATE; if ( type == SqlParse.QT_DELETE || type == SqlParse.QT_UPDATE ) cursor = parser.getCursorName(); msg.LockConnection(); try { String sql = parser.parseSQL( parse_escapes ); if ( mode == QUERY ) { int concurrency = getConcurrency( parser.getConcurrency() ); if ( conn.select_loops && crsr_name == null && concurrency != DrvConst.DRV_CRSR_UPDATE && conn.msg_protocol_level >= MSG_PROTO_2 ) { /* ** Select statement using a select loop. */ bool needEOG = true; msg.begin( MSG_QUERY ); msg.write( MSG_QRY_EXQ ); if ( conn.msg_protocol_level >= MSG_PROTO_3 ) { msg.write( MSG_QP_FLAGS ); msg.write( (short)4 ); msg.write( MSG_QF_FETCH_FIRST | MSG_QF_AUTO_CLOSE ); needEOG = false; } msg.write( MSG_QP_QTXT ); msg.write( sql ); msg.done( true ); if ( (rsmd = readResults( timeout, needEOG )) == null ) throw SqlEx.get( ERR_GC4017_NO_RESULT_SET ); resultSet = new RsltSlct( conn, this, rsmd, rslt_val_stmt, getPreFetchSize(), msg.moreMessages()); } else { /* ** Select statement using a cursor. Generate a ** cursor ID if not provided by the application. */ short flags = 0; bool needEOG = true; cursor = (crsr_name != null) ? crsr_name : conn.getUniqueID( crsr_prefix ); /* ** Parser removes FOR READONLY clause because it isn't ** a part of Ingres SELECT syntax. Tell server that ** cursor should be READONLY (kludge older protocol ** by restoring clause to query). */ if ( concurrency == DrvConst.DRV_CRSR_READONLY ) if ( conn.msg_protocol_level < MSG_PROTO_2 ) sql += " for readonly"; else if ( conn.msg_protocol_level < MSG_PROTO_3 ) flags |= MSG_QF_READONLY; else { flags |= MSG_QF_READONLY | MSG_QF_FETCH_FIRST; needEOG = false; } if ( conn.msg_protocol_level >= MSG_PROTO_3 ) flags |= MSG_QF_AUTO_CLOSE; msg.begin( MSG_QUERY ); msg.write( MSG_QRY_OCQ ); if ( flags != 0 ) { msg.write( MSG_QP_FLAGS ); msg.write( (short)2 ); msg.write( flags ); } msg.write( MSG_QP_CRSR_NAME ); msg.write( cursor ); msg.write( MSG_QP_QTXT ); msg.write( sql ); msg.done( true ); if ( (rsmd = readResults( timeout, needEOG )) == null ) throw SqlEx.get( ERR_GC4017_NO_RESULT_SET ); /* ** The cursor name is passed to the result-set ** for updatable cursors or if provided by the ** application (2.1 API spec). */ if ( (rslt_flags & MSG_RF_READ_ONLY) == 0 ) { resultSet = new RsltUpd( conn, this, rsmd, rslt_val_stmt, cursor ); if ( msg.moreMessages() ) readResults( timeout, needEOG ); } else { if ( rs_concur == DrvConst.DRV_CRSR_UPDATE ) setWarning( SqlEx.get( ERR_GC4016_RS_CHANGED ) ); resultSet = new RsltCurs( conn, this, rsmd, rslt_val_stmt, crsr_name, getPreFetchSize(), msg.moreMessages() ); } msg.UnlockConnection(); } } else if ( cursor != null ) { /* ** Positioned Delete/Update. */ msg.begin( MSG_QUERY ); msg.write( (type == SqlParse.QT_DELETE) ? MSG_QRY_CDEL : MSG_QRY_CUPD ); msg.write( MSG_QP_CRSR_NAME ); msg.write( cursor ); msg.write( MSG_QP_QTXT ); msg.write( sql ); msg.done( true ); if ( readResults( timeout, true ) != null ) // shouldn't happen throw SqlEx.get( ERR_GC4018_RESULT_SET_NOT_PERMITTED ); msg.UnlockConnection(); } else { /* ** Non-query statement. */ msg.begin( MSG_QUERY ); msg.write( MSG_QRY_EXQ ); msg.write( MSG_QP_QTXT ); msg.write( sql ); msg.done( true ); if ( (rsmd = readResults( timeout, true )) == null ) msg.UnlockConnection(); // We be done. else { /* ** Query unexpectedly returned a result-set. ** We need to cleanup the tuple stream and ** statement in the server. The easiest ** way to do this is go ahead and create a ** result-set and close it. */ resultSet = new RsltSlct( conn, this, rsmd, rslt_val_stmt, 1, false ); try { resultSet.shut(); } catch( SqlEx ) {} resultSet = null; throw SqlEx.get( ERR_GC4018_RESULT_SET_NOT_PERMITTED ); } } } catch( SqlEx ex ) { if ( trace.enabled() ) trace.log( title + ".execute(): error executing query" ); if ( trace.enabled( 1 ) ) ex.trace( trace ); msg.UnlockConnection(); throw ex; } return; }
/* ** Dispose ** ** History: ** 27-Aug-02 (thoda04) ** Created. */ /// <summary> /// Release resources used by IngresDataReader. /// </summary> /// <param name="disposing"></param> protected override void Dispose(bool disposing) { /*if disposing == true then method called by user code if disposing == false then method called by runtime from inside the finalizer and we should not reference other objects. */ if (disposing) { Close(); _connection = null; _resultset = null; } }
/* ** Name: clearQueryResults ** ** Description: ** Clears the direct results of a query: update count and result-set. ** Clearing the result-set is optional and controlled by close parameter. ** ** Input: ** close Close result-set? ** ** Output: ** None. ** ** Returns: ** void. ** ** History: ** 19-Feb-03 (gordy) ** Created. */ protected void clearQueryResults( bool close ) { lock(this) { if ( close && resultSet != null ) { try { resultSet.shut(); } catch( SqlEx ) {} resultSet = null; } rslt_rowcount = false; rslt_val_rowcnt = 0; return; } }