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

rewrite sql where empty array parameter. #698

Merged
merged 3 commits into from
Jan 6, 2021

Conversation

fredliex
Copy link
Contributor

@fredliex fredliex commented Jan 6, 2021

Code

var result = connection.ExecuteQuery("SELECT * FROM [sc].[IdentityTable] WHERE ColumnInt IN (@ColumnInt);", 
      new { ColumnInt = new int[0] });

Exception

Microsoft.Data.SqlClient.SqlException
  HResult=0x80131904
  Message=Must declare the scalar variable "@ColumnInt"。
  Source=Core Microsoft SqlClient Data Provider
  StackTrace: 
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) in /_/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnection.cs:line 1858

Command watch

command.CommandText = "SELECT * FROM [sc].[IdentityTable] WHERE ColumnInt IN (@ColumnInt);"
command.Parameters (count = 0)

Revise

When the parameter is an empty set, replace @arg with (select @arg where 1 = 0).
And set a DbNull parameter in command.Parameters.

Example

-- @normal = new[] { 1, 2 }
-- @empty = @emptyA = @emptyB = new int[0]
where id in (@normal)		--> where id in (@normal0, @normal1)
where id in (@empty)		--> where id in ((select @empty where 1 = 0))
where id in (@empty, @normal)	--> where id in ((select @empty where 1 = 0), @normal0, @normal1)
where id in (@emptyA, @emptyB)	--> where id in ((select @emptyA where 1 = 0), (select @emptyB where 1 = 0))

@fredliex
Copy link
Contributor Author

fredliex commented Jan 6, 2021

select * from someTable where id in ((select 3 where 1 = 0), 1, 2)

The above syntax has been tested in databases:

@@ -3083,7 +3083,8 @@ internal static IEnumerable<Field> GetQualifiedFields<TEntity>(IEnumerable<Field
var items = values is IEnumerable<object> ? (IEnumerable<object>)values : values.WithType<object>();
if (items.Any() != true)
{
return commandText;
var parameter = parameterName.AsParameter(dbSetting);
return commandText.Replace(parameter, string.Concat("(select ", parameter, " where 1 = 0)"));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small comment, let us make all the SQL statement UPPERCASE like SELECT * FROM Table WHERE 1 = 0;.

@mikependon
Copy link
Owner

Thank you for this PR, you are really maturing and expanding the capability of this ORM. 🛩️ This PR is great and we need to update the documentation here, feel free to put it there, otherwise, I can also put it there soon.

Please continue to do this and I am happy to really shout you out in Twitter and to any other social media if you have an account there!

@mikependon
Copy link
Owner

A small question from me 😄, why did not you just make a little hack here?

-- @normal = new[] { 1, 2 }
-- @empty = @emptyA = @emptyB = new int[0]
where id in (@normal)		--> where id in (@normal0, @normal1)
where id in (@empty)		--> where 1 = 0 // Only if all the passed parameters are null or empty
where id in (@empty, @normal)	--> where id in (@normal0, @normal1) // ignoring the empty
where id in (@emptyA, @emptyB)	--> where 1 = 0 // Only if all the passed parameters are null or empty

Just a small thoughts. But TBH, the code change you made is very minimal, so it will merge it in a while.

@fredliex
Copy link
Contributor Author

fredliex commented Jan 6, 2021

I have pushed a commit to change uppercase.

@fredliex
Copy link
Contributor Author

fredliex commented Jan 6, 2021

A small question from me 😄, why did not you just make a little hack here?

-- @normal = new[] { 1, 2 }
-- @empty = @emptyA = @emptyB = new int[0]
where id in (@normal)		--> where id in (@normal0, @normal1)
where id in (@empty)		--> where 1 = 0 // Only if all the passed parameters are null or empty
where id in (@empty, @normal)	--> where id in (@normal0, @normal1) // ignoring the empty
where id in (@emptyA, @emptyB)	--> where 1 = 0 // Only if all the passed parameters are null or empty

Just a small thoughts. But TBH, the code change you made is very minimal, so it will merge it in a while.

Because such a processing method will be very simple, just replace @empty.
If want to change it to where 1 = 0, we need to analyze the context of sql, and the processing logic will become very complicated.

@mikependon
Copy link
Owner

That makes sense and based on your changes, it is very minimal. Thanks for your contributions as always.

@mikependon mikependon merged commit e8ba286 into master Jan 6, 2021
@fredliex fredliex deleted the fix/Execute_EmptyArrayParameter branch January 6, 2021 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants