From b164a087479e149e26155739f83d9397e46a2d22 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Wed, 28 Jun 2023 16:44:49 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E4=BF=AE=E5=A4=8D=20pgsql=20Geo=20?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E8=87=AA=E5=AE=9A=E4=B9=89=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E6=B7=B1=E5=BA=A6=E9=97=AE=E9=A2=98=EF=BC=9B#1422?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Examples/base_entity/Program.cs | 134 ++++++++++++++------------- FreeSql/Internal/CommonExpression.cs | 8 +- 2 files changed, 74 insertions(+), 68 deletions(-) diff --git a/Examples/base_entity/Program.cs b/Examples/base_entity/Program.cs index a23228df..7e14b11b 100644 --- a/Examples/base_entity/Program.cs +++ b/Examples/base_entity/Program.cs @@ -590,7 +590,7 @@ namespace base_entity //.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) //.UseConnectionString(FreeSql.DataType.OdbcDameng, "Driver={DM8 ODBC DRIVER};Server=127.0.0.1:5236;Persist Security Info=False;Trusted_Connection=Yes;UID=USER1;PWD=123456789") - .UseConnectionString(DataType.QuestDb, "host=localhost;port=8812;username=admin;password=quest;database=qdb;ServerCompatibilityMode=NoTypeLoading;") + //.UseConnectionString(DataType.QuestDb, "host=localhost;port=8812;username=admin;password=quest;database=qdb;ServerCompatibilityMode=NoTypeLoading;") .UseMonitorCommand(cmd => { Console.WriteLine(cmd.CommandText + "\r\n"); @@ -602,6 +602,73 @@ namespace base_entity BaseEntity.Initialization(fsql, () => _asyncUow.Value); #endregion + + fsql.Aop.ParseExpression += (_, e) => + { + if (fsql.Ado.DataType == DataType.PostgreSQL) + { + if (e.Expression is MethodCallExpression callExp && + callExp.Object is not null && typeof(Geometry).IsAssignableFrom(callExp.Method.DeclaringType)) + { + var instance = callExp.Object; + var arguments = callExp.Arguments; + var Function = new Func((dbfunc, args, returnType) => + { + var inputArgs = string.Join(", ", args.Select(a => + { + //var testParse = fsql.Aop.ParseExpressionHandler(fsql, new FreeSql.Aop.ParseExpressionEventArgs(a, e.FreeParse, e.Tables)); + return e.FreeParse(a); + })); + return $"{dbfunc}({inputArgs})"; + }); + e.Result = callExp.Method.Name switch + { + nameof(Geometry.AsBinary) => Function("ST_AsBinary", new[] { instance }, typeof(byte[])), + nameof(Geometry.AsText) => Function("ST_AsText", new[] { instance }, typeof(string)), + nameof(Geometry.Buffer) => Function("ST_Buffer", new[] { instance }.Concat(arguments).ToArray(), typeof(Geometry)), + nameof(Geometry.Contains) => Function("ST_Contains", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.ConvexHull) => Function("ST_ConvexHull", new[] { instance }, typeof(Geometry)), + nameof(Geometry.CoveredBy) => Function("ST_CoveredBy", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.Covers) => Function("ST_Covers", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.Crosses) => Function("ST_Crosses", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.Disjoint) => Function("ST_Disjoint", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.Difference) => Function("ST_Difference", new[] { instance, arguments[0] }, typeof(Geometry)), + nameof(Geometry.Distance) => Function("ST_Distance", new[] { instance }.Concat(arguments).ToArray(), typeof(double)), + nameof(Geometry.EqualsExact) => Function("ST_OrderingEquals", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.EqualsTopologically) => Function("ST_Equals", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.GetGeometryN) => Function("ST_GeometryN", new[] { instance, arguments[0] }, typeof(Geometry)), + nameof(Polygon.GetInteriorRingN) => Function("ST_InteriorRingN", new[] { instance, arguments[0] }, typeof(Geometry)), + nameof(LineString.GetPointN) => Function("ST_PointN", new[] { instance, arguments[0] }, typeof(Geometry)), + nameof(Geometry.Intersection) => Function("ST_Intersection", new[] { instance, arguments[0] }, typeof(Geometry)), + nameof(Geometry.Intersects) => Function("ST_Intersects", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.IsWithinDistance) => Function("ST_DWithin", new[] { instance }.Concat(arguments).ToArray(), typeof(bool)), + nameof(Geometry.Normalized) => Function("ST_Normalize", new[] { instance }, typeof(Geometry)), + nameof(Geometry.Overlaps) => Function("ST_Overlaps", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.Relate) => Function("ST_Relate", new[] { instance, arguments[0], arguments[1] }, typeof(bool)), + nameof(Geometry.Reverse) => Function("ST_Reverse", new[] { instance }, typeof(Geometry)), + nameof(Geometry.SymmetricDifference) => Function("ST_SymDifference", new[] { instance, arguments[0] }, typeof(Geometry)), + nameof(Geometry.ToBinary) => Function("ST_AsBinary", new[] { instance }, typeof(byte[])), + nameof(Geometry.ToText) => Function("ST_AsText", new[] { instance }, typeof(string)), + nameof(Geometry.Touches) => Function("ST_Touches", new[] { instance, arguments[0] }, typeof(bool)), + nameof(Geometry.Within) => Function("ST_Within", new[] { instance, arguments[0] }, typeof(bool)), + + nameof(Geometry.Union) when arguments.Count == 0 => Function("ST_UnaryUnion", new[] { instance }, typeof(Geometry)), + nameof(Geometry.Union) when arguments.Count == 1 => Function("ST_Union", new[] { instance, arguments[0] }, typeof(Geometry)), + + _ => null + }; + + } + } + }; + if (fsql.Ado.DataType == DataType.PostgreSQL) + { + Npgsql.NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite(); + var geo = new Point(10, 20); + var xxx = fsql.Select() + .Where(a => geo.GetGeometryN(0).Distance(a.Center) < 100).ToSql(); + } + var qr1 = fsql.SelectLongSequence(10, () => new { rndstr = QuestFunc.rnd_str(10, 5, 10, 0), @@ -1006,71 +1073,6 @@ var sql11111 = fsql.Select() .ToSql(); - fsql.Aop.ParseExpression += (_, e) => - { - if (fsql.Ado.DataType == DataType.PostgreSQL) - { - if (e.Expression is MethodCallExpression callExp && - callExp.Object is not null && typeof(Geometry).IsAssignableFrom(callExp.Method.DeclaringType)) - { - var instance = callExp.Object; - var arguments = callExp.Arguments; - var Function = new Func((dbfunc, args, returnType) => - { - var inputArgs = string.Join(", ", args.Select(a => - { - //var testParse = fsql.Aop.ParseExpressionHandler(fsql, new FreeSql.Aop.ParseExpressionEventArgs(a, e.FreeParse, e.Tables)); - return e.FreeParse(a); - })); - return $"{dbfunc}({inputArgs})"; - }); - e.Result = callExp.Method.Name switch - { - nameof(Geometry.AsBinary) => Function("ST_AsBinary", new[] { instance }, typeof(byte[])), - nameof(Geometry.AsText) => Function("ST_AsText", new[] { instance }, typeof(string)), - nameof(Geometry.Buffer) => Function("ST_Buffer", new[] { instance }.Concat(arguments).ToArray(), typeof(Geometry)), - nameof(Geometry.Contains) => Function("ST_Contains", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.ConvexHull) => Function("ST_ConvexHull", new[] { instance }, typeof(Geometry)), - nameof(Geometry.CoveredBy) => Function("ST_CoveredBy", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.Covers) => Function("ST_Covers", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.Crosses) => Function("ST_Crosses", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.Disjoint) => Function("ST_Disjoint", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.Difference) => Function("ST_Difference", new[] { instance, arguments[0] }, typeof(Geometry)), - nameof(Geometry.Distance) => Function("ST_Distance", new[] { instance }.Concat(arguments).ToArray(), typeof(double)), - nameof(Geometry.EqualsExact) => Function("ST_OrderingEquals", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.EqualsTopologically) => Function("ST_Equals", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.GetGeometryN) => Function("ST_GeometryN", new[] { instance, arguments[0] }, typeof(Geometry)), - nameof(Polygon.GetInteriorRingN) => Function("ST_InteriorRingN", new[] { instance, arguments[0] }, typeof(Geometry)), - nameof(LineString.GetPointN) => Function("ST_PointN", new[] { instance, arguments[0] }, typeof(Geometry)), - nameof(Geometry.Intersection) => Function("ST_Intersection", new[] { instance, arguments[0] }, typeof(Geometry)), - nameof(Geometry.Intersects) => Function("ST_Intersects", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.IsWithinDistance) => Function("ST_DWithin", new[] { instance }.Concat(arguments).ToArray(), typeof(bool)), - nameof(Geometry.Normalized) => Function("ST_Normalize", new[] { instance }, typeof(Geometry)), - nameof(Geometry.Overlaps) => Function("ST_Overlaps", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.Relate) => Function("ST_Relate", new[] { instance, arguments[0], arguments[1] }, typeof(bool)), - nameof(Geometry.Reverse) => Function("ST_Reverse", new[] { instance }, typeof(Geometry)), - nameof(Geometry.SymmetricDifference) => Function("ST_SymDifference", new[] { instance, arguments[0] }, typeof(Geometry)), - nameof(Geometry.ToBinary) => Function("ST_AsBinary", new[] { instance }, typeof(byte[])), - nameof(Geometry.ToText) => Function("ST_AsText", new[] { instance }, typeof(string)), - nameof(Geometry.Touches) => Function("ST_Touches", new[] { instance, arguments[0] }, typeof(bool)), - nameof(Geometry.Within) => Function("ST_Within", new[] { instance, arguments[0] }, typeof(bool)), - - nameof(Geometry.Union) when arguments.Count == 0 => Function("ST_UnaryUnion", new[] { instance }, typeof(Geometry)), - nameof(Geometry.Union) when arguments.Count == 1 => Function("ST_Union", new[] { instance, arguments[0] }, typeof(Geometry)), - - _ => null - }; - - } - } - }; - if (fsql.Ado.DataType == DataType.PostgreSQL) - { - Npgsql.NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite(); - var geo = new Point(10, 20); - fsql.Select() - .Where(a => geo.Distance(a.Center) < 100).ToList(); - } var items = new List(); for (var a = 0; a < 3; a++) items.Add(new User1 { Id = Guid.NewGuid(), Avatar = $"avatar{a}" }); diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index adec61b2..eff9ee4b 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -937,9 +937,12 @@ namespace FreeSql.Internal { if (exp == null) return ""; if (tsc.dbParams != null && tsc.mapColumnTmp != null && tsc.mapColumnTmp.CsType.NullableTypeOrThis() != exp.Type) tsc.SetMapColumnTmp(null); - if (tsc.isDisableDiyParse == false) + if (tsc.isDisableDiyParse == false && tsc.parseDepth < 20) { - var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(ukexp, tsc.CloneDisableDiyParse()), tsc._tables); + var aopTsc = tsc.CloneDisableDiyParse(); + aopTsc.parseDepth = tsc.parseDepth + 1; + aopTsc.isDisableDiyParse = false; //用深度控制 + var args = new Aop.ParseExpressionEventArgs(exp, ukexp => ExpressionLambdaToSql(ukexp, aopTsc), tsc._tables); if (_common._orm.Aop.ParseExpressionHandler != null) { _common._orm.Aop.ParseExpressionHandler(this, args); @@ -2276,6 +2279,7 @@ namespace FreeSql.Internal public List whereGlobalFilter { get; set; } public List dbParams { get; set; } public string alias001 { get; set; } //单表字段的表别名 + public int parseDepth { get; set; } //Aop 解析深度,防止死循环 public ExpTSC SetMapColumnTmp(ColumnInfo col) {