- 增加 QuestDB 时序数据库支持;(感谢 Daily 贡献)#1429

This commit is contained in:
2881099 2023-02-23 01:55:28 +08:00
parent 6843beeabe
commit e186eec7b4
16 changed files with 44 additions and 311 deletions

View File

@ -85,6 +85,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Extensions.Aggregat
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "orm_vs", "Examples\orm_vs\orm_vs.csproj", "{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "orm_vs", "Examples\orm_vs\orm_vs.csproj", "{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreeSql.Provider.QuestDb", "Providers\FreeSql.Provider.QuestDb\FreeSql.Provider.QuestDb.csproj", "{FEE501EB-60D1-4370-BC65-F939BCA7F32E}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -467,6 +469,18 @@ Global
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x64.Build.0 = Release|Any CPU {9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x64.Build.0 = Release|Any CPU
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x86.ActiveCfg = Release|Any CPU {9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x86.ActiveCfg = Release|Any CPU
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x86.Build.0 = Release|Any CPU {9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D}.Release|x86.Build.0 = Release|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Debug|x64.ActiveCfg = Debug|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Debug|x64.Build.0 = Debug|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Debug|x86.ActiveCfg = Debug|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Debug|x86.Build.0 = Debug|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Release|Any CPU.Build.0 = Release|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Release|x64.ActiveCfg = Release|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Release|x64.Build.0 = Release|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Release|x86.ActiveCfg = Release|Any CPU
{FEE501EB-60D1-4370-BC65-F939BCA7F32E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -499,10 +513,11 @@ Global
{28163C3B-B2E6-432D-AAC3-F5F19374BE31} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B} {28163C3B-B2E6-432D-AAC3-F5F19374BE31} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
{5C78C4CE-3CDC-49C3-AF34-556567B95F2A} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA} {5C78C4CE-3CDC-49C3-AF34-556567B95F2A} = {4A92E8A6-9A6D-41A1-9CDA-DE10899648AA}
{9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B} {9D7EA01A-110A-4A0C-A46B-9A0FBC88DD3D} = {94C8A78D-AA15-47B2-A348-530CD86BFC1B}
{FEE501EB-60D1-4370-BC65-F939BCA7F32E} = {2A381C57-2697-427B-9F10-55DA11FD02E4}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {089687FA-5D21-40AC-BA8A-AA0D1E1H7F98}
RESX_PrefixTranslations = True
RESX_NeutralResourcesLanguage = en-US RESX_NeutralResourcesLanguage = en-US
RESX_PrefixTranslations = True
SolutionGuid = {089687FA-5D21-40AC-BA8A-AA0D1E1H7F98}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -24,7 +24,7 @@ namespace FreeSql.QuestDb.Curd
public OnConflictDoUpdate(IInsert<T1> insert, Expression<Func<T1, object>> columns = null) public OnConflictDoUpdate(IInsert<T1> insert, Expression<Func<T1, object>> columns = null)
{ {
_pgsqlInsert = insert as QuestDbInsert<T1>; _pgsqlInsert = insert as QuestDbInsert<T1>;
if (_pgsqlInsert == null) throw new Exception(CoreStrings.S_Features_Unique("OnConflictDoUpdate", "PostgreSQL")); if (_pgsqlInsert == null) throw new Exception(CoreStrings.S_Features_Unique("OnConflictDoUpdate", "QuestDb"));
if (_pgsqlInsert._noneParameterFlag == "c") _pgsqlInsert._noneParameterFlag = "cu"; if (_pgsqlInsert._noneParameterFlag == "c") _pgsqlInsert._noneParameterFlag = "cu";
if (columns != null) if (columns != null)

View File

@ -7,7 +7,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace FreeSql.PostgreSQL.Curd namespace FreeSql.QuestDb.Curd
{ {
class QuestDbDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> class QuestDbDelete<T1> : Internal.CommonProvider.DeleteProvider<T1>

View File

@ -1,6 +1,5 @@
using FreeSql.Internal; using FreeSql.Internal;
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using NetTopologySuite.Mathematics;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections; using System.Collections;

View File

@ -18,7 +18,7 @@
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
<DelaySign>false</DelaySign> <DelaySign>false</DelaySign>
<Version>4.0.0.1</Version> <Version>3.2.688-preview20230216</Version>
</PropertyGroup> </PropertyGroup>
<!--<ItemGroup> <!--<ItemGroup>
@ -32,18 +32,16 @@
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Npgsql.LegacyPostgis" Version="5.0.11" /> <PackageReference Include="Npgsql" Version="5.0.11" />
<PackageReference Include="Npgsql.NetTopologySuite" Version="5.0.11" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'"> <ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<PackageReference Include="Npgsql.LegacyPostgis" Version="4.1.7" /> <PackageReference Include="Npgsql" Version="4.1.7" />
<PackageReference Include="Npgsql.NetTopologySuite" Version="4.1.7" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net45'"> <ItemGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net45'">
<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.11" /> <PackageReference Include="Npgsql" Version="4.0.11" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\Demo\FreeSql\FreeSql\FreeSql.csproj" /> <ProjectReference Include="..\..\FreeSql\FreeSql.csproj" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net45'"> <PropertyGroup Condition="'$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net45'">

View File

@ -15,13 +15,13 @@ namespace FreeSql.QuestDb
{ {
class QuestDbAdo : FreeSql.Internal.CommonProvider.AdoProvider class QuestDbAdo : FreeSql.Internal.CommonProvider.AdoProvider
{ {
public QuestDbAdo() : base(DataType.PostgreSQL, null, null) { } public QuestDbAdo() : base(DataType.QuestDb, null, null) { }
public QuestDbAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func<DbConnection> connectionFactory) : base(DataType.PostgreSQL, masterConnectionString, slaveConnectionStrings) public QuestDbAdo(CommonUtils util, string masterConnectionString, string[] slaveConnectionStrings, Func<DbConnection> connectionFactory) : base(DataType.QuestDb, masterConnectionString, slaveConnectionStrings)
{ {
base._util = util; base._util = util;
if (connectionFactory != null) if (connectionFactory != null)
{ {
var pool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.PostgreSQL, connectionFactory); var pool = new FreeSql.Internal.CommonProvider.DbConnectionPool(DataType.QuestDb, connectionFactory);
ConnectionString = pool.TestConnection?.ConnectionString; ConnectionString = pool.TestConnection?.ConnectionString;
MasterPool = pool; MasterPool = pool;
return; return;

View File

@ -22,7 +22,7 @@ namespace FreeSql.QuestDb
{ {
this.availableHandler = availableHandler; this.availableHandler = availableHandler;
this.unavailableHandler = unavailableHandler; this.unavailableHandler = unavailableHandler;
var policy = new PostgreSQLConnectionPoolPolicy var policy = new QuestDbConnectionPoolPolicy
{ {
_pool = this, _pool = this,
Name = name Name = name
@ -42,11 +42,11 @@ namespace FreeSql.QuestDb
} }
} }
class PostgreSQLConnectionPoolPolicy : IPolicy<DbConnection> class QuestDbConnectionPoolPolicy : IPolicy<DbConnection>
{ {
internal QuestDbConnectionPool _pool; internal QuestDbConnectionPool _pool;
public string Name { get; set; } = $"PostgreSQL NpgsqlConnection {CoreStrings.S_ObjectPool}"; public string Name { get; set; } = $"QuestDb NpgsqlConnection {CoreStrings.S_ObjectPool}";
public int PoolSize { get; set; } = 50; public int PoolSize { get; set; } = 50;
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10); public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(20); public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(20);

View File

@ -1,157 +0,0 @@
using Newtonsoft.Json.Linq;
using Npgsql;
using NpgsqlTypes;
using System;
using System.Collections;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
namespace Newtonsoft.Json
{
public class QuestDbTypesConverter : JsonConverter
{
private static readonly Type typeof_BitArray = typeof(BitArray);
private static readonly Type typeof_NpgsqlPoint = typeof(NpgsqlPoint);
private static readonly Type typeof_NpgsqlLine = typeof(NpgsqlLine);
private static readonly Type typeof_NpgsqlLSeg = typeof(NpgsqlLSeg);
private static readonly Type typeof_NpgsqlBox = typeof(NpgsqlBox);
private static readonly Type typeof_NpgsqlPath = typeof(NpgsqlPath);
private static readonly Type typeof_NpgsqlPolygon = typeof(NpgsqlPolygon);
private static readonly Type typeof_NpgsqlCircle = typeof(NpgsqlCircle);
private static readonly Type typeof_Cidr = typeof((IPAddress, int));
private static readonly Type typeof_IPAddress = typeof(IPAddress);
private static readonly Type typeof_PhysicalAddress = typeof(PhysicalAddress);
private static readonly Type typeof_String = typeof(string);
private static readonly Type typeof_NpgsqlRange_int = typeof(NpgsqlRange<int>);
private static readonly Type typeof_NpgsqlRange_long = typeof(NpgsqlRange<long>);
private static readonly Type typeof_NpgsqlRange_decimal = typeof(NpgsqlRange<decimal>);
private static readonly Type typeof_NpgsqlRange_DateTime = typeof(NpgsqlRange<DateTime>);
public override bool CanConvert(Type objectType)
{
Type ctype = objectType.IsArray ? objectType.GetElementType() : objectType;
var ctypeGenericType1 = ctype.GenericTypeArguments.FirstOrDefault();
if (ctype == typeof_BitArray) return true;
if (ctype == typeof_NpgsqlPoint || ctypeGenericType1 == typeof_NpgsqlPoint) return true;
if (ctype == typeof_NpgsqlLine || ctypeGenericType1 == typeof_NpgsqlLine) return true;
if (ctype == typeof_NpgsqlLSeg || ctypeGenericType1 == typeof_NpgsqlLSeg) return true;
if (ctype == typeof_NpgsqlBox || ctypeGenericType1 == typeof_NpgsqlBox) return true;
if (ctype == typeof_NpgsqlPath || ctypeGenericType1 == typeof_NpgsqlPath) return true;
if (ctype == typeof_NpgsqlPolygon || ctypeGenericType1 == typeof_NpgsqlPolygon) return true;
if (ctype == typeof_NpgsqlCircle || ctypeGenericType1 == typeof_NpgsqlCircle) return true;
if (ctype == typeof_Cidr || ctypeGenericType1 == typeof_Cidr) return true;
if (ctype == typeof_IPAddress) return true;
if (ctype == typeof_PhysicalAddress) return true;
if (ctype == typeof_NpgsqlRange_int || ctypeGenericType1 == typeof_NpgsqlRange_int) return true;
if (ctype == typeof_NpgsqlRange_long || ctypeGenericType1 == typeof_NpgsqlRange_long) return true;
if (ctype == typeof_NpgsqlRange_decimal || ctypeGenericType1 == typeof_NpgsqlRange_decimal) return true;
if (ctype == typeof_NpgsqlRange_DateTime || ctypeGenericType1 == typeof_NpgsqlRange_DateTime) return true;
return false;
}
private object YieldJToken(Type ctype, JToken jt, int rank)
{
if (jt.Type == JTokenType.Null) return null;
if (rank == 0)
{
var ctypeGenericType1 = ctype.GenericTypeArguments.FirstOrDefault();//ctype.Namespace == "System" && ctype.Name.StartsWith("Nullable`") ? ctype.GenericTypeArguments.FirstOrDefault() : null;
if (ctype == typeof_BitArray) return jt.ToString().ToBitArray();
if (ctype == typeof_NpgsqlPoint || ctypeGenericType1 == typeof_NpgsqlPoint) return NpgsqlPoint.Parse(jt.ToString());
if (ctype == typeof_NpgsqlLine || ctypeGenericType1 == typeof_NpgsqlLine) return NpgsqlLine.Parse(jt.ToString());
if (ctype == typeof_NpgsqlLSeg || ctypeGenericType1 == typeof_NpgsqlLSeg) return NpgsqlLSeg.Parse(jt.ToString());
if (ctype == typeof_NpgsqlBox || ctypeGenericType1 == typeof_NpgsqlBox) return NpgsqlBox.Parse(jt.ToString());
if (ctype == typeof_NpgsqlPath || ctypeGenericType1 == typeof_NpgsqlPath) return NpgsqlPath.Parse(jt.ToString());
if (ctype == typeof_NpgsqlPolygon || ctypeGenericType1 == typeof_NpgsqlPolygon) return NpgsqlPolygon.Parse(jt.ToString());
if (ctype == typeof_NpgsqlCircle || ctypeGenericType1 == typeof_NpgsqlCircle) return NpgsqlCircle.Parse(jt.ToString());
if (ctype == typeof_Cidr || ctypeGenericType1 == typeof_Cidr)
{
var cidrArgs = jt.ToString().Split(new[] { '/' }, 2);
return (IPAddress.Parse(cidrArgs.First()), cidrArgs.Length >= 2 ? int.TryParse(cidrArgs[1], out var tryCdirSubnet) ? tryCdirSubnet : 0 : 0);
}
if (ctype == typeof_IPAddress) return IPAddress.Parse(jt.ToString());
if (ctype == typeof_PhysicalAddress) return PhysicalAddress.Parse(jt.ToString());
if (ctype == typeof_NpgsqlRange_int || ctypeGenericType1 == typeof_NpgsqlRange_int) return jt.ToString().ToNpgsqlRange<int>();
if (ctype == typeof_NpgsqlRange_long || ctypeGenericType1 == typeof_NpgsqlRange_long) return jt.ToString().ToNpgsqlRange<long>();
if (ctype == typeof_NpgsqlRange_decimal || ctypeGenericType1 == typeof_NpgsqlRange_decimal) return jt.ToString().ToNpgsqlRange<decimal>();
if (ctype == typeof_NpgsqlRange_DateTime || ctypeGenericType1 == typeof_NpgsqlRange_DateTime) return jt.ToString().ToNpgsqlRange<DateTime>();
return null;
}
var jtarr = jt.ToArray();
var ret = Array.CreateInstance(ctype, jtarr.Length);
var jtarrIdx = 0;
foreach (var a in jtarr)
{
var t2 = YieldJToken(ctype, a, rank - 1);
ret.SetValue(t2, jtarrIdx++);
}
return ret;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
int rank = objectType.IsArray ? objectType.GetArrayRank() : 0;
Type ctype = objectType.IsArray ? objectType.GetElementType() : objectType;
var ret = YieldJToken(ctype, JToken.Load(reader), rank);
if (ret != null && rank > 0) return ret;
return ret;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Type objectType = value.GetType();
if (objectType.IsArray)
{
int rank = objectType.GetArrayRank();
int[] indices = new int[rank];
GetJObject(value as Array, indices, 0).WriteTo(writer);
}
else
GetJObject(value).WriteTo(writer);
}
public static JToken GetJObject(object value)
{
if (value is BitArray) return JToken.FromObject((value as BitArray)?.To1010());
if (value is IPAddress) return JToken.FromObject((value as IPAddress)?.ToString());
if (value is ValueTuple<IPAddress, int> || value is ValueTuple<IPAddress, int>?)
{
ValueTuple<IPAddress, int>? cidrValue = (ValueTuple<IPAddress, int>?)value;
return JToken.FromObject(cidrValue == null ? null : $"{cidrValue.Value.Item1.ToString()}/{cidrValue.Value.Item2.ToString()}");
}
return JToken.FromObject(value?.ToString());
}
public static JToken GetJObject(Array value, int[] indices, int idx)
{
if (idx == indices.Length)
{
return GetJObject(value.GetValue(indices));
}
JArray ja = new JArray();
if (indices.Length == 1)
{
foreach (object a in value)
ja.Add(GetJObject(a));
return ja;
}
int lb = value.GetLowerBound(idx);
int ub = value.GetUpperBound(idx);
for (int b = lb; b <= ub; b++)
{
indices[idx] = b;
ja.Add(GetJObject(value, indices, idx + 1));
}
return ja;
}
}
}

View File

@ -1,73 +0,0 @@
using NpgsqlTypes;
using System;
using System.Collections;
public static partial class QuestDbTypesExtensions
{
/// <summary>
/// 测量两个经纬度的距离,返回单位:米
/// </summary>
/// <param name="that">经纬坐标1</param>
/// <param name="point">经纬坐标2</param>
/// <returns>返回距离(单位:米)</returns>
public static double Distance(this NpgsqlPoint that, NpgsqlPoint point)
{
double radLat1 = (double)(that.Y) * Math.PI / 180d;
double radLng1 = (double)(that.X) * Math.PI / 180d;
double radLat2 = (double)(point.Y) * Math.PI / 180d;
double radLng2 = (double)(point.X) * Math.PI / 180d;
return 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin((radLat1 - radLat2) / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin((radLng1 - radLng2) / 2), 2))) * 6378137;
}
#if net40
#else
/// <summary>
/// 测量两个经纬度的距离,返回单位:米
/// </summary>
/// <param name="that">经纬坐标1</param>
/// <param name="point">经纬坐标2</param>
/// <returns>返回距离(单位:米)</returns>
public static double Distance(this Npgsql.LegacyPostgis.PostgisPoint that, Npgsql.LegacyPostgis.PostgisPoint point)
{
double radLat1 = (double)(that.Y) * Math.PI / 180d;
double radLng1 = (double)(that.X) * Math.PI / 180d;
double radLat2 = (double)(point.Y) * Math.PI / 180d;
double radLng2 = (double)(point.X) * Math.PI / 180d;
return 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin((radLat1 - radLat2) / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin((radLng1 - radLng2) / 2), 2))) * 6378137;
}
public static NpgsqlRange<T> ToNpgsqlRange<T>(this string that)
{
var s = that;
if (string.IsNullOrEmpty(s) || s == "empty") return NpgsqlRange<T>.Empty;
string s1 = s.Trim('(', ')', '[', ']');
string[] ss = s1.Split(new char[] { ',' }, 2);
if (ss.Length != 2) return NpgsqlRange<T>.Empty;
T t1 = default(T);
T t2 = default(T);
if (!string.IsNullOrEmpty(ss[0])) t1 = (T)Convert.ChangeType(ss[0], typeof(T));
if (!string.IsNullOrEmpty(ss[1])) t2 = (T)Convert.ChangeType(ss[1], typeof(T));
return new NpgsqlRange<T>(t1, s[0] == '[', s[0] == '(', t2, s[s.Length - 1] == ']', s[s.Length - 1] == ')');
}
#endif
public static string To1010(this BitArray ba)
{
char[] ret = new char[ba.Length];
for (int a = 0; a < ba.Length; a++) ret[a] = ba[a] ? '1' : '0';
return new string(ret);
}
/// <summary>
/// 将 1010101010 这样的二进制字符串转换成 BitArray
/// </summary>
/// <param name="_1010Str">1010101010</param>
/// <returns></returns>
public static BitArray ToBitArray(this string _1010Str)
{
if (_1010Str == null) return null;
BitArray ret = new BitArray(_1010Str.Length);
for (int a = 0; a < _1010Str.Length; a++) ret[a] = _1010Str[a] == '1';
return ret;
}
}

View File

@ -2,7 +2,6 @@
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using FreeSql.Provider.QuestDb.Subtable; using FreeSql.Provider.QuestDb.Subtable;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Npgsql.LegacyPostgis;
using NpgsqlTypes; using NpgsqlTypes;
using System; using System;
using System.Collections; using System.Collections;

View File

@ -2,7 +2,6 @@
using FreeSql.Internal; using FreeSql.Internal;
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Npgsql.LegacyPostgis;
using NpgsqlTypes; using NpgsqlTypes;
using System; using System;
using System.Collections; using System.Collections;
@ -412,12 +411,6 @@ namespace FreeSql.QuestDb
"JsonConvert.SerializeObject({0})", "Dictionary<string, string>", "JsonConvert.SerializeObject({0})", "Dictionary<string, string>",
typeof(Dictionary<string, string>), typeof(Dictionary<string, string>), "{0}", "GetValue") typeof(Dictionary<string, string>), typeof(Dictionary<string, string>), "{0}", "GetValue")
}, },
{
(int)NpgsqlDbType.Geometry,
("(PostgisGeometry)", "JsonConvert.DeserializeObject<PostgisGeometry>({0})",
"JsonConvert.SerializeObject({0})", "PostgisGeometry", typeof(PostgisGeometry),
typeof(PostgisGeometry), "{0}", "GetValue")
},
/*** array ***/ /*** array ***/
@ -665,12 +658,6 @@ namespace FreeSql.QuestDb
typeof(Dictionary<string, string>[]), typeof(Dictionary<string, string>[]), "{0}", typeof(Dictionary<string, string>[]), typeof(Dictionary<string, string>[]), "{0}",
"GetValue") "GetValue")
}, },
{
(int)(NpgsqlDbType.Geometry | NpgsqlDbType.Array),
("(PostgisGeometry[])", "JsonConvert.DeserializeObject<PostgisGeometry[]>({0})",
"JsonConvert.SerializeObject({0})", "PostgisGeometry[]", typeof(PostgisGeometry[]),
typeof(PostgisGeometry[]), "{0}", "GetValue")
},
}; };
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc)

View File

@ -30,10 +30,10 @@ public static partial class QuestDbGlobalExtensions
/// <param name="that"></param> /// <param name="that"></param>
/// <param name="args"></param> /// <param name="args"></param>
/// <returns></returns> /// <returns></returns>
public static string FormatPostgreSQL(this string that, params object[] args) => public static string FormatQuestDb(this string that, params object[] args) =>
_postgresqlAdo.Addslashes(that, args); _QuestDbAdo.Addslashes(that, args);
static QuestDbAdo _postgresqlAdo = new QuestDbAdo(); static QuestDbAdo _QuestDbAdo = new QuestDbAdo();
/// <summary> /// <summary>

View File

@ -1,11 +1,9 @@
using FreeSql.Internal; using FreeSql.Internal;
using FreeSql.Internal.CommonProvider; using FreeSql.Internal.CommonProvider;
using FreeSql.PostgreSQL.Curd;
using FreeSql.Provider.QuestDb; using FreeSql.Provider.QuestDb;
using FreeSql.QuestDb.Curd; using FreeSql.QuestDb.Curd;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Npgsql.LegacyPostgis;
using NpgsqlTypes; using NpgsqlTypes;
using System; using System;
using System.Collections; using System.Collections;
@ -42,26 +40,6 @@ namespace FreeSql.QuestDb
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<decimal>)] = true; Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<decimal>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<DateTime>)] = true; Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NpgsqlRange<DateTime>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisMultiPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisMultiLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisMultiPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisGeometry)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(PostgisGeometryCollection)] = true;
#if nts
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.Point)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.LineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.Polygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.MultiPoint)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.MultiLineString)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.MultiPolygon)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.Geometry)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(NetTopologySuite.Geometries.GeometryCollection)] = true;
#endif
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(Dictionary<string, string>)] = true; Utils.dicExecuteArrayRowReadClassOrTuple[typeof(Dictionary<string, string>)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JToken)] = true; Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JToken)] = true;
Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JObject)] = true; Utils.dicExecuteArrayRowReadClassOrTuple[typeof(JObject)] = true;

View File

@ -2,7 +2,6 @@
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Npgsql; using Npgsql;
using Npgsql.LegacyPostgis;
using NpgsqlTypes; using NpgsqlTypes;
using System; using System;
using System.Collections; using System.Collections;
@ -237,7 +236,7 @@ namespace FreeSql.QuestDb
return ret; return ret;
}); });
public override string FormatSql(string sql, params object[] args) => sql?.FormatPostgreSQL(args); public override string FormatSql(string sql, params object[] args) => sql?.FormatQuestDb(args);
public override string QuoteSqlNameAdapter(params string[] name) public override string QuoteSqlNameAdapter(params string[] name)
{ {
@ -273,30 +272,11 @@ namespace FreeSql.QuestDb
public override string QuoteWriteParamterAdapter(Type type, string paramterName) => paramterName; public override string QuoteWriteParamterAdapter(Type type, string paramterName) => paramterName;
protected override string QuoteReadColumnAdapter(Type type, Type mapType, string columnName) => columnName; protected override string QuoteReadColumnAdapter(Type type, Type mapType, string columnName) => columnName;
static ConcurrentDictionary<Type, bool> _dicIsAssignableFromPostgisGeometry =
new ConcurrentDictionary<Type, bool>();
public override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, string specialParamFlag, public override string GetNoneParamaterSqlValue(List<DbParameter> specialParams, string specialParamFlag,
ColumnInfo col, Type type, object value) ColumnInfo col, Type type, object value)
{ {
if (value == null) return "NULL"; if (value == null) return "NULL";
if (type.IsNumberType()) return string.Format(CultureInfo.InvariantCulture, "{0}", value); if (type.IsNumberType()) return string.Format(CultureInfo.InvariantCulture, "{0}", value);
if (_dicIsAssignableFromPostgisGeometry.GetOrAdd(type, t2 =>
{
var t2type = t2.IsArray ? t2.GetElementType() : t2;
return typeof(PostgisGeometry).IsAssignableFrom(t2type)
#if nts
||
typeof(NetTopologySuite.Geometries.Geometry).IsAssignableFrom(t2type)
#endif
;
}))
{
var pam = AppendParamter(specialParams, $"p_{specialParams?.Count}{specialParamFlag}", null, type,
value);
return pam.ParameterName;
}
value = getParamterValue(type, value); value = getParamterValue(type, value);
var type2 = value.GetType(); var type2 = value.GetType();
@ -326,7 +306,7 @@ namespace FreeSql.QuestDb
} }
else if (type2 == typeof(BitArray)) else if (type2 == typeof(BitArray))
{ {
return $"'{(value as BitArray).To1010()}'"; return $"'{To1010(value as BitArray)}'";
} }
else if (type2 == typeof(NpgsqlLine) || type2 == typeof(NpgsqlLine?)) else if (type2 == typeof(NpgsqlLine) || type2 == typeof(NpgsqlLine?))
{ {
@ -346,6 +326,13 @@ namespace FreeSql.QuestDb
return FormatSql("{0}", value, 1); return FormatSql("{0}", value, 1);
} }
string To1010(BitArray ba)
{
char[] ret = new char[ba.Length];
for (int a = 0; a < ba.Length; a++) ret[a] = ba[a] ? '1' : '0';
return new string(ret);
}
} }
} }

View File

@ -20,7 +20,7 @@ FreeSql is a powerful O/RM component, supports .NET Core 2.1+, .NET Framework 4.
- 🌲 Support expression functions, and customizable analysis. - 🌲 Support expression functions, and customizable analysis.
- 🏁 Support one-to-many and many-to-many navigation properties, include and lazy loading. - 🏁 Support one-to-many and many-to-many navigation properties, include and lazy loading.
- 📃 Support Read/Write separation, Splitting Table/Database, Global filters, Optimistic and pessimistic locker. - 📃 Support Read/Write separation, Splitting Table/Database, Global filters, Optimistic and pessimistic locker.
- 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/ClickHouse/MsAccess, etc. - 🌳 Support MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/ClickHouse/QuestDB/MsAccess, etc.
QQ Groups4336577(full)、8578575(full)、**52508226(available)** QQ Groups4336577(full)、8578575(full)、**52508226(available)**

View File

@ -20,7 +20,7 @@ FreeSql 是一款功能强大的对象关系映射O/RM组件支持 .NET
- ✒ 支持 丰富的表达式函数,以及灵活的自定义解析; - ✒ 支持 丰富的表达式函数,以及灵活的自定义解析;
- 🏁 支持 导航属性一对多、多对多贪婪加载,以及延时加载; - 🏁 支持 导航属性一对多、多对多贪婪加载,以及延时加载;
- 📃 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁; - 📃 支持 读写分离、分表分库、过滤器、乐观锁、悲观锁;
- 🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/ClickHouse/Access 等数据库; - 🌳 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/人大金仓/神舟通用/南大通用/翰高/ClickHouse/QuestDB/Access 等数据库;
QQ群4336577(已满)、8578575(已满)、52508226(在线) QQ群4336577(已满)、8578575(已满)、52508226(在线)