Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge more methods from TdsParserStateObject #1843

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -860,7 +860,7 @@ private bool TryCleanPartialRead()
}

#if DEBUG
if (_stateObj._pendingData)
if (_stateObj.HasPendingData)
{
byte token;
if (!_stateObj.TryPeekByte(out token))
@@ -1067,7 +1067,7 @@ private bool TryCloseInternal(bool closeReader)
#else
{
#endif //DEBUG
if ((!_isClosed) && (parser != null) && (stateObj != null) && (stateObj._pendingData))
if ((!_isClosed) && (parser != null) && (stateObj != null) && (stateObj.HasPendingData))
{

// It is possible for this to be called during connection close on a
@@ -1333,7 +1333,7 @@ private bool TryConsumeMetaData()
{
// warning: Don't check the MetaData property within this function
// warning: as it will be a reentrant call
while (_parser != null && _stateObj != null && _stateObj._pendingData && !_metaDataConsumed)
while (_parser != null && _stateObj != null && _stateObj.HasPendingData && !_metaDataConsumed)
{
if (_parser.State == TdsParserState.Broken || _parser.State == TdsParserState.Closed)
{
@@ -3473,7 +3473,7 @@ private bool TryHasMoreResults(out bool moreResults)

Debug.Assert(null != _command, "unexpected null command from the data reader!");

while (_stateObj._pendingData)
while (_stateObj.HasPendingData)
{
byte token;
if (!_stateObj.TryPeekByte(out token))
@@ -3563,7 +3563,7 @@ private bool TryHasMoreRows(out bool moreRows)
moreRows = false;
return true;
}
if (_stateObj._pendingData)
if (_stateObj.HasPendingData)
{
// Consume error's, info's, done's on HasMoreRows, so user obtains error on Read.
// Previous bug where Read() would return false with error on the wire in the case
@@ -3620,7 +3620,7 @@ private bool TryHasMoreRows(out bool moreRows)
moreRows = false;
return false;
}
if (_stateObj._pendingData)
if (_stateObj.HasPendingData)
{
if (!_stateObj.TryPeekByte(out b))
{
@@ -3964,7 +3964,7 @@ private bool TryReadInternal(bool setTimeout, out bool more)
if (moreRows)
{
// read the row from the backend (unless it's an altrow were the marker is already inside the altrow ...)
while (_stateObj._pendingData)
while (_stateObj.HasPendingData)
{
if (_altRowStatus != ALTROWSTATUS.AltRow)
{
@@ -3996,7 +3996,7 @@ private bool TryReadInternal(bool setTimeout, out bool more)
}
}

if (!_stateObj._pendingData)
if (!_stateObj.HasPendingData)
{
if (!TryCloseInternal(false /*closeReader*/))
{
@@ -4020,7 +4020,7 @@ private bool TryReadInternal(bool setTimeout, out bool more)
{
// if we are in SingleRow mode, and we've read the first row,
// read the rest of the rows, if any
while (_stateObj._pendingData && !_sharedState._dataReady)
while (_stateObj.HasPendingData && !_sharedState._dataReady)
{
if (!_parser.TryRun(RunBehavior.ReturnImmediately, _command, this, null, _stateObj, out _sharedState._dataReady))
{
@@ -4061,7 +4061,7 @@ private bool TryReadInternal(bool setTimeout, out bool more)
more = false;

#if DEBUG
if ((!_sharedState._dataReady) && (_stateObj._pendingData))
if ((!_sharedState._dataReady) && (_stateObj.HasPendingData))
{
byte token;
if (!_stateObj.TryPeekByte(out token))
Original file line number Diff line number Diff line change
@@ -910,11 +910,11 @@ override internal void ValidateConnectionForExecute(SqlCommand command)
// or if MARS is off, then a datareader exists
throw ADP.OpenReaderExists(parser.MARSOn); // MDAC 66411
}
else if (!parser.MARSOn && parser._physicalStateObj._pendingData)
else if (!parser.MARSOn && parser._physicalStateObj.HasPendingData)
{
parser.DrainData(parser._physicalStateObj);
}
Debug.Assert(!parser._physicalStateObj._pendingData, "Should not have a busy physicalStateObject at this point!");
Debug.Assert(!parser._physicalStateObj.HasPendingData, "Should not have a busy physicalStateObject at this point!");

parser.RollbackOrphanedAPITransactions();
}
@@ -1073,7 +1073,7 @@ private void ResetConnection()
// obtains a clone.

Debug.Assert(!HasLocalTransactionFromAPI, "Upon ResetConnection SqlInternalConnectionTds has a currently ongoing local transaction.");
Debug.Assert(!_parser._physicalStateObj._pendingData, "Upon ResetConnection SqlInternalConnectionTds has pending data.");
Debug.Assert(!_parser._physicalStateObj.HasPendingData, "Upon ResetConnection SqlInternalConnectionTds has pending data.");

if (_fResetConnection)
{
Original file line number Diff line number Diff line change
@@ -964,7 +964,7 @@ internal TdsParserStateObject GetSession(object owner)
{
session = _sessionPool.GetSession(owner);

Debug.Assert(!session._pendingData, "pending data on a pooled MARS session");
Debug.Assert(!session.HasPendingData, "pending data on a pooled MARS session");
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.TdsParser.GetSession|ADV> {0} getting session {1} from pool", ObjectID, session.ObjectID);
}
else
@@ -1598,7 +1598,7 @@ internal void Deactivate(bool connectionIsDoomed)

if (!connectionIsDoomed && null != _physicalStateObj)
{
if (_physicalStateObj._pendingData)
if (_physicalStateObj.HasPendingData)
{
DrainData(_physicalStateObj);
}
@@ -2479,7 +2479,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead
{
if (token == TdsEnums.SQLERROR)
{
stateObj._errorTokenReceived = true; // Keep track of the fact error token was received - for Done processing.
stateObj.HasReceivedError = true; // Keep track of the fact error token was received - for Done processing.
}

SqlError error;
@@ -3009,18 +3009,18 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead
break;
}

Debug.Assert(stateObj._pendingData || !dataReady, "dataReady is set, but there is no pending data");
Debug.Assert(stateObj.HasPendingData || !dataReady, "dataReady is set, but there is no pending data");
}

// Loop while data pending & runbehavior not return immediately, OR
// if in attention case, loop while no more pending data & attention has not yet been
// received.
while ((stateObj._pendingData &&
while ((stateObj.HasPendingData &&
(RunBehavior.ReturnImmediately != (RunBehavior.ReturnImmediately & runBehavior))) ||
(!stateObj._pendingData && stateObj._attentionSent && !stateObj._attentionReceived));
(!stateObj.HasPendingData && stateObj._attentionSent && !stateObj.HasReceivedAttention));

#if DEBUG
if ((stateObj._pendingData) && (!dataReady))
if ((stateObj.HasPendingData) && (!dataReady))
{
byte token;
if (!stateObj.TryPeekByte(out token))
@@ -3031,7 +3031,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead
}
#endif

if (!stateObj._pendingData)
if (!stateObj.HasPendingData)
{
if (null != CurrentTransaction)
{
@@ -3041,7 +3041,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead

// if we recieved an attention (but this thread didn't send it) then
// we throw an Operation Cancelled error
if (stateObj._attentionReceived)
if (stateObj.HasReceivedAttention)
{
// Dev11 #344723: SqlClient stress test suspends System_Data!Tcp::ReadSync via a call to SqlDataReader::Close
// Spin until SendAttention has cleared _attentionSending, this prevents a race condition between receiving the attention ACK and setting _attentionSent
@@ -3052,7 +3052,7 @@ internal bool TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataRead
{
// Reset attention state.
stateObj._attentionSent = false;
stateObj._attentionReceived = false;
stateObj.HasReceivedAttention = false;

if (RunBehavior.Clean != (RunBehavior.Clean & runBehavior) && !stateObj.IsTimeoutStateExpired)
{
@@ -3518,7 +3518,7 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio
{
Debug.Assert(TdsEnums.DONE_MORE != (status & TdsEnums.DONE_MORE), "Not expecting DONE_MORE when receiving DONE_ATTN");
Debug.Assert(stateObj._attentionSent, "Received attention done without sending one!");
stateObj._attentionReceived = true;
stateObj.HasReceivedAttention = true;
Debug.Assert(stateObj._inBytesUsed == stateObj._inBytesRead && stateObj._inBytesPacket == 0, "DONE_ATTN received with more data left on wire");
}
if ((null != cmd) && (TdsEnums.DONE_COUNT == (status & TdsEnums.DONE_COUNT)))
@@ -3537,13 +3537,13 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio
}

// Skip the bogus DONE counts sent by the server
if (stateObj._receivedColMetaData || (curCmd != TdsEnums.SELECT))
if (stateObj.HasReceivedColumnMetadata || (curCmd != TdsEnums.SELECT))
{
cmd.OnStatementCompleted(count);
}
}

stateObj._receivedColMetaData = false;
stateObj.HasReceivedColumnMetadata = false;

// Surface exception for DONE_ERROR in the case we did not receive an error token
// in the stream, but an error occurred. In these cases, we throw a general server error. The
@@ -3552,7 +3552,7 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio
// the server has reached its max connection limit. Bottom line, we need to throw general
// error in the cases where we did not receive a error token along with the DONE_ERROR.
if ((TdsEnums.DONE_ERROR == (TdsEnums.DONE_ERROR & status)) && stateObj.ErrorCount == 0 &&
stateObj._errorTokenReceived == false && (RunBehavior.Clean != (RunBehavior.Clean & run)))
stateObj.HasReceivedError == false && (RunBehavior.Clean != (RunBehavior.Clean & run)))
{
stateObj.AddError(new SqlError(0, 0, TdsEnums.MIN_ERROR_CLASS, _server, SQLMessage.SevereError(), "", 0));

@@ -3586,17 +3586,17 @@ private bool TryProcessDone(SqlCommand cmd, SqlDataReader reader, ref RunBehavio
// stop if the DONE_MORE bit isn't set (see above for attention handling)
if (TdsEnums.DONE_MORE != (status & TdsEnums.DONE_MORE))
{
stateObj._errorTokenReceived = false;
stateObj.HasReceivedError = false;
if (stateObj._inBytesUsed >= stateObj._inBytesRead)
{
stateObj._pendingData = false;
stateObj.HasPendingData = false;
}
}

// _pendingData set by e.g. 'TdsExecuteSQLBatch'
// _hasOpenResult always set to true by 'WriteMarsHeader'
// HasPendingData set by e.g. 'TdsExecuteSQLBatch'
// HasOpenResult always set to true by 'WriteMarsHeader'
//
if (!stateObj._pendingData && stateObj._hasOpenResult)
if (!stateObj.HasPendingData && stateObj.HasOpenResult)
{
/*
Debug.Assert(!((sqlTransaction != null && _distributedTransaction != null) ||
@@ -5140,7 +5140,7 @@ internal void ThrowUnsupportedCollationEncountered(TdsParserStateObject stateObj
{
DrainData(stateObj);

stateObj._pendingData = false;
stateObj.HasPendingData = false;
}

ThrowExceptionAndWarning(stateObj);
@@ -5742,7 +5742,7 @@ private bool TryCommonProcessMetaData(TdsParserStateObject stateObj, _SqlMetaDat

// We get too many DONE COUNTs from the server, causing too meany StatementCompleted event firings.
// We only need to fire this event when we actually have a meta data stream with 0 or more rows.
stateObj._receivedColMetaData = true;
stateObj.HasReceivedColumnMetadata = true;
return true;
}

@@ -9340,8 +9340,8 @@ internal void TdsLogin(SqlLogin rec,
}

_physicalStateObj.WritePacket(TdsEnums.HARDFLUSH);
_physicalStateObj.ResetSecurePasswordsInfomation(); // Password information is needed only from Login process; done with writing login packet and should clear information
_physicalStateObj._pendingData = true;
_physicalStateObj.ResetSecurePasswordsInformation(); // Password information is needed only from Login process; done with writing login packet and should clear information
_physicalStateObj.HasPendingData = true;
_physicalStateObj._messageStatus = 0;

// Remvove CTAIP Provider after login record is sent.
@@ -9389,7 +9389,7 @@ internal void SendFedAuthToken(SqlFedAuthToken fedAuthToken)
_physicalStateObj.WriteByteArray(accessToken, accessToken.Length, 0);

_physicalStateObj.WritePacket(TdsEnums.HARDFLUSH);
_physicalStateObj._pendingData = true;
_physicalStateObj.HasPendingData = true;
_physicalStateObj._messageStatus = 0;

_connHandler._federatedAuthenticationRequested = true;
@@ -9701,7 +9701,7 @@ internal SqlDataReader TdsExecuteTransactionManagerRequest(

Task writeTask = stateObj.WritePacket(TdsEnums.HARDFLUSH);
Debug.Assert(writeTask == null, "Writes should not pend when writing sync");
stateObj._pendingData = true;
stateObj.HasPendingData = true;
stateObj._messageStatus = 0;

SqlDataReader dtcReader = null;
@@ -11223,7 +11223,7 @@ internal Task WriteBulkCopyDone(TdsParserStateObject stateObj)
WriteShort(0, stateObj);
WriteInt(0, stateObj);

stateObj._pendingData = true;
stateObj.HasPendingData = true;
stateObj._messageStatus = 0;
return stateObj.WritePacket(TdsEnums.HARDFLUSH);
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -181,11 +181,9 @@ internal void PutSession(TdsParserStateObject session)
{
// Session is good to re-use and our cache has space
SqlClientEventSource.Log.TryAdvancedTraceEvent("<sc.TdsParserSessionPool.PutSession|ADV> {0} keeping session {1} cachedCount={2}", ObjectID, session.ObjectID, _cachedCount);
#if NETFRAMEWORK
Debug.Assert(!session._pendingData, "pending data on a pooled session?");
#else

Debug.Assert(!session.HasPendingData, "pending data on a pooled session?");
#endif

_freeStateObjects[_freeStateObjectCount] = session;
_freeStateObjectCount++;
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Text;
using System.Threading.Tasks;
using System.Xml;
using BenchmarkDotNet.Attributes;
@@ -13,6 +14,8 @@ public class SqlCommandRunner : BaseRunner
private static SqlConnection s_sqlConnection;
private Table _table;
private string _query;
private readonly string _query_data_varbinary = "SELECT foo FROM data_varbinary";
private readonly string _query_data_varchar = "SELECT foo FROM data_varchar";

[GlobalSetup]
public void Setup()
@@ -25,12 +28,46 @@ public void Setup()
.InsertBulkRows(s_config.Benchmarks.SqlCommandRunnerConfig.RowCount, s_sqlConnection);

_query = $"SELECT * FROM {_table.Name}";

using var cmd = s_sqlConnection.CreateCommand();
cmd.CommandText = @"
IF OBJECT_ID('dbo.data_varbinary', 'U') IS NOT NULL
DROP TABLE dbo.data_varbinary;
CREATE TABLE dbo.data_varbinary (id INT, foo VARBINARY(MAX))
";
cmd.ExecuteNonQuery();

cmd.CommandText = "INSERT INTO dbo.data_varbinary (id, foo) VALUES (@id, @foo)";
cmd.Parameters.AddWithValue("id", 1);
cmd.Parameters.AddWithValue("foo", new byte[1024 * 1024 * 10]);
cmd.ExecuteNonQuery();

using var cmd2 = s_sqlConnection.CreateCommand();
cmd2.CommandText = @"
IF OBJECT_ID('dbo.data_varchar', 'U') IS NOT NULL
DROP TABLE dbo.data_varchar;
CREATE TABLE dbo.data_varchar (id INT, foo VARCHAR(MAX))
";
cmd2.ExecuteNonQuery();

cmd2.CommandText = "INSERT INTO dbo.data_varchar (id, foo) VALUES (@id, @foo)";
cmd2.Parameters.AddWithValue("id", 1);
cmd2.Parameters.AddWithValue("foo", Encoding.UTF8.GetString(new byte[1024 * 1024 * 10]));
cmd2.ExecuteNonQuery();
}

[GlobalCleanup]
public void Dispose()
{
_table.DropTable(s_sqlConnection);
using var cmd = s_sqlConnection.CreateCommand();
cmd.CommandText = @"IF OBJECT_ID('dbo.data_varbinary', 'U') IS NOT NULL
DROP TABLE data_varbinary;";
cmd.ExecuteNonQuery();
using var cmd2 = s_sqlConnection.CreateCommand();
cmd2.CommandText = @"IF OBJECT_ID('dbo.data_varchar', 'U') IS NOT NULL
DROP TABLE data_varchar;";
cmd2.ExecuteNonQuery();
s_sqlConnection.Close();
SqlConnection.ClearAllPools();
}
@@ -47,8 +84,44 @@ public void ExecuteReader()
[Benchmark]
public async Task ExecuteReaderAsync()
{
using SqlCommand sqlCommand = new(_query, s_sqlConnection);
using SqlDataReader reader = await sqlCommand.ExecuteReaderAsync();
await using SqlCommand sqlCommand = new(_query, s_sqlConnection);
await using SqlDataReader reader = await sqlCommand.ExecuteReaderAsync();
while (await reader.ReadAsync())
{ }
}

[Benchmark]
public void VARBINARY_MAX_ExecuteReader()
{
using SqlCommand sqlCommand = new(_query_data_varbinary, s_sqlConnection);
using SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read())
{ }
}

[Benchmark]
public async Task VARBINARY_MAX_ExecuteReaderAsync()
{
await using SqlCommand sqlCommand = new(_query_data_varbinary, s_sqlConnection);
await using SqlDataReader reader = await sqlCommand.ExecuteReaderAsync();
while (await reader.ReadAsync())
{ }
}

[Benchmark]
public void VARCHAR_MAX_ExecuteReader()
{
using SqlCommand sqlCommand = new(_query_data_varchar, s_sqlConnection);
using SqlDataReader reader = sqlCommand.ExecuteReader();
while (reader.Read())
{ }
}

[Benchmark]
public async Task VARCHAR_MAX_ExecuteReaderAsync()
{
await using SqlCommand sqlCommand = new(_query_data_varchar, s_sqlConnection);
await using SqlDataReader reader = await sqlCommand.ExecuteReaderAsync();
while (await reader.ReadAsync())
{ }
}
@@ -63,7 +136,7 @@ public void ExecuteScalar()
[Benchmark]
public async Task ExecuteScalarAsync()
{
using SqlCommand sqlCommand = new(_query, s_sqlConnection);
await using SqlCommand sqlCommand = new(_query, s_sqlConnection);
_ = await sqlCommand.ExecuteScalarAsync();
}

@@ -77,7 +150,7 @@ public void ExecuteNonQuery()
[Benchmark]
public async Task ExecuteNonQueryAsync()
{
using SqlCommand sqlCommand = new(_query, s_sqlConnection);
await using SqlCommand sqlCommand = new(_query, s_sqlConnection);
await sqlCommand.ExecuteNonQueryAsync();
}

@@ -93,10 +166,45 @@ public void ExecuteXmlReader()
[Benchmark]
public async Task ExecuteXmlReaderAsync()
{
using SqlCommand sqlCommand = new(_query + " FOR XML AUTO, BINARY BASE64", s_sqlConnection);
await using SqlCommand sqlCommand = new(_query + " FOR XML AUTO, BINARY BASE64", s_sqlConnection);
using XmlReader reader = await sqlCommand.ExecuteXmlReaderAsync();
while (await reader.ReadAsync())
{ }
}

[Benchmark]
public void VARBINARY_MAX_ExecuteScalar()
{
using var cmd = new SqlCommand(_query_data_varbinary, s_sqlConnection);

_ = cmd.ExecuteScalar();

}

[Benchmark]
public async Task VARBINARY_MAX_ExecuteScalarAsync()
{
await using var cmd = new SqlCommand(_query_data_varbinary, s_sqlConnection);

_ = await cmd.ExecuteScalarAsync();
}

[Benchmark]
public void VARCHAR_MAX_ExecuteScalar()
{
using var cmd = new SqlCommand(_query_data_varchar, s_sqlConnection);

_ = cmd.ExecuteScalar();

}

[Benchmark]
public async Task VARCHAR_MAX_ExecuteScalarAsync()
{
await using var cmd = new SqlCommand(_query_data_varchar, s_sqlConnection);

_ = await cmd.ExecuteScalarAsync();
}

}
}