internal ForwardsOnlyDataReader GetReader(CommandBehavior cb) { CheckConnectionState(); // Block the notification thread before writing anything to the wire. using (m_Connector.BlockNotificationThread()) { IEnumerable<IServerResponseObject> responseEnum; ForwardsOnlyDataReader reader; m_Connector.SetBackendCommandTimeout(CommandTimeout); if (prepared == PrepareStatus.NeedsPrepare) { PrepareInternal(); } if (prepared == PrepareStatus.NotPrepared) { NpgsqlQuery query; byte[] commandText = GetCommandText(); query = new NpgsqlQuery(commandText); // Write the Query message to the wire. m_Connector.Query(query); // Tell to mediator what command is being sent. if (prepared == PrepareStatus.NotPrepared) { m_Connector.Mediator.SetSqlSent(commandText, NpgsqlMediator.SQLSentType.Simple); } else { m_Connector.Mediator.SetSqlSent(preparedCommandText, NpgsqlMediator.SQLSentType.Execute); } // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread() ); if ( commandType == CommandType.StoredProcedure && reader.FieldCount == 1 && reader.GetDataTypeName(0) == "refcursor" ) { // When a function returns a sole column of refcursor, transparently // FETCH ALL from every such cursor and return those results. StringWriter sw = new StringWriter(); string queryText; while (reader.Read()) { sw.WriteLine("FETCH ALL FROM \"{0}\";", reader.GetString(0)); } reader.Dispose(); queryText = sw.ToString(); if (queryText == "") { queryText = ";"; } // Passthrough the commandtimeout to the inner command, so user can also control its timeout. // TODO: Check if there is a better way to handle that. query = new NpgsqlQuery(queryText); // Write the Query message to the wire. m_Connector.Query(query); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread() ); } } else { // Update the Bind object with current parameter data as needed. BindParameters(); // Write the Bind, Execute, and Sync message to the wire. m_Connector.Bind(bind); m_Connector.Execute(execute); m_Connector.Sync(); // Tell to mediator what command is being sent. m_Connector.Mediator.SetSqlSent(preparedCommandText, NpgsqlMediator.SQLSentType.Execute); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader, possibly with a saved row description from Prepare(). reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread(), true, currentRowDescription ); } return reader; } }
internal ForwardsOnlyDataReader GetReader(CommandBehavior cb) { CheckConnectionState(); // Block the notification thread before writing anything to the wire. using (m_Connector.BlockNotificationThread()) { IEnumerable <IServerResponseObject> responseEnum; ForwardsOnlyDataReader reader; m_Connector.SetBackendCommandTimeout(CommandTimeout); if (prepared == PrepareStatus.NeedsPrepare) { PrepareInternal(); } if (prepared == PrepareStatus.NotPrepared || prepared == PrepareStatus.V2Prepared) { NpgsqlQuery query; byte[] commandText = GetCommandText(); query = NpgsqlQuery.Create(m_Connector.BackendProtocolVersion, commandText); // Write the Query message to the wire. m_Connector.Query(query); // Tell to mediator what command is being sent. if (prepared == PrepareStatus.NotPrepared) { m_Connector.Mediator.SetSqlSent(commandText, NpgsqlMediator.SQLSentType.Simple); } else { m_Connector.Mediator.SetSqlSent(preparedCommandText, NpgsqlMediator.SQLSentType.Execute); } // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread() ); if ( commandType == CommandType.StoredProcedure && reader.FieldCount == 1 && reader.GetDataTypeName(0) == "refcursor" ) { // When a function returns a sole column of refcursor, transparently // FETCH ALL from every such cursor and return those results. StringWriter sw = new StringWriter(); string queryText; while (reader.Read()) { sw.WriteLine("FETCH ALL FROM \"{0}\";", reader.GetString(0)); } reader.Dispose(); queryText = sw.ToString(); if (queryText == "") { queryText = ";"; } // Passthrough the commandtimeout to the inner command, so user can also control its timeout. // TODO: Check if there is a better way to handle that. query = NpgsqlQuery.Create(m_Connector.BackendProtocolVersion, queryText); // Write the Query message to the wire. m_Connector.Query(query); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread() ); } } else { // Update the Bind object with current parameter data as needed. BindParameters(); // Write the Bind, Execute, and Sync message to the wire. m_Connector.Bind(bind); m_Connector.Execute(execute); m_Connector.Sync(); // Tell to mediator what command is being sent. m_Connector.Mediator.SetSqlSent(preparedCommandText, NpgsqlMediator.SQLSentType.Execute); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader, possibly with a saved row description from Prepare(). reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread(), true, currentRowDescription ); } return(reader); } }
internal ForwardsOnlyDataReader GetReader(CommandBehavior cb) { CheckConnectionState(); // reset any responses just before getting new ones Connector.Mediator.ResetResponses(); // Set command timeout. m_Connector.Mediator.CommandTimeout = CommandTimeout; // Block the notification thread before writing anything to the wire. using (m_Connector.BlockNotificationThread()) { IEnumerable<IServerResponseObject> responseEnum; ForwardsOnlyDataReader reader; if (prepared == PrepareStatus.NeedsPrepare) { PrepareInternal(); } if (prepared == PrepareStatus.NotPrepared || prepared == PrepareStatus.V2Prepared) { NpgsqlQuery query; query = new NpgsqlQuery(m_Connector, GetCommandText()); // Write the Query message to the wire. m_Connector.Query(query); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread() ); if ( type == CommandType.StoredProcedure && reader.FieldCount == 1 && reader.GetDataTypeName(0) == "refcursor" ) { // When a function returns a sole column of refcursor, transparently // FETCH ALL from every such cursor and return those results. StringWriter sw = new StringWriter(); string queryText; while (reader.Read()) { sw.WriteLine("FETCH ALL FROM \"{0}\";", reader.GetString(0)); } reader.Dispose(); queryText = sw.ToString(); if (queryText == "") { queryText = ";"; } // Passthrough the commandtimeout to the inner command, so user can also control its timeout. // TODO: Check if there is a better way to handle that. query = new NpgsqlQuery(m_Connector, queryText); // Write the Query message to the wire. m_Connector.Query(query); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread() ); } } else { bool sendPortalDescribe = ! portalDescribeSent; // Update the Bind object with current parameter data as needed. BindParameters(); // Write the Bind message to the wire. m_Connector.Bind(bind); if (sendPortalDescribe) { NpgsqlDescribe portalDescribe = new NpgsqlDescribePortal(bind.PortalName); // Write a Describe message to the wire. m_Connector.Describe(portalDescribe); portalDescribeSent = true; } // Finally, write the Execute and Sync messages to the wire. m_Connector.Execute(execute); m_Connector.Sync(); // Flush and wait for responses. responseEnum = m_Connector.ProcessBackendResponsesEnum(); // Construct the return reader, possibly with a saved row description. reader = new ForwardsOnlyDataReader( responseEnum, cb, this, m_Connector.BlockNotificationThread(), true, currentRowDescription ); if (sendPortalDescribe) { // We sent a Describe message. If the query produces a result set, // PG sent a row description, and the reader has now found it, currentRowDescription = reader.CurrentDescription; } } return reader; } }