Skip to content

Commit

Permalink
feat: allow 'bool?' for status attribute
Browse files Browse the repository at this point in the history
Refs: #344
  • Loading branch information
phnx47 committed Dec 21, 2023
1 parent 5593e8d commit 3f1c976
Show file tree
Hide file tree
Showing 18 changed files with 133 additions and 109 deletions.
2 changes: 1 addition & 1 deletion src/MicroOrm.Dapper.Repositories.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<Description>CRUD for Dapper</Description>
<Copyright>2015 © Serge K</Copyright>
<Authors>Serge K and Contributors</Authors>
<TargetFrameworks>net461;netstandard2.0;net5.0</TargetFrameworks>
<TargetFrameworks>net461;netstandard2.0;net5.0;net7.0</TargetFrameworks>
<LangVersion>11.0</LangVersion>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
Expand Down
29 changes: 19 additions & 10 deletions src/SqlGenerator/SqlGenerator.AppendJoin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,29 @@ private void AppendJoinQuery(JoinAttributeBase attrJoin, StringBuilder joinBuild
var colAttr = deleteAttr.GetCustomAttribute<ColumnAttribute>();
var colName = colAttr == null ? deleteAttr.Name : colAttr.Name;
object deleteValue = Provider == SqlProvider.PostgreSQL ? "true" : 1;
if (deleteAttr.PropertyType.IsEnum)
if(deleteAttr.PropertyType == typeof(bool?))
{
var deleteOption = deleteAttr.PropertyType.GetFields().FirstOrDefault(f => f.GetCustomAttribute<DeletedAttribute>() != null);

if (deleteOption != null)
customFilter = attrJoin.TableAlias == string.Empty
? $"AND {attrJoin.TableName}.{colName} IS NULL "
: $"AND {attrJoin.TableAlias}.{colName} IS NULL ";
}
else
{
if (deleteAttr.PropertyType.IsEnum)
{
var enumValue = Enum.Parse(deleteAttr.PropertyType, deleteOption.Name);
deleteValue = Convert.ChangeType(enumValue, Enum.GetUnderlyingType(deleteAttr.PropertyType));
var deleteOption = deleteAttr.PropertyType.GetFields().FirstOrDefault(f => f.GetCustomAttribute<DeletedAttribute>() != null);

if (deleteOption != null)
{
var enumValue = Enum.Parse(deleteAttr.PropertyType, deleteOption.Name);
deleteValue = Convert.ChangeType(enumValue, Enum.GetUnderlyingType(deleteAttr.PropertyType));

Check warning on line 95 in src/SqlGenerator/SqlGenerator.AppendJoin.cs

View check run for this annotation

Codecov / codecov/patch

src/SqlGenerator/SqlGenerator.AppendJoin.cs#L94-L95

Added lines #L94 - L95 were not covered by tests
}
}
}

customFilter = attrJoin.TableAlias == string.Empty
? $"AND {attrJoin.TableName}.{colName} != {deleteValue} "
: $"AND {attrJoin.TableAlias}.{colName} != {deleteValue} ";
customFilter = attrJoin.TableAlias == string.Empty
? $"AND {attrJoin.TableName}.{colName} != {deleteValue} "
: $"AND {attrJoin.TableAlias}.{colName} != {deleteValue} ";

Check warning on line 101 in src/SqlGenerator/SqlGenerator.AppendJoin.cs

View check run for this annotation

Codecov / codecov/patch

src/SqlGenerator/SqlGenerator.AppendJoin.cs#L100-L101

Added lines #L100 - L101 were not covered by tests
}
}

joinBuilder.Append(attrJoin.TableAlias == string.Empty
Expand Down
17 changes: 15 additions & 2 deletions src/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,27 @@ private void AppendWherePredicateQuery(SqlQuery sqlQuery, Expression<Func<TEntit
dictionaryParams.AddRange(conditions);

if (LogicalDelete && queryType == QueryType.Select)
sqlQuery.SqlBuilder.AppendFormat("({3}) AND {0}.{1} != {2} ", TableName, StatusPropertyName, LogicalDeleteValue, sqlBuilder);
{
if (LogicalDeleteValueNullable)
sqlQuery.SqlBuilder.AppendFormat("({2}) AND {0}.{1} IS NULL ", TableName, StatusPropertyName, sqlBuilder);
else
sqlQuery.SqlBuilder.AppendFormat("({3}) AND {0}.{1} != {2} ", TableName, StatusPropertyName, LogicalDeleteValue, sqlBuilder);
}
else
{
sqlQuery.SqlBuilder.AppendFormat("{0} ", sqlBuilder);
}
}
else
{
if (LogicalDelete && queryType == QueryType.Select)
sqlQuery.SqlBuilder.AppendFormat("WHERE {0}.{1} != {2} ", TableName, StatusPropertyName, LogicalDeleteValue);
{
if (LogicalDeleteValueNullable)
sqlQuery.SqlBuilder.AppendFormat("WHERE {0}.{1} IS NULL ", TableName, StatusPropertyName);
else
sqlQuery.SqlBuilder.AppendFormat("WHERE {0}.{1} != {2} ", TableName, StatusPropertyName, LogicalDeleteValue);

Check warning on line 61 in src/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs

View check run for this annotation

Codecov / codecov/patch

src/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs#L61

Added line #L61 was not covered by tests
}

}

if (LogicalDelete && HasUpdatedAt && queryType == QueryType.Delete)
Expand Down
29 changes: 18 additions & 11 deletions src/SqlGenerator/SqlGenerator.GetSelect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

namespace MicroOrm.Dapper.Repositories.SqlGenerator;


public partial class SqlGenerator<TEntity>
where TEntity : class
{
Expand Down Expand Up @@ -57,8 +56,7 @@ private SqlQuery GetSelect(Expression<Func<TEntity, bool>>? predicate, bool firs
if (Provider == SqlProvider.Oracle)
sqlQuery.SqlBuilder.Append("FETCH FIRST 1 ROW ONLY");
else if (Provider != SqlProvider.MSSQL)
sqlQuery.SqlBuilder
.Append("LIMIT 1");
sqlQuery.SqlBuilder.Append("LIMIT 1");
}

return sqlQuery;
Expand Down Expand Up @@ -293,21 +291,30 @@ public virtual SqlQuery GetSelectById(object id, FilterData? filterData, params
.Append(" ");

if (LogicalDelete)
{
sqlQuery.SqlBuilder
.Append("AND ")
.Append(TableName)
.Append(".")
.Append(StatusPropertyName)
.Append(" != ")
.Append(LogicalDeleteValue)
.Append(" ");
.Append(StatusPropertyName);

if (LogicalDeleteValueNullable)
{
sqlQuery.SqlBuilder
.Append(" IS NULL ");
}
else
{
sqlQuery.SqlBuilder
.Append(" != ")
.Append(LogicalDeleteValue)
.Append(" ");

Check warning on line 311 in src/SqlGenerator/SqlGenerator.GetSelect.cs

View check run for this annotation

Codecov / codecov/patch

src/SqlGenerator/SqlGenerator.GetSelect.cs#L308-L311

Added lines #L308 - L311 were not covered by tests
}
}

if (includes.Length == 0 && Provider != SqlProvider.MSSQL)
{
if (Provider == SqlProvider.Oracle)
sqlQuery.SqlBuilder.Append("FETCH FIRST 1 ROWS ONLY");
else
sqlQuery.SqlBuilder.Append("LIMIT 1");
sqlQuery.SqlBuilder.Append(Provider == SqlProvider.Oracle ? "FETCH FIRST 1 ROWS ONLY" : "LIMIT 1");
}

sqlQuery.SetParam(param);
Expand Down
12 changes: 8 additions & 4 deletions src/SqlGenerator/SqlGenerator.InitLogicalDeleted.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ private void InitLogicalDeleted()
if (deleteAttr == null)
continue;

if (JoinsLogicalDelete == null)
JoinsLogicalDelete = new Dictionary<string, PropertyInfo>();

JoinsLogicalDelete ??= new Dictionary<string, PropertyInfo>();
JoinsLogicalDelete.Add(joinAttr.TableName, deleteAttr);
}

Expand All @@ -41,7 +39,13 @@ private void InitLogicalDeleted()
if (statusProperty.PropertyInfo.PropertyType == typeof(bool))
{
LogicalDelete = true;
LogicalDeleteValue = Provider == SqlProvider.PostgreSQL ? "true" : 1; // true
LogicalDeleteValue = Provider == SqlProvider.PostgreSQL ? "true" : 1;
}
else if (statusProperty.PropertyInfo.PropertyType == typeof(bool?))
{
LogicalDelete = true;
LogicalDeleteValue = Provider == SqlProvider.PostgreSQL ? "true" : 1;
LogicalDeleteValueNullable = true;
}
else if (statusProperty.PropertyInfo.PropertyType.IsEnum)
{
Expand Down
2 changes: 2 additions & 0 deletions src/SqlGenerator/SqlGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public SqlGenerator(SqlProvider provider)

public object? LogicalDeleteValue { get; protected set; }

public bool LogicalDeleteValueNullable { get; protected set; }

/// <summary>
/// In Oracle parameter should be build with : instead of @.
/// </summary>
Expand Down
18 changes: 9 additions & 9 deletions tests/Repositories.Base/BaseRepositoriesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public void Count()
{
var count = Db.Users.Count();
var countHandQuery = Db.Connection
.ExecuteScalar<int>("SELECT COUNT(*) FROM Users WHERE Users.Deleted != " + Db.Users.SqlGenerator.LogicalDeleteValue);
.ExecuteScalar<int>("SELECT COUNT(*) FROM Users WHERE Users.Deleted IS NULL");
Assert.Equal(countHandQuery, count);
}

Expand Down Expand Up @@ -78,15 +78,15 @@ public void CountWithDistinctAndWhere()
public void Find()
{
var user = Db.Users.Find(x => x.Id == 2);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal("TestName1", user.Name);
}

[Fact]
public void FindById()
{
var user = Db.Users.FindById(2);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal("TestName1", user.Name);
}

Expand All @@ -100,15 +100,15 @@ public void FindById_MultiKeys()
public async void FindByIdAsync()
{
var user = await Db.Users.FindByIdAsync(2);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal("TestName1", user.Name);
}

[Fact]
public async void FindByIdAsync_WithJoins_NotNull()
{
var user = await Db.Users.FindByIdAsync<Car, Phone, Address>(1, x => x.Cars, x => x.Phone, x => x.Addresses);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal("TestName0", user.Name);

Assert.NotNull(user.Phone);
Expand Down Expand Up @@ -150,7 +150,7 @@ public async void FindAllAsync_NullPredicate_CheckCount()
protected void FindJoin_CollectionnRecord()
{
var user = Db.Users.Find<Car>(q => q.Id == 1, q => q.Cars);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal("TestName0", user.Name);

Assert.True(user.Cars.Count == 2);
Expand All @@ -160,7 +160,7 @@ protected void FindJoin_CollectionnRecord()
public async void FindJoinAsync_CollectionnRecord()
{
var user = await Db.Users.FindAsync<Car>(q => q.Id == 1, q => q.Cars);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal("TestName0", user.Name);

Assert.True(user.Cars.Count == 2);
Expand Down Expand Up @@ -297,7 +297,7 @@ public async Task FindAsync()
const string name = "TestName3";
{
var user = await Db.Users.FindAsync(x => x.Id == id);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);
Assert.Equal(name, user.Name);
}
{
Expand Down Expand Up @@ -429,7 +429,7 @@ public async Task LogicalDeletedBoolAsync()
const int id = 10;

var user = await Db.Users.FindAsync(x => x.Id == id);
Assert.False(user.Deleted);
Assert.Null(user.Deleted);

var deleted = await Db.Users.DeleteAsync(user);
Assert.True(deleted);
Expand Down
2 changes: 1 addition & 1 deletion tests/Repositories.MSSQL.Tests/DatabaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ void CreateSchema(string dbSchema)
CreateSchema("DAB");

Db.Connection.Execute(
@"CREATE TABLE Users (Id int IDENTITY(1,1) not null, Name varchar(256) not null, AddressId int not null, PhoneId int not null, OfficePhoneId int not null, Deleted bit not null, UpdatedAt datetime2, PRIMARY KEY (Id))");
@"CREATE TABLE Users (Id int IDENTITY(1,1) not null, Name varchar(256) not null, AddressId int not null, PhoneId int not null, OfficePhoneId int not null, Deleted bit, UpdatedAt datetime2, PRIMARY KEY (Id))");
Db.Connection.Execute(
@"CREATE TABLE Cars (Id int IDENTITY(1,1) not null, Name varchar(256) not null, UserId int not null, Status int not null, Data binary(16) null, PRIMARY KEY (Id))");

Expand Down
4 changes: 2 additions & 2 deletions tests/Repositories.MySql.Tests/DatabaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ private void InitDb()

Db.Connection.Execute("CREATE TABLE IF NOT EXISTS `Users` " +
"(`Id` int not null auto_increment, `Name` varchar(256) not null, `AddressId` int not null, `PhoneId` int not null, " +
"`OfficePhoneId` int not null, `Deleted` boolean not null, `UpdatedAt` datetime, PRIMARY KEY (`Id`));");
"`OfficePhoneId` int not null, `Deleted` boolean, `UpdatedAt` datetime, PRIMARY KEY (`Id`));");

Db.Connection.Execute("CREATE TABLE IF NOT EXISTS `Cars` " +
"(`Id` int not null auto_increment, `Name` varchar(256) not null, " +
Expand All @@ -65,6 +65,6 @@ private void InitDb()
private void DropDatabase()
{
Db.Connection.Execute($"DROP DATABASE IF EXISTS {_dbName}");
Db.Connection.Execute($"DROP DATABASE IF EXISTS DAB");
Db.Connection.Execute("DROP DATABASE IF EXISTS DAB");
}
}
2 changes: 1 addition & 1 deletion tests/Repositories.Oracle.Tests/DatabaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ NAME VARCHAR(256) NOT NULL,
ADDRESSID NUMBER NOT NULL,
PHONEID NUMBER NOT NULL,
OFFICEPHONEID NUMBER NOT NULL,
DELETED NUMBER NOT NULL,
DELETED NUMBER,
UPDATEDAT DATE,
PRIMARY KEY (ID))");

Expand Down
2 changes: 1 addition & 1 deletion tests/Repositories.PostgreSQL.Tests/DatabaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void CreateSchema(string dbSchema)
CreateSchema("DAB");

Db.Connection.Execute(
@"CREATE TABLE Users (Id SERIAL not null, Name varchar(256) not null, AddressId int not null, PhoneId int not null, OfficePhoneId int not null, Deleted bool not null, UpdatedAt timestamp, PRIMARY KEY (Id))");
@"CREATE TABLE Users (Id SERIAL not null, Name varchar(256) not null, AddressId int not null, PhoneId int not null, OfficePhoneId int not null, Deleted bool, UpdatedAt timestamp, PRIMARY KEY (Id))");
Db.Connection.Execute(
@"CREATE TABLE Cars (Id SERIAL not null, Name varchar(256) not null, UserId int not null, Status int not null, Data bytea null, PRIMARY KEY (Id))");

Expand Down
2 changes: 1 addition & 1 deletion tests/Repositories.SQLite.Tests/DatabaseFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private void InitDb()

Db.Connection.Execute("CREATE TABLE `Users` " +
"(`Id` integer not null primary key autoincrement, `Name` varchar(256) not null, `AddressId` integer not null, `PhoneId` integer not null, " +
"`OfficePhoneId` integer not null, `Deleted` boolean not null, `UpdatedAt` datetime);");
"`OfficePhoneId` integer not null, `Deleted` boolean, `UpdatedAt` datetime);");

Db.Connection.Execute("CREATE TABLE `Cars` " +
"(`Id` integer not null primary key autoincrement, `Name` varchar(256) not null, " +
Expand Down
Loading

0 comments on commit 3f1c976

Please sign in to comment.