- 修复 pgsql Geo 函数自定义解析深度问题;#1422

This commit is contained in:
2881099 2023-06-28 16:44:49 +08:00
parent ea7dae2fe8
commit b164a08747
2 changed files with 74 additions and 68 deletions

View File

@ -590,7 +590,7 @@ namespace base_entity
//.UseNameConvert(FreeSql.Internal.NameConvertType.ToUpper) //.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(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 => .UseMonitorCommand(cmd =>
{ {
Console.WriteLine(cmd.CommandText + "\r\n"); Console.WriteLine(cmd.CommandText + "\r\n");
@ -602,6 +602,73 @@ namespace base_entity
BaseEntity.Initialization(fsql, () => _asyncUow.Value); BaseEntity.Initialization(fsql, () => _asyncUow.Value);
#endregion #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<string, Expression[], Type, string>((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<City>()
.Where(a => geo.GetGeometryN(0).Distance(a.Center) < 100).ToSql();
}
var qr1 = fsql.SelectLongSequence(10, () => new var qr1 = fsql.SelectLongSequence(10, () => new
{ {
rndstr = QuestFunc.rnd_str(10, 5, 10, 0), rndstr = QuestFunc.rnd_str(10, 5, 10, 0),
@ -1006,71 +1073,6 @@ var sql11111 = fsql.Select<Class1111>()
.ToSql(); .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<string, Expression[], Type, string>((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<City>()
.Where(a => geo.Distance(a.Center) < 100).ToList();
}
var items = new List<User1>(); var items = new List<User1>();
for (var a = 0; a < 3; a++) items.Add(new User1 { Id = Guid.NewGuid(), Avatar = $"avatar{a}" }); for (var a = 0; a < 3; a++) items.Add(new User1 { Id = Guid.NewGuid(), Avatar = $"avatar{a}" });

View File

@ -937,9 +937,12 @@ namespace FreeSql.Internal
{ {
if (exp == null) return ""; if (exp == null) return "";
if (tsc.dbParams != null && tsc.mapColumnTmp != null && tsc.mapColumnTmp.CsType.NullableTypeOrThis() != exp.Type) tsc.SetMapColumnTmp(null); 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) if (_common._orm.Aop.ParseExpressionHandler != null)
{ {
_common._orm.Aop.ParseExpressionHandler(this, args); _common._orm.Aop.ParseExpressionHandler(this, args);
@ -2276,6 +2279,7 @@ namespace FreeSql.Internal
public List<GlobalFilter.Item> whereGlobalFilter { get; set; } public List<GlobalFilter.Item> whereGlobalFilter { get; set; }
public List<DbParameter> dbParams { get; set; } public List<DbParameter> dbParams { get; set; }
public string alias001 { get; set; } //单表字段的表别名 public string alias001 { get; set; } //单表字段的表别名
public int parseDepth { get; set; } //Aop 解析深度,防止死循环
public ExpTSC SetMapColumnTmp(ColumnInfo col) public ExpTSC SetMapColumnTmp(ColumnInfo col)
{ {