Lith 4 月之前
父節點
當前提交
bf3ca64a70

+ 1 - 0
Vitorm.PostgreSQL.sln

@@ -6,6 +6,7 @@ MinimumVisualStudioVersion = 10.0.40219.1
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{75C25D0B-8529-4E3F-AF43-6EC1E9E40828}"
 	ProjectSection(SolutionItems) = preProject
 		README.md = README.md
+		doc\ReleaseNotes.md = doc\ReleaseNotes.md
 	EndProjectSection
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{7904FE51-04FF-4477-8E3A-CC340389EE32}"

+ 0 - 3
src/Vitorm.PostgreSQL/DataProvider.cs

@@ -1,8 +1,5 @@
 using System.Collections.Generic;
 
-using Vitorm.Sql;
-using Vitorm.Sql.DataProvider;
-
 namespace Vitorm.PostgreSQL
 {
     public class DataProvider : SqlDataProvider

+ 0 - 2
src/Vitorm.PostgreSQL/DbConfig.cs

@@ -1,8 +1,6 @@
 using System.Collections.Generic;
 using System.Data;
 
-using Vitorm.Sql;
-
 using ConnectionStringBuilder = global::Npgsql.NpgsqlConnectionStringBuilder;
 using DbConnection = global::Npgsql.NpgsqlConnection;
 

+ 0 - 1
src/Vitorm.PostgreSQL/DbContext_Extensions_UsePostgreSQL.cs

@@ -1,5 +1,4 @@
 using Vitorm.PostgreSQL;
-using Vitorm.Sql;
 
 namespace Vitorm
 {

+ 14 - 75
src/Vitorm.PostgreSQL/SqlTranslateService.cs

@@ -4,13 +4,6 @@ using System.Linq;
 using System.Linq.Expressions;
 using System.Text;
 
-using Vit.Linq;
-using Vit.Linq.ExpressionNodes.ComponentModel;
-
-using Vitorm.Entity;
-using Vitorm.Sql.SqlTranslate;
-using Vitorm.StreamQuery;
-
 namespace Vitorm.PostgreSQL
 {
     public class SqlTranslateService : Vitorm.Sql.SqlTranslate.SqlTranslateService
@@ -18,14 +11,16 @@ namespace Vitorm.PostgreSQL
         public static readonly SqlTranslateService Instance = new SqlTranslateService();
 
         protected override BaseQueryTranslateService queryTranslateService { get; }
-        protected override BaseQueryTranslateService executeUpdateTranslateService => throw new NotImplementedException();
         protected override BaseQueryTranslateService executeDeleteTranslateService { get; }
+        protected override BaseQueryTranslateService executeUpdateTranslateService { get; }
 
         public SqlTranslateService()
         {
-            queryTranslateService = new QueryTranslateService(this);
+            queryTranslateService = new Vitorm.PostgreSQL.TranslateService.QueryTranslateService(this);
 
             executeDeleteTranslateService = new Vitorm.PostgreSQL.TranslateService.ExecuteDeleteTranslateService(this);
+
+            executeUpdateTranslateService = new Vitorm.PostgreSQL.TranslateService.ExecuteUpdateTranslateService(this);
         }
         /// <summary>
         ///     Generates the delimited SQL representation of an identifier (column name, table name, etc.).
@@ -66,7 +61,7 @@ namespace Vitorm.PostgreSQL
                             // ##1 ToString
                             case nameof(object.ToString):
                                 {
-                                    return $"cast({EvalExpression(arg, methodCall.@object)} as Nullable(String) )";
+                                    return $"cast({EvalExpression(arg, methodCall.@object)} as text )";
                                 }
 
                             #region ##2 String method:  StartsWith EndsWith Contains
@@ -119,7 +114,7 @@ namespace Vitorm.PostgreSQL
 
                         if (targetType == typeof(string))
                         {
-                            return $"cast({EvalExpression(arg, convert.body)} as Nullable(String))";
+                            return $"cast({EvalExpression(arg, convert.body)} as text)";
                         }
 
                         return $"cast({EvalExpression(arg, convert.body)} as {targetDbType})";
@@ -131,21 +126,9 @@ namespace Vitorm.PostgreSQL
                         // ##1 String Add
                         if (node.valueType?.ToType() == typeof(string))
                         {
-                            // select ifNull( cast( (userFatherId) as Nullable(String) ) , '' )  from `User` 
-
-                            return $"CONCAT( {BuildSqlSentence(binary.left)} , {BuildSqlSentence(binary.right)} )";
+                            // select CONCAT("fatherId", '' )  from "User"
 
-                            string BuildSqlSentence(ExpressionNode node)
-                            {
-                                if (node.nodeType == NodeType.Constant)
-                                {
-                                    ExpressionNode_Constant constant = node;
-                                    if (constant.value == null) return "''";
-                                    else return $"cast( ({EvalExpression(arg, node)}) as String )";
-                                }
-                                else
-                                    return $"ifNull( cast( ({EvalExpression(arg, node)}) as Nullable(String) ) , '')";
-                            }
+                            return $"CONCAT( {EvalExpression(arg, binary.left)} , {EvalExpression(arg, binary.right)} )";
                         }
 
                         // ##2 Numeric Add
@@ -158,9 +141,9 @@ namespace Vitorm.PostgreSQL
                     }
                 case nameof(ExpressionType.Conditional):
                     {
-                        // IF(`t0`.`fatherId` is not null,true, false)
+                        // select (case when "fatherId" is not null then true else false end)  from "User"
                         ExpressionNode_Conditional conditional = node;
-                        return $"IF({EvalExpression(arg, conditional.Conditional_GetTest())},{EvalExpression(arg, conditional.Conditional_GetIfTrue())},{EvalExpression(arg, conditional.Conditional_GetIfFalse())})";
+                        return $"(case when {EvalExpression(arg, conditional.Conditional_GetTest())} then {EvalExpression(arg, conditional.Conditional_GetIfTrue())} else {EvalExpression(arg, conditional.Conditional_GetIfFalse())} end)";
                     }
                     #endregion
 
@@ -216,11 +199,11 @@ CREATE TABLE IF NOT EXISTS {DelimitTableName(entityDescriptor)} (
         protected readonly static Dictionary<Type, string> columnDbTypeMap = new()
         {
             [typeof(DateTime)] = "timestamp",
-            [typeof(string)] = "varchar(1000)",
+            [typeof(string)] = "text",// varchar(1000)
 
-            [typeof(float)] = "real",
-            [typeof(double)] = "double",
-            [typeof(decimal)] = "numeric",
+            [typeof(float)] = "real", // float4
+            [typeof(double)] = "double precision", // float8
+            [typeof(decimal)] = "decimal",
 
             [typeof(Int64)] = "int8",
             [typeof(Int32)] = "int4",
@@ -266,50 +249,6 @@ CREATE TABLE IF NOT EXISTS {DelimitTableName(entityDescriptor)} (
             // drop table if exists `User`;
             return $@"drop table if exists {DelimitTableName(entityDescriptor)};";
         }
-        public override string PrepareTruncate(IEntityDescriptor entityDescriptor) => throw new NotSupportedException();
-
-        public override string PrepareExecuteUpdate(QueryTranslateArgument arg, CombinedStream combinedStream) => throw new NotImplementedException();
-
-
-        public override string PrepareDelete(SqlTranslateArgument arg)
-        {
-            // ALTER TABLE `User` DELETE WHERE `id`=2;
-            var entityDescriptor = arg.entityDescriptor;
-
-            // #2 build sql
-            string sql = $@"ALTER TABLE {DelimitTableName(entityDescriptor)} DELETE where {DelimitIdentifier(entityDescriptor.keyName)}={GenerateParameterName(entityDescriptor.keyName)} ; ";
-
-            return sql;
-        }
-
-        public override string PrepareDeleteByKeys<Key>(SqlTranslateArgument arg, IEnumerable<Key> keys)
-        {
-            //  ALTER TABLE `User` DELETE WHERE  id in ( 7 ) ;
-
-            var entityDescriptor = arg.entityDescriptor;
-
-            StringBuilder sql = new StringBuilder();
-
-            sql.Append("ALTER TABLE ").Append(DelimitTableName(entityDescriptor)).Append(" DELETE where ").Append(DelimitIdentifier(entityDescriptor.keyName)).Append(" in (");
-
-            if (keys.Any())
-            {
-                foreach (var key in keys)
-                {
-                    sql.Append(GenerateParameterName(arg.AddParamAndGetName(key))).Append(",");
-                }
-                sql.Length--;
-                sql.Append(");");
-            }
-            else
-            {
-                sql.Append("null);");
-            }
-            return sql.ToString();
-        }
-
-
-        public override (string sql, Func<object, Dictionary<string, object>> GetSqlParams) PrepareUpdate(SqlTranslateArgument arg) => throw new NotImplementedException();
 
 
     }

+ 16 - 13
src/Vitorm.PostgreSQL/TranslateService/ExecuteDeleteTranslateService.cs

@@ -1,18 +1,15 @@
-using Vitorm.Sql.SqlTranslate;
-using Vitorm.StreamQuery;
-
-namespace Vitorm.PostgreSQL.TranslateService
+namespace Vitorm.PostgreSQL.TranslateService
 {
     public class ExecuteDeleteTranslateService : BaseQueryTranslateService
     {
         /*
-ALTER TABLE `User` DELETE 
-where id in (
-    select u.id 
-    from `User` u
-    left join `User` father on u.fatherId = father.id 
-    where u.id > 10
-);
+WITH tmp AS (
+    select u."userId" 
+    from "User" u
+    left join "User" father on u."fatherId" = father."userId"
+    where u."userId" > 0
+)
+delete from "User" where "userId" in ( SELECT "userId" FROM tmp );
          */
         public override string BuildQuery(QueryTranslateArgument arg, CombinedStream stream)
         {
@@ -20,11 +17,17 @@ where id in (
 
             var sqlInner = base.BuildQuery(arg, stream);
 
+
             var NewLine = "\r\n";
             var keyName = entityDescriptor.keyName;
 
-            var sql = $"ALTER TABLE {sqlTranslator.DelimitTableName(entityDescriptor)} DELETE";
-            sql += $"{NewLine}where {sqlTranslator.DelimitIdentifier(keyName)} in ({sqlInner})";
+            var sql = $"WITH tmp AS ( {NewLine}";
+            sql += sqlInner;
+
+            sql += $"{NewLine}){NewLine}";
+            sql += $"delete from {sqlTranslator.DelimitTableName(entityDescriptor)} ";
+
+            sql += $"{NewLine}where {sqlTranslator.DelimitIdentifier(keyName)} in ( SELECT {sqlTranslator.DelimitIdentifier(keyName)} FROM tmp ); {NewLine}";
 
             return sql;
         }

+ 84 - 0
src/Vitorm.PostgreSQL/TranslateService/ExecuteUpdateTranslateService.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Vitorm.PostgreSQL.TranslateService
+{
+    public class ExecuteUpdateTranslateService : BaseQueryTranslateService
+    {
+        /*
+
+-- multiple
+WITH tmp AS (
+    select  concat('u' , u."userId", '_' , father."userId") as "userName" , u."userId" 
+    from "User" u
+    left join "User" father on u."fatherId" = father."userId"
+    where u."userId" > 0
+)
+UPDATE "User" t0
+  SET "userName" = tmp."userName"
+from tmp
+where t0."userId" = tmp."userId";
+         */
+        public override string BuildQuery(QueryTranslateArgument arg, CombinedStream stream)
+        {
+            var sqlInner = base.BuildQuery(arg, stream);
+
+            var entityDescriptor = arg.dbContext.GetEntityDescriptor(arg.resultEntityType);
+            var columnsToUpdate = (stream as StreamToUpdate)?.fieldsToUpdate?.memberArgs;
+
+            var NewLine = "\r\n";
+            var keyName = entityDescriptor.keyName;
+
+
+            var sql = $"WITH tmp AS ( {NewLine}";
+            sql += sqlInner;
+
+            sql += $"{NewLine}){NewLine}";
+            sql += $"UPDATE {sqlTranslator.DelimitTableName(entityDescriptor)} t0 {NewLine}";
+            sql += $"  Set ";
+
+            var sqlToUpdateCols = columnsToUpdate
+                .Select(m => m.name)
+                .Select(name =>
+                {
+                    var columnName = entityDescriptor.GetColumnNameByPropertyName(name);
+                    return $"{NewLine}  {sqlTranslator.DelimitIdentifier(columnName)} = {sqlTranslator.GetSqlField("tmp", name)} ";
+                });
+            sql += string.Join(",", sqlToUpdateCols);
+
+            sql += $"{NewLine} from tmp";
+
+            sql += $"{NewLine}where {sqlTranslator.GetSqlField("t0", keyName)}={sqlTranslator.GetSqlField("tmp", keyName)} ";
+
+            return sql;
+        }
+
+
+        public ExecuteUpdateTranslateService(SqlTranslateService sqlTranslator) : base(sqlTranslator)
+        {
+        }
+
+        protected override string ReadSelect(QueryTranslateArgument arg, CombinedStream stream, string prefix = "select")
+        {
+            var entityDescriptor = arg.dbContext.GetEntityDescriptor(arg.resultEntityType);
+            var columnsToUpdate = (stream as StreamToUpdate)?.fieldsToUpdate?.memberArgs;
+
+            if (columnsToUpdate?.Any() != true) throw new ArgumentException("can not get columns to update");
+
+            var sqlFields = new List<string>();
+
+            foreach (var column in columnsToUpdate)
+            {
+                sqlFields.Add($"({sqlTranslator.EvalExpression(arg, column.value)}) as {sqlTranslator.DelimitIdentifier(column.name)}");
+            }
+            // primary key
+            sqlFields.Add($"{sqlTranslator.GetSqlField(stream.source.alias, entityDescriptor.keyName)} as {sqlTranslator.DelimitIdentifier(entityDescriptor.keyName)}");
+
+            return prefix + " " + String.Join(",", sqlFields);
+        }
+
+
+
+    }
+}

+ 70 - 0
src/Vitorm.PostgreSQL/TranslateService/QueryTranslateService.cs

@@ -0,0 +1,70 @@
+using System.Linq;
+
+namespace Vitorm.PostgreSQL.TranslateService
+{
+    public class QueryTranslateService : Vitorm.Sql.SqlTranslate.QueryTranslateService
+    {
+        public QueryTranslateService(SqlTranslateService sqlTranslator) : base(sqlTranslator)
+        {
+        }
+
+        public override string BuildQuery(QueryTranslateArgument arg, CombinedStream stream)
+        {
+
+            string sql = "";
+
+            // #0  select
+            sql += ReadSelect(arg, stream);
+
+
+            #region #1 from
+            sql += "\r\n from " + ReadInnerTable(arg, stream.source);
+            #endregion
+
+            #region #2 join
+            if (stream.joins != null)
+            {
+                sql += ReadJoin(arg, stream);
+            }
+            #endregion
+
+            // #3 where 1=1
+            if (stream.where != null)
+            {
+                var where = sqlTranslator.EvalExpression(arg, stream.where);
+                if (!string.IsNullOrWhiteSpace(where)) sql += "\r\n where " + where;
+            }
+
+            #region #4 group by
+            if (stream.groupByFields != null)
+            {
+                sql += "\r\n group by " + ReadGroupBy(arg, stream);
+            }
+            #endregion
+
+            #region #5 having
+            if (stream.having != null)
+            {
+                var where = sqlTranslator.EvalExpression(arg, stream.having);
+                if (!string.IsNullOrWhiteSpace(where)) sql += "\r\n having " + where;
+            }
+            #endregion
+
+
+            // #6 OrderBy
+            if (stream.orders?.Any() == true)
+            {
+                sql += "\r\n order by " + ReadOrderBy(arg, stream);
+            }
+
+            // #7 Range,  LIMIT 4 OFFSET 3
+            if (stream.take != null || stream.skip != null)
+            {
+                string sqlRange = (stream.take == null ? "" : (" LIMIT " + stream.take)) + (stream.skip == null ? "" : (" OFFSET " + stream.skip));
+                sql += "\r\n " + sqlRange;
+            }
+
+            return sql;
+        }
+    }
+}

+ 0 - 2
test/Vitorm.PostgreSQL.MsTest/CommonTest/CRUDAsync_Test.cs

@@ -2,8 +2,6 @@
 
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
-using Vit.Linq;
-
 namespace Vitorm.MsTest.CommonTest
 {
 

+ 0 - 4
test/Vitorm.PostgreSQL.MsTest/CommonTest/EntityLoader_CustomLoader_Test.cs

@@ -2,10 +2,6 @@
 
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
-using Vitorm.Entity;
-using Vitorm.Entity.Loader.DataAnnotations;
-using Vitorm.Entity.PropertyType;
-
 namespace Vitorm.MsTest.CommonTest
 {
     [TestClass]

+ 1 - 1
test/Vitorm.PostgreSQL.MsTest/CommonTest/Orm_Extensions_ExecuteUpdateAsync_Test.cs

@@ -68,7 +68,7 @@ namespace Vitorm.MsTest.CommonTest
                 Assert.AreEqual(3, count);
 
 
-                var userList = userQuery.ToList();
+                var userList = userQuery.OrderBy(m => m.id).ToList();
                 Assert.AreEqual("u3_1_4_6", userList[0].name);
                 Assert.AreEqual("u3_3_5_6", userList[2].name);
                 Assert.AreEqual("u2_4__", userList[3].name);

+ 1 - 1
test/Vitorm.PostgreSQL.MsTest/CommonTest/Orm_Extensions_ExecuteUpdate_Test.cs

@@ -70,7 +70,7 @@ namespace Vitorm.MsTest.CommonTest
                 Assert.AreEqual(3, count);
 
 
-                var userList = userQuery.ToList();
+                var userList = userQuery.OrderBy(m => m.id).ToList();
                 Assert.AreEqual("u3_1_4_6", userList[0].name);
                 Assert.AreEqual("u3_3_5_6", userList[2].name);
                 Assert.AreEqual("u2_4__", userList[3].name);

+ 0 - 3
test/Vitorm.PostgreSQL.MsTest/CommonTest/Query_FilterRule_Test.cs

@@ -1,9 +1,6 @@
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 using Vit.Core.Module.Serialization;
-using Vit.Linq;
-using Vit.Linq.ComponentModel;
-using Vit.Linq.FilterRules.ComponentModel;
 
 namespace Vitorm.MsTest.CommonTest
 {

+ 0 - 2
test/Vitorm.PostgreSQL.MsTest/CommonTest/Query_FilterRule_WithJoin_Test.cs

@@ -1,8 +1,6 @@
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
 using Vit.Core.Module.Serialization;
-using Vit.Linq;
-using Vit.Linq.ComponentModel;
 
 namespace Vitorm.MsTest.CommonTest
 {

+ 0 - 2
test/Vitorm.PostgreSQL.MsTest/CommonTest/Query_MethodAsync_Test.cs

@@ -2,8 +2,6 @@
 
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
-using Vit.Linq;
-
 namespace Vitorm.MsTest.CommonTest
 {
 

+ 0 - 2
test/Vitorm.PostgreSQL.MsTest/CommonTest/Query_Method_Test.cs

@@ -2,8 +2,6 @@
 
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
-using Vit.Linq;
-
 namespace Vitorm.MsTest.CommonTest
 {
 

+ 0 - 2
test/Vitorm.PostgreSQL.MsTest/CommonTest/Query_ToListAndTotalCount_Test.cs

@@ -2,8 +2,6 @@
 
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
-using Vit.Linq;
-
 namespace Vitorm.MsTest.CommonTest
 {
 

+ 0 - 43
test/Vitorm.PostgreSQL.MsTest/CommonTest/Transaction_Test.cs

@@ -81,49 +81,6 @@ namespace Vitorm.MsTest.CommonTest
 
         }
 
-        [TestMethod]
-        public void Test_NestedTransaction()
-        {
-            #region NestedTransaction
-            {
-                using var dbContext = DataSource.CreateDbContext();
-                var userSet = dbContext.DbSet<User>();
-
-                Assert.AreEqual("u400", userSet.Get(4).name);
-
-                using (var tran1 = dbContext.BeginTransaction())
-                {
-                    dbContext.Update(new User { id = 4, name = "u4001" });
-                    Assert.AreEqual("u4001", userSet.Get(4).name);
-
-                    using (var tran2 = dbContext.BeginTransaction())
-                    {
-                        dbContext.Update(new User { id = 4, name = "u4002" });
-                        Assert.AreEqual("u4002", userSet.Get(4).name);
-                    }
-                    Assert.AreEqual("u4001", userSet.Get(4).name);
-
-                    using (var tran2 = dbContext.BeginTransaction())
-                    {
-                        dbContext.Update(new User { id = 4, name = "u4002" });
-                        Assert.AreEqual("u4002", userSet.Get(4).name);
-                        tran2.Rollback();
-                    }
-                    Assert.AreEqual("u4001", userSet.Get(4).name);
-
-                    using (var tran2 = dbContext.BeginTransaction())
-                    {
-                        dbContext.Update(new User { id = 4, name = "u4003" });
-                        Assert.AreEqual("u4003", userSet.Get(4).name);
-                        tran2.Commit();
-                    }
-                    Assert.AreEqual("u4003", userSet.Get(4).name);
-                }
-
-                Assert.AreEqual("u400", userSet.Get(4).name);
-            }
-            #endregion
-        }
 
 
 

+ 3 - 23
test/Vitorm.PostgreSQL.MsTest/DataSource.cs

@@ -1,7 +1,5 @@
 using Vit.Core.Util.ConfigurationManager;
 
-using Vitorm.Sql;
-
 namespace Vitorm.MsTest
 {
     [System.ComponentModel.DataAnnotations.Schema.Table("User")]
@@ -48,31 +46,13 @@ namespace Vitorm.MsTest
         readonly static string connectionString = Appsettings.json.GetStringByPath("Vitorm.PostgreSQL.connectionString");
 
 
-        public static SqlDbContext CreateDbContextForWriting(bool autoInit = true)
-        {
-            var dbContext = new SqlDbContext();
-            dbContext.UsePostgreSQL(connectionString);
-            dbContext.ChangeDatabase(dbContext.databaseName + "2");
-            if (autoInit) InitDbContext(dbContext);
-            return dbContext;
-        }
+        public static SqlDbContext CreateDbContextForWriting(bool autoInit = true) => CreateDbContext(autoInit);
 
-        static bool initedDefaultIndex = false;
-        public static SqlDbContext CreateDbContext()
+        public static SqlDbContext CreateDbContext(bool autoInit = true)
         {
             var dbContext = new SqlDbContext();
             dbContext.UsePostgreSQL(connectionString);
-
-            lock (typeof(DataSource))
-            {
-                if (!initedDefaultIndex)
-                {
-                    InitDbContext(dbContext);
-
-                    initedDefaultIndex = true;
-                }
-            }
-
+            if (autoInit) InitDbContext(dbContext);
             return dbContext;
         }
 

+ 0 - 2
test/Vitorm.PostgreSQL.MsTest/ExpressionNodesTest/ExpressionTester.cs

@@ -3,8 +3,6 @@ using System.Linq.Expressions;
 
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 
-using Vit.Linq;
-
 namespace Vit.Linq.ExpressionNodes.ExpressionNodesTest
 {