-
Notifications
You must be signed in to change notification settings - Fork 315
Fix | Pass Empty List for SqlDataRecord (#2971) #3518
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Collections.ObjectModel; | ||
|
@@ -1065,13 +1066,7 @@ public override void Cancel() | |
} | ||
|
||
if (!_pendingCancel) | ||
{ | ||
// Do nothing if already pending. | ||
// Before attempting actual cancel, set the _pendingCancel flag to false. | ||
// This denotes to other thread before obtaining stateObject from the | ||
// session pool that there is another thread wishing to cancel. | ||
// The period in question is between entering the ExecuteAPI and obtaining | ||
// a stateObject. | ||
_pendingCancel = true; | ||
|
||
TdsParserStateObject stateObj = _stateObj; | ||
|
@@ -1763,7 +1758,6 @@ private Task InternalExecuteNonQuery( | |
asyncWrite, | ||
isRetry, | ||
methodName); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't really help readability. |
||
if (reader != null) | ||
{ | ||
if (task != null) | ||
|
@@ -2587,7 +2581,6 @@ long firstAttemptStart | |
{ | ||
completion.TrySetResult(retryTask.Result); | ||
} | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change also makes no sense, and I don't see how it compiles at all. Why was this change made? |
||
state: globalCompletion, | ||
TaskScheduler.Default | ||
); | ||
|
@@ -3105,7 +3098,6 @@ private async Task<object> ExecuteScalarUntilEndAsync(SqlDataReader reader, Canc | |
} | ||
|
||
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteXmlReaderAsync[@name="default"]/*'/> | ||
public Task<XmlReader> ExecuteXmlReaderAsync() => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change seems completely random, unrelated to the focus of the PR, and likely doesn't compile. |
||
ExecuteXmlReaderAsync(CancellationToken.None); | ||
|
||
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteXmlReaderAsync[@name="CancellationToken"]/*'/> | ||
|
@@ -4871,7 +4863,6 @@ internal SqlDataReader RunExecuteReader( | |
task: out unused, | ||
usedCache: out _, | ||
method: method); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, removing this line doesn't really aid readability and is unrelated to the PR focus. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All changes above could be because I enable formatting document after saving |
||
Debug.Assert(unused == null, "returned task during synchronous execution"); | ||
return reader; | ||
} | ||
|
@@ -6192,7 +6183,8 @@ private void SetUpRPCParameters(_SqlRPC rpc, bool inSchema, SqlParameterCollecti | |
// Don't assume a default value exists for parameters in the case when | ||
// the user is simply requesting schema. | ||
// TVPs use DEFAULT and do not allow NULL, even for schema only. | ||
if (parameter.Value == null && (!inSchema || SqlDbType.Structured == parameter.SqlDbType)) | ||
if ((parameter.Value == null || (parameter.Value is ICollection collection && collection.Count == 0)) && | ||
sharafabacery marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(!inSchema || parameter.SqlDbType == SqlDbType.Structured)) | ||
{ | ||
options |= TdsEnums.RPC_PARAM_DEFAULT; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,10 @@ | |
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Data; | ||
using Microsoft.Data.Sql; | ||
using Microsoft.Data.SqlClient.Server; | ||
using Xunit; | ||
|
||
namespace Microsoft.Data.SqlClient.Tests | ||
|
@@ -518,5 +520,110 @@ public void ParameterCollectionTest() | |
cmd.Parameters.Remove(cmd.Parameters[0]); | ||
} | ||
} | ||
|
||
#region fixing "Change SqlParameter to allow empty IEnumerable<SqlDataRecord>? #2971" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what to do about these tests. I think someone with a bit more experience in the test area could provide more concrete feedback. @mdaigle ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All changes above could be because I enable formatting document after saving There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there any test need to be done i will do it? |
||
public const string DbName = "TVPTestDb"; | ||
public const string ServerConnection = @"Server=.;Integrated Security=true;Encrypt=false;"; | ||
public static string DbConnection => ServerConnection + $"Initial Catalog={DbName};"; | ||
private static class SqlDataRecordTestCases | ||
{ | ||
public static IEnumerable<object[]> TestSqlDataRecordParameters => new List<object[]> | ||
{ | ||
new object[] { null }, | ||
new object[] { new List<SqlDataRecord>() } // empty list, and the issue it throw an Arrgument Error Exception | ||
}; | ||
} | ||
|
||
private static void CreateDatabaseAndSchema() | ||
{ | ||
string createDb = $@" | ||
IF DB_ID('{DbName}') IS NULL | ||
CREATE DATABASE {DbName};"; | ||
|
||
string createSchema = @" | ||
USE TVPTestDb; | ||
|
||
IF NOT EXISTS (SELECT * FROM sys.types WHERE is_table_type = 1 AND name = 'MySimpleTableType') | ||
BEGIN | ||
CREATE TYPE dbo.MySimpleTableType AS TABLE | ||
( | ||
Id INT, | ||
Name NVARCHAR(100) | ||
); | ||
END; | ||
|
||
IF OBJECT_ID('dbo.TargetTable', 'U') IS NULL | ||
BEGIN | ||
CREATE TABLE dbo.TargetTable | ||
( | ||
Id INT PRIMARY KEY, | ||
Name NVARCHAR(100) | ||
); | ||
END; | ||
|
||
IF OBJECT_ID('dbo.InsertFromTVP', 'P') IS NULL | ||
BEGIN | ||
EXEC(' | ||
CREATE PROCEDURE dbo.InsertFromTVP | ||
@MyTVP dbo.MySimpleTableType READONLY | ||
AS | ||
BEGIN | ||
SET NOCOUNT ON; | ||
INSERT INTO dbo.TargetTable (Id, Name) | ||
SELECT Id, Name FROM @MyTVP; | ||
END | ||
'); | ||
END;"; | ||
|
||
using var conn = new SqlConnection(ServerConnection); | ||
conn.Open(); | ||
new SqlCommand(createDb, conn).ExecuteNonQuery(); | ||
|
||
using var connDb = new SqlConnection(DbConnection); | ||
connDb.Open(); | ||
new SqlCommand(createSchema, connDb).ExecuteNonQuery(); | ||
} | ||
|
||
private static void DeleteDatabase() | ||
{ | ||
string dropDb = $@" | ||
IF DB_ID('{DbName}') IS NOT NULL | ||
BEGIN | ||
ALTER DATABASE {DbName} SET SINGLE_USER WITH ROLLBACK IMMEDIATE; | ||
DROP DATABASE {DbName}; | ||
END;"; | ||
using var conn = new SqlConnection(ServerConnection); | ||
conn.Open(); | ||
new SqlCommand(dropDb, conn).ExecuteNonQuery(); | ||
} | ||
private int perpare_SqlRecord_tests(List<SqlDataRecord> records = null) | ||
{ | ||
SqlConnection cn = new SqlConnection(DbConnection); | ||
|
||
SqlCommand cmd; | ||
// Text, with parameters | ||
cmd = new SqlCommand("dbo.InsertFromTVP", cn); | ||
cmd.CommandType = CommandType.StoredProcedure; | ||
|
||
var paramEmpty = cmd.Parameters.AddWithValue("@MyTVP", records); | ||
paramEmpty.SqlDbType = SqlDbType.Structured; | ||
paramEmpty.TypeName = "dbo.MySimpleTableType"; | ||
cn.Open(); | ||
return cmd.ExecuteNonQuery(); | ||
|
||
} | ||
[Theory] | ||
[MemberData(nameof(SqlDataRecordTestCases.TestSqlDataRecordParameters), MemberType = typeof(SqlDataRecordTestCases))] | ||
public void SqlDataRecord_TABLE_deafult(List<SqlDataRecord> parameters) | ||
{ | ||
CreateDatabaseAndSchema(); | ||
int rowAffects = perpare_SqlRecord_tests(parameters); | ||
DeleteDatabase(); | ||
Assert.Equal(-1, rowAffects); | ||
|
||
} | ||
#endregion | ||
|
||
|
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this change at all, especially since they seem to be completely unrelated to the focus of the PR. We don't want to be removing braces for if statements, and in this particular instance it completely upends the logic of the method.