From e845c790bbee8ea8487a57b58062b3bea81b34e3 Mon Sep 17 00:00:00 2001 From: Bo Hu Date: Thu, 24 Feb 2022 23:36:02 +0100 Subject: [PATCH 1/2] Add support for Oracle12c. --- .../DapperRepository.Insert.cs | 27 +- .../OracleDynamicParametersExtensions.cs | 19 + .../SqlGenerator/SqlGenerator.AppendJoin.cs | 5 +- .../SqlGenerator.AppendWherePredicateQuery.cs | 17 +- .../SqlGenerator.GetBulkInsert.cs | 16 +- .../SqlGenerator.GetBulkUpdate.cs | 30 +- .../SqlGenerator/SqlGenerator.GetDelete.cs | 6 +- .../SqlGenerator/SqlGenerator.GetInsert.cs | 22 +- .../SqlGenerator/SqlGenerator.GetSelect.cs | 26 +- .../SqlGenerator/SqlGenerator.GetTableName.cs | 3 + .../SqlGenerator/SqlGenerator.GetUpdate.cs | 6 +- .../SqlGenerator/SqlGenerator.InitConfig.cs | 14 +- .../SqlGenerator/SqlGenerator.cs | 5 +- .../SqlGenerator/SqlProvider.cs | 7 +- .../Classes/Phone.cs | 6 +- .../DatabaseFixture/InitData.cs | 4 +- .../DatabaseFixture/MsSqlDatabaseFixture.cs | 2 +- .../DatabaseFixture/MySqlDatabaseFixture.cs | 2 +- .../Oracle12cDatabaseFixture.cs | 117 +++ .../DbContexts/OracleDbContext.cs | 40 + .../MicroOrm.Dapper.Repositories.Tests.csproj | 1 + .../Oracle12cRepositoriesTests.cs | 14 + .../RepositoriesTests/RepositoriesTests.cs | 22 +- .../SqlGeneratorTests/MsSqlGeneratorTests.cs | 92 +-- .../SqlGeneratorTests/MySqlGeneratorTests.cs | 24 +- .../Oracle12cSqlGeneratorTests.cs | 699 ++++++++++++++++++ .../PostgresSqlGeneratorTests.cs | 16 +- 27 files changed, 1127 insertions(+), 115 deletions(-) create mode 100644 src/MicroOrm.Dapper.Repositories/Extensions/OracleDynamicParametersExtensions.cs create mode 100644 test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/Oracle12cDatabaseFixture.cs create mode 100644 test/MicroOrm.Dapper.Repositories.Tests/DbContexts/OracleDbContext.cs create mode 100644 test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/Oracle12cRepositoriesTests.cs create mode 100644 test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/Oracle12cSqlGeneratorTests.cs diff --git a/src/MicroOrm.Dapper.Repositories/DapperRepository.Insert.cs b/src/MicroOrm.Dapper.Repositories/DapperRepository.Insert.cs index 149d3c32..d1fdaaf6 100644 --- a/src/MicroOrm.Dapper.Repositories/DapperRepository.Insert.cs +++ b/src/MicroOrm.Dapper.Repositories/DapperRepository.Insert.cs @@ -24,8 +24,18 @@ public virtual bool Insert(TEntity instance, IDbTransaction transaction) var queryResult = SqlGenerator.GetInsert(instance); if (SqlGenerator.IsIdentity) { - var newId = Connection.Query(queryResult.GetSql(), queryResult.Param, transaction).FirstOrDefault(); - return SetValue(newId, instance); + if (SqlGenerator.Provider == Repositories.SqlGenerator.SqlProvider.Oracle) + { + Connection.Execute(queryResult.GetSql(), queryResult.Param, transaction); + int newId = ((DynamicParameters)(queryResult.Param)).Get(":newId"); + return SetValue(newId, instance); + } + else + { + var newId = Connection.Query(queryResult.GetSql(), queryResult.Param, transaction).FirstOrDefault(); + return SetValue(newId, instance); + } + } return Connection.Execute(queryResult.GetSql(), instance, transaction) > 0; @@ -43,8 +53,17 @@ public virtual async Task InsertAsync(TEntity instance, IDbTransaction tra var queryResult = SqlGenerator.GetInsert(instance); if (SqlGenerator.IsIdentity) { - var newId = (await Connection.QueryAsync(queryResult.GetSql(), queryResult.Param, transaction)).FirstOrDefault(); - return SetValue(newId, instance); + if(SqlGenerator.Provider == Repositories.SqlGenerator.SqlProvider.Oracle) + { + await Connection.ExecuteAsync(queryResult.GetSql(), queryResult.Param, transaction); + int newId = ((DynamicParameters)(queryResult.Param)).Get(":newId"); + return SetValue(newId, instance); + } + else + { + var newId = (await Connection.QueryAsync(queryResult.GetSql(), queryResult.Param, transaction)).FirstOrDefault(); + return SetValue(newId, instance); + } } return await Connection.ExecuteAsync(queryResult.GetSql(), instance, transaction) > 0; diff --git a/src/MicroOrm.Dapper.Repositories/Extensions/OracleDynamicParametersExtensions.cs b/src/MicroOrm.Dapper.Repositories/Extensions/OracleDynamicParametersExtensions.cs new file mode 100644 index 00000000..82f83e9b --- /dev/null +++ b/src/MicroOrm.Dapper.Repositories/Extensions/OracleDynamicParametersExtensions.cs @@ -0,0 +1,19 @@ +using System.Data; +using Dapper; + +namespace MicroOrm.Dapper.Repositories.Extensions +{ + /// + /// TODO: + /// Currently it only add output parameter with type DbType.Int32. + /// It should actually check the prima key type then mapping it to different DbType such as DbType.Int64, etc. + /// If GUID support is added, it should also be added here. + /// + internal static class OracleDynamicParametersExtensions + { + public static void AddOracleOutputParameterForId(this DynamicParameters param) + { + param.Add(name: "newId", dbType: DbType.Int32, direction: ParameterDirection.Output); + } + } +} diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendJoin.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendJoin.cs index 3d4413dd..07b341ba 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendJoin.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendJoin.cs @@ -60,11 +60,12 @@ private string AppendJoinToUpdate(TBase entity, SqlQuery originalBuilder, private void AppendJoinQuery(JoinAttributeBase attrJoin, StringBuilder joinBuilder, string tableName) { var joinString = attrJoin.ToString(); + var joinAs = Provider == SqlProvider.Oracle ? " " : " AS "; if (attrJoin is CrossJoinAttribute) { joinBuilder.Append(attrJoin.TableAlias == string.Empty ? $"{joinString} {attrJoin.TableName} " - : $"{joinString} {attrJoin.TableName} AS {attrJoin.TableAlias} "); + : $"{joinString} {attrJoin.TableName}{joinAs}{attrJoin.TableAlias} "); } else { @@ -92,7 +93,7 @@ private void AppendJoinQuery(JoinAttributeBase attrJoin, StringBuilder joinBuild joinBuilder.Append(attrJoin.TableAlias == string.Empty ? $"{joinString} {attrJoin.TableName} ON {tableName}.{attrJoin.Key} = {attrJoin.TableName}.{attrJoin.ExternalKey} {customFilter}" - : $"{joinString} {attrJoin.TableName} AS {attrJoin.TableAlias} ON {tableName}.{attrJoin.Key} = {attrJoin.TableAlias}.{attrJoin.ExternalKey} {customFilter}"); + : $"{joinString} {attrJoin.TableName}{joinAs}{attrJoin.TableAlias} ON {tableName}.{attrJoin.Key} = {attrJoin.TableAlias}.{attrJoin.ExternalKey} {customFilter}"); } } diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs index 21575d97..e5ab36f1 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.AppendWherePredicateQuery.cs @@ -1,8 +1,10 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; +using Dapper; using MicroOrm.Dapper.Repositories.Extensions; using MicroOrm.Dapper.Repositories.SqlGenerator.QueryExpressions; @@ -104,8 +106,21 @@ private void BuildQuerySql(IList queryProperties, { var vKey = string.Format("{0}_p{1}", qpExpr.PropertyName, qLevel); //Handle multiple uses of a field - sqlBuilder.AppendFormat("{0}.{1} {2} @{3}", tableName, columnName, qpExpr.QueryOperator, vKey); + sqlBuilder.AppendFormat("{0}.{1} {2} " + ParameterSymbol + "{3}", tableName, columnName, qpExpr.QueryOperator, vKey); conditions.Add(new KeyValuePair(vKey, qpExpr.PropertyValue)); + + // in oracle, we should pass a null value instead of an empty list in case of query something like "select * from sometable where id in :id " and :id is empty. + // make sure firsty the value in params is a type of generic list. + // i dont like this solution. if anyone has a better way plz commit. + if (Provider == SqlProvider.Oracle) + { + if(conditions[0].Value.GetType() != null && conditions[0].Value.GetType().IsGenericType && conditions[0].Value.GetType().GetGenericTypeDefinition() == typeof(List<>)) + { + var value = conditions[0].Value as IList; + if (value.Count == 0) + conditions[0] = new KeyValuePair(vKey, null); + } + } } qLevel++; diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkInsert.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkInsert.cs index 2bcf0ad7..b8319abe 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkInsert.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkInsert.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Dapper; using MicroOrm.Dapper.Repositories.Attributes; namespace MicroOrm.Dapper.Repositories.SqlGenerator @@ -50,11 +51,18 @@ public virtual SqlQuery GetBulkInsert(IEnumerable entities) // ReSharper disable once PossibleNullReferenceException parameters.Add(property.PropertyName + i, entityType.GetProperty(property.PropertyName).GetValue(entity, null)); - values.Add(string.Format("({0})", string.Join(", ", properties.Select(p => "@" + p.PropertyName + i)))); + values.Add(string.Format("({0})", string.Join(", ", properties.Select(p => ParameterSymbol + p.PropertyName + i)))); + } + if(Provider != SqlProvider.Oracle) { + query.SqlBuilder.AppendFormat("INSERT INTO {0} ({1}) VALUES {2}", TableName, string.Join(", ", properties.Select(p => p.ColumnName)), + string.Join(",", values)); // values + } + else + { + query.SqlBuilder.AppendFormat("INSERT INTO {0} ({1})", TableName, string.Join(", ", properties.Select(p => p.ColumnName))); + var singleInsert = values.Select(v => " SELECT " + v.Substring(1, v.Length-2) + " FROM DUAL "); + query.SqlBuilder.Append(string.Join("UNION ALL", singleInsert)); } - - query.SqlBuilder.AppendFormat("INSERT INTO {0} ({1}) VALUES {2}", TableName, string.Join(", ", properties.Select(p => p.ColumnName)), - string.Join(",", values)); // values query.SetParam(parameters); diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkUpdate.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkUpdate.cs index 93c502db..4b45b649 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkUpdate.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetBulkUpdate.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Text; using MicroOrm.Dapper.Repositories.Attributes; namespace MicroOrm.Dapper.Repositories.SqlGenerator @@ -26,6 +27,9 @@ public virtual SqlQuery GetBulkUpdate(IEnumerable entities) var parameters = new Dictionary(); + //In Oracle we use MERGE INTO to excute multipe update with argument. + List singleSelectsForOracle = new List(); + for (var i = 0; i < entitiesArray.Length; i++) { var entity = entitiesArray[i]; @@ -43,11 +47,19 @@ public virtual SqlQuery GetBulkUpdate(IEnumerable entities) UpdatedAtProperty.SetValue(entity, offset.DateTime); } - if (i > 0) - query.SqlBuilder.Append("; "); + if (Provider != SqlProvider.Oracle) + { + if (i > 0) + query.SqlBuilder.Append("; "); - query.SqlBuilder.Append( - $"UPDATE {TableName} SET {string.Join(", ", properties.Select(p => $"{p.ColumnName} = @{p.PropertyName}{i}"))} WHERE {string.Join(" AND ", KeySqlProperties.Where(p => !p.IgnoreUpdate).Select(p => $"{p.ColumnName} = @{p.PropertyName}{i}"))}"); + query.SqlBuilder.Append( + $"UPDATE {TableName} SET {string.Join(", ", properties.Select(p => $"{p.ColumnName} = {ParameterSymbol}{p.PropertyName}{i}"))} WHERE {string.Join(" AND ", KeySqlProperties.Where(p => !p.IgnoreUpdate).Select(p => $"{p.ColumnName} = {ParameterSymbol}{p.PropertyName}{i}"))}"); + } + else + { + var singleSelect = $"SELECT {string.Join(", ", properties.Select(p => $"{ParameterSymbol}{p.PropertyName}{i} AS {p.ColumnName}"))}, {string.Join(" , ", KeySqlProperties.Where(p => !p.IgnoreUpdate).Select(p => $"{ParameterSymbol}{p.PropertyName}{i} AS {p.ColumnName}"))} FROM DUAL"; + singleSelectsForOracle.Add(singleSelect); + } // ReSharper disable PossibleNullReferenceException foreach (var property in properties) @@ -61,6 +73,16 @@ public virtual SqlQuery GetBulkUpdate(IEnumerable entities) query.SetParam(parameters); + if (Provider == SqlProvider.Oracle) + { + var unionTName = $"{TableName}_BULKUPDATE"; + var unionSelect = string.Join(" UNION ALL ", singleSelectsForOracle); + var unionOn = $"({string.Join(" AND ", KeySqlProperties.Where(p => !p.IgnoreUpdate).Select(p => $"{unionTName}.{p.ColumnName} = {TableName}.{p.ColumnName}"))})"; + var unionSet = $"{string.Join(",", properties.Select(p => $"{p.ColumnName} = {unionTName}.{p.ColumnName} "))}"; + + query.SqlBuilder.Append($"MERGE INTO {TableName} {TableName} USING ({unionSelect}) {unionTName} ON {unionOn} WHEN MATCHED THEN UPDATE SET {unionSet}"); + } + return query; } } diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetDelete.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetDelete.cs index a0044333..0765bf32 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetDelete.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetDelete.cs @@ -15,7 +15,7 @@ public virtual SqlQuery GetDelete(TEntity entity) { var sqlQuery = new SqlQuery(); var whereAndSql = - string.Join(" AND ", KeySqlProperties.Select(p => string.Format("{0}.{1} = @{2}", TableName, p.ColumnName, p.PropertyName))); + string.Join(" AND ", KeySqlProperties.Select(p => string.Format("{0}.{1} = {2}", TableName, p.ColumnName, ParameterSymbol+p.PropertyName))); if (!LogicalDelete) { @@ -51,7 +51,7 @@ public virtual SqlQuery GetDelete(TEntity entity) sqlQuery.SqlBuilder .Append(", ") .Append(UpdatedAtPropertyMetadata.ColumnName) - .Append(" = @") + .Append($" = {ParameterSymbol}") .Append(UpdatedAtPropertyMetadata.PropertyName); } @@ -89,7 +89,7 @@ public virtual SqlQuery GetDelete(Expression> predicate) sqlQuery.SqlBuilder .Append(", ") .Append(UpdatedAtPropertyMetadata.ColumnName) - .Append(" = @") + .Append($" = {ParameterSymbol}") .Append(UpdatedAtPropertyMetadata.PropertyName); diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetInsert.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetInsert.cs index 7789efd0..2eca6627 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetInsert.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetInsert.cs @@ -1,7 +1,9 @@ using System; using System.Linq; using System.Reflection; +using Dapper; using MicroOrm.Dapper.Repositories.Attributes; +using MicroOrm.Dapper.Repositories.Extensions; namespace MicroOrm.Dapper.Repositories.SqlGenerator { @@ -33,8 +35,22 @@ public virtual SqlQuery GetInsert(TEntity entity) var query = new SqlQuery(entity); + //sorry, dapper doesn't support guid mapping in oracle. + //I can not convert guid to bytearray to build a seperate params, it can not be achieved in this lib. + //see details below to get more informations. + //https://github.com/DapperLib/Dapper/issues/633 + //https://github.com/DapperLib/Dapper/issues/637 + //https://github.com/vauto/Dapper.Database/pull/1 + + if (Provider == SqlProvider.Oracle) + { + var oracleParams = new DynamicParameters(entity); + oracleParams.AddOracleOutputParameterForId(); + query.SetParam(oracleParams); + } + query.SqlBuilder.AppendFormat("INSERT INTO {0} ({1}) VALUES ({2})", TableName, string.Join(", ", properties.Select(p => p.ColumnName)), - string.Join(", ", properties.Select(p => "@" + p.PropertyName))); // values + string.Join(", ", properties.Select(p => ParameterSymbol + p.PropertyName))); // values if (IsIdentity) switch (Provider) @@ -55,6 +71,10 @@ public virtual SqlQuery GetInsert(TEntity entity) query.SqlBuilder.Append(" RETURNING " + IdentitySqlProperty.ColumnName); break; + case SqlProvider.Oracle: + query.SqlBuilder.Append(" RETURNING " + IdentitySqlProperty.ColumnName + " INTO :newId"); + break; + default: throw new ArgumentOutOfRangeException(); } diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetSelect.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetSelect.cs index 3420246f..3d351d1e 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetSelect.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetSelect.cs @@ -55,7 +55,9 @@ private SqlQuery GetSelect(Expression> predicate, bool first } else { - if (Provider != SqlProvider.MSSQL) + if (Provider == SqlProvider.Oracle) + sqlQuery.SqlBuilder.Append("FETCH FIRST 1 ROW ONLY"); + else if (Provider != SqlProvider.MSSQL) sqlQuery.SqlBuilder .Append("LIMIT 1"); } @@ -79,6 +81,14 @@ private void SetLimit(SqlQuery sqlQuery, FilterData filterData) sqlQuery.SqlBuilder.Append(filterData.LimitInfo.Limit); sqlQuery.SqlBuilder.Append(" ROWS ONLY"); } + else if (Provider == SqlProvider.Oracle) + { + sqlQuery.SqlBuilder.Append("OFFSET "); + sqlQuery.SqlBuilder.Append(filterData.LimitInfo.Offset ?? 0); + sqlQuery.SqlBuilder.Append(" ROWS FETCH NEXT "); + sqlQuery.SqlBuilder.Append(filterData.LimitInfo.Limit); + sqlQuery.SqlBuilder.Append(" ROWS ONLY"); + } else { sqlQuery.SqlBuilder.Append("LIMIT "); @@ -118,7 +128,7 @@ private void SetOrder(SqlQuery sqlQuery, FilterData filterData) var count = filterData.OrderInfo.Columns.Count; foreach (var col in filterData.OrderInfo.Columns) { - if (UseQuotationMarks == true && Provider != SqlProvider.SQLite) + if (UseQuotationMarks == true && Provider != SqlProvider.SQLite && Provider != SqlProvider.Oracle) { sqlQuery.SqlBuilder.Append(Provider == SqlProvider.MSSQL ? $"[{col}]" : $"`{col}`"); } @@ -254,7 +264,8 @@ public SqlQuery GetSelectById(object id, FilterData filterData, params Expressio .Append(TableName) .Append(".") .Append(keyProperty.ColumnName) - .Append(" = @") + .Append(" = ") + .Append(ParameterSymbol) .Append(keyProperty.PropertyName) .Append(" "); @@ -269,8 +280,12 @@ public SqlQuery GetSelectById(object id, FilterData filterData, params Expressio .Append(" "); if (includes.Length == 0 && Provider != SqlProvider.MSSQL) - sqlQuery.SqlBuilder - .Append("LIMIT 1"); + { + if(Provider == SqlProvider.Oracle) + sqlQuery.SqlBuilder.Append("FETCH FIRST 1 ROWS ONLY"); + else + sqlQuery.SqlBuilder.Append("LIMIT 1"); + } sqlQuery.SetParam(dictionary); return sqlQuery; @@ -326,7 +341,6 @@ private SqlQuery InitBuilderSelect(bool firstOnly, FilterData filterData) query.SqlBuilder.Append(filterData?.SelectInfo?.Columns == null ? GetFieldsSelect(TableName, SqlProperties, UseQuotationMarks == true) : GetFieldsSelect(filterData.SelectInfo.Columns)); - return query; } diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetTableName.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetTableName.cs index a0bd0c3a..387d448e 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetTableName.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetTableName.cs @@ -60,6 +60,9 @@ private string GetTableNameWithQuotes(JoinAttributeBase attrJoin, SqlPropertyMet break; + case SqlProvider.Oracle: + break; + default: throw new ArgumentOutOfRangeException(nameof(Provider)); } diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetUpdate.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetUpdate.cs index 4ec1bc7b..b4a507de 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetUpdate.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.GetUpdate.cs @@ -57,7 +57,7 @@ public virtual SqlQuery GetUpdate(TEntity entity, params Expression !p.IgnoreUpdate) - .Select(p => $"{TableName}.{p.ColumnName} = @{entity.GetType().Name}{p.PropertyName}"))); + .Select(p => $"{TableName}.{p.ColumnName} = {ParameterSymbol}{entity.GetType().Name}{p.PropertyName}"))); if (query.Param == null || !(query.Param is Dictionary parameters)) parameters = new Dictionary(); @@ -192,12 +192,12 @@ private string GetFieldsUpdate(string tableName, IEnumerable $"{(useMarks ? p.ColumnName : p.CleanColumnName)} = @{p.PropertyInfo.ReflectedType.Name}{p.PropertyName}")); + .Select(p => $"{(useMarks ? p.ColumnName : p.CleanColumnName)} = {ParameterSymbol}{p.PropertyInfo.ReflectedType.Name}{p.PropertyName}")); } else { return string.Join(", ", properties - .Select(p => $"{tableName}.{(useMarks ? p.ColumnName : p.CleanColumnName)} = @{p.PropertyInfo.ReflectedType.Name}{p.PropertyName}")); + .Select(p => $"{tableName}.{(useMarks ? p.ColumnName : p.CleanColumnName)} = {ParameterSymbol}{p.PropertyInfo.ReflectedType.Name}{p.PropertyName}")); } } } diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.InitConfig.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.InitConfig.cs index 39266831..e0636776 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.InitConfig.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.InitConfig.cs @@ -1,4 +1,6 @@ +using Dapper; using System; +using System.Data; namespace MicroOrm.Dapper.Repositories.SqlGenerator { @@ -29,7 +31,9 @@ private void InitConfig() case SqlProvider.SQLite: //SQLite doesn't use it. break; - + case SqlProvider.Oracle: + //Oracle doesn't use it. + break; default: throw new ArgumentOutOfRangeException(nameof(Provider)); } @@ -40,6 +44,14 @@ private void InitConfig() foreach (var propertyMetadata in SqlJoinProperties) propertyMetadata.TableName = GetTableNameWithSchemaPrefix(propertyMetadata.TableName, propertyMetadata.TableSchema); } + + // set ParameterSymbol with : and mapping Boolean type to Int + if (Provider == SqlProvider.Oracle) + { + ParameterSymbol = ":" ; + SqlMapper.AddTypeMap(typeof(bool), DbType.Int32); + } + } private void InitMetaData(string startQuotationMark, string endQuotationMark) diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.cs index 81a580bb..34f5c60f 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlGenerator.cs @@ -104,7 +104,10 @@ public SqlGenerator(SqlProvider provider) /// public object LogicalDeleteValue { get; protected set; } - + /// + /// In Oracle parameter should be build with : instead of @. + /// + public string ParameterSymbol { get; protected set; } = "@"; private enum QueryType { Select, diff --git a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlProvider.cs b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlProvider.cs index 33f4fed0..d746d262 100644 --- a/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlProvider.cs +++ b/src/MicroOrm.Dapper.Repositories/SqlGenerator/SqlProvider.cs @@ -24,6 +24,11 @@ public enum SqlProvider /// /// SQLite /// - SQLite + SQLite, + + /// + /// Oracle + /// + Oracle } } diff --git a/test/MicroOrm.Dapper.Repositories.Tests/Classes/Phone.cs b/test/MicroOrm.Dapper.Repositories.Tests/Classes/Phone.cs index 13aac142..5faf4515 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/Classes/Phone.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/Classes/Phone.cs @@ -1,4 +1,4 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using MicroOrm.Dapper.Repositories.Attributes; @@ -11,11 +11,11 @@ public class Phone [Identity] public int Id { get; set; } - public string Number { get; set; } + public string PNumber { get; set; } public bool IsActive { get; set; } [IgnoreUpdate] public string Code { get; set; } } -} \ No newline at end of file +} diff --git a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/InitData.cs b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/InitData.cs index f2aab723..3ab1f594 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/InitData.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/InitData.cs @@ -9,8 +9,8 @@ public static void Execute(IDbContext db) { db.Address.Insert(new Address { Street = "Street0", CityId = "MSK" }); - db.Phones.Insert(new Phone { Number = "123", IsActive = true, Code = "UK" }); - db.Phones.Insert(new Phone { Number = "333", IsActive = false, Code = "UK" }); + db.Phones.Insert(new Phone { PNumber = "123", IsActive = true, Code = "UK" }); + db.Phones.Insert(new Phone { PNumber = "333", IsActive = false, Code = "UK" }); for (var i = 0; i < 10; i++) db.Users.Insert(new User diff --git a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MsSqlDatabaseFixture.cs b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MsSqlDatabaseFixture.cs index a0fce048..91330787 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MsSqlDatabaseFixture.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MsSqlDatabaseFixture.cs @@ -46,7 +46,7 @@ void CreateSchema(string dbSchema) Db.Connection.Execute(@"CREATE TABLE Cities (Identifier uniqueidentifier not null, Name varchar(256) not null)"); Db.Connection.Execute(@"CREATE TABLE Reports (Id int not null, AnotherId int not null, UserId int not null, PRIMARY KEY (Id, AnotherId))"); Db.Connection.Execute( - @"CREATE TABLE DAB.Phones (Id int IDENTITY(1,1) not null, Number varchar(256) not null, IsActive bit not null, Code varchar(256) not null, PRIMARY KEY (Id))"); + @"CREATE TABLE DAB.Phones (Id int IDENTITY(1,1) not null, PNumber varchar(256) not null, IsActive bit not null, Code varchar(256) not null, PRIMARY KEY (Id))"); InitData.Execute(Db); } diff --git a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MySqlDatabaseFixture.cs b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MySqlDatabaseFixture.cs index ba9a53d3..ec9c7060 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MySqlDatabaseFixture.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/MySqlDatabaseFixture.cs @@ -40,7 +40,7 @@ private void InitDb() Db.Connection.Execute($"USE `DAB`"); Db.Connection.Execute("CREATE TABLE IF NOT EXISTS `Phones` " + - "(`Id` int not null auto_increment, `Number` varchar(256) not null, " + + "(`Id` int not null auto_increment, `PNumber` varchar(256) not null, " + "`IsActive` boolean not null, `Code` varchar(256) not null, PRIMARY KEY (`Id`));"); Db.Connection.Execute($"USE `{_dbName}`"); diff --git a/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/Oracle12cDatabaseFixture.cs b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/Oracle12cDatabaseFixture.cs new file mode 100644 index 00000000..8de16c18 --- /dev/null +++ b/test/MicroOrm.Dapper.Repositories.Tests/DatabaseFixture/Oracle12cDatabaseFixture.cs @@ -0,0 +1,117 @@ +using Dapper; +using MicroOrm.Dapper.Repositories.Tests.DbContexts; +using System; + + +namespace MicroOrm.Dapper.Repositories.Tests.DatabaseFixture +{ + public class Oracle12cDatabaseFixture : IDisposable + { + /* + * https://github.com/MaksymBilenko/docker-oracle-12c + * docker pull quay.io/maksymbilenko/oracle-12c + * docker run -d -p 8080:8080 -p 1521:1521 quay.io/maksymbilenko/oracle-12c + */ + public Oracle12cDatabaseFixture() + { + Db = new OracleDbContext("DATA SOURCE=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)));User Id=system;Password=oracle"); + + InitDb(); + } + public OracleDbContext Db { get; } + public void Dispose() + { + Db.Dispose(); + } + + private void InitDb() + { + ClearDb(); + SetupSchema(); + Db.Connection.Execute( + @"CREATE TABLE USERS ( + ID NUMBER GENERATED ALWAYS AS IDENTITY(START WITH 1 INCREMENT BY 1), + NAME VARCHAR(256) NOT NULL, + ADDRESSID NUMBER NOT NULL, + PHONEID NUMBER NOT NULL, + OFFICEPHONEID NUMBER NOT NULL, + DELETED NUMBER NOT NULL, + UPDATEDAT DATE, + PRIMARY KEY (ID))"); + + Db.Connection.Execute( + @"CREATE TABLE CARS ( + ID NUMBER GENERATED ALWAYS AS IDENTITY(START WITH 1 INCREMENT BY 1), + NAME VARCHAR(256) NOT NULL, + USERID NUMBER NOT NULL, + STATUS NUMBER NOT NULL, + DATA RAW(16) NULL, + PRIMARY KEY (ID))"); + + Db.Connection.Execute( + @"CREATE TABLE ADDRESSES ( + ID NUMBER GENERATED ALWAYS AS IDENTITY(START WITH 1 INCREMENT BY 1), + STREET VARCHAR(256) NOT NULL, + CITYID VARCHAR(256) NOT NULL, + PRIMARY KEY (ID))"); + + Db.Connection.Execute( + @"CREATE TABLE CITIES ( + IDENTIFIER RAW(16) NOT NULL, + NAME VARCHAR(256) NOT NULL)"); + + Db.Connection.Execute( + @"CREATE TABLE DAB.PHONES ( + ID NUMBER GENERATED ALWAYS AS IDENTITY(START WITH 1 INCREMENT BY 1), + PNUMBER VARCHAR(256) NOT NULL, + ISACTIVE NUMBER(1) NOT NULL, + CODE VARCHAR(256) NOT NULL, + PRIMARY KEY (ID))"); + + Db.Connection.Execute( + @"CREATE TABLE REPORTS ( + ID NUMBER NOT NULL, + ANOTHERID NUMBER NOT NULL, + USERID NUMBER NOT NULL, + PRIMARY KEY (ID, ANOTHERID))"); + + InitData.Execute(Db); + } + + private void ClearDb() + { + void DropTable(string name) + { + Db.Connection.Execute($@"BEGIN + EXECUTE IMMEDIATE 'DROP TABLE ' || '{name}'; + EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -942 THEN + RAISE; + END IF; + END;"); + } + + DropTable("USERS"); + DropTable("CARS"); + DropTable("ADDRESSES"); + DropTable("CITIES"); + DropTable("REPORTS"); + DropTable("PHONES"); + } + + private void SetupSchema() + { + Db.Connection.Execute($@"BEGIN + EXECUTE IMMEDIATE 'DROP USER DAB CASCADE'; + EXCEPTION + WHEN OTHERS THEN + IF SQLCODE != -1918 THEN + RAISE; + END IF; + END;"); + Db.Connection.Execute($"CREATE USER DAB IDENTIFIED BY pwd"); + Db.Connection.Execute($"ALTER USER DAB QUOTA UNLIMITED ON USERS"); + } + } +} diff --git a/test/MicroOrm.Dapper.Repositories.Tests/DbContexts/OracleDbContext.cs b/test/MicroOrm.Dapper.Repositories.Tests/DbContexts/OracleDbContext.cs new file mode 100644 index 00000000..4cac00b9 --- /dev/null +++ b/test/MicroOrm.Dapper.Repositories.Tests/DbContexts/OracleDbContext.cs @@ -0,0 +1,40 @@ +using MicroOrm.Dapper.Repositories.DbContext; +using MicroOrm.Dapper.Repositories.SqlGenerator; +using MicroOrm.Dapper.Repositories.Tests.Classes; +using Oracle.ManagedDataAccess.Client; + + +namespace MicroOrm.Dapper.Repositories.Tests.DbContexts +{ + public class OracleDbContext : DapperDbContext, IDbContext + { + private IDapperRepository
_address; + + private IDapperRepository _cars; + + private IDapperRepository _users; + + private IDapperRepository _cities; + + private IDapperRepository _reports; + + private IDapperRepository _phones; + + public OracleDbContext(string connectionString) + : base(new OracleConnection(connectionString)) + { + } + + public IDapperRepository
Address => _address ?? (_address = new DapperRepository
(Connection, new SqlGenerator
(SqlProvider.Oracle))); + + public IDapperRepository Users => _users ?? (_users = new DapperRepository(Connection, new SqlGenerator(SqlProvider.Oracle))); + + public IDapperRepository Cars => _cars ?? (_cars = new DapperRepository(Connection, new SqlGenerator(SqlProvider.Oracle))); + + public IDapperRepository Cities => _cities ?? (_cities = new DapperRepository(Connection, new SqlGenerator(SqlProvider.Oracle))); + + public IDapperRepository Reports => _reports ?? (_reports = new DapperRepository(Connection, new SqlGenerator(SqlProvider.Oracle))); + + public IDapperRepository Phones => _phones ?? (_phones = new DapperRepository(Connection, new SqlGenerator(SqlProvider.Oracle))); + } +} diff --git a/test/MicroOrm.Dapper.Repositories.Tests/MicroOrm.Dapper.Repositories.Tests.csproj b/test/MicroOrm.Dapper.Repositories.Tests/MicroOrm.Dapper.Repositories.Tests.csproj index f516b485..58859bac 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/MicroOrm.Dapper.Repositories.Tests.csproj +++ b/test/MicroOrm.Dapper.Repositories.Tests/MicroOrm.Dapper.Repositories.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/Oracle12cRepositoriesTests.cs b/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/Oracle12cRepositoriesTests.cs new file mode 100644 index 00000000..399777fd --- /dev/null +++ b/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/Oracle12cRepositoriesTests.cs @@ -0,0 +1,14 @@ +using MicroOrm.Dapper.Repositories.Tests.DatabaseFixture; +using Xunit; +using Xunit.Abstractions; + +namespace MicroOrm.Dapper.Repositories.Tests.RepositoriesTests +{ + public class Oracle12cRepositoriesTests : RepositoriesTests, IClassFixture + { + public Oracle12cRepositoriesTests(Oracle12cDatabaseFixture Oracle12cDatabaseFixture, ITestOutputHelper testOutputHelper) + : base(Oracle12cDatabaseFixture.Db, testOutputHelper) + { + } + } +} diff --git a/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/RepositoriesTests.cs b/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/RepositoriesTests.cs index d832a6b0..b1499e6f 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/RepositoriesTests.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/RepositoriesTests/RepositoriesTests.cs @@ -22,7 +22,7 @@ protected RepositoriesTests(IDbContext db, ITestOutputHelper testOutputHelper) _testOutputHelper = testOutputHelper; MicroOrmConfig.AllowKeyAsIdentity = false; } - + [Fact] public async Task ChangeDateInsertAndFind() { @@ -166,10 +166,10 @@ public async void FindJoinAsync_CollectionnRecord() [Fact] public async Task FindThroughtNavigationProperty() { - var user = await _db.Users.FindAsync(x => x.Phone.Number == "123", x => x.Phone); + var user = await _db.Users.FindAsync(x => x.Phone.PNumber == "123", x => x.Phone); Assert.Equal("TestName0", user.Name); - var user1 = await _db.Users.FindAsync(x => x.Phone.Number == "2223", x => x.Phone); + var user1 = await _db.Users.FindAsync(x => x.Phone.PNumber == "2223", x => x.Phone); Assert.Null(user1); } @@ -218,13 +218,13 @@ public async Task FindPhoneAsyncDifferentBoolQuery() var phone1 = await _db.Phones.FindAsync(x => x.IsActive); Assert.NotNull(phone1); - var phone2 = await _db.Phones.FindAsync(x => x.Number == "123" && !x.IsActive); + var phone2 = await _db.Phones.FindAsync(x => x.PNumber == "123" && !x.IsActive); Assert.Null(phone2); var phone3 = await _db.Phones.FindAsync(x => x.Id == 1 && x.IsActive); Assert.NotNull(phone3); - var phone4 = await _db.Phones.FindAsync(x => x.Number == "333" && !x.IsActive); + var phone4 = await _db.Phones.FindAsync(x => x.PNumber == "333" && !x.IsActive); Assert.NotNull(phone4); } @@ -253,7 +253,7 @@ public void FindAllJoin3Table() Assert.True(user.Cars.Count == 2); Assert.Equal("TestCar0", user.Cars.First().Name); Assert.Equal("Street0", user.Addresses.Street); - Assert.Equal("123", user.Phone.Number); + Assert.Equal("123", user.Phone.PNumber); } [Fact] @@ -263,7 +263,7 @@ public async Task FindAllJoin3TableAsync() Assert.True(user.Cars.Count == 2); Assert.Equal("TestCar0", user.Cars.First().Name); Assert.Equal("Street0", user.Addresses.Street); - Assert.Equal("123", user.Phone.Number); + Assert.Equal("123", user.Phone.PNumber); } [Fact] @@ -272,8 +272,8 @@ public void FindAllJoinSameTableTwice() var user = _db.Users.FindAll(x => x.Id == 1, q => q.OfficePhone, q => q.Cars, q => q.Phone).First(); Assert.True(user.Cars.Count == 2); Assert.Equal("TestCar0", user.Cars.First().Name); - Assert.Equal("333", user.OfficePhone.Number); - Assert.Equal("123", user.Phone.Number); + Assert.Equal("333", user.OfficePhone.PNumber); + Assert.Equal("123", user.Phone.PNumber); } [Fact] @@ -282,8 +282,8 @@ public async void FindAllJoinSameTableTwiceAsync() var user = (await _db.Users.FindAllAsync(x => x.Id == 1, q => q.OfficePhone, q => q.Cars, q => q.Phone)).First(); Assert.True(user.Cars.Count == 2); Assert.Equal("TestCar0", user.Cars.First().Name); - Assert.Equal("333", user.OfficePhone.Number); - Assert.Equal("123", user.Phone.Number); + Assert.Equal("333", user.OfficePhone.PNumber); + Assert.Equal("123", user.Phone.PNumber); } [Fact] diff --git a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MsSqlGeneratorTests.cs b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MsSqlGeneratorTests.cs index 56e777c6..d15f31f9 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MsSqlGeneratorTests.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MsSqlGeneratorTests.cs @@ -151,7 +151,7 @@ public static void BoolFalseEqualNotPredicate() Assert.True(Convert.ToBoolean(parameters["IsActive_p0"])); Assert.Equal( - "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[Number], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] != @IsActive_p0", + "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[PNumber], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] != @IsActive_p0", sqlQuery.GetSql()); } @@ -165,7 +165,7 @@ public static void BoolFalseEqualPredicate() Assert.False(Convert.ToBoolean(parameters["IsActive_p0"])); Assert.Equal( - "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[Number], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0", + "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[PNumber], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0", sqlQuery.GetSql()); } @@ -179,7 +179,7 @@ public static void BoolFalsePredicate() Assert.False(Convert.ToBoolean(parameters["IsActive_p0"])); Assert.Equal( - "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[Number], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0", + "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[PNumber], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0", sqlQuery.GetSql()); } @@ -193,7 +193,7 @@ public static void BoolTruePredicate() Assert.True(Convert.ToBoolean(parameters["IsActive_p0"])); Assert.Equal( - "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[Number], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0", + "SELECT TOP 1 [DAB].[Phones].[Id], [DAB].[Phones].[PNumber], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0", sqlQuery.GetSql()); } @@ -232,14 +232,14 @@ public static void BulkUpdate() ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); var phones = new List { - new Phone { Id = 10, IsActive = true, Number = "111" }, - new Phone { Id = 10, IsActive = false, Number = "222" } + new Phone { Id = 10, IsActive = true, PNumber = "111" }, + new Phone { Id = 10, IsActive = false, PNumber = "222" } }; var sqlQuery = userSqlGenerator.GetBulkUpdate(phones); - Assert.Equal("UPDATE [DAB].[Phones] SET [Number] = @Number0, [IsActive] = @IsActive0 WHERE [Id] = @Id0; " + - "UPDATE [DAB].[Phones] SET [Number] = @Number1, [IsActive] = @IsActive1 WHERE [Id] = @Id1", sqlQuery.GetSql()); + Assert.Equal("UPDATE [DAB].[Phones] SET [PNumber] = @PNumber0, [IsActive] = @IsActive0 WHERE [Id] = @Id0; " + + "UPDATE [DAB].[Phones] SET [PNumber] = @PNumber1, [IsActive] = @IsActive1 WHERE [Id] = @Id1", sqlQuery.GetSql()); } [Fact] @@ -317,7 +317,7 @@ public static void LogicalleleteWithUpdatedAtWithPredicate() public static void Delete() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); - var phone = new Phone { Id = 10, Code = "ZZZ", IsActive = true, Number = "111" }; + var phone = new Phone { Id = 10, Code = "ZZZ", IsActive = true, PNumber = "111" }; var sqlQuery = userSqlGenerator.GetDelete(phone); Assert.Equal("DELETE FROM [DAB].[Phones] WHERE [DAB].[Phones].[Id] = @Id", sqlQuery.GetSql()); @@ -349,9 +349,9 @@ public static void LogicalDeletePredicate() public static void DeleteWithMultiplePredicate() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); - var sqlQuery = userSqlGenerator.GetDelete(x => x.IsActive && x.Number == "111"); + var sqlQuery = userSqlGenerator.GetDelete(x => x.IsActive && x.PNumber == "111"); - Assert.Equal("DELETE FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0 AND [DAB].[Phones].[Number] = @Number_p1", sqlQuery.GetSql()); + Assert.Equal("DELETE FROM [DAB].[Phones] WHERE [DAB].[Phones].[IsActive] = @IsActive_p0 AND [DAB].[Phones].[PNumber] = @PNumber_p1", sqlQuery.GetSql()); } [Fact] @@ -411,24 +411,24 @@ public static void JoinBracelets() public static void NavigationPredicate() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); - var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Phone.Number == "123", null, user => user.Phone); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Phone.PNumber == "123", null, user => user.Phone); Assert.Equal("SELECT [Users].[Id], [Users].[Name], [Users].[AddressId], [Users].[PhoneId], [Users].[OfficePhoneId], [Users].[Deleted], [Users].[UpdatedAt], " + - "[Phones_PhoneId].[Id], [Phones_PhoneId].[Number], [Phones_PhoneId].[IsActive], [Phones_PhoneId].[Code] " + + "[Phones_PhoneId].[Id], [Phones_PhoneId].[PNumber], [Phones_PhoneId].[IsActive], [Phones_PhoneId].[Code] " + "FROM [Users] INNER JOIN [DAB].[Phones] AS [Phones_PhoneId] ON [Users].[PhoneId] = [Phones_PhoneId].[Id] " + - "WHERE ([Phones_PhoneId].[Number] = @PhoneNumber_p0) AND [Users].[Deleted] != 1", sqlQuery.GetSql()); + "WHERE ([Phones_PhoneId].[PNumber] = @PhonePNumber_p0) AND [Users].[Deleted] != 1", sqlQuery.GetSql()); } [Fact] public static void NavigationPredicateNoQuotationMarks() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, false); - var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Phone.Number == "123", null, user => user.Phone); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Phone.PNumber == "123", null, user => user.Phone); Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt, " + - "Phones_PhoneId.Id, Phones_PhoneId.Number, Phones_PhoneId.IsActive, Phones_PhoneId.Code " + + "Phones_PhoneId.Id, Phones_PhoneId.PNumber, Phones_PhoneId.IsActive, Phones_PhoneId.Code " + "FROM Users INNER JOIN DAB.Phones AS Phones_PhoneId ON Users.PhoneId = Phones_PhoneId.Id " + - "WHERE (Phones_PhoneId.Number = @PhoneNumber_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + "WHERE (Phones_PhoneId.PNumber = @PhonePNumber_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); } [Fact] @@ -561,10 +561,10 @@ public static void SelectPaged() public static void UpdateExclude() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); - var phone = new Phone { Id = 10, Code = "ZZZ", IsActive = true, Number = "111" }; + var phone = new Phone { Id = 10, Code = "ZZZ", IsActive = true, PNumber = "111" }; var sqlQuery = userSqlGenerator.GetUpdate(phone); - Assert.Equal("UPDATE [DAB].[Phones] SET [DAB].[Phones].[Number] = @PhoneNumber, [DAB].[Phones].[IsActive] = @PhoneIsActive WHERE [DAB].[Phones].[Id] = @PhoneId", + Assert.Equal("UPDATE [DAB].[Phones] SET [DAB].[Phones].[PNumber] = @PhonePNumber, [DAB].[Phones].[IsActive] = @PhoneIsActive WHERE [DAB].[Phones].[Id] = @PhoneId", sqlQuery.GetSql()); } @@ -581,51 +581,51 @@ public static void UpdateWithPredicate() public static void SelectGroupConditionsWithPredicate() { ISqlGenerator phoneSqlGenerator = new SqlGenerator(_sqlConnector, true); - var sPrefix = "SELECT [DAB].[Phones].[Id], [DAB].[Phones].[Number], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE "; + var sPrefix = "SELECT [DAB].[Phones].[Id], [DAB].[Phones].[PNumber], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE "; - var sqlQuery1 = phoneSqlGenerator.GetSelectAll(x => (x.IsActive && x.Id == 123) || (x.Id == 456 && x.Number == "456"), null); + var sqlQuery1 = phoneSqlGenerator.GetSelectAll(x => (x.IsActive && x.Id == 123) || (x.Id == 456 && x.PNumber == "456"), null); Assert.Equal( - sPrefix + "([DAB].[Phones].[IsActive] = @IsActive_p0 AND [DAB].[Phones].[Id] = @Id_p1) OR ([DAB].[Phones].[Id] = @Id_p2 AND [DAB].[Phones].[Number] = @Number_p3)", + sPrefix + "([DAB].[Phones].[IsActive] = @IsActive_p0 AND [DAB].[Phones].[Id] = @Id_p1) OR ([DAB].[Phones].[Id] = @Id_p2 AND [DAB].[Phones].[PNumber] = @PNumber_p3)", sqlQuery1.GetSql()); - var sqlQuery2 = phoneSqlGenerator.GetSelectAll(x => !x.IsActive || (x.Id == 456 && x.Number == "456"), null); - Assert.Equal(sPrefix + "[DAB].[Phones].[IsActive] = @IsActive_p0 OR ([DAB].[Phones].[Id] = @Id_p1 AND [DAB].[Phones].[Number] = @Number_p2)", sqlQuery2.GetSql()); + var sqlQuery2 = phoneSqlGenerator.GetSelectAll(x => !x.IsActive || (x.Id == 456 && x.PNumber == "456"), null); + Assert.Equal(sPrefix + "[DAB].[Phones].[IsActive] = @IsActive_p0 OR ([DAB].[Phones].[Id] = @Id_p1 AND [DAB].[Phones].[PNumber] = @PNumber_p2)", sqlQuery2.GetSql()); - var sqlQuery3 = phoneSqlGenerator.GetSelectAll(x => (x.Id == 456 && x.Number == "456") || x.Id == 123, null); - Assert.Equal(sPrefix + "([DAB].[Phones].[Id] = @Id_p0 AND [DAB].[Phones].[Number] = @Number_p1) OR [DAB].[Phones].[Id] = @Id_p2", sqlQuery3.GetSql()); + var sqlQuery3 = phoneSqlGenerator.GetSelectAll(x => (x.Id == 456 && x.PNumber == "456") || x.Id == 123, null); + Assert.Equal(sPrefix + "([DAB].[Phones].[Id] = @Id_p0 AND [DAB].[Phones].[PNumber] = @PNumber_p1) OR [DAB].[Phones].[Id] = @Id_p2", sqlQuery3.GetSql()); - var sqlQuery4 = phoneSqlGenerator.GetSelectAll(x => x.Number == "1" && (x.IsActive || x.Number == "456") && x.Id == 123, null); + var sqlQuery4 = phoneSqlGenerator.GetSelectAll(x => x.PNumber == "1" && (x.IsActive || x.PNumber == "456") && x.Id == 123, null); Assert.Equal( sPrefix + - "[DAB].[Phones].[Number] = @Number_p0 AND ([DAB].[Phones].[IsActive] = @IsActive_p1 OR [DAB].[Phones].[Number] = @Number_p2) AND [DAB].[Phones].[Id] = @Id_p3", + "[DAB].[Phones].[PNumber] = @PNumber_p0 AND ([DAB].[Phones].[IsActive] = @IsActive_p1 OR [DAB].[Phones].[PNumber] = @PNumber_p2) AND [DAB].[Phones].[Id] = @Id_p3", sqlQuery4.GetSql()); - var sqlQuery5 = phoneSqlGenerator.GetSelectAll(x => x.Number == "1" && (x.IsActive || x.Number == "456" || x.Number == "678") && x.Id == 123, null); + var sqlQuery5 = phoneSqlGenerator.GetSelectAll(x => x.PNumber == "1" && (x.IsActive || x.PNumber == "456" || x.PNumber == "678") && x.Id == 123, null); Assert.Equal( sPrefix + - "[DAB].[Phones].[Number] = @Number_p0 AND ([DAB].[Phones].[IsActive] = @IsActive_p1 OR [DAB].[Phones].[Number] = @Number_p2 OR [DAB].[Phones].[Number] = @Number_p3) AND [DAB].[Phones].[Id] = @Id_p4", + "[DAB].[Phones].[PNumber] = @PNumber_p0 AND ([DAB].[Phones].[IsActive] = @IsActive_p1 OR [DAB].[Phones].[PNumber] = @PNumber_p2 OR [DAB].[Phones].[PNumber] = @PNumber_p3) AND [DAB].[Phones].[Id] = @Id_p4", sqlQuery5.GetSql()); var ids = new List(); var sqlQuery6 = phoneSqlGenerator.GetSelectAll(x => !x.IsActive || (x.IsActive && ids.Contains(x.Id)), null); Assert.Equal(sPrefix + "[DAB].[Phones].[IsActive] = @IsActive_p0 OR ([DAB].[Phones].[IsActive] = @IsActive_p1 AND [DAB].[Phones].[Id] IN @Id_p2)", sqlQuery6.GetSql()); - var sqlQuery7 = phoneSqlGenerator.GetSelectAll(x => (x.IsActive && x.Id == 123) && (x.Id == 456 && x.Number == "456"), null); + var sqlQuery7 = phoneSqlGenerator.GetSelectAll(x => (x.IsActive && x.Id == 123) && (x.Id == 456 && x.PNumber == "456"), null); Assert.Equal( - sPrefix + "[DAB].[Phones].[IsActive] = @IsActive_p0 AND [DAB].[Phones].[Id] = @Id_p1 AND [DAB].[Phones].[Id] = @Id_p2 AND [DAB].[Phones].[Number] = @Number_p3", + sPrefix + "[DAB].[Phones].[IsActive] = @IsActive_p0 AND [DAB].[Phones].[Id] = @Id_p1 AND [DAB].[Phones].[Id] = @Id_p2 AND [DAB].[Phones].[PNumber] = @PNumber_p3", sqlQuery7.GetSql()); var sqlQuery8 = phoneSqlGenerator.GetSelectAll( - x => x.Number == "1" && (x.IsActive || x.Number == "456" || x.Number == "123" || (x.Id == 1213 && x.Number == "678")) && x.Id == 123, null); + x => x.PNumber == "1" && (x.IsActive || x.PNumber == "456" || x.PNumber == "123" || (x.Id == 1213 && x.PNumber == "678")) && x.Id == 123, null); Assert.Equal( sPrefix + - "[DAB].[Phones].[Number] = @Number_p0 AND ([DAB].[Phones].[IsActive] = @IsActive_p1 OR [DAB].[Phones].[Number] = @Number_p2 OR [DAB].[Phones].[Number] = @Number_p3 OR ([DAB].[Phones].[Id] = @Id_p4 AND [DAB].[Phones].[Number] = @Number_p5)) AND [DAB].[Phones].[Id] = @Id_p6", + "[DAB].[Phones].[PNumber] = @PNumber_p0 AND ([DAB].[Phones].[IsActive] = @IsActive_p1 OR [DAB].[Phones].[PNumber] = @PNumber_p2 OR [DAB].[Phones].[PNumber] = @PNumber_p3 OR ([DAB].[Phones].[Id] = @Id_p4 AND [DAB].[Phones].[PNumber] = @PNumber_p5)) AND [DAB].[Phones].[Id] = @Id_p6", sqlQuery8.GetSql()); - var sqlQuery9 = phoneSqlGenerator.GetSelectAll(x => (x.Id == 456 && x.Number == "456") && x.Id == 123 && (x.Id == 4567 && x.Number == "4567"), null); + var sqlQuery9 = phoneSqlGenerator.GetSelectAll(x => (x.Id == 456 && x.PNumber == "456") && x.Id == 123 && (x.Id == 4567 && x.PNumber == "4567"), null); Assert.Equal( sPrefix + - "[DAB].[Phones].[Id] = @Id_p0 AND [DAB].[Phones].[Number] = @Number_p1 AND [DAB].[Phones].[Id] = @Id_p2 AND [DAB].[Phones].[Id] = @Id_p3 AND [DAB].[Phones].[Number] = @Number_p4", + "[DAB].[Phones].[Id] = @Id_p0 AND [DAB].[Phones].[PNumber] = @PNumber_p1 AND [DAB].[Phones].[Id] = @Id_p2 AND [DAB].[Phones].[Id] = @Id_p3 AND [DAB].[Phones].[PNumber] = @PNumber_p4", sqlQuery9.GetSql()); } @@ -634,23 +634,23 @@ public static void SelectGroupConditionsNavigationPredicate() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); var sPrefix = "SELECT [Users].[Id], [Users].[Name], [Users].[AddressId], [Users].[PhoneId], [Users].[OfficePhoneId], [Users].[Deleted], [Users].[UpdatedAt], " + - "[Phones_PhoneId].[Id], [Phones_PhoneId].[Number], [Phones_PhoneId].[IsActive], [Phones_PhoneId].[Code] " + + "[Phones_PhoneId].[Id], [Phones_PhoneId].[PNumber], [Phones_PhoneId].[IsActive], [Phones_PhoneId].[Code] " + "FROM [Users] INNER JOIN [DAB].[Phones] AS [Phones_PhoneId] ON [Users].[PhoneId] = [Phones_PhoneId].[Id] " + "WHERE "; - var sqlQuery1 = userSqlGenerator.GetSelectFirst(x => x.Phone.Number == "123" || (x.Name == "abc" && x.Phone.IsActive), null, user => user.Phone); + var sqlQuery1 = userSqlGenerator.GetSelectFirst(x => x.Phone.PNumber == "123" || (x.Name == "abc" && x.Phone.IsActive), null, user => user.Phone); Assert.Equal( sPrefix + - "([Phones_PhoneId].[Number] = @PhoneNumber_p0 OR ([Users].[Name] = @Name_p1 AND [Phones_PhoneId].[IsActive] = @PhoneIsActive_p2)) AND [Users].[Deleted] != 1", + "([Phones_PhoneId].[PNumber] = @PhonePNumber_p0 OR ([Users].[Name] = @Name_p1 AND [Phones_PhoneId].[IsActive] = @PhoneIsActive_p2)) AND [Users].[Deleted] != 1", sqlQuery1.GetSql()); var ids = new List(); var sqlQuery2 = userSqlGenerator.GetSelectFirst( - x => x.Phone.Number != "123" && (x.Name != "abc" || !x.Phone.IsActive || !ids.Contains(x.PhoneId) || !ids.Contains(x.Phone.Id)) && + x => x.Phone.PNumber != "123" && (x.Name != "abc" || !x.Phone.IsActive || !ids.Contains(x.PhoneId) || !ids.Contains(x.Phone.Id)) && (x.Name == "abc" || x.Phone.IsActive), null, user => user.Phone); Assert.Equal( sPrefix + - "([Phones_PhoneId].[Number] != @PhoneNumber_p0 AND ([Users].[Name] != @Name_p1 OR [Phones_PhoneId].[IsActive] = @PhoneIsActive_p2 OR [Users].[PhoneId] NOT IN @PhoneId_p3 OR [Phones_PhoneId].[Id] NOT IN @PhoneId_p4) AND ([Users].[Name] = @Name_p5 OR [Phones_PhoneId].[IsActive] = @PhoneIsActive_p6)) AND [Users].[Deleted] != 1", + "([Phones_PhoneId].[PNumber] != @PhonePNumber_p0 AND ([Users].[Name] != @Name_p1 OR [Phones_PhoneId].[IsActive] = @PhoneIsActive_p2 OR [Users].[PhoneId] NOT IN @PhoneId_p3 OR [Phones_PhoneId].[Id] NOT IN @PhoneId_p4) AND ([Users].[Name] = @Name_p5 OR [Phones_PhoneId].[IsActive] = @PhoneIsActive_p6)) AND [Users].[Deleted] != 1", sqlQuery2.GetSql()); } @@ -658,7 +658,7 @@ public static void SelectGroupConditionsNavigationPredicate() public static void SelectLikeWithPredicate() { ISqlGenerator phoneSqlGenerator1 = new SqlGenerator(_sqlConnector, true); - var sPrefix1 = "SELECT [DAB].[Phones].[Id], [DAB].[Phones].[Number], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE "; + var sPrefix1 = "SELECT [DAB].[Phones].[Id], [DAB].[Phones].[PNumber], [DAB].[Phones].[IsActive], [DAB].[Phones].[Code] FROM [DAB].[Phones] WHERE "; var sqlQuery11 = phoneSqlGenerator1.GetSelectAll(x => x.Code.StartsWith("123", StringComparison.OrdinalIgnoreCase) || !x.Code.EndsWith("456") || x.Code.Contains("789"), null); @@ -671,17 +671,17 @@ public static void SelectLikeWithPredicate() ISqlGenerator userSqlGenerator2 = new SqlGenerator(_sqlConnector, true); var sPrefix2 = "SELECT [Users].[Id], [Users].[Name], [Users].[AddressId], [Users].[PhoneId], [Users].[OfficePhoneId], [Users].[Deleted], [Users].[UpdatedAt], " + - "[Phones_PhoneId].[Id], [Phones_PhoneId].[Number], [Phones_PhoneId].[IsActive], [Phones_PhoneId].[Code] " + + "[Phones_PhoneId].[Id], [Phones_PhoneId].[PNumber], [Phones_PhoneId].[IsActive], [Phones_PhoneId].[Code] " + "FROM [Users] INNER JOIN [DAB].[Phones] AS [Phones_PhoneId] ON [Users].[PhoneId] = [Phones_PhoneId].[Id] " + "WHERE "; - var sqlQuery21 = userSqlGenerator2.GetSelectFirst(x => x.Phone.Number.StartsWith("123") || (!x.Name.Contains("abc") && x.Phone.IsActive), null, user => user.Phone); + var sqlQuery21 = userSqlGenerator2.GetSelectFirst(x => x.Phone.PNumber.StartsWith("123") || (!x.Name.Contains("abc") && x.Phone.IsActive), null, user => user.Phone); Assert.Equal( sPrefix2 + - "([Phones_PhoneId].[Number] LIKE @PhoneNumber_p0 OR ([Users].[Name] NOT LIKE @Name_p1 AND [Phones_PhoneId].[IsActive] = @PhoneIsActive_p2)) AND [Users].[Deleted] != 1", + "([Phones_PhoneId].[PNumber] LIKE @PhonePNumber_p0 OR ([Users].[Name] NOT LIKE @Name_p1 AND [Phones_PhoneId].[IsActive] = @PhoneIsActive_p2)) AND [Users].[Deleted] != 1", sqlQuery21.GetSql()); var parameters21 = sqlQuery21.Param as IDictionary; - Assert.True("123%" == parameters21["PhoneNumber_p0"].ToString()); + Assert.True("123%" == parameters21["PhonePNumber_p0"].ToString()); Assert.True("%abc%" == parameters21["Name_p1"].ToString()); } } diff --git a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MySqlGeneratorTests.cs b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MySqlGeneratorTests.cs index 63499592..fd405c2e 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MySqlGeneratorTests.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/MySqlGeneratorTests.cs @@ -42,14 +42,14 @@ public void BulkUpdate() ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector); var phones = new List { - new Phone {Id = 10, IsActive = true, Number = "111"}, - new Phone {Id = 10, IsActive = false, Number = "222"} + new Phone {Id = 10, IsActive = true, PNumber = "111"}, + new Phone {Id = 10, IsActive = false, PNumber = "222"} }; var sqlQuery = userSqlGenerator.GetBulkUpdate(phones); - Assert.Equal("UPDATE DAB.Phones SET Number = @Number0, IsActive = @IsActive0 WHERE Id = @Id0; " + - "UPDATE DAB.Phones SET Number = @Number1, IsActive = @IsActive1 WHERE Id = @Id1", sqlQuery.GetSql()); + Assert.Equal("UPDATE DAB.Phones SET PNumber = @PNumber0, IsActive = @IsActive0 WHERE Id = @Id0; " + + "UPDATE DAB.Phones SET PNumber = @PNumber1, IsActive = @IsActive1 WHERE Id = @Id1", sqlQuery.GetSql()); } [Fact] @@ -58,14 +58,14 @@ public void BulkUpdate_QuoMarks() ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); var phones = new List { - new Phone {Id = 10, IsActive = true, Number = "111"}, - new Phone {Id = 10, IsActive = false, Number = "222"} + new Phone {Id = 10, IsActive = true, PNumber = "111"}, + new Phone {Id = 10, IsActive = false, PNumber = "222"} }; var sqlQuery = userSqlGenerator.GetBulkUpdate(phones); - Assert.Equal("UPDATE `DAB`.`Phones` SET `Number` = @Number0, `IsActive` = @IsActive0 WHERE `Id` = @Id0; " + - "UPDATE `DAB`.`Phones` SET `Number` = @Number1, `IsActive` = @IsActive1 WHERE `Id` = @Id1", sqlQuery.GetSql()); + Assert.Equal("UPDATE `DAB`.`Phones` SET `PNumber` = @PNumber0, `IsActive` = @IsActive0 WHERE `Id` = @Id0; " + + "UPDATE `DAB`.`Phones` SET `PNumber` = @PNumber1, `IsActive` = @IsActive1 WHERE `Id` = @Id1", sqlQuery.GetSql()); } [Fact] @@ -73,11 +73,11 @@ public void Update_Dictionary() { ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); Dictionary fieldDict = new Dictionary(); - fieldDict.Add("Number", "18573175437"); + fieldDict.Add("PNumber", "18573175437"); var sqlQuery = userSqlGenerator.GetUpdate(p => p.Id == 1, fieldDict); string sql = sqlQuery.GetSql(); - Assert.Equal("UPDATE `DAB`.`Phones` SET `DAB`.`Phones`.`Number` = @PhoneNumber WHERE `DAB`.`Phones`.`Id` = @Id_p0", sql); + Assert.Equal("UPDATE `DAB`.`Phones` SET `DAB`.`Phones`.`PNumber` = @PhonePNumber WHERE `DAB`.`Phones`.`Id` = @Id_p0", sql); } [Fact] @@ -87,10 +87,10 @@ public void Update_Anonymous() var sqlQuery = userSqlGenerator.GetUpdate(p => p.Id == 1, new { - Number = "18573175437" + PNumber = "18573175437" }); string sql = sqlQuery.GetSql(); - Assert.Equal("UPDATE `DAB`.`Phones` SET `DAB`.`Phones`.`Number` = @PhoneNumber WHERE `DAB`.`Phones`.`Id` = @Id_p0", sql); + Assert.Equal("UPDATE `DAB`.`Phones` SET `DAB`.`Phones`.`PNumber` = @PhonePNumber WHERE `DAB`.`Phones`.`Id` = @Id_p0", sql); } [Fact] diff --git a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/Oracle12cSqlGeneratorTests.cs b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/Oracle12cSqlGeneratorTests.cs new file mode 100644 index 00000000..f4602948 --- /dev/null +++ b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/Oracle12cSqlGeneratorTests.cs @@ -0,0 +1,699 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using MicroOrm.Dapper.Repositories.Config; +using MicroOrm.Dapper.Repositories.SqlGenerator; +using MicroOrm.Dapper.Repositories.SqlGenerator.Filters; +using MicroOrm.Dapper.Repositories.Tests.Classes; +using Xunit; + +namespace MicroOrm.Dapper.Repositories.Tests.SqlGeneratorTests +{ + public class Oracle12cSqlGeneratorTests + { + private const SqlProvider _sqlConnector = SqlProvider.Oracle; + + [Fact] + public static void Count() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetCount(null); + Assert.Equal("SELECT COUNT(*) FROM Users WHERE Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void CountWithDistinct() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetCount(null, user => user.AddressId); + Assert.Equal("SELECT COUNT(DISTINCT Users.AddressId) FROM Users WHERE Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void CountWithDistinctAndWhere() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetCount(x => x.PhoneId == 1, user => user.AddressId); + Assert.Equal("SELECT COUNT(DISTINCT Users.AddressId) FROM Users WHERE (Users.PhoneId = :PhoneId_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void ChangeDate_Insert() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + + var user = new User { Name = "Dude" }; + userSqlGenerator.GetInsert(user); + Assert.NotNull(user.UpdatedAt); + } + + [Fact] + public static void ChangeDate_Update() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + + var user = new User { Name = "Dude" }; + userSqlGenerator.GetUpdate(user); + Assert.NotNull(user.UpdatedAt); + } + + [Fact] + public static void ExpressionArgumentException() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + + var isExceptions = false; + + try + { + var sumAr = new List { 1, 2, 3 }; + userSqlGenerator.GetSelectAll(x => sumAr.All(z => x.Id == z), null); + } + catch (NotSupportedException ex) + { + Assert.Contains("'All' method is not supported", ex.Message); + isExceptions = true; + } + + Assert.True(isExceptions, "Contains no cast exception"); + } + + [Fact] + public static void ExpressionComplicatedCollectionContains() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + + var isExceptions = false; + + try + { + var tmp = new ComplicatedObj(); + + var id = 1; + var ids = new List { 1, 2, 3 }; + var farIds = tmp.FieldArIds; + var pNames = tmp.PropertyNames; + + var sfarIds = ComplicatedObj.StaticFieldArIds; + var spNames = ComplicatedObj.StaticPropertyNames; + + userSqlGenerator.GetSelectAll( + x => ( + (ids.Contains(x.Id) || farIds.Contains(x.Id) || sfarIds.Contains(x.Id) + || tmp.FieldArIds.Contains(x.Id) || x.Id == tmp.Id + || ComplicatedObj.StaticFieldArIds.Contains(x.Id) + || x.Id == id) + && (pNames.Contains(x.Name) || spNames.Contains(x.Name) + || tmp.PropertyNames.Contains(x.Name) || tmp.FieldNames.Contains(x.Name) + || ComplicatedObj.StaticFieldNames.Contains(x.Name) + || ComplicatedObj.StaticPropertyNames.Contains(x.Name) + || x.Name == ComplicatedObj.StaticName + || x.Name == ComplicatedObj.StaticPropertyName + || x.Name == tmp.PropertName + || x.Name == Guid.NewGuid().ToString() + || x.Name == string.Empty) + ), null); + } + catch (NotSupportedException ex) + { + Assert.Contains("isn't supported", ex.Message); + isExceptions = true; + } + + Assert.False(isExceptions, "Complicated_Collection_Contains MemberAccess exception"); + } + + [Fact] + public static void ExpressionNullablePerformance() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + + var i = 0; + var today = DateTime.Now.Date; + var tomorrow = today.AddDays(1); + while (i++ < 10) + { + userSqlGenerator.GetSelectAll(x => x.UpdatedAt >= today, null); + userSqlGenerator.GetSelectAll(x => x.UpdatedAt < tomorrow, null); + userSqlGenerator.GetSelectAll(x => x.UpdatedAt >= today && x.UpdatedAt < tomorrow, null); + } + + Assert.False(false, "dual ExpressionNullablePerformance"); + } + + [Fact] + public static void BoolFalseEqualNotPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.IsActive != true, null); + + var parameters = sqlQuery.Param as IDictionary; + Assert.True(Convert.ToBoolean(parameters["IsActive_p0"])); + + Assert.Equal( + "SELECT Phones.Id, Phones.PNumber, Phones.IsActive, Phones.Code FROM Phones WHERE Phones.IsActive != :IsActive_p0 FETCH FIRST 1 ROW ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void BoolFalseEqualPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.IsActive == false, null); + + var parameters = sqlQuery.Param as IDictionary; + Assert.False(Convert.ToBoolean(parameters["IsActive_p0"])); + + Assert.Equal( + "SELECT Phones.Id, Phones.PNumber, Phones.IsActive, Phones.Code FROM Phones WHERE Phones.IsActive = :IsActive_p0 FETCH FIRST 1 ROW ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void BoolFalsePredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => !x.IsActive, null); + + var parameters = sqlQuery.Param as IDictionary; + Assert.False(Convert.ToBoolean(parameters["IsActive_p0"])); + + Assert.Equal( + "SELECT Phones.Id, Phones.PNumber, Phones.IsActive, Phones.Code FROM Phones WHERE Phones.IsActive = :IsActive_p0 FETCH FIRST 1 ROW ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void BoolTruePredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.IsActive, null); + + var parameters = sqlQuery.Param as IDictionary; + Assert.True(Convert.ToBoolean(parameters["IsActive_p0"])); + + Assert.Equal( + "SELECT Phones.Id, Phones.PNumber, Phones.IsActive, Phones.Code FROM Phones WHERE Phones.IsActive = :IsActive_p0 FETCH FIRST 1 ROW ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void BulkInsertMultiple() + { + ISqlGenerator
userSqlGenerator = new SqlGenerator
(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetBulkInsert(new List
{ new Address(), new Address() }); + + //Assert.Equal("INSERT INTO Addresses (Street, CityId) VALUES (:Street0, :CityId0),(:Street1, :CityId1)", sqlQuery.GetSql()); + Assert.Equal("INSERT INTO Addresses (Street, CityId) SELECT :Street0, :CityId0 FROM DUAL UNION ALL SELECT :Street1, :CityId1 FROM DUAL", sqlQuery.GetSql()); + } + + [Fact] + public static void BulkInsertOne() + { + ISqlGenerator
userSqlGenerator = new SqlGenerator
(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetBulkInsert(new List
{ new Address() }); + + Assert.Equal("INSERT INTO Addresses (Street, CityId) SELECT :Street0, :CityId0 FROM DUAL", sqlQuery.GetSql()); + } + + [Fact] + public static void BulkInsertOneKeyAsIdentity() + { + MicroOrmConfig.AllowKeyAsIdentity = true; + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetBulkInsert(new List { new AddressKeyAsIdentity() }); + + Assert.Equal("INSERT INTO Addresses (Street, CityId) SELECT :Street0, :CityId0 FROM DUAL", sqlQuery.GetSql()); + MicroOrmConfig.AllowKeyAsIdentity = false; + } + + [Fact] + public static void BulkUpdate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var phones = new List + { + new Phone { Id = 10, IsActive = true, PNumber = "111" }, + new Phone { Id = 10, IsActive = false, PNumber = "222" } + }; + + var sqlQuery = userSqlGenerator.GetBulkUpdate(phones); + + Assert.Equal("MERGE INTO Phones Phones " + + "USING (" + + "SELECT :PNumber0 AS PNumber, :IsActive0 AS IsActive, :Id0 AS Id FROM DUAL " + + "UNION ALL " + + "SELECT :PNumber1 AS PNumber, :IsActive1 AS IsActive, :Id1 AS Id FROM DUAL" + + ") Phones_BULKUPDATE ON (Phones_BULKUPDATE.Id = Phones.Id) " + + "WHEN MATCHED THEN UPDATE SET PNumber = Phones_BULKUPDATE.PNumber ,IsActive = Phones_BULKUPDATE.IsActive", sqlQuery.GetSql()); + } + + [Fact] + public static void BulkUpdateIgnoreOneOfKeys() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var reports = new List + { + new Report { Id = 10, AnotherId = 10, UserId = 22 }, + new Report { Id = 10, AnotherId = 10, UserId = 23 } + }; + + var sqlQuery = userSqlGenerator.GetBulkUpdate(reports); + + Assert.Equal("MERGE INTO Reports Reports " + + "USING (" + + "SELECT :UserId0 AS UserId, :AnotherId0 AS AnotherId FROM DUAL " + + "UNION ALL " + + "SELECT :UserId1 AS UserId, :AnotherId1 AS AnotherId FROM DUAL" + + ") Reports_BULKUPDATE ON (Reports_BULKUPDATE.AnotherId = Reports.AnotherId) " + + "WHEN MATCHED THEN UPDATE SET UserId = Reports_BULKUPDATE.UserId", sqlQuery.GetSql()); + } + + [Fact] + public static void ContainsPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var ids = new List(); + var sqlQuery = userSqlGenerator.GetSelectAll(x => ids.Contains(x.Id), null); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt " + + "FROM Users WHERE (Users.Id IN :Id_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void ContainsArrayPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var ids = new int[] { }; + var sqlQuery = userSqlGenerator.GetSelectAll(x => ids.Contains(x.Id), null); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt " + + "FROM Users WHERE (Users.Id IN :Id_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void NotContainsPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var ids = new List(); + var sqlQuery = userSqlGenerator.GetSelectAll(x => !ids.Contains(x.Id), null); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt " + + "FROM Users WHERE (Users.Id NOT IN :Id_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void LogicalDeleteWithUpdatedAt() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector); + var user = new User() { Id = 10 }; + var sqlQuery = userSqlGenerator.GetDelete(user); + var sql = sqlQuery.GetSql(); + + Assert.Equal("UPDATE Users SET Deleted = 1, UpdatedAt = :UpdatedAt WHERE Users.Id = :Id", sql); + } + + [Fact] + public static void LogicalleleteWithUpdatedAtWithPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector); + var user = new User() { Id = 10 }; + var sqlQuery = userSqlGenerator.GetDelete(user); + var sql = sqlQuery.GetSql(); + + Assert.Equal("UPDATE Users SET Deleted = 1, UpdatedAt = :UpdatedAt WHERE Users.Id = :Id", sql); + } + + [Fact] + public static void Delete() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var phone = new Phone { Id = 10, Code = "ZZZ", IsActive = true, PNumber = "111" }; + var sqlQuery = userSqlGenerator.GetDelete(phone); + + Assert.Equal("DELETE FROM Phones WHERE Phones.Id = :Id", sqlQuery.GetSql()); + } + + [Fact] + public static void LogicalDeleteEntity() + { + ISqlGenerator sqlGenerator = new SqlGenerator(_sqlConnector); + var car = new Car() { Id = 10, Name = "LogicalDelete", UserId = 5 }; + + var sqlQuery = sqlGenerator.GetDelete(car); + var realSql = sqlQuery.GetSql(); + Assert.Equal("UPDATE Cars SET Status = -1 WHERE Cars.Id = :Id", realSql); + } + + [Fact] + public static void LogicalDeletePredicate() + { + ISqlGenerator sqlGenerator = new SqlGenerator(_sqlConnector); + + var sqlQuery = sqlGenerator.GetDelete(q => q.Id == 10); + var realSql = sqlQuery.GetSql(); + + Assert.Equal("UPDATE Cars SET Status = -1 WHERE Cars.Id = :Id_p0", realSql); + } + + [Fact] + public static void DeleteWithMultiplePredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetDelete(x => x.IsActive && x.PNumber == "111"); + + Assert.Equal("DELETE FROM Phones WHERE Phones.IsActive = :IsActive_p0 AND Phones.PNumber = :PNumber_p1", sqlQuery.GetSql()); + } + + [Fact] + public static void DeleteWithSinglePredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetDelete(x => x.IsActive); + + Assert.Equal("DELETE FROM Phones WHERE Phones.IsActive = :IsActive_p0", sqlQuery.GetSql()); + } + + [Fact] + public static void InsertQuoMarks() + { + ISqlGenerator
userSqlGenerator = new SqlGenerator
(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetInsert(new Address()); + + Assert.Equal("INSERT INTO Addresses (Street, CityId) VALUES (:Street, :CityId) RETURNING Id INTO :newId", sqlQuery.GetSql()); + } + + [Fact] + public void Insert_AllowKeyAsIdentity_QuoMarks() + { + MicroOrmConfig.AllowKeyAsIdentity = true; + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetInsert(new AddressKeyAsIdentity()); + + Assert.Equal("INSERT INTO Addresses (Street, CityId) VALUES (:Street, :CityId) RETURNING Id INTO :newId", sqlQuery.GetSql()); + MicroOrmConfig.AllowKeyAsIdentity = false; + } + + [Fact] + public static void IsNull() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectAll(user => user.UpdatedAt == null, null); + + Assert.Equal( + "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users " + + "WHERE (Users.UpdatedAt IS NULL) AND Users.Deleted != 1", sqlQuery.GetSql()); + Assert.DoesNotContain("== NULL", sqlQuery.GetSql()); + } + + [Fact] + public static void JoinBracelets() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectAll(null, null, user => user.Cars); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt, " + + "Cars_Id.Id, Cars_Id.Name, Cars_Id.Data, Cars_Id.UserId, Cars_Id.Status " + + "FROM Users LEFT JOIN Cars Cars_Id ON Users.Id = Cars_Id.UserId " + + "WHERE Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void NavigationPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Phone.PNumber == "123", null, user => user.Phone); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt, " + + "Phones_PhoneId.Id, Phones_PhoneId.PNumber, Phones_PhoneId.IsActive, Phones_PhoneId.Code " + + "FROM Users INNER JOIN Phones Phones_PhoneId ON Users.PhoneId = Phones_PhoneId.Id " + + "WHERE (Phones_PhoneId.PNumber = :PhonePNumber_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void NavigationPredicateNoQuotationMarks() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, false); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Phone.PNumber == "123", null, user => user.Phone); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt, " + + "Phones_PhoneId.Id, Phones_PhoneId.PNumber, Phones_PhoneId.IsActive, Phones_PhoneId.Code " + + "FROM Users INNER JOIN DAB.Phones Phones_PhoneId ON Users.PhoneId = Phones_PhoneId.Id " + + "WHERE (Phones_PhoneId.PNumber = :PhonePNumber_p0) AND Users.Deleted != 1", sqlQuery.GetSql()); + } + + [Fact] + public static void SelectBetweenWithLogicalDelete() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, false); + var sqlQuery = userSqlGenerator.GetSelectBetween(1, 10, null, x => x.Id); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users " + + "WHERE Users.Deleted != 1 AND Users.Id BETWEEN '1' AND '10'", sqlQuery.GetSql()); + } + + [Fact] + public static void SelectBetweenWithLogicalDeleteBraclets() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectBetween(1, 10, null, x => x.Id); + + Assert.Equal( + "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users " + + "WHERE Users.Deleted != 1 AND Users.Id BETWEEN '1' AND '10'", sqlQuery.GetSql()); + } + + [Fact] + public static void SelectBetweenWithoutLogicalDelete() + { + ISqlGenerator
userSqlGenerator = new SqlGenerator
(_sqlConnector, false); + var sqlQuery = userSqlGenerator.GetSelectBetween(1, 10, null, x => x.Id); + + Assert.Equal("SELECT Addresses.Id, Addresses.Street, Addresses.CityId FROM Addresses " + + "WHERE Addresses.Id BETWEEN '1' AND '10'", sqlQuery.GetSql()); + } + + [Fact] + public static void SelectBetweenWithoutLogicalDeleteBraclets() + { + ISqlGenerator
userSqlGenerator = new SqlGenerator
(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectBetween(1, 10, null, x => x.Id); + + Assert.Equal("SELECT Addresses.Id, Addresses.Street, Addresses.CityId FROM Addresses " + + "WHERE Addresses.Id BETWEEN '1' AND '10'", sqlQuery.GetSql()); + } + + [Fact] + public static void SelectById() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectById(1, null); + + Assert.Equal("SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt " + + "FROM Users WHERE Users.Id = :Id AND Users.Deleted != 1 FETCH FIRST 1 ROWS ONLY", sqlQuery.GetSql()); + } + + + [Fact] + public static void SelectByIdJoin() + { + var generator = new SqlGenerator
(_sqlConnector, true); + var sqlQuery = generator.GetSelectById(1, null, q => q.Users); + Assert.Equal("SELECT Addresses.Id, Addresses.Street, Addresses.CityId, Users.Id, Users.Name, Users.AddressId, Users.PhoneId, " + + "Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Addresses " + + "LEFT JOIN Users ON Addresses.Id = Users.AddressId WHERE Addresses.Id = :Id", sqlQuery.GetSql()); + } + + [Fact] + public static void SelectFirst() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sqlQuery = userSqlGenerator.GetSelectFirst(x => x.Id == 2, null); + Assert.Equal( + "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users WHERE (Users.Id = :Id_p0) AND Users.Deleted != 1 FETCH FIRST 1 ROW ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void SelectLimit() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var filterData = new FilterData(); + var data = filterData.LimitInfo ?? new LimitInfo(); + data.Limit = 10u; + filterData.LimitInfo = data; + + var sqlQuery = userSqlGenerator.GetSelectAll(x => x.Id == 2, filterData); + Assert.Equal( + "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users WHERE (Users.Id = :Id_p0) AND Users.Deleted != 1 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void SelectOrderBy() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var filterData = new FilterData(); + + var data = filterData.OrderInfo ?? new OrderInfo(); + data.Columns = new List { "Id" }; + data.Direction = OrderInfo.SortDirection.ASC; + filterData.OrderInfo = data; + + var sqlQuery = userSqlGenerator.GetSelectAll(x => x.Id == 2, filterData); + Assert.Equal( + "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users WHERE (Users.Id = :Id_p0) AND Users.Deleted != 1 ORDER BY Id ASC", + sqlQuery.GetSql()); + } + + [Fact] + public static void SelectPaged() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var filterData = new FilterData(); + + var data = filterData.OrderInfo ?? new OrderInfo(); + data.Columns = new List { "Id" }; + data.Direction = OrderInfo.SortDirection.ASC; + filterData.OrderInfo = data; + + var dataLimit = filterData.LimitInfo ?? new LimitInfo(); + dataLimit.Limit = 10u; + dataLimit.Offset = 5u; + filterData.LimitInfo = dataLimit; + + var sqlQuery = userSqlGenerator.GetSelectAll(x => x.Id == 2, filterData); + Assert.Equal( + "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt FROM Users WHERE (Users.Id = :Id_p0) AND Users.Deleted != 1 ORDER BY Id ASC OFFSET 5 ROWS FETCH NEXT 10 ROWS ONLY", + sqlQuery.GetSql()); + } + + [Fact] + public static void UpdateExclude() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var phone = new Phone { Id = 10, Code = "ZZZ", IsActive = true, PNumber = "111" }; + var sqlQuery = userSqlGenerator.GetUpdate(phone); + + Assert.Equal("UPDATE Phones SET Phones.PNumber = :PhonePNumber, Phones.IsActive = :PhoneIsActive WHERE Phones.Id = :PhoneId", + sqlQuery.GetSql()); + } + + [Fact] + public static void UpdateWithPredicate() + { + ISqlGenerator sqlGenerator = new SqlGenerator(_sqlConnector); + var sqlQuery = sqlGenerator.GetUpdate(q => q.Identifier == Guid.Empty, new City()); + var sql = sqlQuery.GetSql(); + Assert.Equal("UPDATE Cities SET Cities.Identifier = :CityIdentifier, Cities.Name = :CityName WHERE Cities.Identifier = :Identifier_p0", sql); + } + + [Fact] + public static void SelectGroupConditionsWithPredicate() + { + ISqlGenerator phoneSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sPrefix = "SELECT Phones.Id, Phones.PNumber, Phones.IsActive, Phones.Code FROM Phones WHERE "; + + var sqlQuery1 = phoneSqlGenerator.GetSelectAll(x => (x.IsActive && x.Id == 123) || (x.Id == 456 && x.PNumber == "456"), null); + Assert.Equal( + sPrefix + "(Phones.IsActive = :IsActive_p0 AND Phones.Id = :Id_p1) OR (Phones.Id = :Id_p2 AND Phones.PNumber = :PNumber_p3)", + sqlQuery1.GetSql()); + + var sqlQuery2 = phoneSqlGenerator.GetSelectAll(x => !x.IsActive || (x.Id == 456 && x.PNumber == "456"), null); + Assert.Equal(sPrefix + "Phones.IsActive = :IsActive_p0 OR (Phones.Id = :Id_p1 AND Phones.PNumber = :PNumber_p2)", sqlQuery2.GetSql()); + + var sqlQuery3 = phoneSqlGenerator.GetSelectAll(x => (x.Id == 456 && x.PNumber == "456") || x.Id == 123, null); + Assert.Equal(sPrefix + "(Phones.Id = :Id_p0 AND Phones.PNumber = :PNumber_p1) OR Phones.Id = :Id_p2", sqlQuery3.GetSql()); + + var sqlQuery4 = phoneSqlGenerator.GetSelectAll(x => x.PNumber == "1" && (x.IsActive || x.PNumber == "456") && x.Id == 123, null); + Assert.Equal( + sPrefix + + "Phones.PNumber = :PNumber_p0 AND (Phones.IsActive = :IsActive_p1 OR Phones.PNumber = :PNumber_p2) AND Phones.Id = :Id_p3", + sqlQuery4.GetSql()); + + var sqlQuery5 = phoneSqlGenerator.GetSelectAll(x => x.PNumber == "1" && (x.IsActive || x.PNumber == "456" || x.PNumber == "678") && x.Id == 123, null); + Assert.Equal( + sPrefix + + "Phones.PNumber = :PNumber_p0 AND (Phones.IsActive = :IsActive_p1 OR Phones.PNumber = :PNumber_p2 OR Phones.PNumber = :PNumber_p3) AND Phones.Id = :Id_p4", + sqlQuery5.GetSql()); + + var ids = new List(); + var sqlQuery6 = phoneSqlGenerator.GetSelectAll(x => !x.IsActive || (x.IsActive && ids.Contains(x.Id)), null); + Assert.Equal(sPrefix + "Phones.IsActive = :IsActive_p0 OR (Phones.IsActive = :IsActive_p1 AND Phones.Id IN :Id_p2)", sqlQuery6.GetSql()); + + var sqlQuery7 = phoneSqlGenerator.GetSelectAll(x => (x.IsActive && x.Id == 123) && (x.Id == 456 && x.PNumber == "456"), null); + Assert.Equal( + sPrefix + "Phones.IsActive = :IsActive_p0 AND Phones.Id = :Id_p1 AND Phones.Id = :Id_p2 AND Phones.PNumber = :PNumber_p3", + sqlQuery7.GetSql()); + + var sqlQuery8 = phoneSqlGenerator.GetSelectAll( + x => x.PNumber == "1" && (x.IsActive || x.PNumber == "456" || x.PNumber == "123" || (x.Id == 1213 && x.PNumber == "678")) && x.Id == 123, null); + Assert.Equal( + sPrefix + + "Phones.PNumber = :PNumber_p0 AND (Phones.IsActive = :IsActive_p1 OR Phones.PNumber = :PNumber_p2 OR Phones.PNumber = :PNumber_p3 OR (Phones.Id = :Id_p4 AND Phones.PNumber = :PNumber_p5)) AND Phones.Id = :Id_p6", + sqlQuery8.GetSql()); + + var sqlQuery9 = phoneSqlGenerator.GetSelectAll(x => (x.Id == 456 && x.PNumber == "456") && x.Id == 123 && (x.Id == 4567 && x.PNumber == "4567"), null); + Assert.Equal( + sPrefix + + "Phones.Id = :Id_p0 AND Phones.PNumber = :PNumber_p1 AND Phones.Id = :Id_p2 AND Phones.Id = :Id_p3 AND Phones.PNumber = :PNumber_p4", + sqlQuery9.GetSql()); + } + + [Fact] + public static void SelectGroupConditionsNavigationPredicate() + { + ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); + var sPrefix = "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt, " + + "Phones_PhoneId.Id, Phones_PhoneId.PNumber, Phones_PhoneId.IsActive, Phones_PhoneId.Code " + + "FROM Users INNER JOIN Phones Phones_PhoneId ON Users.PhoneId = Phones_PhoneId.Id " + + "WHERE "; + + var sqlQuery1 = userSqlGenerator.GetSelectFirst(x => x.Phone.PNumber == "123" || (x.Name == "abc" && x.Phone.IsActive), null, user => user.Phone); + Assert.Equal( + sPrefix + + "(Phones_PhoneId.PNumber = :PhonePNumber_p0 OR (Users.Name = :Name_p1 AND Phones_PhoneId.IsActive = :PhoneIsActive_p2)) AND Users.Deleted != 1", + sqlQuery1.GetSql()); + + var ids = new List(); + var sqlQuery2 = userSqlGenerator.GetSelectFirst( + x => x.Phone.PNumber != "123" && (x.Name != "abc" || !x.Phone.IsActive || !ids.Contains(x.PhoneId) || !ids.Contains(x.Phone.Id)) && + (x.Name == "abc" || x.Phone.IsActive), null, user => user.Phone); + Assert.Equal( + sPrefix + + "(Phones_PhoneId.PNumber != :PhonePNumber_p0 AND (Users.Name != :Name_p1 OR Phones_PhoneId.IsActive = :PhoneIsActive_p2 OR Users.PhoneId NOT IN :PhoneId_p3 OR Phones_PhoneId.Id NOT IN :PhoneId_p4) AND (Users.Name = :Name_p5 OR Phones_PhoneId.IsActive = :PhoneIsActive_p6)) AND Users.Deleted != 1", + sqlQuery2.GetSql()); + } + + [Fact] + public static void SelectLikeWithPredicate() + { + ISqlGenerator phoneSqlGenerator1 = new SqlGenerator(_sqlConnector, true); + var sPrefix1 = "SELECT Phones.Id, Phones.PNumber, Phones.IsActive, Phones.Code FROM Phones WHERE "; + + var sqlQuery11 = phoneSqlGenerator1.GetSelectAll(x => x.Code.StartsWith("123", StringComparison.OrdinalIgnoreCase) || !x.Code.EndsWith("456") || x.Code.Contains("789"), + null); + Assert.Equal(sPrefix1 + "Phones.Code LIKE :Code_p0 OR Phones.Code NOT LIKE :Code_p1 OR Phones.Code LIKE :Code_p2", sqlQuery11.GetSql()); + + var parameters11 = sqlQuery11.Param as IDictionary; + Assert.True("123%" == parameters11["Code_p0"].ToString()); + Assert.True("%456" == parameters11["Code_p1"].ToString()); + Assert.True("%789%" == parameters11["Code_p2"].ToString()); + + ISqlGenerator userSqlGenerator2 = new SqlGenerator(_sqlConnector, true); + var sPrefix2 = "SELECT Users.Id, Users.Name, Users.AddressId, Users.PhoneId, Users.OfficePhoneId, Users.Deleted, Users.UpdatedAt, " + + "Phones_PhoneId.Id, Phones_PhoneId.PNumber, Phones_PhoneId.IsActive, Phones_PhoneId.Code " + + "FROM Users INNER JOIN Phones Phones_PhoneId ON Users.PhoneId = Phones_PhoneId.Id " + + "WHERE "; + + var sqlQuery21 = userSqlGenerator2.GetSelectFirst(x => x.Phone.PNumber.StartsWith("123") || (!x.Name.Contains("abc") && x.Phone.IsActive), null, user => user.Phone); + Assert.Equal( + sPrefix2 + + "(Phones_PhoneId.PNumber LIKE :PhonePNumber_p0 OR (Users.Name NOT LIKE :Name_p1 AND Phones_PhoneId.IsActive = :PhoneIsActive_p2)) AND Users.Deleted != 1", + sqlQuery21.GetSql()); + var parameters21 = sqlQuery21.Param as IDictionary; + Assert.True("123%" == parameters21["PhonePNumber_p0"].ToString()); + Assert.True("%abc%" == parameters21["Name_p1"].ToString()); + } + } +} diff --git a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/PostgresSqlGeneratorTests.cs b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/PostgresSqlGeneratorTests.cs index 2357f9be..9de94021 100644 --- a/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/PostgresSqlGeneratorTests.cs +++ b/test/MicroOrm.Dapper.Repositories.Tests/SqlGeneratorTests/PostgresSqlGeneratorTests.cs @@ -100,14 +100,14 @@ public static void BulkUpdate() ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector); var phones = new List { - new Phone { Id = 10, IsActive = true, Number = "111" }, - new Phone { Id = 10, IsActive = false, Number = "222" } + new Phone { Id = 10, IsActive = true, PNumber = "111" }, + new Phone { Id = 10, IsActive = false, PNumber = "222" } }; var sqlQuery = userSqlGenerator.GetBulkUpdate(phones); - Assert.Equal("UPDATE DAB.Phones SET Number = @Number0, IsActive = @IsActive0 WHERE Id = @Id0; " + - "UPDATE DAB.Phones SET Number = @Number1, IsActive = @IsActive1 WHERE Id = @Id1", sqlQuery.GetSql()); + Assert.Equal("UPDATE DAB.Phones SET PNumber = @PNumber0, IsActive = @IsActive0 WHERE Id = @Id0; " + + "UPDATE DAB.Phones SET PNumber = @PNumber1, IsActive = @IsActive1 WHERE Id = @Id1", sqlQuery.GetSql()); } [Fact] @@ -116,14 +116,14 @@ public static void BulkUpdate_QuoMarks() ISqlGenerator userSqlGenerator = new SqlGenerator(_sqlConnector, true); var phones = new List { - new Phone { Id = 10, IsActive = true, Number = "111" }, - new Phone { Id = 10, IsActive = false, Number = "222" } + new Phone { Id = 10, IsActive = true, PNumber = "111" }, + new Phone { Id = 10, IsActive = false, PNumber = "222" } }; var sqlQuery = userSqlGenerator.GetBulkUpdate(phones); - Assert.Equal("UPDATE \"DAB\".\"Phones\" SET \"Number\" = @Number0, \"IsActive\" = @IsActive0 WHERE \"Id\" = @Id0; " + - "UPDATE \"DAB\".\"Phones\" SET \"Number\" = @Number1, \"IsActive\" = @IsActive1 WHERE \"Id\" = @Id1", sqlQuery.GetSql()); + Assert.Equal("UPDATE \"DAB\".\"Phones\" SET \"PNumber\" = @PNumber0, \"IsActive\" = @IsActive0 WHERE \"Id\" = @Id0; " + + "UPDATE \"DAB\".\"Phones\" SET \"PNumber\" = @PNumber1, \"IsActive\" = @IsActive1 WHERE \"Id\" = @Id1", sqlQuery.GetSql()); } } } From 4c20b25312505dfc9097b42c41278b1933a30c4c Mon Sep 17 00:00:00 2001 From: Bo Hu Date: Thu, 24 Feb 2022 23:43:22 +0100 Subject: [PATCH 2/2] Add some infors in readme for oracle. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index e9d200a4..5d015ffa 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ The original idea was taken from [Yoinbol](https://github.com/Yoinbol/MicroOrm.P All tests with MSSQL and MySQL has passed, PostgreSQL and SQLite tests are being developed. +It support the Oracle12c except for GUID issue. Tests has passed. + ## Installation ```sh @@ -74,6 +76,12 @@ Automatically set DataTime.UtcNow (You can use local date or define offset) for * Supports complex primary keys. * Supports simple Joins. * For this moment, with MSSQL you can only use limit with offset if you call OrderBy first, otherwise limit will be ignored. +* It has a problem when try to use GUID with dapper in Oracle. In this case it doesn't work. + details see + https://github.com/DapperLib/Dapper/issues/633 + https://github.com/DapperLib/Dapper/issues/637 + https://github.com/vauto/Dapper.Database/pull/1 + ### Maps