mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
pgsql DbFirst 完成未测试;oracle 适配进行中
This commit is contained in:
parent
a6e44a4cd1
commit
5eb451fc76
21
FreeSql.Tests/PostgreSQL/PostgreSQLDbFirstTest.cs
Normal file
21
FreeSql.Tests/PostgreSQL/PostgreSQLDbFirstTest.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using System;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace FreeSql.Tests.PostgreSQL {
|
||||||
|
public class PostgreSQLDbFirstTest {
|
||||||
|
[Fact]
|
||||||
|
public void GetDatabases() {
|
||||||
|
|
||||||
|
var t1 = g.pgsql.DbFirst.GetDatabases();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetTablesByDatabase() {
|
||||||
|
|
||||||
|
var t2 = g.pgsql.DbFirst.GetTablesByDatabase(g.pgsql.DbFirst.GetDatabases()[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
FreeSql/Extensions/FreeSqlGlobalExtensions.cs
Normal file
54
FreeSql/Extensions/FreeSqlGlobalExtensions.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using NpgsqlTypes;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
public static class FreeSqlGlobalExtensions {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 测量两个经纬度的距离,返回单位:米
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="that">经纬坐标1</param>
|
||||||
|
/// <param name="point">经纬坐标2</param>
|
||||||
|
/// <returns>返回距离(单位:米)</returns>
|
||||||
|
public static double Distance(this Point that, Point 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 object GetEnum<T>(this IDataReader dr, int index) {
|
||||||
|
string value = dr.GetString(index);
|
||||||
|
Type t = typeof(T);
|
||||||
|
foreach (var f in t.GetFields())
|
||||||
|
if (f.GetCustomAttribute<DescriptionAttribute>()?.Description == value || f.Name == value) return Enum.Parse(t, f.Name, true);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToDescriptionOrString(this Enum item) {
|
||||||
|
string name = item.ToString();
|
||||||
|
var desc = item.GetType().GetField(name)?.GetCustomAttribute<DescriptionAttribute>();
|
||||||
|
return desc?.Description ?? name;
|
||||||
|
}
|
||||||
|
public static long ToInt64(this Enum item) {
|
||||||
|
return Convert.ToInt64(item);
|
||||||
|
}
|
||||||
|
public static IEnumerable<T> ToSet<T>(this long value) {
|
||||||
|
List<T> ret = new List<T>();
|
||||||
|
if (value == 0) return ret;
|
||||||
|
Type t = typeof(T);
|
||||||
|
foreach (FieldInfo f in t.GetFields()) {
|
||||||
|
if (f.FieldType != t) continue;
|
||||||
|
object o = Enum.Parse(t, f.Name, true);
|
||||||
|
long v = (long)o;
|
||||||
|
if ((value & v) == v) ret.Add((T)o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
public static class StringExtensions {
|
public static class FreeSqlStringExtensions {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
|
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
|
||||||
@ -24,6 +24,14 @@
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string FormatPostgreSQL(this string that, params object[] args) => _postgresqlAdo.Addslashes(that, args);
|
public static string FormatPostgreSQL(this string that, params object[] args) => _postgresqlAdo.Addslashes(that, args);
|
||||||
static FreeSql.PostgreSQL.PostgreSQLAdo _postgresqlAdo = new FreeSql.PostgreSQL.PostgreSQLAdo();
|
static FreeSql.PostgreSQL.PostgreSQLAdo _postgresqlAdo = new FreeSql.PostgreSQL.PostgreSQLAdo();
|
||||||
|
/// <summary>
|
||||||
|
/// 特殊处理类似 string.Format 的使用方法,防止注入,以及 IS NULL 转换
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="that"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string FormatOracleSQL(this string that, params object[] args) => _oracleAdo.Addslashes(that, args);
|
||||||
|
static FreeSql.Oracle.OracleAdo _oracleAdo = new FreeSql.Oracle.OracleAdo();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace System.Runtime.CompilerServices {
|
namespace System.Runtime.CompilerServices {
|
@ -1,39 +0,0 @@
|
|||||||
using NpgsqlTypes;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
namespace NpgsqlTypes {
|
|
||||||
public static class FreeSqlExtensions {
|
|
||||||
|
|
||||||
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="_1010">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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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] == ')');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@
|
|||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||||
<PackageReference Include="Npgsql" Version="4.0.4" />
|
<PackageReference Include="Npgsql" Version="4.0.4" />
|
||||||
<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.4" />
|
<PackageReference Include="Npgsql.LegacyPostgis" Version="4.0.4" />
|
||||||
|
<PackageReference Include="Oracle.ManagedDataAccess.Core" Version="2.18.3" />
|
||||||
<PackageReference Include="SafeObjectPool" Version="1.0.12" />
|
<PackageReference Include="SafeObjectPool" Version="1.0.12" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.6.0" />
|
<PackageReference Include="System.Data.SqlClient" Version="4.6.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -92,6 +92,7 @@ namespace FreeSql {
|
|||||||
case DataType.MySql: ret = new MySql.MySqlProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
case DataType.MySql: ret = new MySql.MySqlProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
||||||
case DataType.SqlServer: ret = new SqlServer.SqlServerProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
case DataType.SqlServer: ret = new SqlServer.SqlServerProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
||||||
case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
case DataType.PostgreSQL: ret = new PostgreSQL.PostgreSQLProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
||||||
|
//case DataType.Oracle: ret = new Oracle.OracleProvider(_cache, _logger, _masterConnectionString, _slaveConnectionString); break;
|
||||||
}
|
}
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;
|
ret.CodeFirst.IsAutoSyncStructure = _isAutoSyncStructure;
|
||||||
@ -104,5 +105,5 @@ namespace FreeSql {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DataType { MySql, SqlServer, PostgreSQL }
|
public enum DataType { MySql, SqlServer, PostgreSQL, /*Oracle*/ }
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToSql() {
|
public virtual string ToSql() {
|
||||||
if (_source == null || _source.Any() == false) return null;
|
if (_source == null || _source.Any() == false) return null;
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append("(");
|
sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append("(");
|
||||||
|
@ -20,47 +20,4 @@ public static partial class MygisTypesExtensions {
|
|||||||
double radLng2 = (double)(point.X) * 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;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 测量两个经纬度的距离,返回单位:米
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="that">经纬坐标1</param>
|
|
||||||
/// <param name="point">经纬坐标2</param>
|
|
||||||
/// <returns>返回距离(单位:米)</returns>
|
|
||||||
public static double Distance(this Point that, Point 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 object GetEnum<T>(this IDataReader dr, int index) {
|
|
||||||
string value = dr.GetString(index);
|
|
||||||
Type t = typeof(T);
|
|
||||||
foreach (var f in t.GetFields())
|
|
||||||
if (f.GetCustomAttribute<DescriptionAttribute>()?.Description == value || f.Name == value) return Enum.Parse(t, f.Name, true);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ToDescriptionOrString(this Enum item) {
|
|
||||||
string name = item.ToString();
|
|
||||||
var desc = item.GetType().GetField(name)?.GetCustomAttribute<DescriptionAttribute>();
|
|
||||||
return desc?.Description ?? name;
|
|
||||||
}
|
|
||||||
public static long ToInt64(this Enum item) {
|
|
||||||
return Convert.ToInt64(item);
|
|
||||||
}
|
|
||||||
public static IEnumerable<T> ToSet<T>(this long value) {
|
|
||||||
List<T> ret = new List<T>();
|
|
||||||
if (value == 0) return ret;
|
|
||||||
Type t = typeof(T);
|
|
||||||
foreach (FieldInfo f in t.GetFields()) {
|
|
||||||
if (f.FieldType != t) continue;
|
|
||||||
object o = Enum.Parse(t, f.Name, true);
|
|
||||||
long v = (long)o;
|
|
||||||
if ((value & v) == v) ret.Add((T)o);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -85,7 +85,7 @@ namespace FreeSql.MySql {
|
|||||||
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
||||||
var database = conn.Value.Database;
|
var database = conn.Value.Database;
|
||||||
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
||||||
if (string.Compare(database, db) != 0) try { conn.Value.ChangeDatabase(db); } catch { }
|
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db);
|
||||||
try {
|
try {
|
||||||
using (var cmd = conn.Value.CreateCommand()) {
|
using (var cmd = conn.Value.CreateCommand()) {
|
||||||
cmd.CommandText = sql;
|
cmd.CommandText = sql;
|
||||||
@ -107,16 +107,16 @@ namespace FreeSql.MySql {
|
|||||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||||
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
|
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
|
||||||
|
|
||||||
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $"select 1 from pg_database where datname='{tbname[0]}'") == null) //创建数据库
|
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, " select 1 from pg_database where datname={0}".FormatMySql(tbname[0])) == null) //创建数据库
|
||||||
sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" default charset utf8 COLLATE utf8_general_ci;\r\n");
|
sb.Append($"CREATE DATABASE IF NOT EXISTS ").Append(_commonUtils.QuoteSqlName(tbname[0])).Append(" default charset utf8 COLLATE utf8_general_ci;\r\n");
|
||||||
|
|
||||||
var sbalter = new StringBuilder();
|
var sbalter = new StringBuilder();
|
||||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||||
if (ExecuteScalar(tbname[0], "SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tbname)) == null) { //表不存在
|
if (ExecuteScalar(tbname[0], " SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tbname)) == null) { //表不存在
|
||||||
if (tboldname != null) {
|
if (tboldname != null) {
|
||||||
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $"select 1 from information_schema.schemata where schema_name='{tboldname[0]}'") == null ||
|
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, " select 1 from information_schema.schemata where schema_name={0}".FormatMySql(tboldname[0])) == null ||
|
||||||
ExecuteScalar(tboldname[0], "SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tboldname)) == null)
|
ExecuteScalar(tboldname[0], " SELECT 1 FROM information_schema.TABLES WHERE table_schema={0} and table_name={1}".FormatMySql(tboldname)) == null)
|
||||||
//数据库或模式或表不存在
|
//数据库或表不存在
|
||||||
tboldname = null;
|
tboldname = null;
|
||||||
}
|
}
|
||||||
if (tboldname == null) {
|
if (tboldname == null) {
|
||||||
@ -149,11 +149,8 @@ namespace FreeSql.MySql {
|
|||||||
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
||||||
|
|
||||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||||
var addcols = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
|
var sql = @"
|
||||||
foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value);
|
select
|
||||||
var surplus = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
|
||||||
var dbcols = new List<DbColumnInfo>();
|
|
||||||
var sql = @"select
|
|
||||||
a.column_name,
|
a.column_name,
|
||||||
a.column_type,
|
a.column_type,
|
||||||
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
|
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
|
||||||
|
@ -116,8 +116,8 @@ namespace FreeSql.MySql {
|
|||||||
{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
|
{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(Enum), typeof(Enum), "{0}", "GetInt64") },
|
||||||
{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
|
{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(Enum), typeof(Enum), "{0}", "GetInt64") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
|
{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
|
||||||
};
|
};
|
||||||
@ -131,7 +131,7 @@ namespace FreeSql.MySql {
|
|||||||
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
||||||
|
|
||||||
public List<string> GetDatabases() {
|
public List<string> GetDatabases() {
|
||||||
var sql = @"select schema_name from information_schema.schemata where schema_name not in ('information_schema', 'mysql', 'performance_schema')";
|
var sql = @" select schema_name from information_schema.schemata where schema_name not in ('information_schema', 'mysql', 'performance_schema')";
|
||||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
||||||
}
|
}
|
||||||
@ -143,7 +143,8 @@ namespace FreeSql.MySql {
|
|||||||
|
|
||||||
if (database == null || database.Any() == false) return loc1;
|
if (database == null || database.Any() == false) return loc1;
|
||||||
var databaseIn = string.Join(",", database.Select(a => "{0}".FormatMySql(a)));
|
var databaseIn = string.Join(",", database.Select(a => "{0}".FormatMySql(a)));
|
||||||
var sql = string.Format(@"select
|
var sql = string.Format(@"
|
||||||
|
select
|
||||||
concat(a.table_schema, '.', a.table_name) 'id',
|
concat(a.table_schema, '.', a.table_name) 'id',
|
||||||
a.table_schema 'schema',
|
a.table_schema 'schema',
|
||||||
a.table_name 'table',
|
a.table_name 'table',
|
||||||
@ -180,7 +181,8 @@ where a.table_schema in ({0})", databaseIn);
|
|||||||
var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
|
var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
|
||||||
var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
|
var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
|
||||||
|
|
||||||
sql = string.Format(@"select
|
sql = string.Format(@"
|
||||||
|
select
|
||||||
concat(a.table_schema, '.', a.table_name),
|
concat(a.table_schema, '.', a.table_name),
|
||||||
a.column_name,
|
a.column_name,
|
||||||
a.data_type,
|
a.data_type,
|
||||||
@ -225,7 +227,8 @@ where a.table_schema in ({1}) and a.table_name in ({0})
|
|||||||
loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
|
loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sql = string.Format(@"select
|
sql = string.Format(@"
|
||||||
|
select
|
||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
||||||
a.column_name,
|
a.column_name,
|
||||||
concat(a.constraint_schema, '/', a.table_name, '/', a.constraint_name) 'index_id',
|
concat(a.constraint_schema, '/', a.table_name, '/', a.constraint_name) 'index_id',
|
||||||
@ -282,7 +285,8 @@ where a.constraint_schema in ({1}) and a.table_name in ({0}) and isnull(position
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sql = string.Format(@"select
|
sql = string.Format(@"
|
||||||
|
select
|
||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
||||||
a.column_name,
|
a.column_name,
|
||||||
concat(a.constraint_schema, '/', a.constraint_name) 'FKId',
|
concat(a.constraint_schema, '/', a.constraint_name) 'FKId',
|
||||||
|
@ -9,8 +9,8 @@ namespace FreeSql.MySql {
|
|||||||
|
|
||||||
class MySqlUtils : CommonUtils {
|
class MySqlUtils : CommonUtils {
|
||||||
IFreeSql _orm;
|
IFreeSql _orm;
|
||||||
public MySqlUtils(IFreeSql mysql) {
|
public MySqlUtils(IFreeSql orm) {
|
||||||
_orm = mysql;
|
_orm = orm;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
|
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
|
||||||
|
45
FreeSql/Oracle/Curd/OracleDelete.cs
Normal file
45
FreeSql/Oracle/Curd/OracleDelete.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle.Curd {
|
||||||
|
|
||||||
|
class OracleDelete<T1> : Internal.CommonProvider.DeleteProvider<T1> where T1 : class {
|
||||||
|
public OracleDelete(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
||||||
|
: base(orm, commonUtils, commonExpression, dywhere) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<T1> ExecuteDeleted() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return new List<T1>();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(sql).Append(" RETURNING ");
|
||||||
|
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
return _orm.Ado.Query<T1>(CommandType.Text, sb.ToString(), _params.ToArray());
|
||||||
|
}
|
||||||
|
async public override Task<List<T1>> ExecuteDeletedAsync() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return new List<T1>();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(sql).Append(" RETURNING ");
|
||||||
|
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
return await _orm.Ado.QueryAsync<T1>(CommandType.Text, sb.ToString(), _params.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
FreeSql/Oracle/Curd/OracleInsert.cs
Normal file
105
FreeSql/Oracle/Curd/OracleInsert.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle.Curd {
|
||||||
|
|
||||||
|
class OracleInsert<T1> : Internal.CommonProvider.InsertProvider<T1> where T1 : class {
|
||||||
|
public OracleInsert(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression)
|
||||||
|
: base(orm, commonUtils, commonExpression) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToSql() {
|
||||||
|
if (_source == null || _source.Any() == false) return null;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append("INSERT INTO ").Append(_commonUtils.QuoteSqlName(_table.DbName)).Append("(");
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values)
|
||||||
|
if (_ignore.ContainsKey(col.Attribute.Name) == false) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteSqlName(col.Attribute.Name));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
sb.Append(") VALUES");
|
||||||
|
_params = new DbParameter[colidx * _source.Count];
|
||||||
|
var didx = 0;
|
||||||
|
foreach (var d in _source) {
|
||||||
|
if (didx > 0) sb.Append(", ");
|
||||||
|
sb.Append("(");
|
||||||
|
var colidx2 = 0;
|
||||||
|
foreach (var col in _table.Columns.Values)
|
||||||
|
if (_ignore.ContainsKey(col.Attribute.Name) == false) {
|
||||||
|
if (colidx2 > 0) sb.Append(", ");
|
||||||
|
if (col.Attribute.IsIdentity) {
|
||||||
|
sb.Append(_commonUtils.QuoteSqlName($"{Utils.GetCsName(_table.DbName)}_seq_{col.Attribute.Name}")).Append(".nextval");
|
||||||
|
} else {
|
||||||
|
sb.Append(_commonUtils.QuoteWriteParamter(col.CsType, $"{_commonUtils.QuoteParamterName(col.CsName)}{didx}"));
|
||||||
|
_params[didx * colidx + colidx2] = _commonUtils.AppendParamter(null, $"{col.CsName}{didx}", col.CsType, _table.Properties.TryGetValue(col.CsName, out var tryp) ? tryp.GetValue(d) : null);
|
||||||
|
}
|
||||||
|
++colidx2;
|
||||||
|
}
|
||||||
|
sb.Append(")");
|
||||||
|
++didx;
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override long ExecuteIdentity() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return 0;
|
||||||
|
|
||||||
|
var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity);
|
||||||
|
if (identCols.Any() == false) {
|
||||||
|
_orm.Ado.ExecuteNonQuery(CommandType.Text, sql, _params);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0;
|
||||||
|
}
|
||||||
|
async public override Task<long> ExecuteIdentityAsync() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return 0;
|
||||||
|
|
||||||
|
var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity);
|
||||||
|
if (identCols.Any() == false) {
|
||||||
|
await _orm.Ado.ExecuteNonQueryAsync(CommandType.Text, sql, _params);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<T1> ExecuteInserted() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return new List<T1>();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(sql).Append(" RETURNING ");
|
||||||
|
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
return _orm.Ado.Query<T1>(CommandType.Text, sb.ToString(), _params);
|
||||||
|
}
|
||||||
|
async public override Task<List<T1>> ExecuteInsertedAsync() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return new List<T1>();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(sql).Append(" RETURNING ");
|
||||||
|
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
return await _orm.Ado.QueryAsync<T1>(CommandType.Text, sb.ToString(), _params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
126
FreeSql/Oracle/Curd/OracleSelect.cs
Normal file
126
FreeSql/Oracle/Curd/OracleSelect.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle.Curd {
|
||||||
|
|
||||||
|
class OracleSelect<T1> : FreeSql.Internal.CommonProvider.Select1Provider<T1> where T1 : class {
|
||||||
|
|
||||||
|
internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List<SelectTableInfo> _tables, IFreeSql _orm) {
|
||||||
|
if (_orm.CodeFirst.IsAutoSyncStructure)
|
||||||
|
_orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray());
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(_select);
|
||||||
|
sb.Append(field);
|
||||||
|
if (string.IsNullOrEmpty(_orderby) == false && (_skip > 0 || _limit > 0)) sb.Append(", ROWNUM AS __rownum__");
|
||||||
|
sb.Append(" \r\nFROM ");
|
||||||
|
var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray();
|
||||||
|
var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray();
|
||||||
|
for (var a = 0; a < tbsfrom.Length; a++) {
|
||||||
|
sb.Append(_commonUtils.QuoteSqlName(tbsfrom[a].Table.DbName)).Append(" ").Append(tbsfrom[a].Alias);
|
||||||
|
if (tbsjoin.Length > 0) {
|
||||||
|
//如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1
|
||||||
|
for (var b = 1; b < tbsfrom.Length; b++)
|
||||||
|
sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbsfrom[b].Table.DbName)).Append(" ").Append(tbsfrom[b].Alias).Append(" ON 1 = 1");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (a < tbsfrom.Length - 1) sb.Append(", ");
|
||||||
|
}
|
||||||
|
foreach (var tb in tbsjoin) {
|
||||||
|
if (tb.Type == SelectTableInfoType.Parent) continue;
|
||||||
|
switch (tb.Type) {
|
||||||
|
case SelectTableInfoType.LeftJoin:
|
||||||
|
sb.Append(" \r\nLEFT JOIN ");
|
||||||
|
break;
|
||||||
|
case SelectTableInfoType.InnerJoin:
|
||||||
|
sb.Append(" \r\nINNER JOIN ");
|
||||||
|
break;
|
||||||
|
case SelectTableInfoType.RightJoin:
|
||||||
|
sb.Append(" \r\nRIGHT JOIN ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sb.Append(_commonUtils.QuoteSqlName(tb.Table.DbName)).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On);
|
||||||
|
}
|
||||||
|
if (_join.Length > 0) sb.Append(_join);
|
||||||
|
|
||||||
|
var sbqf = new StringBuilder();
|
||||||
|
foreach (var tb in _tables) {
|
||||||
|
if (tb.Type == SelectTableInfoType.Parent) continue;
|
||||||
|
if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false)
|
||||||
|
sbqf.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")");
|
||||||
|
}
|
||||||
|
if (_where.Length > 0) {
|
||||||
|
sb.Append(" \r\nWHERE ").Append(_where.ToString().Substring(5));
|
||||||
|
if (string.IsNullOrEmpty(_orderby) == false && (_skip > 0 || _limit > 0)) sb.Append(" AND ROWNUM < ").Append(_skip + _limit + 1);
|
||||||
|
if (sbqf.Length > 0) sb.Append(sbqf.ToString());
|
||||||
|
} else {
|
||||||
|
if (string.IsNullOrEmpty(_orderby) == false && (_skip > 0 || _limit > 0)) {
|
||||||
|
sb.Append(" \r\nWHERE ROWNUM < ").Append(_skip + _limit + 1);
|
||||||
|
if (sbqf.Length > 0) sb.Append(sbqf.Remove(0, 5));
|
||||||
|
}
|
||||||
|
else if (sbqf.Length > 0) sb.Append(" \r\nWHERE ").Append(sbqf.Remove(0, 5));
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(_groupby) == false) {
|
||||||
|
sb.Append(_groupby);
|
||||||
|
if (string.IsNullOrEmpty(_having) == false)
|
||||||
|
sb.Append(" \r\nHAVING ").Append(_having.Substring(5));
|
||||||
|
}
|
||||||
|
sb.Append(_orderby);
|
||||||
|
if (string.IsNullOrEmpty(_orderby) == false) {
|
||||||
|
if (_skip > 0 && _limit > 0) sb.Insert(0, "SELECT t.* FROM (SELECT ROWNUM AS rt.*, __rownum__ FROM (").Append(") rt WHERE ROWNUM < ").Append(_skip + _limit + 1).Append(") t WHERE t.__rownum__ > ").Append(_skip);
|
||||||
|
else if (_skip > 0 || _limit > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM < ").Append(_skip + _limit + 1);
|
||||||
|
} else if (_skip > 0)
|
||||||
|
sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE t.__rownum__ > ").Append(_skip);
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override ISelect<T1, T2, T3> From<T2, T3>(Expression<Func<ISelectFromExpression<T1>, T2, T3, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4> From<T2, T3, T4>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4, T5> From<T2, T3, T4, T5>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4, T5, T6> From<T2, T3, T4, T5, T6>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4, T5, T6, T7> From<T2, T3, T4, T5, T6, T7>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8> From<T2, T3, T4, T5, T6, T7, T8>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> From<T2, T3, T4, T5, T6, T7, T8, T9>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override ISelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> From<T2, T3, T4, T5, T6, T7, T8, T9, T10>(Expression<Func<ISelectFromExpression<T1>, T2, T3, T4, T5, T6, T7, T8, T9, T10, ISelectFromExpression<T1>>> exp) { this.InternalFrom(exp?.Body); var ret = new OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(_orm, _commonUtils, _commonExpression, null); OracleSelect<T1>.CopyData(this, ret); return ret; }
|
||||||
|
public override string ToSql(string field = null) => ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3> : FreeSql.Internal.CommonProvider.Select3Provider<T1, T2, T3> where T1 : class where T2 : class where T3 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4> : FreeSql.Internal.CommonProvider.Select4Provider<T1, T2, T3, T4> where T1 : class where T2 : class where T3 : class where T4 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4, T5> : FreeSql.Internal.CommonProvider.Select5Provider<T1, T2, T3, T4, T5> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4, T5, T6> : FreeSql.Internal.CommonProvider.Select6Provider<T1, T2, T3, T4, T5, T6> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4, T5, T6, T7> : FreeSql.Internal.CommonProvider.Select7Provider<T1, T2, T3, T4, T5, T6, T7> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8> : FreeSql.Internal.CommonProvider.Select8Provider<T1, T2, T3, T4, T5, T6, T7, T8> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9> : FreeSql.Internal.CommonProvider.Select9Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
class OracleSelect<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> : FreeSql.Internal.CommonProvider.Select10Provider<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> where T1 : class where T2 : class where T3 : class where T4 : class where T5 : class where T6 : class where T7 : class where T8 : class where T9 : class where T10 : class {
|
||||||
|
public OracleSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { }
|
||||||
|
public override string ToSql(string field = null) => OracleSelect<T1>.ToSqlStatic(_commonUtils, _select, field ?? this.GetAllField().field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm);
|
||||||
|
}
|
||||||
|
}
|
78
FreeSql/Oracle/Curd/OracleUpdate.cs
Normal file
78
FreeSql/Oracle/Curd/OracleUpdate.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle.Curd {
|
||||||
|
|
||||||
|
class OracleUpdate<T1> : Internal.CommonProvider.UpdateProvider<T1> where T1 : class {
|
||||||
|
|
||||||
|
public OracleUpdate(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere)
|
||||||
|
: base(orm, commonUtils, commonExpression, dywhere) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<T1> ExecuteUpdated() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return new List<T1>();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(sql).Append(" RETURNING ");
|
||||||
|
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
return _orm.Ado.Query<T1>(CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
|
||||||
|
}
|
||||||
|
async public override Task<List<T1>> ExecuteUpdatedAsync() {
|
||||||
|
var sql = this.ToSql();
|
||||||
|
if (string.IsNullOrEmpty(sql)) return new List<T1>();
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.Append(sql).Append(" RETURNING ");
|
||||||
|
|
||||||
|
var colidx = 0;
|
||||||
|
foreach (var col in _table.Columns.Values) {
|
||||||
|
if (colidx > 0) sb.Append(", ");
|
||||||
|
sb.Append(_commonUtils.QuoteReadColumn(col.CsType, _commonUtils.QuoteSqlName(col.Attribute.Name))).Append(" as ").Append(_commonUtils.QuoteSqlName(col.CsName));
|
||||||
|
++colidx;
|
||||||
|
}
|
||||||
|
return await _orm.Ado.QueryAsync<T1>(CommandType.Text, sb.ToString(), _params.Concat(_paramsSource).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ToSqlCase(StringBuilder caseWhen, ColumnInfo[] primarys) {
|
||||||
|
if (_table.Primarys.Length == 1) {
|
||||||
|
caseWhen.Append(_commonUtils.QuoteReadColumn(_table.Primarys.First().CsType, _commonUtils.QuoteSqlName(_table.Primarys.First().Attribute.Name)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
caseWhen.Append("(");
|
||||||
|
var pkidx = 0;
|
||||||
|
foreach (var pk in _table.Primarys) {
|
||||||
|
if (pkidx > 0) caseWhen.Append(" || ");
|
||||||
|
caseWhen.Append(_commonUtils.QuoteReadColumn(pk.CsType, _commonUtils.QuoteSqlName(pk.Attribute.Name)));
|
||||||
|
++pkidx;
|
||||||
|
}
|
||||||
|
caseWhen.Append(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ToSqlWhen(StringBuilder sb, ColumnInfo[] primarys, object d) {
|
||||||
|
if (_table.Primarys.Length == 1) {
|
||||||
|
sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(_table.Primarys.First().CsName, out var tryp2) ? tryp2.GetValue(d) : null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sb.Append("(");
|
||||||
|
var pkidx = 0;
|
||||||
|
foreach (var pk in _table.Primarys) {
|
||||||
|
if (pkidx > 0) sb.Append(" || ");
|
||||||
|
sb.Append(_commonUtils.FormatSql("{0}", _table.Properties.TryGetValue(pk.CsName, out var tryp2) ? tryp2.GetValue(d) : null));
|
||||||
|
++pkidx;
|
||||||
|
}
|
||||||
|
sb.Append(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
FreeSql/Oracle/OracleAdo/OracleAdo.cs
Normal file
65
FreeSql/Oracle/OracleAdo/OracleAdo.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Oracle.ManagedDataAccess.Client;
|
||||||
|
using SafeObjectPool;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
class OracleAdo : FreeSql.Internal.CommonProvider.AdoProvider {
|
||||||
|
CommonUtils _util;
|
||||||
|
|
||||||
|
public OracleAdo() : base(null, null) { }
|
||||||
|
public OracleAdo(CommonUtils util, ICache cache, ILogger log, string masterConnectionString, string[] slaveConnectionStrings) : base(cache, log) {
|
||||||
|
this._util = util;
|
||||||
|
MasterPool = new OracleConnectionPool("主库", masterConnectionString, null, null);
|
||||||
|
if (slaveConnectionStrings != null) {
|
||||||
|
foreach (var slaveConnectionString in slaveConnectionStrings) {
|
||||||
|
var slavePool = new OracleConnectionPool($"从库{SlavePools.Count + 1}", slaveConnectionString, () => Interlocked.Decrement(ref slaveUnavailables), () => Interlocked.Increment(ref slaveUnavailables));
|
||||||
|
SlavePools.Add(slavePool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static DateTime dt1970 = new DateTime(1970, 1, 1);
|
||||||
|
public override object AddslashesProcessParam(object param) {
|
||||||
|
if (param == null) return "NULL";
|
||||||
|
if (param is bool || param is bool?)
|
||||||
|
return (bool)param ? 1 : 0;
|
||||||
|
else if (param is string)
|
||||||
|
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
|
||||||
|
else if (param is Enum)
|
||||||
|
return ((Enum)param).ToInt64();
|
||||||
|
else if (decimal.TryParse(string.Concat(param), out var trydec))
|
||||||
|
return param;
|
||||||
|
else if (param is DateTime)
|
||||||
|
return string.Concat("'", ((DateTime)param).ToString("yyyy-MM-dd HH:mm:ss"), "'");
|
||||||
|
else if (param is DateTime?)
|
||||||
|
return string.Concat("'", (param as DateTime?).Value.ToString("yyyy-MM-dd HH:mm:ss"), "'");
|
||||||
|
else if (param is TimeSpan)
|
||||||
|
return ((TimeSpan)param).Ticks / 10;
|
||||||
|
else if (param is TimeSpan?)
|
||||||
|
return (param as TimeSpan?).Value.Ticks / 10;
|
||||||
|
else if (param is IEnumerable) {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var ie = param as IEnumerable;
|
||||||
|
foreach (var z in ie) sb.Append(",").Append(AddslashesProcessParam(z));
|
||||||
|
return sb.Length == 0 ? "(NULL)" : sb.Remove(0, 1).Insert(0, "(").Append(")").ToString();
|
||||||
|
}
|
||||||
|
return string.Concat("'", param.ToString().Replace("'", "''"), "'");
|
||||||
|
//if (param is string) return string.Concat('N', nparms[a]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DbCommand CreateCommand() {
|
||||||
|
return new OracleCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ReturnConnection(ObjectPool<DbConnection> pool, Object<DbConnection> conn, Exception ex) {
|
||||||
|
(pool as OracleConnectionPool).Return(conn, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DbParameter[] GetDbParamtersByObject(string sql, object obj) => _util.GetDbParamtersByObject(sql, obj);
|
||||||
|
}
|
||||||
|
}
|
153
FreeSql/Oracle/OracleAdo/OracleConnectionPool.cs
Normal file
153
FreeSql/Oracle/OracleAdo/OracleConnectionPool.cs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
using Oracle.ManagedDataAccess.Client;
|
||||||
|
using SafeObjectPool;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
|
||||||
|
public class OracleConnectionPool : ObjectPool<DbConnection> {
|
||||||
|
|
||||||
|
internal Action availableHandler;
|
||||||
|
internal Action unavailableHandler;
|
||||||
|
|
||||||
|
public OracleConnectionPool(string name, string connectionString, Action availableHandler, Action unavailableHandler) : base(null) {
|
||||||
|
var policy = new OracleConnectionPoolPolicy {
|
||||||
|
_pool = this,
|
||||||
|
Name = name
|
||||||
|
};
|
||||||
|
this.Policy = policy;
|
||||||
|
policy.ConnectionString = connectionString;
|
||||||
|
|
||||||
|
this.availableHandler = availableHandler;
|
||||||
|
this.unavailableHandler = unavailableHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Return(Object<DbConnection> obj, Exception exception, bool isRecreate = false) {
|
||||||
|
if (exception != null && exception is OracleException) {
|
||||||
|
|
||||||
|
if (exception is System.IO.IOException) {
|
||||||
|
|
||||||
|
base.SetUnavailable(exception);
|
||||||
|
|
||||||
|
} else if (obj.Value.Ping() == false) {
|
||||||
|
|
||||||
|
base.SetUnavailable(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Return(obj, isRecreate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OracleConnectionPoolPolicy : IPolicy<DbConnection> {
|
||||||
|
|
||||||
|
internal OracleConnectionPool _pool;
|
||||||
|
public string Name { get; set; } = "Oracle Connection 对象池";
|
||||||
|
public int PoolSize { get; set; } = 100;
|
||||||
|
public TimeSpan SyncGetTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
||||||
|
public int AsyncGetCapacity { get; set; } = 10000;
|
||||||
|
public bool IsThrowGetTimeoutException { get; set; } = true;
|
||||||
|
public int CheckAvailableInterval { get; set; } = 5;
|
||||||
|
|
||||||
|
private string _connectionString;
|
||||||
|
public string ConnectionString {
|
||||||
|
get => _connectionString;
|
||||||
|
set {
|
||||||
|
_connectionString = value ?? "";
|
||||||
|
Match m = Regex.Match(_connectionString, @"Max\s*pool\s*size\s*=\s*(\d+)", RegexOptions.IgnoreCase);
|
||||||
|
if (m.Success == false || int.TryParse(m.Groups[1].Value, out var poolsize) == false || poolsize <= 0) poolsize = 100;
|
||||||
|
PoolSize = poolsize;
|
||||||
|
|
||||||
|
var initConns = new Object<DbConnection>[poolsize];
|
||||||
|
for (var a = 0; a < poolsize; a++) try { initConns[a] = _pool.Get(); } catch { }
|
||||||
|
foreach (var conn in initConns) _pool.Return(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool OnCheckAvailable(Object<DbConnection> obj) {
|
||||||
|
if (obj.Value.State == ConnectionState.Closed) obj.Value.Open();
|
||||||
|
var cmd = obj.Value.CreateCommand();
|
||||||
|
cmd.CommandText = "select 1";
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbConnection OnCreate() {
|
||||||
|
var conn = new OracleConnection(_connectionString);
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnDestroy(DbConnection obj) {
|
||||||
|
if (obj.State != ConnectionState.Closed) obj.Close();
|
||||||
|
obj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGet(Object<DbConnection> obj) {
|
||||||
|
|
||||||
|
if (_pool.IsAvailable) {
|
||||||
|
|
||||||
|
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
obj.Value.Open();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
if (_pool.SetUnavailable(ex) == true)
|
||||||
|
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async public Task OnGetAsync(Object<DbConnection> obj) {
|
||||||
|
|
||||||
|
if (_pool.IsAvailable) {
|
||||||
|
|
||||||
|
if (obj.Value.State != ConnectionState.Open || DateTime.Now.Subtract(obj.LastReturnTime).TotalSeconds > 60 && obj.Value.Ping() == false) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
await obj.Value.OpenAsync();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
if (_pool.SetUnavailable(ex) == true)
|
||||||
|
throw new Exception($"【{this.Name}】状态不可用,等待后台检查程序恢复方可使用。{ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnGetTimeout() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReturn(Object<DbConnection> obj) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnAvailable() {
|
||||||
|
_pool.availableHandler?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnUnavailable() {
|
||||||
|
_pool.unavailableHandler?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DbConnectionExtensions {
|
||||||
|
|
||||||
|
public static bool Ping(this DbConnection that) {
|
||||||
|
try {
|
||||||
|
var cmd = that.CreateCommand();
|
||||||
|
cmd.CommandText = "select 1";
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
try { that.Close(); } catch { }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
297
FreeSql/Oracle/OracleCodeFirst.cs
Normal file
297
FreeSql/Oracle/OracleCodeFirst.cs
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
using FreeSql.DatabaseModel;
|
||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using Oracle.ManagedDataAccess.Client;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
|
||||||
|
class OracleCodeFirst : ICodeFirst {
|
||||||
|
IFreeSql _orm;
|
||||||
|
protected CommonUtils _commonUtils;
|
||||||
|
protected CommonExpression _commonExpression;
|
||||||
|
public OracleCodeFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
|
||||||
|
_orm = orm;
|
||||||
|
_commonUtils = commonUtils;
|
||||||
|
_commonExpression = commonExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAutoSyncStructure { get; set; } = true;
|
||||||
|
public bool IsSyncStructureToLower { get; set; } = false;
|
||||||
|
|
||||||
|
static object _dicCsToDbLock = new object();
|
||||||
|
static Dictionary<string, (OracleDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)> _dicCsToDb = new Dictionary<string, (OracleDbType type, string dbtype, string dbtypeFull, bool? isUnsigned, bool? isnullable, object defaultValue)>() {
|
||||||
|
{ typeof(bool).FullName, (OracleDbType.Boolean, "number","number(1) NOT NULL", null, false, false) },{ typeof(bool?).FullName, (OracleDbType.Boolean, "number","number(1) NULL", null, true, null) },
|
||||||
|
|
||||||
|
{ typeof(sbyte).FullName, (OracleDbType.Byte, "number", "number(4) NOT NULL", false, false, 0) },{ typeof(sbyte?).FullName, (OracleDbType.Byte, "number", "number(4) NULL", false, true, null) },
|
||||||
|
{ typeof(short).FullName, (OracleDbType.Int16, "number","number(4) NOT NULL", false, false, 0) },{ typeof(short?).FullName, (OracleDbType.Int16, "number", "number(4) NULL", false, true, null) },
|
||||||
|
{ typeof(int).FullName, (OracleDbType.Int32, "number", "number(8) NOT NULL", false, false, 0) },{ typeof(int?).FullName, (OracleDbType.Int32, "number", "number(8) NULL", false, true, null) },
|
||||||
|
{ typeof(long).FullName, (OracleDbType.Int64, "number","number(16) NOT NULL", false, false, 0) },{ typeof(long?).FullName, (OracleDbType.Int64, "bigint","bigint(16) NULL", false, true, null) },
|
||||||
|
|
||||||
|
{ typeof(byte).FullName, (OracleDbType.Byte, "number","number(2) NOT NULL", true, false, 0) },{ typeof(byte?).FullName, (OracleDbType.Byte, "number","number(2) NULL", true, true, null) },
|
||||||
|
{ typeof(ushort).FullName, (OracleDbType.Int16, "number","number(8) NOT NULL", true, false, 0) },{ typeof(ushort?).FullName, (OracleDbType.Int16, "number", "number(8) NULL", true, true, null) },
|
||||||
|
{ typeof(uint).FullName, (OracleDbType.Int32, "number", "number(16) NOT NULL", true, false, 0) },{ typeof(uint?).FullName, (OracleDbType.Int32, "number", "number(16) NULL", true, true, null) },
|
||||||
|
{ typeof(ulong).FullName, (OracleDbType.Int64, "number", "number(32) NOT NULL", true, false, 0) },{ typeof(ulong?).FullName, (OracleDbType.Int64, "number", "number(32) NULL", true, true, null) },
|
||||||
|
|
||||||
|
{ typeof(double).FullName, (OracleDbType.Double, "double", "double(126) NOT NULL", false, false, 0) },{ typeof(double?).FullName, (OracleDbType.Double, "double", "double(126) NULL", false, true, null) },
|
||||||
|
{ typeof(float).FullName, (OracleDbType.Single, "float","float(63) NOT NULL", false, false, 0) },{ typeof(float?).FullName, (OracleDbType.Single, "float","float(63) NULL", false, true, null) },
|
||||||
|
{ typeof(decimal).FullName, (OracleDbType.Decimal, "number", "number(10,2) NOT NULL", false, false, 0) },{ typeof(decimal?).FullName, (OracleDbType.Decimal, "number", "number(10,2) NULL", false, true, null) },
|
||||||
|
|
||||||
|
{ typeof(TimeSpan).FullName, (OracleDbType.IntervalDS, "interval day to second","interval day(2) to second(6) NOT NULL", false, false, 0) },{ typeof(TimeSpan?).FullName, (OracleDbType.IntervalDS, "interval day to second", "interval day(2) to second(6) NULL",false, true, null) },
|
||||||
|
{ typeof(DateTime).FullName, (OracleDbType.TimeStamp, "timestamp", "timestamp(6) NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (OracleDbType.TimeStamp, "timestamp", "timestamp(6) NULL", false, true, null) },
|
||||||
|
{ typeof(DateTimeOffset).FullName, (OracleDbType.TimeStampLTZ, "timestamp with local time zone", "timestamp(6) with local time zone NOT NULL", false, false, new DateTime(1970,1,1)) },{ typeof(DateTime?).FullName, (OracleDbType.TimeStamp, "timestamp with local time zone", "timestamp(6) with local time zone NULL", false, true, null) },
|
||||||
|
|
||||||
|
{ typeof(byte[]).FullName, (OracleDbType.Blob, "blog", "blog(4000) NULL", false, null, new byte[0]) },
|
||||||
|
{ typeof(string).FullName, (OracleDbType.NVarchar2, "nvarchar2", "nvarchar2(255) NULL", false, null, "") },
|
||||||
|
|
||||||
|
{ typeof(Guid).FullName, (OracleDbType.Char, "char", "char(36 BYTE)", false, false, Guid.Empty) },{ typeof(Guid?).FullName, (OracleDbType.Char, "char", "char(36 BYTE) NULL", false, true, null) },
|
||||||
|
};
|
||||||
|
|
||||||
|
public (int type, string dbtype, string dbtypeFull, bool? isnullable, object defaultValue)? GetDbInfo(Type type) {
|
||||||
|
if (_dicCsToDb.TryGetValue(type.FullName, out var trydc)) return new (int, string, string, bool?, object)?(((int)trydc.type, trydc.dbtype, trydc.dbtypeFull, trydc.isnullable, trydc.defaultValue));
|
||||||
|
if (type.IsArray) return null;
|
||||||
|
var enumType = type.IsEnum ? type : null;
|
||||||
|
if (enumType == null && type.FullName.StartsWith("System.Nullable`1[") && type.GenericTypeArguments.Length == 1 && type.GenericTypeArguments.First().IsEnum) enumType = type.GenericTypeArguments.First();
|
||||||
|
if (enumType != null) {
|
||||||
|
var newItem = enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any() ?
|
||||||
|
(OracleDbType.Int32, "number", $"number(16){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0)) :
|
||||||
|
(OracleDbType.Int64, "number", $"number(32){(type.IsEnum ? " NOT NULL" : "")}", false, type.IsEnum ? false : true, Enum.GetValues(enumType).GetValue(0));
|
||||||
|
if (_dicCsToDb.ContainsKey(type.FullName) == false) {
|
||||||
|
lock (_dicCsToDbLock) {
|
||||||
|
if (_dicCsToDb.ContainsKey(type.FullName) == false)
|
||||||
|
_dicCsToDb.Add(type.FullName, newItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ((int)newItem.Item1, newItem.Item2, newItem.Item3, newItem.Item5, newItem.Item6);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetComparisonDDLStatements<TEntity>() => this.GetComparisonDDLStatements(typeof(TEntity));
|
||||||
|
public string GetComparisonDDLStatements(params Type[] entityTypes) {
|
||||||
|
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
||||||
|
var seqcols = new List<(ColumnInfo, string[], bool)>(); //序列
|
||||||
|
|
||||||
|
var database = conn.Value.Database;
|
||||||
|
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
||||||
|
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db);
|
||||||
|
try {
|
||||||
|
using (var cmd = conn.Value.CreateCommand()) {
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.CommandType = CommandType.Text;
|
||||||
|
return cmd.ExecuteScalar();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(database);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
try {
|
||||||
|
foreach (var entityType in entityTypes) {
|
||||||
|
if (sb.Length > 0) sb.Append("\r\n");
|
||||||
|
var tb = _commonUtils.GetTableByEntity(entityType);
|
||||||
|
var tbname = tb.DbName.Split(new[] { '.' }, 2);
|
||||||
|
if (tbname?.Length == 1) tbname = new[] { database, tbname[0] };
|
||||||
|
|
||||||
|
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||||
|
if (tboldname?.Length == 1) tboldname = new[] { database, tboldname[0] };
|
||||||
|
|
||||||
|
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, " select 1 from sys.dba_users where username={0}".FormatOracleSQL(tbname[0])) == null) //创建数据库
|
||||||
|
throw new NotImplementedException($"Oracle CodeFirst 不支持代码创建 tablespace 与 schemas {tbname[0]}");
|
||||||
|
|
||||||
|
var sbalter = new StringBuilder();
|
||||||
|
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||||
|
if (ExecuteScalar(tbname[0], " select 1 from all_tab_comments where owner={0} and table_name={1}".FormatOracleSQL(tbname)) == null) { //表不存在
|
||||||
|
if (tboldname != null) {
|
||||||
|
if (ExecuteScalar(tboldname[0], " select 1 from all_tab_comments where owner={0} and table_name={1}".FormatOracleSQL(tboldname)) == null)
|
||||||
|
//模式或表不存在
|
||||||
|
tboldname = null;
|
||||||
|
}
|
||||||
|
if (tboldname == null) {
|
||||||
|
//创建表
|
||||||
|
sb.Append("CREATE TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" (");
|
||||||
|
foreach (var tbcol in tb.Columns.Values) {
|
||||||
|
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
|
||||||
|
if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true));
|
||||||
|
}
|
||||||
|
if (tb.Primarys.Any() == false)
|
||||||
|
sb.Remove(sb.Length - 1, 1);
|
||||||
|
else {
|
||||||
|
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk PRIMARY KEY (");
|
||||||
|
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||||
|
sb.Remove(sb.Length - 2, 2).Append(")");
|
||||||
|
}
|
||||||
|
sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n;\r\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//如果新表,旧表在一个模式下,直接修改表名
|
||||||
|
if (string.Compare(tbname[0], tboldname[0], true) == 0)
|
||||||
|
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
|
||||||
|
else {
|
||||||
|
//如果新表,旧表不在一起,创建新表,导入数据,删除旧表
|
||||||
|
istmpatler = true;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
||||||
|
|
||||||
|
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||||
|
var addcols = new Dictionary<string, ColumnInfo>(StringComparer.CurrentCultureIgnoreCase);
|
||||||
|
foreach (var tbcol in tb.Columns) addcols.Add(tbcol.Value.Attribute.Name, tbcol.Value);
|
||||||
|
var surplus = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||||
|
var dbcols = new List<DbColumnInfo>();
|
||||||
|
var sql = $@"
|
||||||
|
select
|
||||||
|
column_name,
|
||||||
|
data_type,
|
||||||
|
data_length,
|
||||||
|
data_precision,
|
||||||
|
data_scale,
|
||||||
|
char_used,
|
||||||
|
case when nullable = 'Y' then 1 else 0 end,
|
||||||
|
nvl((select 1 from user_sequences where sequence_name='{Utils.GetCsName(string.Join(".", tboldname ?? tbname))}_seq_'||all_tab_columns.column_name), 0)
|
||||||
|
from all_tab_columns
|
||||||
|
where owner={{0}} and table_name={{1}}".FormatOracleSQL(tboldname ?? tbname);
|
||||||
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => {
|
||||||
|
var sqlType = string.Concat(a[1]);
|
||||||
|
var data_length = long.Parse(string.Concat(a[2]));
|
||||||
|
long.TryParse(string.Concat(a[3]), out var data_precision);
|
||||||
|
long.TryParse(string.Concat(a[4]), out var data_scale);
|
||||||
|
var char_used = string.Concat(a[5]);
|
||||||
|
if (Regex.IsMatch(sqlType, @"INTERVAL DAY\(\d+\) TO SECOND\(\d+\)", RegexOptions.IgnoreCase)) {
|
||||||
|
} else if (Regex.IsMatch(sqlType, @"INTERVAL YEAR\(\d+\) TO MONTH", RegexOptions.IgnoreCase)) {
|
||||||
|
} else if (sqlType.StartsWith("TIMESTAMP", StringComparison.CurrentCultureIgnoreCase)) {
|
||||||
|
} else if (char_used.ToLower() == "c") {
|
||||||
|
sqlType += $"({data_length} CHAR)";
|
||||||
|
} else if (char_used.ToLower() == "b") {
|
||||||
|
sqlType += $"({data_length} BYTE)";
|
||||||
|
} else if (sqlType.ToLower() == "float") {
|
||||||
|
sqlType += $"({data_precision})";
|
||||||
|
} else if (data_precision > 0 && data_scale > 0) {
|
||||||
|
sqlType += $"({data_precision},{data_scale})";
|
||||||
|
} else {
|
||||||
|
sqlType += $"({data_length})";
|
||||||
|
}
|
||||||
|
return new {
|
||||||
|
column = string.Concat(a[0]),
|
||||||
|
sqlType,
|
||||||
|
is_nullable = string.Concat(a[6]) == "1",
|
||||||
|
is_identity = string.Concat(a[7]) == "1"
|
||||||
|
};
|
||||||
|
}, StringComparer.CurrentCultureIgnoreCase);
|
||||||
|
|
||||||
|
if (istmpatler == false) {
|
||||||
|
foreach (var tbcol in tb.Columns.Values) {
|
||||||
|
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||||
|
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||||
|
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false)
|
||||||
|
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY (").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.DbType).Append(");\r\n");
|
||||||
|
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) {
|
||||||
|
if (tbcol.Attribute.IsNullable == false)
|
||||||
|
sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(_commonUtils.FormatSql(" = {0}", tbcol.Attribute.DbDefautValue)).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" IS NULL;\r\n");
|
||||||
|
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable ? "" : "NOT").Append(" NULL;\r\n");
|
||||||
|
}
|
||||||
|
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
|
||||||
|
seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity));
|
||||||
|
if (tbstructcol.column == tbcol.Attribute.OldName)
|
||||||
|
//修改列名
|
||||||
|
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.OldName)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//添加列
|
||||||
|
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n");
|
||||||
|
sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(_commonUtils.FormatSql(" = {0};\r\n", tbcol.Attribute.DbDefautValue));
|
||||||
|
if (tbcol.Attribute.IsNullable == false) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" MODIFY ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" NOT NULL;\r\n");
|
||||||
|
if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, tbcol.Attribute.IsIdentity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (istmpatler == false) {
|
||||||
|
sb.Append(sbalter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
|
||||||
|
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}");
|
||||||
|
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FreeSqlTmp_{tbname[1]}");
|
||||||
|
//创建临时表
|
||||||
|
sb.Append("CREATE TABLE ").Append(tmptablename).Append(" (");
|
||||||
|
foreach (var tbcol in tb.Columns.Values) {
|
||||||
|
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
|
||||||
|
if (tbcol.Attribute.IsIdentity) seqcols.Add((tbcol, tbname, true));
|
||||||
|
}
|
||||||
|
if (tb.Primarys.Any() == false)
|
||||||
|
sb.Remove(sb.Length - 1, 1);
|
||||||
|
else {
|
||||||
|
sb.Append(" \r\n CONSTRAINT ").Append(tbname[0]).Append("_").Append(tbname[1]).Append("_pk PRIMARY KEY (");
|
||||||
|
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||||
|
sb.Remove(sb.Length - 2, 2).Append(")");
|
||||||
|
}
|
||||||
|
sb.Append("\r\n) LOGGING \r\nNOCOMPRESS \r\nNOCACHE\r\n;\r\n");
|
||||||
|
sb.Append("INSERT INTO ").Append(tmptablename).Append(" (");
|
||||||
|
foreach (var tbcol in tb.Columns.Values)
|
||||||
|
sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
|
||||||
|
sb.Remove(sb.Length - 2, 2).Append(")\r\nSELECT ");
|
||||||
|
foreach (var tbcol in tb.Columns.Values) {
|
||||||
|
var insertvalue = "NULL";
|
||||||
|
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
|
||||||
|
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) {
|
||||||
|
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
|
||||||
|
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) {
|
||||||
|
//insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})";
|
||||||
|
}
|
||||||
|
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
|
||||||
|
insertvalue = $"nvl({insertvalue},{_commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''")})";
|
||||||
|
} else if (tbcol.Attribute.IsNullable == false)
|
||||||
|
insertvalue = _commonUtils.FormatSql("{0}", tbcol.Attribute.DbDefautValue).Replace("'", "''");
|
||||||
|
sb.Append(insertvalue).Append(", ");
|
||||||
|
}
|
||||||
|
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n");
|
||||||
|
sb.Append("DROP TABLE ").Append(tablename).Append(";\r\n");
|
||||||
|
sb.Append("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(";\r\n");
|
||||||
|
}
|
||||||
|
foreach (var seqcol in seqcols) {
|
||||||
|
var tbname = seqcol.Item2;
|
||||||
|
var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_seq_{seqcol.Item1.Attribute.Name}");
|
||||||
|
var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
|
||||||
|
var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name);
|
||||||
|
sb.Append("DROP SEQUENCE ").Append(seqname).Append(";\r\n");
|
||||||
|
if (seqcol.Item3) {
|
||||||
|
var startWith = _orm.Ado.ExecuteScalar(CommandType.Text, $" select nvl({colname2},0) from {tbname2}");
|
||||||
|
sb.Append("CREATE SEQUENCE ").Append(seqname).Append(" start with ").Append(startWith).Append(";\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.Length == 0 ? null : sb.ToString();
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
conn.Value.ChangeDatabase(database);
|
||||||
|
_orm.Ado.MasterPool.Return(conn);
|
||||||
|
} catch {
|
||||||
|
_orm.Ado.MasterPool.Return(conn, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConcurrentDictionary<string, bool> dicSyced = new ConcurrentDictionary<string, bool>();
|
||||||
|
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
|
||||||
|
public bool SyncStructure(params Type[] entityTypes) {
|
||||||
|
if (entityTypes == null) return true;
|
||||||
|
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
|
||||||
|
if (syncTypes.Any() == false) return true;
|
||||||
|
var ddl = this.GetComparisonDDLStatements(syncTypes);
|
||||||
|
if (string.IsNullOrEmpty(ddl)) {
|
||||||
|
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var affrows = _orm.Ado.ExecuteNonQuery(CommandType.Text, ddl);
|
||||||
|
foreach (var syncType in syncTypes) dicSyced.TryAdd(syncType.FullName, true);
|
||||||
|
return affrows > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
385
FreeSql/Oracle/OracleDbFirst.cs
Normal file
385
FreeSql/Oracle/OracleDbFirst.cs
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
using FreeSql.DatabaseModel;
|
||||||
|
using FreeSql.Internal;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
class OracleDbFirst : IDbFirst {
|
||||||
|
IFreeSql _orm;
|
||||||
|
protected CommonUtils _commonUtils;
|
||||||
|
protected CommonExpression _commonExpression;
|
||||||
|
public OracleDbFirst(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression) {
|
||||||
|
_orm = orm;
|
||||||
|
_commonUtils = commonUtils;
|
||||||
|
_commonExpression = commonExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetDbType(DbColumnInfo column) => (int)GetMySqlDbType(column);
|
||||||
|
MySqlDbType GetMySqlDbType(DbColumnInfo column) {
|
||||||
|
var is_unsigned = column.DbTypeTextFull.ToLower().EndsWith(" unsigned");
|
||||||
|
switch (column.DbTypeText.ToLower()) {
|
||||||
|
case "bit": return MySqlDbType.Bit;
|
||||||
|
|
||||||
|
case "tinyint": return is_unsigned ? MySqlDbType.UByte : MySqlDbType.Byte;
|
||||||
|
case "smallint": return is_unsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16;
|
||||||
|
case "mediumint": return is_unsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24;
|
||||||
|
case "int": return is_unsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32;
|
||||||
|
case "bigint": return is_unsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64;
|
||||||
|
|
||||||
|
case "real":
|
||||||
|
case "double": return MySqlDbType.Double;
|
||||||
|
case "float": return MySqlDbType.Float;
|
||||||
|
case "numeric":
|
||||||
|
case "decimal": return MySqlDbType.Decimal;
|
||||||
|
|
||||||
|
case "year": return MySqlDbType.Year;
|
||||||
|
case "time": return MySqlDbType.Time;
|
||||||
|
case "date": return MySqlDbType.Date;
|
||||||
|
case "timestamp": return MySqlDbType.Timestamp;
|
||||||
|
case "datetime": return MySqlDbType.DateTime;
|
||||||
|
|
||||||
|
case "tinyblob": return MySqlDbType.TinyBlob;
|
||||||
|
case "blob": return MySqlDbType.Blob;
|
||||||
|
case "mediumblob": return MySqlDbType.MediumBlob;
|
||||||
|
case "longblob": return MySqlDbType.LongBlob;
|
||||||
|
|
||||||
|
case "binary": return MySqlDbType.Binary;
|
||||||
|
case "varbinary": return MySqlDbType.VarBinary;
|
||||||
|
|
||||||
|
case "tinytext": return MySqlDbType.TinyText;
|
||||||
|
case "text": return MySqlDbType.Text;
|
||||||
|
case "mediumtext": return MySqlDbType.MediumText;
|
||||||
|
case "longtext": return MySqlDbType.LongText;
|
||||||
|
|
||||||
|
case "char": return column.MaxLength == 36 ? MySqlDbType.Guid : MySqlDbType.String;
|
||||||
|
case "varchar": return MySqlDbType.VarChar;
|
||||||
|
|
||||||
|
case "set": return MySqlDbType.Set;
|
||||||
|
case "enum": return MySqlDbType.Enum;
|
||||||
|
|
||||||
|
case "point": return MySqlDbType.Geometry;
|
||||||
|
case "linestring": return MySqlDbType.Geometry;
|
||||||
|
case "polygon": return MySqlDbType.Geometry;
|
||||||
|
case "geometry": return MySqlDbType.Geometry;
|
||||||
|
case "multipoint": return MySqlDbType.Geometry;
|
||||||
|
case "multilinestring": return MySqlDbType.Geometry;
|
||||||
|
case "multipolygon": return MySqlDbType.Geometry;
|
||||||
|
case "geometrycollection": return MySqlDbType.Geometry;
|
||||||
|
default: return MySqlDbType.String;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
|
||||||
|
{ (int)MySqlDbType.Bit, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Byte, ("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetByte") },
|
||||||
|
{ (int)MySqlDbType.Int16, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
|
||||||
|
{ (int)MySqlDbType.Int24, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
||||||
|
{ (int)MySqlDbType.Int32, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
||||||
|
{ (int)MySqlDbType.Int64, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.UByte, ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
|
||||||
|
{ (int)MySqlDbType.UInt16, ("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt16") },
|
||||||
|
{ (int)MySqlDbType.UInt24, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
|
||||||
|
{ (int)MySqlDbType.UInt32, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
|
||||||
|
{ (int)MySqlDbType.UInt64, ("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetInt64") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
|
||||||
|
{ (int)MySqlDbType.Float, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
|
||||||
|
{ (int)MySqlDbType.Decimal, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Year, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
||||||
|
{ (int)MySqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
|
||||||
|
{ (int)MySqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
||||||
|
{ (int)MySqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
||||||
|
{ (int)MySqlDbType.DateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.TinyBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
|
{ (int)MySqlDbType.Blob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
|
{ (int)MySqlDbType.MediumBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
|
{ (int)MySqlDbType.LongBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Binary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
|
{ (int)MySqlDbType.VarBinary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.TinyText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
{ (int)MySqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
{ (int)MySqlDbType.MediumText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
{ (int)MySqlDbType.LongText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Guid, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid?", typeof(Guid), typeof(Guid?), "{0}", "GetString") },
|
||||||
|
{ (int)MySqlDbType.String, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
|
||||||
|
{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
|
||||||
|
|
||||||
|
{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
|
||||||
|
};
|
||||||
|
|
||||||
|
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
|
||||||
|
public string GetCsParse(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csParse : null;
|
||||||
|
public string GetCsStringify(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csStringify : null;
|
||||||
|
public string GetCsType(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csType : trydc.csType.Replace("?", "")) : null;
|
||||||
|
public Type GetCsTypeInfo(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeInfo : null;
|
||||||
|
public string GetCsTypeValue(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.csTypeValue : null;
|
||||||
|
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
||||||
|
|
||||||
|
public List<string> GetDatabases() {
|
||||||
|
var sql = @" select username from sys.dba_users";
|
||||||
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
|
||||||
|
var loc1 = new List<DbTableInfo>();
|
||||||
|
var loc2 = new Dictionary<string, DbTableInfo>();
|
||||||
|
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
|
||||||
|
|
||||||
|
if (database == null || database.Any() == false) return loc1;
|
||||||
|
var databaseIn = string.Join(",", database.Select(a => "{0}".FormatMySql(a)));
|
||||||
|
var sql = string.Format(@"
|
||||||
|
select
|
||||||
|
concat(a.table_schema, '.', a.table_name) 'id',
|
||||||
|
a.table_schema 'schema',
|
||||||
|
a.table_name 'table',
|
||||||
|
a.table_type 'type'
|
||||||
|
from information_schema.tables a
|
||||||
|
where a.table_schema in ({0})", databaseIn);
|
||||||
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
var loc6 = new List<string>();
|
||||||
|
var loc66 = new List<string>();
|
||||||
|
foreach (var row in ds) {
|
||||||
|
var table_id = string.Concat(row[0]);
|
||||||
|
var schema = string.Concat(row[1]);
|
||||||
|
var table = string.Concat(row[2]);
|
||||||
|
var type = string.Concat(row[3]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE;
|
||||||
|
if (database.Length == 1) {
|
||||||
|
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
||||||
|
schema = "";
|
||||||
|
}
|
||||||
|
loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Type = type });
|
||||||
|
loc3.Add(table_id, new Dictionary<string, DbColumnInfo>());
|
||||||
|
switch (type) {
|
||||||
|
case DbTableType.TABLE:
|
||||||
|
case DbTableType.VIEW:
|
||||||
|
loc6.Add(table.Replace("'", "''"));
|
||||||
|
break;
|
||||||
|
case DbTableType.StoreProcedure:
|
||||||
|
loc66.Add(table.Replace("'", "''"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loc6.Count == 0) return loc1;
|
||||||
|
var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
|
||||||
|
var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
|
||||||
|
|
||||||
|
sql = string.Format(@"
|
||||||
|
select
|
||||||
|
concat(a.table_schema, '.', a.table_name),
|
||||||
|
a.column_name,
|
||||||
|
a.data_type,
|
||||||
|
ifnull(a.character_maximum_length, 0) 'len',
|
||||||
|
a.column_type,
|
||||||
|
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
|
||||||
|
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity',
|
||||||
|
a.column_comment 'comment'
|
||||||
|
from information_schema.columns a
|
||||||
|
where a.table_schema in ({1}) and a.table_name in ({0})
|
||||||
|
", loc8, databaseIn);
|
||||||
|
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
foreach (var row in ds) {
|
||||||
|
string table_id = string.Concat(row[0]);
|
||||||
|
string column = string.Concat(row[1]);
|
||||||
|
string type = string.Concat(row[2]);
|
||||||
|
//long max_length = long.Parse(string.Concat(row[3]));
|
||||||
|
string sqlType = string.Concat(row[4]);
|
||||||
|
var m_len = Regex.Match(sqlType, @"\w+\((\d+)");
|
||||||
|
int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1;
|
||||||
|
bool is_nullable = string.Concat(row[5]) == "1";
|
||||||
|
bool is_identity = string.Concat(row[6]) == "1";
|
||||||
|
string comment = string.Concat(row[7]);
|
||||||
|
if (max_length == 0) max_length = -1;
|
||||||
|
if (database.Length == 1) {
|
||||||
|
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
||||||
|
}
|
||||||
|
loc3[table_id].Add(column, new DbColumnInfo {
|
||||||
|
Name = column,
|
||||||
|
MaxLength = max_length,
|
||||||
|
IsIdentity = is_identity,
|
||||||
|
IsNullable = is_nullable,
|
||||||
|
IsPrimary = false,
|
||||||
|
DbTypeText = type,
|
||||||
|
DbTypeTextFull = sqlType,
|
||||||
|
Table = loc2[table_id],
|
||||||
|
Coment = comment
|
||||||
|
});
|
||||||
|
loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]);
|
||||||
|
loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = string.Format(@"
|
||||||
|
select
|
||||||
|
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
||||||
|
a.column_name,
|
||||||
|
concat(a.constraint_schema, '/', a.table_name, '/', a.constraint_name) 'index_id',
|
||||||
|
1 'IsUnique',
|
||||||
|
case when constraint_name = 'PRIMARY' then 1 else 0 end 'IsPrimaryKey',
|
||||||
|
0 'IsClustered',
|
||||||
|
0 'IsDesc'
|
||||||
|
from information_schema.key_column_usage a
|
||||||
|
where a.constraint_schema in ({1}) and a.table_name in ({0}) and isnull(position_in_unique_constraint)
|
||||||
|
", loc8, databaseIn);
|
||||||
|
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
|
||||||
|
var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
|
||||||
|
foreach (var row in ds) {
|
||||||
|
string table_id = string.Concat(row[0]);
|
||||||
|
string column = string.Concat(row[1]);
|
||||||
|
string index_id = string.Concat(row[2]);
|
||||||
|
bool is_unique = string.Concat(row[3]) == "1";
|
||||||
|
bool is_primary_key = string.Concat(row[4]) == "1";
|
||||||
|
bool is_clustered = string.Concat(row[5]) == "1";
|
||||||
|
int is_desc = int.Parse(string.Concat(row[6]));
|
||||||
|
if (database.Length == 1) {
|
||||||
|
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
||||||
|
}
|
||||||
|
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
|
||||||
|
var loc9 = loc3[table_id][column];
|
||||||
|
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
|
||||||
|
|
||||||
|
Dictionary<string, List<DbColumnInfo>> loc10 = null;
|
||||||
|
List<DbColumnInfo> loc11 = null;
|
||||||
|
if (!indexColumns.TryGetValue(table_id, out loc10))
|
||||||
|
indexColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
|
||||||
|
if (!loc10.TryGetValue(index_id, out loc11))
|
||||||
|
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
|
||||||
|
loc11.Add(loc9);
|
||||||
|
if (is_unique) {
|
||||||
|
if (!uniqueColumns.TryGetValue(table_id, out loc10))
|
||||||
|
uniqueColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
|
||||||
|
if (!loc10.TryGetValue(index_id, out loc11))
|
||||||
|
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
|
||||||
|
loc11.Add(loc9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (string table_id in indexColumns.Keys) {
|
||||||
|
foreach (var columns in indexColumns[table_id].Values)
|
||||||
|
loc2[table_id].Indexes.Add(columns);
|
||||||
|
}
|
||||||
|
foreach (string table_id in uniqueColumns.Keys) {
|
||||||
|
foreach (var columns in uniqueColumns[table_id].Values) {
|
||||||
|
columns.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
|
||||||
|
loc2[table_id].Uniques.Add(columns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = string.Format(@"
|
||||||
|
select
|
||||||
|
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
||||||
|
a.column_name,
|
||||||
|
concat(a.constraint_schema, '/', a.constraint_name) 'FKId',
|
||||||
|
concat(a.referenced_table_schema, '.', a.referenced_table_name) 'ref_table_id',
|
||||||
|
1 'IsForeignKey',
|
||||||
|
a.referenced_column_name 'ref_column'
|
||||||
|
from information_schema.key_column_usage a
|
||||||
|
where a.constraint_schema in ({1}) and a.table_name in ({0}) and not isnull(position_in_unique_constraint)
|
||||||
|
", loc8, databaseIn);
|
||||||
|
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
|
||||||
|
foreach (var row in ds) {
|
||||||
|
string table_id = string.Concat(row[0]);
|
||||||
|
string column = string.Concat(row[1]);
|
||||||
|
string fk_id = string.Concat(row[2]);
|
||||||
|
string ref_table_id = string.Concat(row[3]);
|
||||||
|
bool is_foreign_key = string.Concat(row[4]) == "1";
|
||||||
|
string referenced_column = string.Concat(row[5]);
|
||||||
|
if (database.Length == 1) {
|
||||||
|
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
||||||
|
ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1);
|
||||||
|
}
|
||||||
|
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
|
||||||
|
var loc9 = loc3[table_id][column];
|
||||||
|
if (loc2.ContainsKey(ref_table_id) == false) continue;
|
||||||
|
var loc10 = loc2[ref_table_id];
|
||||||
|
var loc11 = loc3[ref_table_id][referenced_column];
|
||||||
|
|
||||||
|
Dictionary<string, DbForeignInfo> loc12 = null;
|
||||||
|
DbForeignInfo loc13 = null;
|
||||||
|
if (!fkColumns.TryGetValue(table_id, out loc12))
|
||||||
|
fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
|
||||||
|
if (!loc12.TryGetValue(fk_id, out loc13))
|
||||||
|
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 });
|
||||||
|
loc13.Columns.Add(loc9);
|
||||||
|
loc13.ReferencedColumns.Add(loc11);
|
||||||
|
}
|
||||||
|
foreach (var table_id in fkColumns.Keys)
|
||||||
|
foreach (var fk in fkColumns[table_id].Values)
|
||||||
|
loc2[table_id].Foreigns.Add(fk);
|
||||||
|
|
||||||
|
foreach (var table_id in loc3.Keys) {
|
||||||
|
foreach (var loc5 in loc3[table_id].Values) {
|
||||||
|
loc2[table_id].Columns.Add(loc5);
|
||||||
|
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
|
||||||
|
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var loc4 in loc2.Values) {
|
||||||
|
if (loc4.Primarys.Count == 0 && loc4.Uniques.Count > 0) {
|
||||||
|
foreach (var loc5 in loc4.Uniques[0]) {
|
||||||
|
loc5.IsPrimary = true;
|
||||||
|
loc4.Primarys.Add(loc5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
|
||||||
|
loc4.Columns.Sort((c1, c2) => {
|
||||||
|
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
|
||||||
|
if (compare == 0) {
|
||||||
|
bool b1 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c1.Name) != null) != null;
|
||||||
|
bool b2 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c2.Name) != null) != null;
|
||||||
|
compare = b2.CompareTo(b1);
|
||||||
|
}
|
||||||
|
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
|
||||||
|
return compare;
|
||||||
|
});
|
||||||
|
loc1.Add(loc4);
|
||||||
|
}
|
||||||
|
loc1.Sort((t1, t2) => {
|
||||||
|
var ret = t1.Schema.CompareTo(t2.Schema);
|
||||||
|
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
foreach(var loc4 in loc1) {
|
||||||
|
var dicUniques = new Dictionary<string, List<DbColumnInfo>>();
|
||||||
|
if (loc4.Primarys.Count > 0) dicUniques.Add(string.Join(",", loc4.Primarys.Select(a => a.Name)), loc4.Primarys);
|
||||||
|
foreach(var loc5 in loc4.Uniques) {
|
||||||
|
var dickey = string.Join(",", loc5.Select(a => a.Name));
|
||||||
|
if (dicUniques.ContainsKey(dickey)) continue;
|
||||||
|
dicUniques.Add(dickey, loc5);
|
||||||
|
}
|
||||||
|
loc4.Uniques = dicUniques.Values.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
loc2.Clear();
|
||||||
|
loc3.Clear();
|
||||||
|
return loc1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
|
||||||
|
return new List<DbEnumInfo>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
315
FreeSql/Oracle/OracleExpression.cs
Normal file
315
FreeSql/Oracle/OracleExpression.cs
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
class OracleExpression : CommonExpression {
|
||||||
|
|
||||||
|
public OracleExpression(CommonUtils common) : base(common) { }
|
||||||
|
|
||||||
|
internal override string ExpressionLambdaToSqlOther(Expression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
switch (exp.NodeType) {
|
||||||
|
case ExpressionType.Call:
|
||||||
|
var callExp = exp as MethodCallExpression;
|
||||||
|
var objExp = callExp.Object;
|
||||||
|
var objType = objExp?.Type;
|
||||||
|
if (objType?.FullName == "System.Byte[]") return null;
|
||||||
|
|
||||||
|
var argIndex = 0;
|
||||||
|
if (objType == null && callExp.Method.DeclaringType.FullName == typeof(Enumerable).FullName) {
|
||||||
|
objExp = callExp.Arguments.FirstOrDefault();
|
||||||
|
objType = objExp?.Type;
|
||||||
|
argIndex++;
|
||||||
|
}
|
||||||
|
if (objType == null) objType = callExp.Method.DeclaringType;
|
||||||
|
if (objType != null) {
|
||||||
|
var left = objExp == null ? null : getExp(objExp);
|
||||||
|
if (objType.IsArray == true) {
|
||||||
|
switch (callExp.Method.Name) {
|
||||||
|
case "Contains":
|
||||||
|
//判断 in
|
||||||
|
return $"({getExp(callExp.Arguments[argIndex])}) in {left}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ExpressionType.NewArrayInit:
|
||||||
|
var arrExp = exp as NewArrayExpression;
|
||||||
|
var arrSb = new StringBuilder();
|
||||||
|
arrSb.Append("(");
|
||||||
|
for (var a = 0; a < arrExp.Expressions.Count; a++) {
|
||||||
|
if (a > 0) arrSb.Append(",");
|
||||||
|
arrSb.Append(getExp(arrExp.Expressions[a]));
|
||||||
|
}
|
||||||
|
return arrSb.Append(")").ToString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
if (exp.Expression == null) {
|
||||||
|
switch (exp.Member.Name) {
|
||||||
|
case "Empty": return "''";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
switch (exp.Member.Name) {
|
||||||
|
case "Length": return $"char_length({left})";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
internal override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
if (exp.Expression == null) {
|
||||||
|
switch (exp.Member.Name) {
|
||||||
|
case "Now": return "now()";
|
||||||
|
case "UtcNow": return "utc_timestamp()";
|
||||||
|
case "Today": return "curdate()";
|
||||||
|
case "MinValue": return "cast('0001/1/1 0:00:00' as datetime)";
|
||||||
|
case "MaxValue": return "cast('9999/12/31 23:59:59' as datetime)";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
switch (exp.Member.Name) {
|
||||||
|
case "Date": return $"cast(date_format({left},'%Y-%m-%d') as datetime)";
|
||||||
|
case "TimeOfDay": return $"timestampdiff(microsecond, date_format({left},'%Y-%m-%d'), {left})";
|
||||||
|
case "DayOfWeek": return $"(dayofweek({left})-1)";
|
||||||
|
case "Day": return $"dayofmonth({left})";
|
||||||
|
case "DayOfYear": return $"dayofyear({left})";
|
||||||
|
case "Month": return $"month({left})";
|
||||||
|
case "Year": return $"year({left})";
|
||||||
|
case "Hour": return $"hour({left})";
|
||||||
|
case "Minute": return $"minute({left})";
|
||||||
|
case "Second": return $"second({left})";
|
||||||
|
case "Millisecond": return $"floor(microsecond({left})/1000)";
|
||||||
|
case "Ticks": return $"(timestampdiff(microsecond, '0001-1-1', {left})*10)";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
internal override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
if (exp.Expression == null) {
|
||||||
|
switch (exp.Member.Name) {
|
||||||
|
case "Zero": return "0";
|
||||||
|
case "MinValue": return "-922337203685477580"; //微秒 Ticks / 10
|
||||||
|
case "MaxValue": return "922337203685477580";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var left = ExpressionLambdaToSql(exp.Expression, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
switch (exp.Member.Name) {
|
||||||
|
case "Days": return $"(({left}) div {(long)1000000 * 60 * 60 * 24})";
|
||||||
|
case "Hours": return $"(({left}) div {(long)1000000 * 60 * 60} mod 24)";
|
||||||
|
case "Milliseconds": return $"(({left}) div 1000 mod 1000)";
|
||||||
|
case "Minutes": return $"(({left}) div {(long)1000000 * 60} mod 60)";
|
||||||
|
case "Seconds": return $"(({left}) div 1000000 mod 60)";
|
||||||
|
case "Ticks": return $"(({left}) * 10)";
|
||||||
|
case "TotalDays": return $"(({left}) / {(long)1000000 * 60 * 60 * 24})";
|
||||||
|
case "TotalHours": return $"(({left}) / {(long)1000000 * 60 * 60})";
|
||||||
|
case "TotalMilliseconds": return $"(({left}) / 1000)";
|
||||||
|
case "TotalMinutes": return $"(({left}) / {(long)1000000 * 60})";
|
||||||
|
case "TotalSeconds": return $"(({left}) / 1000000)";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
if (exp.Object == null) {
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "IsNullOrEmpty":
|
||||||
|
var arg1 = getExp(exp.Arguments[0]);
|
||||||
|
return $"({arg1} is null or {arg1} = '')";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var left = getExp(exp.Object);
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "StartsWith":
|
||||||
|
case "EndsWith":
|
||||||
|
case "Contains":
|
||||||
|
var args0Value = getExp(exp.Arguments[0]);
|
||||||
|
if (args0Value == "NULL") return $"({left}) IS NULL";
|
||||||
|
if (exp.Method.Name == "StartsWith") return $"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"concat({args0Value}, '%')")}";
|
||||||
|
if (exp.Method.Name == "EndsWith") return $"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"concat('%', {args0Value})")}";
|
||||||
|
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
|
||||||
|
return $"({left}) LIKE concat('%', {args0Value}, '%')";
|
||||||
|
case "ToLower": return $"lower({left})";
|
||||||
|
case "ToUpper": return $"upper({left})";
|
||||||
|
case "Substring":
|
||||||
|
var substrArgs1 = getExp(exp.Arguments[0]);
|
||||||
|
if (long.TryParse(substrArgs1, out var testtrylng1)) substrArgs1 = (testtrylng1 + 1).ToString();
|
||||||
|
else substrArgs1 += "+1";
|
||||||
|
if (exp.Arguments.Count == 1) return $"substr({left}, {substrArgs1})";
|
||||||
|
return $"substr({left}, {substrArgs1}, {getExp(exp.Arguments[1])})";
|
||||||
|
case "IndexOf":
|
||||||
|
var indexOfFindStr = getExp(exp.Arguments[0]);
|
||||||
|
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") {
|
||||||
|
var locateArgs1 = getExp(exp.Arguments[1]);
|
||||||
|
if (long.TryParse(locateArgs1, out var testtrylng2)) locateArgs1 = (testtrylng2 + 1).ToString();
|
||||||
|
else locateArgs1 += "+1";
|
||||||
|
return $"(locate({left}, {indexOfFindStr}, {locateArgs1})-1)";
|
||||||
|
}
|
||||||
|
return $"(locate({left}, {indexOfFindStr})-1)";
|
||||||
|
case "PadLeft":
|
||||||
|
if (exp.Arguments.Count == 1) return $"lpad({left}, {getExp(exp.Arguments[0])})";
|
||||||
|
return $"lpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||||
|
case "PadRight":
|
||||||
|
if (exp.Arguments.Count == 1) return $"rpad({left}, {getExp(exp.Arguments[0])})";
|
||||||
|
return $"rpad({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||||
|
case "Trim":
|
||||||
|
case "TrimStart":
|
||||||
|
case "TrimEnd":
|
||||||
|
if (exp.Arguments.Count == 0) {
|
||||||
|
if (exp.Method.Name == "Trim") return $"trim({left})";
|
||||||
|
if (exp.Method.Name == "TrimStart") return $"ltrim({left})";
|
||||||
|
if (exp.Method.Name == "TrimEnd") return $"rtrim({left})";
|
||||||
|
}
|
||||||
|
foreach (var argsTrim02 in exp.Arguments) {
|
||||||
|
var argsTrim01s = new[] { argsTrim02 };
|
||||||
|
if (argsTrim02.NodeType == ExpressionType.NewArrayInit) {
|
||||||
|
var arritem = argsTrim02 as NewArrayExpression;
|
||||||
|
argsTrim01s = arritem.Expressions.ToArray();
|
||||||
|
}
|
||||||
|
foreach (var argsTrim01 in argsTrim01s) {
|
||||||
|
if (exp.Method.Name == "Trim") left = $"trim({getExp(argsTrim01)} from {left})";
|
||||||
|
if (exp.Method.Name == "TrimStart") left = $"trim(leading {getExp(argsTrim01)} from {left})";
|
||||||
|
if (exp.Method.Name == "TrimEnd") left = $"trim(trailing {getExp(argsTrim01)} from {left})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||||
|
case "CompareTo": return $"strcmp({left}, {getExp(exp.Arguments[0])})";
|
||||||
|
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||||
|
}
|
||||||
|
internal override string ExpressionLambdaToSqlCallMath(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "Abs": return $"abs({getExp(exp.Arguments[0])})";
|
||||||
|
case "Sign": return $"sign({getExp(exp.Arguments[0])})";
|
||||||
|
case "Floor": return $"floor({getExp(exp.Arguments[0])})";
|
||||||
|
case "Ceiling": return $"ceiling({getExp(exp.Arguments[0])})";
|
||||||
|
case "Round":
|
||||||
|
if (exp.Arguments.Count > 1 && exp.Arguments[1].Type.FullName == "System.Int32") return $"round({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||||
|
return $"round({getExp(exp.Arguments[0])})";
|
||||||
|
case "Exp": return $"exp({getExp(exp.Arguments[0])})";
|
||||||
|
case "Log": return $"log({getExp(exp.Arguments[0])})";
|
||||||
|
case "Log10": return $"log10({getExp(exp.Arguments[0])})";
|
||||||
|
case "Pow": return $"pow({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||||
|
case "Sqrt": return $"sqrt({getExp(exp.Arguments[0])})";
|
||||||
|
case "Cos": return $"cos({getExp(exp.Arguments[0])})";
|
||||||
|
case "Sin": return $"sin({getExp(exp.Arguments[0])})";
|
||||||
|
case "Tan": return $"tan({getExp(exp.Arguments[0])})";
|
||||||
|
case "Acos": return $"acos({getExp(exp.Arguments[0])})";
|
||||||
|
case "Asin": return $"asin({getExp(exp.Arguments[0])})";
|
||||||
|
case "Atan": return $"atan({getExp(exp.Arguments[0])})";
|
||||||
|
case "Atan2": return $"atan2({getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||||
|
case "Truncate": return $"truncate({getExp(exp.Arguments[0])}, 0)";
|
||||||
|
}
|
||||||
|
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||||
|
}
|
||||||
|
internal override string ExpressionLambdaToSqlCallDateTime(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
if (exp.Object == null) {
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "Compare": return $"({getExp(exp.Arguments[0])} - ({getExp(exp.Arguments[1])}))";
|
||||||
|
case "DaysInMonth": return $"dayofmonth(last_day(concat({getExp(exp.Arguments[0])}, '-', {getExp(exp.Arguments[1])}, '-01')))";
|
||||||
|
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
|
||||||
|
|
||||||
|
case "IsLeapYear":
|
||||||
|
var isLeapYearArgs1 = getExp(exp.Arguments[0]);
|
||||||
|
return $"(({isLeapYearArgs1})%4=0 AND ({isLeapYearArgs1})%100<>0 OR ({isLeapYearArgs1})%400=0)";
|
||||||
|
|
||||||
|
case "Parse": return $"cast({getExp(exp.Arguments[0])} as datetime)";
|
||||||
|
case "ParseExact":
|
||||||
|
case "TryParse":
|
||||||
|
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as datetime)";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var left = getExp(exp.Object);
|
||||||
|
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "Add": return $"date_add({left}, interval ({args1}) microsecond)";
|
||||||
|
case "AddDays": return $"date_add({left}, interval ({args1}) day)";
|
||||||
|
case "AddHours": return $"date_add({left}, interval ({args1}) hour)";
|
||||||
|
case "AddMilliseconds": return $"date_add({left}, interval ({args1})*1000 microsecond)";
|
||||||
|
case "AddMinutes": return $"date_add({left}, interval ({args1}) minute)";
|
||||||
|
case "AddMonths": return $"date_add({left}, interval ({args1}) month)";
|
||||||
|
case "AddSeconds": return $"date_add({left}, interval ({args1}) second)";
|
||||||
|
case "AddTicks": return $"date_add({left}, interval ({args1})/10 microsecond)";
|
||||||
|
case "AddYears": return $"date_add({left}, interval ({args1}) year)";
|
||||||
|
case "Subtract":
|
||||||
|
if (exp.Arguments[0].Type.FullName == "System.DateTime" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.DateTime")
|
||||||
|
return $"timestampdiff(microsecond, {args1}, {left})";
|
||||||
|
if (exp.Arguments[0].Type.FullName == "System.TimeSpan" || exp.Arguments[0].Type.GenericTypeArguments.FirstOrDefault()?.FullName == "System.TimeSpan")
|
||||||
|
return $"date_sub({left}, interval ({args1}) microsecond)";
|
||||||
|
break;
|
||||||
|
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
|
||||||
|
case "CompareTo": return $"(({left}) - ({getExp(exp.Arguments[0])}))";
|
||||||
|
case "ToString": return $"date_format({left}, '%Y-%m-%d %H:%i:%s.%f')";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||||
|
}
|
||||||
|
internal override string ExpressionLambdaToSqlCallTimeSpan(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
if (exp.Object == null) {
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "Compare": return $"({getExp(exp.Arguments[0])}-({getExp(exp.Arguments[1])}))";
|
||||||
|
case "Equals": return $"({getExp(exp.Arguments[0])} = {getExp(exp.Arguments[1])})";
|
||||||
|
case "FromDays": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60 * 60 * 24})";
|
||||||
|
case "FromHours": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60 * 60})";
|
||||||
|
case "FromMilliseconds": return $"(({getExp(exp.Arguments[0])})*1000)";
|
||||||
|
case "FromMinutes": return $"(({getExp(exp.Arguments[0])})*{(long)1000000 * 60})";
|
||||||
|
case "FromSeconds": return $"(({getExp(exp.Arguments[0])})*1000000)";
|
||||||
|
case "FromTicks": return $"(({getExp(exp.Arguments[0])})/10)";
|
||||||
|
case "Parse": return $"cast({getExp(exp.Arguments[0])} as signed)";
|
||||||
|
case "ParseExact":
|
||||||
|
case "TryParse":
|
||||||
|
case "TryParseExact": return $"cast({getExp(exp.Arguments[0])} as signed)";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var left = getExp(exp.Object);
|
||||||
|
var args1 = exp.Arguments.Count == 0 ? null : getExp(exp.Arguments[0]);
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "Add": return $"({left}+{args1})";
|
||||||
|
case "Subtract": return $"({left}-({args1}))";
|
||||||
|
case "Equals": return $"({left} = {getExp(exp.Arguments[0])})";
|
||||||
|
case "CompareTo": return $"({left}-({getExp(exp.Arguments[0])}))";
|
||||||
|
case "ToString": return $"cast({left} as char)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||||
|
}
|
||||||
|
internal override string ExpressionLambdaToSqlCallConvert(MethodCallExpression exp, List<SelectTableInfo> _tables, List<SelectColumnInfo> _selectColumnMap, Func<Expression[], string> getSelectGroupingMapString, SelectTableInfoType tbtype, bool isQuoteName) {
|
||||||
|
Func<Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
|
||||||
|
if (exp.Object == null) {
|
||||||
|
switch (exp.Method.Name) {
|
||||||
|
case "ToBoolean": return $"({getExp(exp.Arguments[0])} not in ('0','false'))";
|
||||||
|
case "ToByte": return $"cast({getExp(exp.Arguments[0])} as unsigned)";
|
||||||
|
case "ToChar": return $"substr(cast({getExp(exp.Arguments[0])} as char), 1, 1)";
|
||||||
|
case "ToDateTime": return $"cast({getExp(exp.Arguments[0])} as datetime)";
|
||||||
|
case "ToDecimal": return $"cast({getExp(exp.Arguments[0])} as decimal(36,18))";
|
||||||
|
case "ToDouble": return $"cast({getExp(exp.Arguments[0])} as decimal(32,16))";
|
||||||
|
case "ToInt16":
|
||||||
|
case "ToInt32":
|
||||||
|
case "ToInt64":
|
||||||
|
case "ToSByte": return $"cast({getExp(exp.Arguments[0])} as signed)";
|
||||||
|
case "ToSingle": return $"cast({getExp(exp.Arguments[0])} as decimal(14,7))";
|
||||||
|
case "ToString": return $"cast({getExp(exp.Arguments[0])} as char)";
|
||||||
|
case "ToUInt16":
|
||||||
|
case "ToUInt32":
|
||||||
|
case "ToUInt64": return $"cast({getExp(exp.Arguments[0])} as unsigned)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Exception($"MySqlExpression 未现实函数表达式 {exp} 解析");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
FreeSql/Oracle/OracleProvider.cs
Normal file
49
FreeSql/Oracle/OracleProvider.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.CommonProvider;
|
||||||
|
using FreeSql.Oracle.Curd;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
|
||||||
|
class OracleProvider : IFreeSql {
|
||||||
|
|
||||||
|
public ISelect<T1> Select<T1>() where T1 : class => new OracleSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||||
|
public ISelect<T1> Select<T1>(object dywhere) where T1 : class => new OracleSelect<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||||
|
public IInsert<T1> Insert<T1>() where T1 : class => new OracleInsert<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||||
|
public IInsert<T1> Insert<T1>(T1 source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||||
|
public IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class => this.Insert<T1>().AppendData(source);
|
||||||
|
public IUpdate<T1> Update<T1>() where T1 : class => new OracleUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||||
|
public IUpdate<T1> Update<T1>(object dywhere) where T1 : class => new OracleUpdate<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||||
|
public IDelete<T1> Delete<T1>() where T1 : class => new OracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, null);
|
||||||
|
public IDelete<T1> Delete<T1>(object dywhere) where T1 : class => new OracleDelete<T1>(this, this.InternalCommonUtils, this.InternalCommonExpression, dywhere);
|
||||||
|
|
||||||
|
public IAdo Ado { get; }
|
||||||
|
public ICache Cache { get; }
|
||||||
|
public ICodeFirst CodeFirst { get; }
|
||||||
|
public IDbFirst DbFirst { get; }
|
||||||
|
public OracleProvider(IDistributedCache cache, ILogger log, string masterConnectionString, string[] slaveConnectionString) {
|
||||||
|
if (log == null) log = new LoggerFactory(new[] { new Microsoft.Extensions.Logging.Debug.DebugLoggerProvider() }).CreateLogger("FreeSql.Oracle");
|
||||||
|
|
||||||
|
this.InternalCommonUtils = new OracleUtils(this);
|
||||||
|
this.InternalCommonExpression = new OracleExpression(this.InternalCommonUtils);
|
||||||
|
|
||||||
|
this.Cache = new CacheProvider(cache, log);
|
||||||
|
this.Ado = new OracleAdo(this.InternalCommonUtils, this.Cache, log, masterConnectionString, slaveConnectionString);
|
||||||
|
|
||||||
|
this.DbFirst = new OracleDbFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||||
|
this.InternalCommonUtils.CodeFirst = this.CodeFirst = new OracleCodeFirst(this, this.InternalCommonUtils, this.InternalCommonExpression);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal CommonUtils InternalCommonUtils { get; }
|
||||||
|
internal CommonExpression InternalCommonExpression { get; }
|
||||||
|
|
||||||
|
public void Transaction(Action handler) => Ado.Transaction(handler);
|
||||||
|
|
||||||
|
public void Transaction(Action handler, TimeSpan timeout) => Ado.Transaction(handler, timeout);
|
||||||
|
}
|
||||||
|
}
|
47
FreeSql/Oracle/OracleUtils.cs
Normal file
47
FreeSql/Oracle/OracleUtils.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using FreeSql.Internal;
|
||||||
|
using FreeSql.Internal.Model;
|
||||||
|
using Oracle.ManagedDataAccess.Client;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data.Common;
|
||||||
|
|
||||||
|
namespace FreeSql.Oracle {
|
||||||
|
|
||||||
|
class OracleUtils : CommonUtils {
|
||||||
|
IFreeSql _orm;
|
||||||
|
public OracleUtils(IFreeSql orm) {
|
||||||
|
_orm = orm;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
|
||||||
|
if (string.IsNullOrEmpty(parameterName)) parameterName = $"p_{_params?.Count}";
|
||||||
|
else if (_orm.CodeFirst.IsSyncStructureToLower) parameterName = parameterName.ToLower();
|
||||||
|
var ret = new OracleParameter { ParameterName = $"@{parameterName}", Value = value };
|
||||||
|
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
|
||||||
|
if (tp != null) {
|
||||||
|
ret.OracleDbType = (OracleDbType)tp.Value;
|
||||||
|
}
|
||||||
|
_params?.Add(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override DbParameter[] GetDbParamtersByObject(string sql, object obj) =>
|
||||||
|
Utils.GetDbParamtersByObject<OracleParameter>(sql, obj, "@", (name, type, value) => {
|
||||||
|
var ret = new OracleParameter { ParameterName = $"@{name}", Value = value };
|
||||||
|
var tp = _orm.CodeFirst.GetDbInfo(type)?.type;
|
||||||
|
if (tp != null) {
|
||||||
|
ret.OracleDbType = (OracleDbType)tp.Value;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
internal override string FormatSql(string sql, params object[] args) => sql?.FormatOracleSQL(args);
|
||||||
|
internal override string QuoteSqlName(string name) => $"\"{name.Trim('"').Replace(".", "\".\"")}\"";
|
||||||
|
internal override string QuoteParamterName(string name) => $"@{(_orm.CodeFirst.IsSyncStructureToLower ? name.ToLower() : name)}";
|
||||||
|
internal override string IsNull(string sql, object value) => $"nvl({sql}, {value})";
|
||||||
|
internal override string StringConcat(string left, string right, Type leftType, Type rightType) => $"{left} || {right}";
|
||||||
|
|
||||||
|
internal override string QuoteWriteParamter(Type type, string paramterName) => paramterName;
|
||||||
|
internal override string QuoteReadColumn(Type type, string columnName) => columnName;
|
||||||
|
}
|
||||||
|
}
|
@ -16,13 +16,23 @@ namespace FreeSql.PostgreSQL.Curd {
|
|||||||
var sql = this.ToSql();
|
var sql = this.ToSql();
|
||||||
if (string.IsNullOrEmpty(sql)) return 0;
|
if (string.IsNullOrEmpty(sql)) return 0;
|
||||||
|
|
||||||
return long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(_table.Columns.Where(a => a.Value.Attribute.IsIdentity).FirstOrDefault().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0;
|
var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity);
|
||||||
|
if (identCols.Any() == false) {
|
||||||
|
_orm.Ado.ExecuteNonQuery(CommandType.Text, sql, _params);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return long.TryParse(string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0;
|
||||||
}
|
}
|
||||||
async public override Task<long> ExecuteIdentityAsync() {
|
async public override Task<long> ExecuteIdentityAsync() {
|
||||||
var sql = this.ToSql();
|
var sql = this.ToSql();
|
||||||
if (string.IsNullOrEmpty(sql)) return 0;
|
if (string.IsNullOrEmpty(sql)) return 0;
|
||||||
|
|
||||||
return long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(_table.Columns.Where(a => a.Value.Attribute.IsIdentity).FirstOrDefault().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0;
|
var identCols = _table.Columns.Where(a => a.Value.Attribute.IsIdentity);
|
||||||
|
if (identCols.Any() == false) {
|
||||||
|
await _orm.Ado.ExecuteNonQueryAsync(CommandType.Text, sql, _params);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return long.TryParse(string.Concat(await _orm.Ado.ExecuteScalarAsync(CommandType.Text, string.Concat(sql, " RETURNING ", _commonUtils.QuoteSqlName(identCols.First().Value.Attribute.Name)), _params)), out var trylng) ? trylng : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<T1> ExecuteInserted() {
|
public override List<T1> ExecuteInserted() {
|
||||||
|
@ -25,6 +25,7 @@ namespace FreeSql.PostgreSQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DateTime dt1970 = new DateTime(1970, 1, 1);
|
static DateTime dt1970 = new DateTime(1970, 1, 1);
|
||||||
public override object AddslashesProcessParam(object param) {
|
public override object AddslashesProcessParam(object param) {
|
||||||
bool isdic = false;
|
bool isdic = false;
|
||||||
|
@ -136,7 +136,7 @@ namespace FreeSql.PostgreSQL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DbConnectionExtensions {
|
static class DbConnectionExtensions {
|
||||||
|
|
||||||
public static bool Ping(this DbConnection that) {
|
public static bool Ping(this DbConnection that) {
|
||||||
try {
|
try {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Npgsql.LegacyPostgis;
|
using Npgsql.LegacyPostgis;
|
||||||
using NpgsqlTypes;
|
using NpgsqlTypes;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
public static partial class PostgreSQLTypesExtensions {
|
public static partial class PostgreSQLTypesExtensions {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -30,4 +31,35 @@ public static partial class PostgreSQLTypesExtensions {
|
|||||||
double radLng2 = (double)(point.X) * 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;
|
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 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="_1010">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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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] == ')');
|
||||||
|
}
|
||||||
}
|
}
|
@ -132,14 +132,14 @@ namespace FreeSql.PostgreSQL {
|
|||||||
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
var tboldname = tb.DbOldName?.Split(new[] { '.' }, 2); //旧表名
|
||||||
if (tboldname?.Length == 1) tboldname = new[] { "public", tboldname[0] };
|
if (tboldname?.Length == 1) tboldname = new[] { "public", tboldname[0] };
|
||||||
|
|
||||||
if (string.Compare(tbname[0], "public", true) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, $"select 1 from pg_namespace where nspname='{tbname[0]}'") == null) //创建模式
|
if (string.Compare(tbname[0], "public", true) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, " select 1 from pg_namespace where nspname={0}".FormatPostgreSQL(tbname[0])) == null) //创建模式
|
||||||
sb.Append("CREATE SCHEMA IF NOT EXISTS ").Append(tbname[0]).Append(";\r\n");
|
sb.Append("CREATE SCHEMA IF NOT EXISTS ").Append(tbname[0]).Append(";\r\n");
|
||||||
|
|
||||||
var sbalter = new StringBuilder();
|
var sbalter = new StringBuilder();
|
||||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tbname)) == null) { //表不存在
|
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format(" select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tbname)) == null) { //表不存在
|
||||||
if (tboldname != null) {
|
if (tboldname != null) {
|
||||||
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format("select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tboldname)) == null)
|
if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format(" select 1 from pg_tables a inner join pg_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tboldname)) == null)
|
||||||
//旧表不存在
|
//旧表不存在
|
||||||
tboldname = null;
|
tboldname = null;
|
||||||
}
|
}
|
||||||
@ -171,7 +171,8 @@ namespace FreeSql.PostgreSQL {
|
|||||||
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
tboldname = null; //如果新表已经存在,不走改表名逻辑
|
||||||
|
|
||||||
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
|
||||||
var sql = @"select
|
var sql = @"
|
||||||
|
select
|
||||||
a.attname,
|
a.attname,
|
||||||
t.typname,
|
t.typname,
|
||||||
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
|
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
|
||||||
@ -194,7 +195,7 @@ where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(tboldname ?? tbname
|
|||||||
var type = string.Concat(a[1]);
|
var type = string.Concat(a[1]);
|
||||||
var sqlType = string.Concat(a[3]);
|
var sqlType = string.Concat(a[3]);
|
||||||
var max_length = long.Parse(string.Concat(a[2]));
|
var max_length = long.Parse(string.Concat(a[2]));
|
||||||
switch (sqlType) {
|
switch (sqlType.ToLower()) {
|
||||||
case "bool": case "name": case "bit": case "varbit": case "bpchar": case "varchar": case "bytea": case "text": case "uuid": break;
|
case "bool": case "name": case "bit": case "varbit": case "bpchar": case "varchar": case "bytea": case "text": case "uuid": break;
|
||||||
default: max_length *= 8; break;
|
default: max_length *= 8; break;
|
||||||
}
|
}
|
||||||
@ -288,7 +289,7 @@ where ns.nspname = {0} and c.relname = {1}".FormatPostgreSQL(tboldname ?? tbname
|
|||||||
if (seqcol.Item3) {
|
if (seqcol.Item3) {
|
||||||
sb.Append("CREATE SEQUENCE ").Append(seqname).Append(";\r\n");
|
sb.Append("CREATE SEQUENCE ").Append(seqname).Append(";\r\n");
|
||||||
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT nextval('").Append(seqname).Append("'::regclass);\r\n");
|
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT nextval('").Append(seqname).Append("'::regclass);\r\n");
|
||||||
sb.Append("SELECT case when max(").Append(colname2).Append(") is null then 0 else setval('").Append(seqname).Append("', max(").Append(colname2).Append(")) end FROM ").Append(tbname2).Append(";\r\n");
|
sb.Append(" SELECT case when max(").Append(colname2).Append(") is null then 0 else setval('").Append(seqname).Append("', max(").Append(colname2).Append(")) end FROM ").Append(tbname2).Append(";\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb.Length == 0 ? null : sb.ToString();
|
return sb.Length == 0 ? null : sb.ToString();
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
using FreeSql.DatabaseModel;
|
using FreeSql.DatabaseModel;
|
||||||
using FreeSql.Internal;
|
using FreeSql.Internal;
|
||||||
using MySql.Data.MySqlClient;
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Npgsql.LegacyPostgis;
|
||||||
|
using NpgsqlTypes;
|
||||||
|
using SafeObjectPool;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace FreeSql.PostgreSQL {
|
namespace FreeSql.PostgreSQL {
|
||||||
@ -18,107 +25,168 @@ namespace FreeSql.PostgreSQL {
|
|||||||
_commonExpression = commonExpression;
|
_commonExpression = commonExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetDbType(DbColumnInfo column) => (int)GetMySqlDbType(column);
|
public int GetDbType(DbColumnInfo column) => (int)GetNpgsqlDbType(column);
|
||||||
MySqlDbType GetMySqlDbType(DbColumnInfo column) {
|
NpgsqlDbType GetNpgsqlDbType(DbColumnInfo column) {
|
||||||
var is_unsigned = column.DbTypeTextFull.ToLower().EndsWith(" unsigned");
|
var dbtype = column.DbTypeText;
|
||||||
switch (column.DbTypeText.ToLower()) {
|
var isarray = dbtype.EndsWith("[]");
|
||||||
case "bit": return MySqlDbType.Bit;
|
if (isarray) dbtype = dbtype.Remove(dbtype.Length - 2);
|
||||||
|
NpgsqlDbType ret = NpgsqlDbType.Unknown;
|
||||||
|
switch (dbtype.ToLower().TrimStart('_')) {
|
||||||
|
case "int2": ret = NpgsqlDbType.Smallint;break;
|
||||||
|
case "int4": ret = NpgsqlDbType.Integer; break;
|
||||||
|
case "int8": ret = NpgsqlDbType.Bigint; break;
|
||||||
|
case "numeric": ret = NpgsqlDbType.Numeric; break;
|
||||||
|
case "float4": ret = NpgsqlDbType.Real; break;
|
||||||
|
case "float8": ret = NpgsqlDbType.Double; break;
|
||||||
|
case "money": ret = NpgsqlDbType.Money; break;
|
||||||
|
|
||||||
case "tinyint": return is_unsigned ? MySqlDbType.UByte : MySqlDbType.Byte;
|
case "bpchar": ret = NpgsqlDbType.Char; break;
|
||||||
case "smallint": return is_unsigned ? MySqlDbType.UInt16 : MySqlDbType.Int16;
|
case "varchar": ret = NpgsqlDbType.Varchar; break;
|
||||||
case "mediumint": return is_unsigned ? MySqlDbType.UInt24 : MySqlDbType.Int24;
|
case "text": ret = NpgsqlDbType.Text; break;
|
||||||
case "int": return is_unsigned ? MySqlDbType.UInt32 : MySqlDbType.Int32;
|
|
||||||
case "bigint": return is_unsigned ? MySqlDbType.UInt64 : MySqlDbType.Int64;
|
|
||||||
|
|
||||||
case "real":
|
case "timestamp": ret = NpgsqlDbType.Timestamp; break;
|
||||||
case "double": return MySqlDbType.Double;
|
case "timestamptz": ret = NpgsqlDbType.TimestampTz; break;
|
||||||
case "float": return MySqlDbType.Float;
|
case "date": ret = NpgsqlDbType.Date; break;
|
||||||
case "numeric":
|
case "time": ret = NpgsqlDbType.Time; break;
|
||||||
case "decimal": return MySqlDbType.Decimal;
|
case "timetz": ret = NpgsqlDbType.TimeTz; break;
|
||||||
|
case "interval": ret = NpgsqlDbType.Interval; break;
|
||||||
|
|
||||||
case "year": return MySqlDbType.Year;
|
case "bool": ret = NpgsqlDbType.Boolean; break;
|
||||||
case "time": return MySqlDbType.Time;
|
case "bytea": ret = NpgsqlDbType.Bytea; break;
|
||||||
case "date": return MySqlDbType.Date;
|
case "bit": ret = NpgsqlDbType.Bit; break;
|
||||||
case "timestamp": return MySqlDbType.Timestamp;
|
case "varbit": ret = NpgsqlDbType.Varbit; break;
|
||||||
case "datetime": return MySqlDbType.DateTime;
|
|
||||||
|
|
||||||
case "tinyblob": return MySqlDbType.TinyBlob;
|
case "point": ret = NpgsqlDbType.Point; break;
|
||||||
case "blob": return MySqlDbType.Blob;
|
case "line": ret = NpgsqlDbType.Line; break;
|
||||||
case "mediumblob": return MySqlDbType.MediumBlob;
|
case "lseg": ret = NpgsqlDbType.LSeg; break;
|
||||||
case "longblob": return MySqlDbType.LongBlob;
|
case "box": ret = NpgsqlDbType.Box; break;
|
||||||
|
case "path": ret = NpgsqlDbType.Path; break;
|
||||||
|
case "polygon": ret = NpgsqlDbType.Polygon; break;
|
||||||
|
case "circle": ret = NpgsqlDbType.Circle; break;
|
||||||
|
|
||||||
case "binary": return MySqlDbType.Binary;
|
case "cidr": ret = NpgsqlDbType.Cidr; break;
|
||||||
case "varbinary": return MySqlDbType.VarBinary;
|
case "inet": ret = NpgsqlDbType.Inet; break;
|
||||||
|
case "macaddr": ret = NpgsqlDbType.MacAddr; break;
|
||||||
|
|
||||||
case "tinytext": return MySqlDbType.TinyText;
|
case "json": ret = NpgsqlDbType.Json; break;
|
||||||
case "text": return MySqlDbType.Text;
|
case "jsonb": ret = NpgsqlDbType.Jsonb; break;
|
||||||
case "mediumtext": return MySqlDbType.MediumText;
|
case "uuid": ret = NpgsqlDbType.Uuid; break;
|
||||||
case "longtext": return MySqlDbType.LongText;
|
|
||||||
|
|
||||||
case "char": return MySqlDbType.String;
|
case "int4range": ret = NpgsqlDbType.Range | NpgsqlDbType.Integer; break;
|
||||||
case "varchar": return MySqlDbType.VarChar;
|
case "int8range": ret = NpgsqlDbType.Range | NpgsqlDbType.Bigint; break;
|
||||||
|
case "numrange": ret = NpgsqlDbType.Range | NpgsqlDbType.Numeric; break;
|
||||||
|
case "tsrange": ret = NpgsqlDbType.Range | NpgsqlDbType.Timestamp; break;
|
||||||
|
case "tstzrange": ret = NpgsqlDbType.Range | NpgsqlDbType.TimestampTz; break;
|
||||||
|
case "daterange": ret = NpgsqlDbType.Range | NpgsqlDbType.Date; break;
|
||||||
|
|
||||||
case "set": return MySqlDbType.Set;
|
case "hstore": ret = NpgsqlDbType.Hstore; break;
|
||||||
case "enum": return MySqlDbType.Enum;
|
case "geometry": ret = NpgsqlDbType.Geometry; break;
|
||||||
|
|
||||||
case "point": return MySqlDbType.Geometry;
|
|
||||||
case "linestring": return MySqlDbType.Geometry;
|
|
||||||
case "polygon": return MySqlDbType.Geometry;
|
|
||||||
case "geometry": return MySqlDbType.Geometry;
|
|
||||||
case "multipoint": return MySqlDbType.Geometry;
|
|
||||||
case "multilinestring": return MySqlDbType.Geometry;
|
|
||||||
case "multipolygon": return MySqlDbType.Geometry;
|
|
||||||
case "geometrycollection": return MySqlDbType.Geometry;
|
|
||||||
default: return MySqlDbType.String;
|
|
||||||
}
|
}
|
||||||
|
return isarray ? (ret | NpgsqlDbType.Array) : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
|
static readonly Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)> _dicDbToCs = new Dictionary<int, (string csConvert, string csParse, string csStringify, string csType, Type csTypeInfo, Type csNullableTypeInfo, string csTypeValue, string dataReaderMethod)>() {
|
||||||
{ (int)MySqlDbType.Bit, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
|
{ (int)NpgsqlDbType.Smallint, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
|
||||||
|
{ (int)NpgsqlDbType.Integer, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
||||||
|
{ (int)NpgsqlDbType.Bigint, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
|
||||||
|
{ (int)NpgsqlDbType.Numeric, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
|
||||||
|
{ (int)NpgsqlDbType.Real, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
|
||||||
|
{ (int)NpgsqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
|
||||||
|
{ (int)NpgsqlDbType.Money, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.Byte, ("(sbyte?)", "sbyte.Parse({0})", "{0}.ToString()", "sbyte?", typeof(sbyte), typeof(sbyte?), "{0}.Value", "GetByte") },
|
{ (int)NpgsqlDbType.Char, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.Int16, ("(short?)", "short.Parse({0})", "{0}.ToString()", "short?", typeof(short), typeof(short?), "{0}.Value", "GetInt16") },
|
{ (int)NpgsqlDbType.Varchar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.Int24, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
{ (int)NpgsqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.Int32, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
|
||||||
{ (int)MySqlDbType.Int64, ("(long?)", "long.Parse({0})", "{0}.ToString()", "long?", typeof(long), typeof(long?), "{0}.Value", "GetInt64") },
|
|
||||||
|
|
||||||
{ (int)MySqlDbType.UByte, ("(byte?)", "byte.Parse({0})", "{0}.ToString()", "byte?", typeof(byte), typeof(byte?), "{0}.Value", "GetByte") },
|
{ (int)NpgsqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
||||||
{ (int)MySqlDbType.UInt16, ("(ushort?)", "ushort.Parse({0})", "{0}.ToString()", "ushort?", typeof(ushort), typeof(ushort?), "{0}.Value", "GetInt16") },
|
{ (int)NpgsqlDbType.TimestampTz, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
||||||
{ (int)MySqlDbType.UInt24, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
|
{ (int)NpgsqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
||||||
{ (int)MySqlDbType.UInt32, ("(uint?)", "uint.Parse({0})", "{0}.ToString()", "uint?", typeof(uint), typeof(uint?), "{0}.Value", "GetInt32") },
|
{ (int)NpgsqlDbType.Time, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
|
||||||
{ (int)MySqlDbType.UInt64, ("(ulong?)", "ulong.Parse({0})", "{0}.ToString()", "ulong?", typeof(ulong), typeof(ulong?), "{0}.Value", "GetInt64") },
|
{ (int)NpgsqlDbType.TimeTz, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
|
||||||
|
{ (int)NpgsqlDbType.Interval, ("(TimeSpan?)", "TimeSpan.Parse(double.Parse({0}))", "{0}.Ticks.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.Double, ("(double?)", "double.Parse({0})", "{0}.ToString()", "double?", typeof(double), typeof(double?), "{0}.Value", "GetDouble") },
|
{ (int)NpgsqlDbType.Boolean, ("(bool?)", "{0} == \"1\"", "{0} == true ? \"1\" : \"0\"", "bool?", typeof(bool), typeof(bool?), "{0}.Value", "GetBoolean") },
|
||||||
{ (int)MySqlDbType.Float, ("(float?)", "float.Parse({0})", "{0}.ToString()", "float?", typeof(float), typeof(float?), "{0}.Value", "GetFloat") },
|
{ (int)NpgsqlDbType.Bytea, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.Decimal, ("(decimal?)", "decimal.Parse({0})", "{0}.ToString()", "decimal?", typeof(decimal), typeof(decimal?), "{0}.Value", "GetDecimal") },
|
{ (int)NpgsqlDbType.Bit, ("(BitArray)", "{0}.ToBitArray()", "{0}.To1010()", "BitArray", typeof(BitArray), typeof(BitArray), "{0}", "GetValue") },
|
||||||
|
{ (int)NpgsqlDbType.Varbit, ("(BitArray)", "{0}.ToBitArray()", "{0}.To1010()", "BitArray", typeof(BitArray), typeof(BitArray), "{0}", "GetValue") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.Year, ("(int?)", "int.Parse({0})", "{0}.ToString()", "int?", typeof(int), typeof(int?), "{0}.Value", "GetInt32") },
|
{ (int)NpgsqlDbType.Point, ("(NpgsqlPoint?)", "NpgsqlPoint.Parse({0})", "{0}.ToString()", "NpgsqlPoint", typeof(NpgsqlPoint), typeof(NpgsqlPoint?), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.Time, ("(TimeSpan?)", "TimeSpan.FromSeconds(double.Parse({0}))", "{0}.ToString()", "TimeSpan?", typeof(TimeSpan), typeof(TimeSpan?), "{0}.Value", "GetValue") },
|
{ (int)NpgsqlDbType.Line, ("(NpgsqlLine?)", "NpgsqlLine.Parse({0})", "{0}.ToString()", "NpgsqlLine", typeof(NpgsqlLine), typeof(NpgsqlLine?), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.Date, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
{ (int)NpgsqlDbType.LSeg, ("(NpgsqlLSeg?)", "NpgsqlLSeg.Parse({0})", "{0}.ToString()", "NpgsqlLSeg", typeof(NpgsqlLSeg), typeof(NpgsqlLSeg?), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.Timestamp, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.TotalSeconds.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
{ (int)NpgsqlDbType.Box, ("(NpgsqlBox?)", "NpgsqlBox.Parse({0})", "{0}.ToString()", "NpgsqlBox", typeof(NpgsqlBox), typeof(NpgsqlBox?), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.DateTime, ("(DateTime?)", "new DateTime(long.Parse({0}))", "{0}.Ticks.ToString()", "DateTime?", typeof(DateTime), typeof(DateTime?), "{0}.Value", "GetDateTime") },
|
{ (int)NpgsqlDbType.Path, ("(NpgsqlPath?)", "NpgsqlPath.Parse({0})", "{0}.ToString()", "NpgsqlPath", typeof(NpgsqlPath), typeof(NpgsqlPath?), "{0}", "GetValue") },
|
||||||
|
{ (int)NpgsqlDbType.Polygon, ("(NpgsqlPolygon?)", "NpgsqlPolygon.Parse({0})", "{0}.ToString()", "NpgsqlPolygon", typeof(NpgsqlPolygon), typeof(NpgsqlPolygon?), "{0}", "GetValue") },
|
||||||
|
{ (int)NpgsqlDbType.Circle, ("(NpgsqlCircle?)", "NpgsqlCircle.Parse({0})", "{0}.ToString()", "NpgsqlCircle", typeof(NpgsqlCircle), typeof(NpgsqlCircle?), "{0}", "GetValue") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.TinyBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
{ (int)NpgsqlDbType.Cidr, ("((IPAddress, int)?)", "(IPAddress, int)({0})", "{0}.ToString()", "(IPAddress, int)", typeof((IPAddress, int)), typeof((IPAddress, int)?), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.Blob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
{ (int)NpgsqlDbType.Inet, ("(IPAddress)", "IPAddress.Parse({0})", "{0}.ToString()", "IPAddress", typeof(IPAddress), typeof(IPAddress), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.MediumBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
{ (int)NpgsqlDbType.MacAddr, ("(PhysicalAddress?)", "PhysicalAddress.Parse({0})", "{0}.ToString()", "PhysicalAddress", typeof(PhysicalAddress), typeof(PhysicalAddress), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.LongBlob, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
|
||||||
|
|
||||||
{ (int)MySqlDbType.Binary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
{ (int)NpgsqlDbType.Json, ("(JToken)", "JToken.Parse({0})", "{0}.ToString()", "JToken", typeof(JToken), typeof(JToken), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.VarBinary, ("(byte[])", "Convert.FromBase64String({0})", "Convert.ToBase64String({0})", "byte[]", typeof(byte[]), typeof(byte[]), "{0}", "GetValue") },
|
{ (int)NpgsqlDbType.Jsonb, ("(JToken)", "JToken.Parse({0})", "{0}.ToString()", "JToken", typeof(JToken), typeof(JToken), "{0}", "GetString") },
|
||||||
|
{ (int)NpgsqlDbType.Uuid, ("(Guid?)", "Guid.Parse({0})", "{0}.ToString()", "Guid", typeof(Guid), typeof(Guid?), "{0}", "GetString") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.TinyText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Integer), ("(NpgsqlRange<int>?)", "{0}.ToNpgsqlRange<int>()", "{0}.ToString()", "NpgsqlRange<int>", typeof(NpgsqlRange<int>), typeof(NpgsqlRange<int>?), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.Text, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Bigint), ("(NpgsqlRange<long>?)", "{0}.ToNpgsqlRange<long>()", "{0}.ToString()", "NpgsqlRange<long>", typeof(NpgsqlRange<long>), typeof(NpgsqlRange<long>?), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.MediumText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Numeric), ("(NpgsqlRange<decimal>?)", "{0}.ToNpgsqlRange<decimal>()", "{0}.ToString()", "NpgsqlRange<decimal>", typeof(NpgsqlRange<decimal>), typeof(NpgsqlRange<decimal>?), "{0}", "GetString") },
|
||||||
{ (int)MySqlDbType.LongText, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Timestamp), ("(NpgsqlRange<DateTime>?)", "{0}.ToNpgsqlRange<DateTime>()", "{0}.ToString()", "NpgsqlRange<DateTime>", typeof(NpgsqlRange<DateTime>), typeof(NpgsqlRange<DateTime>?), "{0}", "GetString") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.TimestampTz), ("(NpgsqlRange<DateTime>?)", "{0}.ToNpgsqlRange<DateTime>()", "{0}.ToString()", "NpgsqlRange<DateTime>", typeof(NpgsqlRange<DateTime>), typeof(NpgsqlRange<DateTime>?), "{0}", "GetString") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Date), ("(NpgsqlRange<DateTime>?)", "{0}.ToNpgsqlRange<DateTime>()", "{0}.ToString()", "NpgsqlRange<DateTime>", typeof(NpgsqlRange<DateTime>), typeof(NpgsqlRange<DateTime>?), "{0}", "GetString") },
|
||||||
|
|
||||||
{ (int)MySqlDbType.String, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)NpgsqlDbType.Hstore, ("(Dictionary<string, string>)", "JsonConvert.DeserializeObject<Dictionary<string, string>>({0})", "JsonConvert.SerializeObject({0})", "Dictionary<string, string>", typeof(Dictionary<string, string>), typeof(Dictionary<string, string>), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.VarString, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
{ (int)NpgsqlDbType.Geometry, ("(PostgisGeometry)", "JsonConvert.DeserializeObject<PostgisGeometry>({0})", "JsonConvert.SerializeObject({0})", "PostgisGeometry", typeof(PostgisGeometry), typeof(PostgisGeometry), "{0}", "GetValue") },
|
||||||
{ (int)MySqlDbType.VarChar, ("", "{0}.Replace(StringifySplit, \"|\")", "{0}.Replace(\"|\", StringifySplit)", "string", typeof(string), typeof(string), "{0}", "GetString") },
|
|
||||||
|
|
||||||
{ (int)MySqlDbType.Set, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Set", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
|
/*** array ***/
|
||||||
{ (int)MySqlDbType.Enum, ("(long?)", "long.Parse({0})", "{0}.ToInt64().ToString()", "Enum", typeof(bool), typeof(Enum), "{0}", "GetInt64") },
|
|
||||||
|
|
||||||
{ (int)MySqlDbType.Geometry, ("(MygisGeometry)", "MygisGeometry.Parse({0}.Replace(StringifySplit, \"|\"))", "{0}.AsText().Replace(\"|\", StringifySplit)", "MygisGeometry", typeof(MygisGeometry), typeof(MygisGeometry), "{0}", "GetString") },
|
{ (int)(NpgsqlDbType.Smallint | NpgsqlDbType.Array), ("(short[])", "JsonConvert.DeserializeObject<short[]>({0})", "JsonConvert.SerializeObject({0})", "short[]", typeof(short[]), typeof(short[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Integer | NpgsqlDbType.Array), ("(int[])", "JsonConvert.DeserializeObject<int[]>({0})", "JsonConvert.SerializeObject({0})", "int[]", typeof(int[]), typeof(int[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Bigint | NpgsqlDbType.Array), ("(long[])", "JsonConvert.DeserializeObject<long[]>({0})", "JsonConvert.SerializeObject({0})", "long[]", typeof(long[]), typeof(long[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Numeric | NpgsqlDbType.Array), ("(decimal[])", "JsonConvert.DeserializeObject<decimal[]>({0})", "JsonConvert.SerializeObject({0})", "decimal[]", typeof(decimal[]), typeof(decimal[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Real | NpgsqlDbType.Array), ("(float[])", "JsonConvert.DeserializeObject<float[]>({0})", "JsonConvert.SerializeObject({0})", "float[]", typeof(float[]), typeof(float[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Double | NpgsqlDbType.Array), ("(double[])", "JsonConvert.DeserializeObject<double[]>({0})", "JsonConvert.SerializeObject({0})", "double[]", typeof(double[]), typeof(double[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Money | NpgsqlDbType.Array), ("(decimal[])", "JsonConvert.DeserializeObject<decimal[]>({0})", "JsonConvert.SerializeObject({0})", "decimal[]", typeof(decimal[]), typeof(decimal[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Char | NpgsqlDbType.Array), ("(string[])", "JsonConvert.DeserializeObject<string[]>({0})", "JsonConvert.SerializeObject({0})", "string[]", typeof(string[]), typeof(string[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Varchar | NpgsqlDbType.Array), ("(string[])", "JsonConvert.DeserializeObject<string[]>({0})", "JsonConvert.SerializeObject({0})", "string[]", typeof(string[]), typeof(string[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Text | NpgsqlDbType.Array), ("(string[])", "JsonConvert.DeserializeObject<string[]>({0})", "JsonConvert.SerializeObject({0})", "string[]", typeof(string[]), typeof(string[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Timestamp | NpgsqlDbType.Array), ("(DateTime[])", "JsonConvert.DeserializeObject<DateTime[]>({0})", "JsonConvert.SerializeObject({0})", "DateTime[]", typeof(DateTime[]), typeof(DateTime[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.TimestampTz | NpgsqlDbType.Array), ("(DateTime[])", "JsonConvert.DeserializeObject<DateTime[]>({0})", "JsonConvert.SerializeObject({0})", "DateTime[]", typeof(DateTime[]), typeof(DateTime[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Date | NpgsqlDbType.Array), ("(DateTime[])", "JsonConvert.DeserializeObject<DateTime[]>({0})", "JsonConvert.SerializeObject({0})", "DateTime[]", typeof(DateTime[]), typeof(DateTime[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Time | NpgsqlDbType.Array), ("(TimeSpan[])", "JsonConvert.DeserializeObject<TimeSpan[]>({0})", "JsonConvert.SerializeObject({0})", "TimeSpan[]", typeof(TimeSpan[]), typeof(TimeSpan[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.TimeTz | NpgsqlDbType.Array), ("(TimeSpan[])", "JsonConvert.DeserializeObject<TimeSpan[]>({0})", "JsonConvert.SerializeObject({0})", "TimeSpan[]", typeof(TimeSpan[]), typeof(TimeSpan[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Interval | NpgsqlDbType.Array), ("(TimeSpan[])", "JsonConvert.DeserializeObject<TimeSpan[]>({0})", "JsonConvert.SerializeObject({0})", "TimeSpan[]", typeof(TimeSpan[]), typeof(TimeSpan[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Boolean | NpgsqlDbType.Array), ("(bool[])", "JsonConvert.DeserializeObject<bool[]>({0})", "JsonConvert.SerializeObject({0})", "bool[]", typeof(bool[]), typeof(bool[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Bytea | NpgsqlDbType.Array), ("(byte[][])", "JsonConvert.DeserializeObject<byte[][]>({0})", "JsonConvert.SerializeObject({0})", "byte[][]", typeof(byte[][]), typeof(byte[][]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Bit | NpgsqlDbType.Array), ("(BitArray[])", "JsonConvert.DeserializeObject<BitArray[]>({0})", "JsonConvert.SerializeObject({0})", "BitArray[]", typeof(BitArray[]), typeof(BitArray[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Varbit | NpgsqlDbType.Array), ("(BitArray[])", "JsonConvert.DeserializeObject<BitArray[]>({0})", "JsonConvert.SerializeObject({0})", "BitArray[]", typeof(BitArray[]), typeof(BitArray[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Point | NpgsqlDbType.Array), ("(NpgsqlPoint[])", "JsonConvert.DeserializeObject<NpgsqlPoint[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlPoint[]", typeof(NpgsqlPoint[]), typeof(NpgsqlPoint[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Line | NpgsqlDbType.Array), ("(NpgsqlLine[])", "JsonConvert.DeserializeObject<BNpgsqlLineitArray[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlLine[]", typeof(NpgsqlLine[]), typeof(NpgsqlLine[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.LSeg | NpgsqlDbType.Array), ("(NpgsqlLSeg[])", "JsonConvert.DeserializeObject<NpgsqlLSeg[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlLSeg[]", typeof(NpgsqlLSeg[]), typeof(NpgsqlLSeg[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Box | NpgsqlDbType.Array), ("(NpgsqlBox[])", "JsonConvert.DeserializeObject<NpgsqlBox[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlBox[]", typeof(NpgsqlBox[]), typeof(NpgsqlBox[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Path | NpgsqlDbType.Array), ("(NpgsqlPath[])", "JsonConvert.DeserializeObject<NpgsqlPath[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlPath[]", typeof(NpgsqlPath[]), typeof(NpgsqlPath[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Polygon | NpgsqlDbType.Array), ("(NpgsqlPolygon[])", "JsonConvert.DeserializeObject<NpgsqlPolygon[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlPolygon[]", typeof(NpgsqlPolygon[]), typeof(NpgsqlPolygon[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Circle | NpgsqlDbType.Array), ("(NpgsqlCircle[])", "JsonConvert.DeserializeObject<NpgsqlCircle[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlCircle[]", typeof(NpgsqlCircle[]), typeof(NpgsqlCircle[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Cidr | NpgsqlDbType.Array), ("((IPAddress, int)[])", "JsonConvert.DeserializeObject<(IPAddress, int)[]>({0})", "JsonConvert.SerializeObject({0})", "(IPAddress, int)[]", typeof((IPAddress, int)[]), typeof((IPAddress, int)[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Inet | NpgsqlDbType.Array), ("(IPAddress[])", "JsonConvert.DeserializeObject<IPAddress[]>({0})", "JsonConvert.SerializeObject({0})", "IPAddress[]", typeof(IPAddress[]), typeof(IPAddress[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.MacAddr | NpgsqlDbType.Array), ("(PhysicalAddress[])", "JsonConvert.DeserializeObject<PhysicalAddress[]>({0})", "JsonConvert.SerializeObject({0})", "PhysicalAddress[]", typeof(PhysicalAddress[]), typeof(PhysicalAddress[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Json | NpgsqlDbType.Array), ("(JToken[])", "JsonConvert.DeserializeObject<JToken[]>({0})", "JsonConvert.SerializeObject({0})", "JToken[]", typeof(JToken[]), typeof(JToken[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Jsonb | NpgsqlDbType.Array), ("(JToken[])", "JsonConvert.DeserializeObject<JToken[]>({0})", "JsonConvert.SerializeObject({0})", "JToken[]", typeof(JToken[]), typeof(JToken[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Uuid | NpgsqlDbType.Array), ("(Guid[])", "JsonConvert.DeserializeObject<Guid[]>({0})", "JsonConvert.SerializeObject({0})", "Guid[]", typeof(Guid[]), typeof(Guid[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Integer | NpgsqlDbType.Array), ("(NpgsqlRange<int>[])", "JsonConvert.DeserializeObject<NpgsqlRange<int>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<int>[]", typeof(NpgsqlRange<int>[]), typeof(NpgsqlRange<int>[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Bigint | NpgsqlDbType.Array), ("(NpgsqlRange<long>[])", "JsonConvert.DeserializeObject<NpgsqlRange<long>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<long>[]", typeof(NpgsqlRange<long>[]), typeof(NpgsqlRange<long>[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Numeric | NpgsqlDbType.Array), ("(NpgsqlRange<decimal>[])", "JsonConvert.DeserializeObject<NpgsqlRange<decimal>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<decimal>[]", typeof(NpgsqlRange<decimal>[]), typeof(NpgsqlRange<decimal>[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Timestamp | NpgsqlDbType.Array), ("(NpgsqlRange<DateTime>[])", "JsonConvert.DeserializeObject<NpgsqlRange<DateTime>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<DateTime>[]", typeof(NpgsqlRange<DateTime>[]), typeof(NpgsqlRange<DateTime>[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.TimestampTz | NpgsqlDbType.Array), ("(NpgsqlRange<DateTime>[])", "JsonConvert.DeserializeObject<NpgsqlRange<DateTime>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<DateTime>[]", typeof(NpgsqlRange<DateTime>[]), typeof(NpgsqlRange<DateTime>[]), "{0}", "GetValue") },
|
||||||
|
{ (int)(NpgsqlDbType.Range | NpgsqlDbType.Date | NpgsqlDbType.Array), ("(NpgsqlRange<DateTime>[])", "JsonConvert.DeserializeObject<NpgsqlRange<DateTime>[]>({0})", "JsonConvert.SerializeObject({0})", "NpgsqlRange<DateTime>[]", typeof(NpgsqlRange<DateTime>[]), typeof(NpgsqlRange<DateTime>[]), "{0}", "GetValue") },
|
||||||
|
|
||||||
|
{ (int)(NpgsqlDbType.Hstore | NpgsqlDbType.Array), ("(Dictionary<string, string>[])", "JsonConvert.DeserializeObject<Dictionary<string, string>[]>({0})", "JsonConvert.SerializeObject({0})", "Dictionary<string, string>[]", typeof(Dictionary<string, string>[]), typeof(Dictionary<string, string>[]), "{0}", "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) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
|
public string GetCsConvert(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? (column.IsNullable ? trydc.csConvert : trydc.csConvert.Replace("?", "")) : null;
|
||||||
@ -130,252 +198,313 @@ namespace FreeSql.PostgreSQL {
|
|||||||
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
||||||
|
|
||||||
public List<string> GetDatabases() {
|
public List<string> GetDatabases() {
|
||||||
var sql = @"select schema_name from information_schema.schemata where schema_name not in ('information_schema', 'mysql', 'performance_schema')";
|
var sql = @" select datname from pg_database where datname not in ('template1', 'template0')";
|
||||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
|
public List<DbTableInfo> GetTablesByDatabase(params string[] database) {
|
||||||
var loc1 = new List<DbTableInfo>();
|
var olddatabase = "";
|
||||||
var loc2 = new Dictionary<string, DbTableInfo>();
|
using (var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5))) {
|
||||||
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
|
olddatabase = conn.Value.Database;
|
||||||
|
|
||||||
if (database == null || database.Any() == false) return loc1;
|
|
||||||
var databaseIn = string.Join(",", database.Select(a => "{0}".FormatMySql(a)));
|
|
||||||
var sql = string.Format(@"select
|
|
||||||
concat(a.table_schema, '.', a.table_name) 'id',
|
|
||||||
a.table_schema 'schema',
|
|
||||||
a.table_name 'table',
|
|
||||||
a.table_type 'type'
|
|
||||||
from information_schema.tables a
|
|
||||||
where a.table_schema in ({0})", databaseIn);
|
|
||||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
|
||||||
if (ds == null) return loc1;
|
|
||||||
|
|
||||||
var loc6 = new List<string>();
|
|
||||||
var loc66 = new List<string>();
|
|
||||||
foreach (var row in ds) {
|
|
||||||
var table_id = string.Concat(row[0]);
|
|
||||||
var schema = string.Concat(row[1]);
|
|
||||||
var table = string.Concat(row[2]);
|
|
||||||
var type = string.Concat(row[3]) == "VIEW" ? DbTableType.VIEW : DbTableType.TABLE;
|
|
||||||
if (database.Length == 1) {
|
|
||||||
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
|
||||||
schema = "";
|
|
||||||
}
|
|
||||||
loc2.Add(table_id, new DbTableInfo { Id = table_id, Schema = schema, Name = table, Type = type });
|
|
||||||
loc3.Add(table_id, new Dictionary<string, DbColumnInfo>());
|
|
||||||
switch (type) {
|
|
||||||
case DbTableType.TABLE:
|
|
||||||
case DbTableType.VIEW:
|
|
||||||
loc6.Add(table.Replace("'", "''"));
|
|
||||||
break;
|
|
||||||
case DbTableType.StoreProcedure:
|
|
||||||
loc66.Add(table.Replace("'", "''"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (loc6.Count == 0) return loc1;
|
var dbs = database?.ToArray() ?? new[] { olddatabase };
|
||||||
var loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
|
var tables = new List<DbTableInfo>();
|
||||||
var loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
|
|
||||||
|
|
||||||
sql = string.Format(@"select
|
foreach (var db in dbs) {
|
||||||
concat(a.table_schema, '.', a.table_name),
|
if (string.IsNullOrEmpty(db) || string.Compare(db, olddatabase, true) != 0) continue;
|
||||||
a.column_name,
|
|
||||||
a.data_type,
|
|
||||||
ifnull(a.character_maximum_length, 0) 'len',
|
|
||||||
a.column_type,
|
|
||||||
case when a.is_nullable = 'YES' then 1 else 0 end 'is_nullable',
|
|
||||||
case when locate('auto_increment', a.extra) > 0 then 1 else 0 end 'is_identity',
|
|
||||||
a.column_comment 'comment'
|
|
||||||
from information_schema.columns a
|
|
||||||
where a.table_schema in ({1}) and a.table_name in ({0})
|
|
||||||
", loc8, databaseIn);
|
|
||||||
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
|
||||||
if (ds == null) return loc1;
|
|
||||||
|
|
||||||
foreach (var row in ds) {
|
var loc1 = new List<DbTableInfo>();
|
||||||
string table_id = string.Concat(row[0]);
|
var loc2 = new Dictionary<string, DbTableInfo>();
|
||||||
string column = string.Concat(row[1]);
|
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
|
||||||
string type = string.Concat(row[2]);
|
|
||||||
//long max_length = long.Parse(string.Concat(row[3]));
|
var sql = $@"
|
||||||
string sqlType = string.Concat(row[4]);
|
select
|
||||||
var m_len = Regex.Match(sqlType, @"\w+\((\d+)");
|
b.nspname || '.' || a.tablename,
|
||||||
int max_length = m_len.Success ? int.Parse(m_len.Groups[1].Value) : -1;
|
a.schemaname,
|
||||||
bool is_nullable = string.Concat(row[5]) == "1";
|
a.tablename ,
|
||||||
bool is_identity = string.Concat(row[6]) == "1";
|
'TABLE'
|
||||||
string comment = string.Concat(row[7]);
|
from pg_tables a
|
||||||
if (max_length == 0) max_length = -1;
|
inner join pg_namespace b on b.nspname = a.schemaname
|
||||||
if (database.Length == 1) {
|
where a.schemaname not in ('pg_catalog', 'information_schema', 'topology')
|
||||||
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
and b.nspname || '.' || a.tablename not in ('public.spatial_ref_sys')
|
||||||
|
|
||||||
|
union all
|
||||||
|
|
||||||
|
select
|
||||||
|
b.nspname || '.' || a.relname,
|
||||||
|
b.nspname,
|
||||||
|
a.relname,
|
||||||
|
'VIEW'
|
||||||
|
from pg_class a
|
||||||
|
inner join pg_namespace b on b.oid = a.relnamespace
|
||||||
|
where b.nspname not in ('pg_catalog', 'information_schema') and a.relkind in ('m','v')
|
||||||
|
and b.nspname || '.' || a.relname not in ('public.geography_columns','public.geometry_columns','public.raster_columns','public.raster_overviews')
|
||||||
|
";
|
||||||
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
var loc6 = new List<string>();
|
||||||
|
var loc66 = new List<string>();
|
||||||
|
foreach (object[] row in ds) {
|
||||||
|
var object_id = string.Concat(row[0]);
|
||||||
|
var owner = string.Concat(row[1]);
|
||||||
|
var table = string.Concat(row[2]);
|
||||||
|
Enum.TryParse<DbTableType>(string.Concat(row[3]), out var type);
|
||||||
|
loc2.Add(object_id, new DbTableInfo { Id = object_id.ToString(), Schema = owner, Name = table, Type = type });
|
||||||
|
loc3.Add(object_id, new Dictionary<string, DbColumnInfo>());
|
||||||
|
switch (type) {
|
||||||
|
case DbTableType.VIEW:
|
||||||
|
case DbTableType.TABLE:
|
||||||
|
loc6.Add(object_id);
|
||||||
|
break;
|
||||||
|
case DbTableType.StoreProcedure:
|
||||||
|
loc66.Add(object_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loc3[table_id].Add(column, new DbColumnInfo {
|
if (loc6.Count == 0) return loc1;
|
||||||
Name = column,
|
string loc8 = "'" + string.Join("','", loc6.ToArray()) + "'";
|
||||||
MaxLength = max_length,
|
string loc88 = "'" + string.Join("','", loc66.ToArray()) + "'";
|
||||||
IsIdentity = is_identity,
|
|
||||||
IsNullable = is_nullable,
|
|
||||||
IsPrimary = false,
|
|
||||||
DbTypeText = type,
|
|
||||||
DbTypeTextFull = sqlType,
|
|
||||||
Table = loc2[table_id],
|
|
||||||
Coment = comment
|
|
||||||
});
|
|
||||||
loc3[table_id][column].DbType = this.GetDbType(loc3[table_id][column]);
|
|
||||||
loc3[table_id][column].CsType = this.GetCsTypeInfo(loc3[table_id][column]);
|
|
||||||
}
|
|
||||||
|
|
||||||
sql = string.Format(@"select
|
sql = $@"
|
||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
select
|
||||||
a.column_name,
|
ns.nspname || '.' || c.relname as id,
|
||||||
concat(a.constraint_schema, '/', a.table_name, '/', a.constraint_name) 'index_id',
|
t.typname,
|
||||||
1 'IsUnique',
|
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
|
||||||
case when constraint_name = 'PRIMARY' then 1 else 0 end 'IsPrimaryKey',
|
case when t.typelem = 0 then t.typname else t2.typname end,
|
||||||
0 'IsClustered',
|
case when a.attnotnull then 0 else 1 end as is_nullable,
|
||||||
0 'IsDesc'
|
e.adsrc as is_identity,
|
||||||
from information_schema.key_column_usage a
|
--case when e.adsrc = 'nextval(''' || case when ns.nspname = 'public' then '' else ns.nspname || '.' end || c.relname || '_' || a.attname || '_seq''::regclass)' then 1 else 0 end as is_identity,
|
||||||
where a.constraint_schema in ({1}) and a.table_name in ({0}) and isnull(position_in_unique_constraint)
|
d.description as comment,
|
||||||
", loc8, databaseIn);
|
a.attndims,
|
||||||
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
case when t.typelem = 0 then t.typtype else t2.typtype end,
|
||||||
if (ds == null) return loc1;
|
ns2.nspname,
|
||||||
|
a.attnum
|
||||||
|
from pg_class c
|
||||||
|
inner join pg_attribute a on a.attnum > 0 and a.attrelid = c.oid
|
||||||
|
inner join pg_type t on t.oid = a.atttypid
|
||||||
|
left join pg_type t2 on t2.oid = t.typelem
|
||||||
|
left join pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
|
||||||
|
left join pg_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
|
||||||
|
inner join pg_namespace ns on ns.oid = c.relnamespace
|
||||||
|
inner join pg_namespace ns2 on ns2.oid = t.typnamespace
|
||||||
|
where ns.nspname || '.' || c.relname in ({loc88})";
|
||||||
|
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
|
foreach (object[] row in ds) {
|
||||||
var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
|
var object_id = string.Concat(row[0]);
|
||||||
foreach (var row in ds) {
|
var column = string.Concat(row[1]);
|
||||||
string table_id = string.Concat(row[0]);
|
var type = string.Concat(row[2]);
|
||||||
string column = string.Concat(row[1]);
|
var max_length = int.Parse(string.Concat(row[3]));
|
||||||
string index_id = string.Concat(row[2]);
|
var sqlType = string.Concat(row[4]);
|
||||||
bool is_unique = string.Concat(row[3]) == "1";
|
var is_nullable = string.Concat(row[5]) == "1";
|
||||||
bool is_primary_key = string.Concat(row[4]) == "1";
|
var is_identity = string.Concat(row[6]).StartsWith(@"nextval('") && string.Concat(row[6]).EndsWith(@"_seq'::regclass)");
|
||||||
bool is_clustered = string.Concat(row[5]) == "1";
|
var comment = string.Concat(row[7]);
|
||||||
int is_desc = int.Parse(string.Concat(row[6]));
|
int attndims = int.Parse(string.Concat(row[8]));
|
||||||
if (database.Length == 1) {
|
string typtype = string.Concat(row[9]);
|
||||||
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
string owner = string.Concat(row[10]);
|
||||||
|
int attnum = int.Parse(string.Concat(row[11]));
|
||||||
|
switch (sqlType.ToLower()) {
|
||||||
|
case "bool": case "name": case "bit": case "varbit": case "bpchar": case "varchar": case "bytea": case "text": case "uuid": break;
|
||||||
|
default: max_length *= 8; break;
|
||||||
|
}
|
||||||
|
if (max_length <= 0) max_length = -1;
|
||||||
|
if (type.StartsWith("_")) {
|
||||||
|
type = type.Substring(1);
|
||||||
|
if (attndims == 0) attndims++;
|
||||||
|
}
|
||||||
|
if (sqlType.StartsWith("_")) sqlType = sqlType.Substring(1);
|
||||||
|
|
||||||
|
loc3[object_id].Add(column, new DbColumnInfo {
|
||||||
|
Name = column,
|
||||||
|
MaxLength = max_length,
|
||||||
|
IsIdentity = is_identity,
|
||||||
|
IsNullable = is_nullable,
|
||||||
|
IsPrimary = false,
|
||||||
|
DbTypeText = type,
|
||||||
|
DbTypeTextFull = sqlType,
|
||||||
|
Table = loc2[object_id],
|
||||||
|
Coment = comment
|
||||||
|
});
|
||||||
|
loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]);
|
||||||
|
loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]);
|
||||||
}
|
}
|
||||||
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
|
|
||||||
var loc9 = loc3[table_id][column];
|
|
||||||
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
|
|
||||||
|
|
||||||
Dictionary<string, List<DbColumnInfo>> loc10 = null;
|
sql = $@"
|
||||||
List<DbColumnInfo> loc11 = null;
|
select
|
||||||
if (!indexColumns.TryGetValue(table_id, out loc10))
|
ns.nspname || '.' || d.relname as table_id,
|
||||||
indexColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
|
c.attname,
|
||||||
if (!loc10.TryGetValue(index_id, out loc11))
|
ns.nspname || '/' || d.relname || '/' || b.relname as index_id,
|
||||||
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
|
case when a.indisunique then 1 else 0 end IsUnique,
|
||||||
loc11.Add(loc9);
|
case when a.indisprimary then 1 else 0 end IsPrimary,
|
||||||
if (is_unique) {
|
case when a.indisclustered then 0 else 1 end IsClustered,
|
||||||
if (!uniqueColumns.TryGetValue(table_id, out loc10))
|
0 IsDesc,
|
||||||
uniqueColumns.Add(table_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
|
a.indkey::text,
|
||||||
|
c.attnum
|
||||||
|
from pg_index a
|
||||||
|
inner join pg_class b on b.oid = a.indexrelid
|
||||||
|
inner join pg_attribute c on c.attnum > 0 and c.attrelid = b.oid
|
||||||
|
inner join pg_namespace ns on ns.oid = b.relnamespace
|
||||||
|
inner join pg_class d on d.oid = a.indrelid
|
||||||
|
where ns.nspname || '.' || d.relname in ({loc8})
|
||||||
|
";
|
||||||
|
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
var indexColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
|
||||||
|
var uniqueColumns = new Dictionary<string, Dictionary<string, List<DbColumnInfo>>>();
|
||||||
|
foreach (object[] row in ds) {
|
||||||
|
var object_id = string.Concat(row[0]);
|
||||||
|
var column = string.Concat(row[1]);
|
||||||
|
var index_id = string.Concat(row[2]);
|
||||||
|
var is_unique = string.Concat(row[3]) == "1";
|
||||||
|
var is_primary_key = string.Concat(row[4]) == "1";
|
||||||
|
var is_clustered = string.Concat(row[5]) == "1";
|
||||||
|
var is_desc = int.Parse(string.Concat(row[6]));
|
||||||
|
var inkey = string.Concat(row[7]).Split(' ');
|
||||||
|
var attnum = int.Parse(string.Concat(row[8]));
|
||||||
|
attnum = int.Parse(inkey[attnum - 1]);
|
||||||
|
foreach (string tc in loc3[object_id].Keys) {
|
||||||
|
if (loc3[object_id][tc].DbTypeText.EndsWith("[]")) {
|
||||||
|
column = tc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (loc3.ContainsKey(object_id) == false || loc3[object_id].ContainsKey(column) == false) continue;
|
||||||
|
var loc9 = loc3[object_id][column];
|
||||||
|
if (loc9.IsPrimary == false && is_primary_key) loc9.IsPrimary = is_primary_key;
|
||||||
|
|
||||||
|
Dictionary<string, List<DbColumnInfo>> loc10 = null;
|
||||||
|
List<DbColumnInfo> loc11 = null;
|
||||||
|
if (!indexColumns.TryGetValue(object_id, out loc10))
|
||||||
|
indexColumns.Add(object_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
|
||||||
if (!loc10.TryGetValue(index_id, out loc11))
|
if (!loc10.TryGetValue(index_id, out loc11))
|
||||||
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
|
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
|
||||||
loc11.Add(loc9);
|
loc11.Add(loc9);
|
||||||
}
|
if (is_unique) {
|
||||||
}
|
if (!uniqueColumns.TryGetValue(object_id, out loc10))
|
||||||
foreach (string table_id in indexColumns.Keys) {
|
uniqueColumns.Add(object_id, loc10 = new Dictionary<string, List<DbColumnInfo>>());
|
||||||
foreach (var columns in indexColumns[table_id].Values)
|
if (!loc10.TryGetValue(index_id, out loc11))
|
||||||
loc2[table_id].Indexes.Add(columns);
|
loc10.Add(index_id, loc11 = new List<DbColumnInfo>());
|
||||||
}
|
loc11.Add(loc9);
|
||||||
foreach (string table_id in uniqueColumns.Keys) {
|
|
||||||
foreach (var columns in uniqueColumns[table_id].Values) {
|
|
||||||
columns.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
|
|
||||||
loc2[table_id].Uniques.Add(columns);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sql = string.Format(@"select
|
|
||||||
concat(a.constraint_schema, '.', a.table_name) 'table_id',
|
|
||||||
a.column_name,
|
|
||||||
concat(a.constraint_schema, '/', a.constraint_name) 'FKId',
|
|
||||||
concat(a.referenced_table_schema, '.', a.referenced_table_name) 'ref_table_id',
|
|
||||||
1 'IsForeignKey',
|
|
||||||
a.referenced_column_name 'ref_column'
|
|
||||||
from information_schema.key_column_usage a
|
|
||||||
where a.constraint_schema in ({1}) and a.table_name in ({0}) and not isnull(position_in_unique_constraint)
|
|
||||||
", loc8, databaseIn);
|
|
||||||
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
|
||||||
if (ds == null) return loc1;
|
|
||||||
|
|
||||||
var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
|
|
||||||
foreach (var row in ds) {
|
|
||||||
string table_id = string.Concat(row[0]);
|
|
||||||
string column = string.Concat(row[1]);
|
|
||||||
string fk_id = string.Concat(row[2]);
|
|
||||||
string ref_table_id = string.Concat(row[3]);
|
|
||||||
bool is_foreign_key = string.Concat(row[4]) == "1";
|
|
||||||
string referenced_column = string.Concat(row[5]);
|
|
||||||
if (database.Length == 1) {
|
|
||||||
table_id = table_id.Substring(table_id.IndexOf('.') + 1);
|
|
||||||
ref_table_id = ref_table_id.Substring(ref_table_id.IndexOf('.') + 1);
|
|
||||||
}
|
|
||||||
if (loc3.ContainsKey(table_id) == false || loc3[table_id].ContainsKey(column) == false) continue;
|
|
||||||
var loc9 = loc3[table_id][column];
|
|
||||||
if (loc2.ContainsKey(ref_table_id) == false) continue;
|
|
||||||
var loc10 = loc2[ref_table_id];
|
|
||||||
var loc11 = loc3[ref_table_id][referenced_column];
|
|
||||||
|
|
||||||
Dictionary<string, DbForeignInfo> loc12 = null;
|
|
||||||
DbForeignInfo loc13 = null;
|
|
||||||
if (!fkColumns.TryGetValue(table_id, out loc12))
|
|
||||||
fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
|
|
||||||
if (!loc12.TryGetValue(fk_id, out loc13))
|
|
||||||
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc10 });
|
|
||||||
loc13.Columns.Add(loc9);
|
|
||||||
loc13.ReferencedColumns.Add(loc11);
|
|
||||||
}
|
|
||||||
foreach (var table_id in fkColumns.Keys)
|
|
||||||
foreach (var fk in fkColumns[table_id].Values)
|
|
||||||
loc2[table_id].Foreigns.Add(fk);
|
|
||||||
|
|
||||||
foreach (var table_id in loc3.Keys) {
|
|
||||||
foreach (var loc5 in loc3[table_id].Values) {
|
|
||||||
loc2[table_id].Columns.Add(loc5);
|
|
||||||
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
|
|
||||||
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (var loc4 in loc2.Values) {
|
|
||||||
if (loc4.Primarys.Count == 0 && loc4.Uniques.Count > 0) {
|
|
||||||
foreach (var loc5 in loc4.Uniques[0]) {
|
|
||||||
loc5.IsPrimary = true;
|
|
||||||
loc4.Primarys.Add(loc5);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
|
foreach (var object_id in indexColumns.Keys) {
|
||||||
loc4.Columns.Sort((c1, c2) => {
|
foreach (List<DbColumnInfo> columns in indexColumns[object_id].Values)
|
||||||
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
|
loc2[object_id].Indexes.Add(columns);
|
||||||
if (compare == 0) {
|
}
|
||||||
bool b1 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c1.Name) != null) != null;
|
foreach (var object_id in uniqueColumns.Keys) {
|
||||||
bool b2 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c2.Name) != null) != null;
|
foreach (var columns in uniqueColumns[object_id].Values) {
|
||||||
compare = b2.CompareTo(b1);
|
columns.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
|
||||||
|
loc2[object_id].Uniques.Add(columns);
|
||||||
}
|
}
|
||||||
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
|
}
|
||||||
return compare;
|
|
||||||
|
sql = $@"
|
||||||
|
select
|
||||||
|
ns.nspname || '.' || b.relname as table_id,
|
||||||
|
array(select attname from pg_attribute where attrelid = a.conrelid and attnum = any(a.conkey)) as column_name,
|
||||||
|
a.connamespace || '/' || a.conname as FKId,
|
||||||
|
ns2.nspname || '.' || c.relname as ref_table_id,
|
||||||
|
1 as IsForeignKey,
|
||||||
|
array(select attname from pg_attribute where attrelid = a.confrelid and attnum = any(a.confkey)) as ref_column,
|
||||||
|
null ref_sln,
|
||||||
|
null ref_table
|
||||||
|
from pg_constraint a
|
||||||
|
inner join pg_class b on b.oid = a.conrelid
|
||||||
|
inner join pg_class c on c.oid = a.confrelid
|
||||||
|
inner join pg_namespace ns on ns.oid = b.relnamespace
|
||||||
|
inner join pg_namespace ns2 on ns2.oid = c.relnamespace
|
||||||
|
where ns.nspname || '.' || b.relname in ({loc8})
|
||||||
|
";
|
||||||
|
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
|
if (ds == null) return loc1;
|
||||||
|
|
||||||
|
var fkColumns = new Dictionary<string, Dictionary<string, DbForeignInfo>>();
|
||||||
|
foreach (object[] row in ds) {
|
||||||
|
var table_id = string.Concat(row[0]);
|
||||||
|
var column = row[1] as string[];
|
||||||
|
var fk_id = string.Concat(row[2]);
|
||||||
|
var ref_table_id = string.Concat(row[3]);
|
||||||
|
var is_foreign_key = string.Concat(row[4]) == "1";
|
||||||
|
var referenced_column = row[5] as string[];
|
||||||
|
var referenced_db = string.Concat(row[6]);
|
||||||
|
var referenced_table = string.Concat(row[7]);
|
||||||
|
|
||||||
|
if (loc2.ContainsKey(ref_table_id) == false) continue;
|
||||||
|
|
||||||
|
Dictionary<string, DbForeignInfo> loc12 = null;
|
||||||
|
DbForeignInfo loc13 = null;
|
||||||
|
if (!fkColumns.TryGetValue(table_id, out loc12))
|
||||||
|
fkColumns.Add(table_id, loc12 = new Dictionary<string, DbForeignInfo>());
|
||||||
|
if (!loc12.TryGetValue(fk_id, out loc13))
|
||||||
|
loc12.Add(fk_id, loc13 = new DbForeignInfo { Table = loc2[table_id], ReferencedTable = loc2[ref_table_id] });
|
||||||
|
|
||||||
|
for (int a = 0; a < column.Length; a++) {
|
||||||
|
loc13.Columns.Add(loc3[table_id][column[a]]);
|
||||||
|
loc13.ReferencedColumns.Add(loc3[ref_table_id][referenced_column[a]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var table_id in fkColumns.Keys)
|
||||||
|
foreach (var fk in fkColumns[table_id].Values)
|
||||||
|
loc2[table_id].Foreigns.Add(fk);
|
||||||
|
|
||||||
|
foreach (var table_id in loc3.Keys) {
|
||||||
|
foreach (var loc5 in loc3[table_id].Values) {
|
||||||
|
loc2[table_id].Columns.Add(loc5);
|
||||||
|
if (loc5.IsIdentity) loc2[table_id].Identitys.Add(loc5);
|
||||||
|
if (loc5.IsPrimary) loc2[table_id].Primarys.Add(loc5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var loc4 in loc2.Values) {
|
||||||
|
if (loc4.Primarys.Count == 0 && loc4.Uniques.Count > 0) {
|
||||||
|
foreach (var loc5 in loc4.Uniques[0]) {
|
||||||
|
loc5.IsPrimary = true;
|
||||||
|
loc4.Primarys.Add(loc5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loc4.Primarys.Sort((c1, c2) => c1.Name.CompareTo(c2.Name));
|
||||||
|
loc4.Columns.Sort((c1, c2) => {
|
||||||
|
int compare = c2.IsPrimary.CompareTo(c1.IsPrimary);
|
||||||
|
if (compare == 0) {
|
||||||
|
bool b1 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c1.Name) != null) != null;
|
||||||
|
bool b2 = loc4.Foreigns.Find(fk => fk.Columns.Find(c3 => c3.Name == c2.Name) != null) != null;
|
||||||
|
compare = b2.CompareTo(b1);
|
||||||
|
}
|
||||||
|
if (compare == 0) compare = c1.Name.CompareTo(c2.Name);
|
||||||
|
return compare;
|
||||||
|
});
|
||||||
|
loc1.Add(loc4);
|
||||||
|
}
|
||||||
|
loc1.Sort((t1, t2) => {
|
||||||
|
var ret = t1.Schema.CompareTo(t2.Schema);
|
||||||
|
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
|
||||||
|
return ret;
|
||||||
});
|
});
|
||||||
loc1.Add(loc4);
|
foreach (var loc4 in loc1) {
|
||||||
}
|
var dicUniques = new Dictionary<string, List<DbColumnInfo>>();
|
||||||
loc1.Sort((t1, t2) => {
|
if (loc4.Primarys.Count > 0) dicUniques.Add(string.Join(",", loc4.Primarys.Select(a => a.Name)), loc4.Primarys);
|
||||||
var ret = t1.Schema.CompareTo(t2.Schema);
|
foreach (var loc5 in loc4.Uniques) {
|
||||||
if (ret == 0) ret = t1.Name.CompareTo(t2.Name);
|
var dickey = string.Join(",", loc5.Select(a => a.Name));
|
||||||
return ret;
|
if (dicUniques.ContainsKey(dickey)) continue;
|
||||||
});
|
dicUniques.Add(dickey, loc5);
|
||||||
foreach (var loc4 in loc1) {
|
}
|
||||||
var dicUniques = new Dictionary<string, List<DbColumnInfo>>();
|
loc4.Uniques = dicUniques.Values.ToList();
|
||||||
if (loc4.Primarys.Count > 0) dicUniques.Add(string.Join(",", loc4.Primarys.Select(a => a.Name)), loc4.Primarys);
|
|
||||||
foreach (var loc5 in loc4.Uniques) {
|
|
||||||
var dickey = string.Join(",", loc5.Select(a => a.Name));
|
|
||||||
if (dicUniques.ContainsKey(dickey)) continue;
|
|
||||||
dicUniques.Add(dickey, loc5);
|
|
||||||
}
|
}
|
||||||
loc4.Uniques = dicUniques.Values.ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
loc2.Clear();
|
loc2.Clear();
|
||||||
loc3.Clear();
|
loc3.Clear();
|
||||||
return loc1;
|
tables.AddRange(loc1);
|
||||||
|
}
|
||||||
|
return tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
|
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) {
|
||||||
if (database == null || database.Length == 0) return new List<DbEnumInfo>();
|
if (database == null || database.Length == 0) return new List<DbEnumInfo>();
|
||||||
var drs = _orm.Ado.Query<(string name, string label)>(CommandType.Text, @"select
|
var drs = _orm.Ado.Query<(string name, string label)>(CommandType.Text, @"
|
||||||
|
select
|
||||||
ns.nspname || '.' || a.typname,
|
ns.nspname || '.' || a.typname,
|
||||||
b.enumlabel
|
b.enumlabel
|
||||||
from pg_type a
|
from pg_type a
|
||||||
|
@ -77,7 +77,7 @@ namespace FreeSql.SqlServer {
|
|||||||
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5));
|
||||||
var database = conn.Value.Database;
|
var database = conn.Value.Database;
|
||||||
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
Func<string, string, object> ExecuteScalar = (db, sql) => {
|
||||||
if (string.Compare(database, db) != 0) try { conn.Value.ChangeDatabase(db); } catch { }
|
if (string.Compare(database, db) != 0) conn.Value.ChangeDatabase(db);
|
||||||
try {
|
try {
|
||||||
using (var cmd = conn.Value.CreateCommand()) {
|
using (var cmd = conn.Value.CreateCommand()) {
|
||||||
cmd.CommandText = sql;
|
cmd.CommandText = sql;
|
||||||
@ -101,18 +101,18 @@ namespace FreeSql.SqlServer {
|
|||||||
if (tboldname?.Length == 1) tboldname = new[] { database, "dbo", tboldname[0] };
|
if (tboldname?.Length == 1) tboldname = new[] { database, "dbo", tboldname[0] };
|
||||||
if (tboldname?.Length == 2) tboldname = new[] { database, tboldname[0], tboldname[1] };
|
if (tboldname?.Length == 2) tboldname = new[] { database, tboldname[0], tboldname[1] };
|
||||||
|
|
||||||
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $"select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库
|
if (string.Compare(tbname[0], database, true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tbname[0]}'") == null) //创建数据库
|
||||||
ExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];");
|
ExecuteScalar(database, $"if not exists(select 1 from sys.databases where name='{tbname[0]}')\r\n\tcreate database [{tbname[0]}];");
|
||||||
if (string.Compare(tbname[1], "dbo", true) != 0 && ExecuteScalar(tbname[0], $"select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式
|
if (string.Compare(tbname[1], "dbo", true) != 0 && ExecuteScalar(tbname[0], $" select 1 from sys.schemas where name='{tbname[1]}'") == null) //创建模式
|
||||||
ExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]");
|
ExecuteScalar(tbname[0], $"create schema [{tbname[1]}] authorization [dbo]");
|
||||||
|
|
||||||
var sbalter = new StringBuilder();
|
var sbalter = new StringBuilder();
|
||||||
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
var istmpatler = false; //创建临时表,导入数据,删除旧表,修改
|
||||||
if (ExecuteScalar(tbname[0], $"select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) { //表不存在
|
if (ExecuteScalar(tbname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tbname[1]}].[{tbname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null) { //表不存在
|
||||||
if (tboldname != null) {
|
if (tboldname != null) {
|
||||||
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $"select 1 from sys.databases where name='{tboldname[0]}'") == null ||
|
if (string.Compare(tboldname[0], tbname[0], true) != 0 && ExecuteScalar(database, $" select 1 from sys.databases where name='{tboldname[0]}'") == null ||
|
||||||
string.Compare(tboldname[1], tbname[1], true) != 0 && ExecuteScalar(tboldname[0], $"select 1 from sys.schemas where name='{tboldname[1]}'") == null ||
|
string.Compare(tboldname[1], tbname[1], true) != 0 && ExecuteScalar(tboldname[0], $" select 1 from sys.schemas where name='{tboldname[1]}'") == null ||
|
||||||
ExecuteScalar(tboldname[0], $"select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null)
|
ExecuteScalar(tboldname[0], $" select 1 from dbo.sysobjects where id = object_id(N'[{tboldname[1]}].[{tboldname[2]}]') and OBJECTPROPERTY(id, N'IsUserTable') = 1") == null)
|
||||||
//数据库或模式或表不存在
|
//数据库或模式或表不存在
|
||||||
tboldname = null;
|
tboldname = null;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ namespace FreeSql.SqlServer {
|
|||||||
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
public string GetDataReaderMethod(DbColumnInfo column) => _dicDbToCs.TryGetValue(column.DbType, out var trydc) ? trydc.dataReaderMethod : null;
|
||||||
|
|
||||||
public List<string> GetDatabases() {
|
public List<string> GetDatabases() {
|
||||||
var sql = @"select name from sys.databases where name not in ('master','tempdb','model','msdb')";
|
var sql = @" select name from sys.databases where name not in ('master','tempdb','model','msdb')";
|
||||||
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
|
||||||
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
|
||||||
}
|
}
|
||||||
@ -306,6 +306,7 @@ use {olddatabase};
|
|||||||
}
|
}
|
||||||
|
|
||||||
sql = $@"
|
sql = $@"
|
||||||
|
use {db};
|
||||||
select
|
select
|
||||||
b.object_id 'Object_id'
|
b.object_id 'Object_id'
|
||||||
,c.name 'Column'
|
,c.name 'Column'
|
||||||
|
@ -9,8 +9,8 @@ namespace FreeSql.SqlServer {
|
|||||||
|
|
||||||
class SqlServerUtils : CommonUtils {
|
class SqlServerUtils : CommonUtils {
|
||||||
IFreeSql _orm;
|
IFreeSql _orm;
|
||||||
public SqlServerUtils(IFreeSql mysql) {
|
public SqlServerUtils(IFreeSql orm) {
|
||||||
_orm = mysql;
|
_orm = orm;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
|
internal override DbParameter AppendParamter(List<DbParameter> _params, string parameterName, Type type, object value) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user