- 增加 FreeSql.Generator 人大金仓 实体类生成器;#325

This commit is contained in:
28810 2020-05-28 02:05:57 +08:00
parent 815372cb7f
commit 8331f43252
10 changed files with 608 additions and 194 deletions

View File

@ -109,7 +109,10 @@ new Colorful.Formatter("v" + string.Join(".", typeof(ConsoleApp).Assembly.GetNam
-DB ""{10},Data Source=document.db"" -DB ""{10},Data Source=document.db""
-DB ""{11},server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user;poolsize=2"" -DB ""{11},server=127.0.0.1;port=5236;user id=2user;password=123456789;database=2user;poolsize=2""
{11} {11}
-DB ""{12},Driver={KingbaseES 8.2 ODBC Driver ANSI};Server=127.0.0.1;Port=54321;UID=USER2;PWD=123456789;database=""
{12}
-Filter Table+View+StoreProcedure -Filter Table+View+StoreProcedure
++ ++
@ -120,7 +123,7 @@ new Colorful.Formatter("v" + string.Join(".", typeof(ConsoleApp).Assembly.GetNam
-FileName {name}.cs -FileName {name}.cs
-Output shell -Output shell
{12} {13}
", Color.SlateGray, ", Color.SlateGray,
new Colorful.Formatter("使用 FreeSql 快速生成数据库的实体类", Color.SlateGray), new Colorful.Formatter("使用 FreeSql 快速生成数据库的实体类", Color.SlateGray),
@ -135,6 +138,7 @@ new Colorful.Formatter("PostgreSQL", Color.Yellow),
new Colorful.Formatter("Oracle", Color.Yellow), new Colorful.Formatter("Oracle", Color.Yellow),
new Colorful.Formatter("Sqlite", Color.Yellow), new Colorful.Formatter("Sqlite", Color.Yellow),
new Colorful.Formatter("Dameng", Color.Yellow), new Colorful.Formatter("Dameng", Color.Yellow),
new Colorful.Formatter("OdbcKingbaseES", Color.Yellow),
new Colorful.Formatter("推荐在实体类目录创建 gen.bat双击它重新所有实体类", Color.ForestGreen) new Colorful.Formatter("推荐在实体类目录创建 gen.bat双击它重新所有实体类", Color.ForestGreen)
); );
wait.Set(); wait.Set();
@ -175,7 +179,8 @@ new Colorful.Formatter("推荐在实体类目录创建 gen.bat双击它重新
case "oracle": ArgsDbType = DataType.Oracle; break; case "oracle": ArgsDbType = DataType.Oracle; break;
case "sqlite": ArgsDbType = DataType.Sqlite; break; case "sqlite": ArgsDbType = DataType.Sqlite; break;
case "dameng": ArgsDbType = DataType.Dameng; break; case "dameng": ArgsDbType = DataType.Dameng; break;
default: throw new ArgumentException($"-DB 参数错误,不支持的类型:{dbargs[0]}"); case "odbckingbasees": ArgsDbType = DataType.OdbcKingbaseES; break;
default: throw new ArgumentException($"-DB 参数错误,不支持的类型:\"{dbargs[0]}\"");
} }
ArgsConnectionString = dbargs[1].Trim(); ArgsConnectionString = dbargs[1].Trim();
a++; a++;

View File

@ -31,6 +31,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj" /> <ProjectReference Include="..\..\Providers\FreeSql.Provider.Dameng\FreeSql.Provider.Dameng.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" /> <ProjectReference Include="..\..\Providers\FreeSql.Provider.MySqlConnector\FreeSql.Provider.MySqlConnector.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Odbc\FreeSql.Provider.Odbc.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj" /> <ProjectReference Include="..\..\Providers\FreeSql.Provider.Oracle\FreeSql.Provider.Oracle.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" /> <ProjectReference Include="..\..\Providers\FreeSql.Provider.PostgreSQL\FreeSql.Provider.PostgreSQL.csproj" />
<ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" /> <ProjectReference Include="..\..\Providers\FreeSql.Provider.Sqlite\FreeSql.Provider.Sqlite.csproj" />

View File

@ -125,13 +125,6 @@
清空状态数据 清空状态数据
</summary> </summary>
</member> </member>
<member name="M:FreeSql.DbSet`1.RemoveAsync(System.Linq.Expressions.Expression{System.Func{`0,System.Boolean}})">
<summary>
根据 lambda 条件删除数据
</summary>
<param name="predicate"></param>
<returns></returns>
</member>
<member name="M:FreeSql.DbSet`1.Add(`0)"> <member name="M:FreeSql.DbSet`1.Add(`0)">
<summary> <summary>
添加 添加
@ -486,14 +479,5 @@
<param name="that"></param> <param name="that"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
<summary>
批量注入 Repository可以参考代码自行调整
</summary>
<param name="services"></param>
<param name="globalDataFilter"></param>
<param name="assemblies"></param>
<returns></returns>
</member>
</members> </members>
</doc> </doc>

View File

@ -6,6 +6,11 @@
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>FreeSql.Tests.Provider.Odbc.xml</DocumentationFile>
<WarningLevel>3</WarningLevel>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit" Version="2.4.0" />

View File

@ -0,0 +1,103 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>FreeSql.Tests.Provider.Odbc</name>
</assembly>
<members>
<member name="M:FreeSql.Tests.Odbc.MySql.MySqlCodeFirstTest.Tb_alltype.Save">
<summary>
保存或添加,如果主键有值则尝试 Update如果影响的行为 0 则尝试 Insert
</summary>
</member>
<member name="T:FreeSql.Tests.Odbc.UnitTest1.NewsArticle">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.ArticleId">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.ArticleTitle">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.CategoryId">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.ChannelId">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.TypeId">
<summary>
类型
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.Summary">
<summary>
内容简介
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.Thumbnail">
<summary>
缩略图
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.Hits">
<summary>
点击量
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.IsDisplay">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.Status">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.CreateTime">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.NewsArticle.ReleaseTime">
<summary>
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.Templates.Id2">
<summary>
测试中文重命名id
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.UnitTest1.Class1.name">
<summary>
姓名
</summary>
</member>
<member name="T:FreeSql.Tests.Odbc.ExamPaper">
<summary>
试卷表
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.ExamPaper.AssessmentPlanId">
<summary>
考核计划ID
</summary>
</member>
<member name="P:FreeSql.Tests.Odbc.ExamPaper.TotalScore">
<summary>
总分
</summary>
</member>
</members>
</doc>

View File

@ -9,16 +9,13 @@ namespace FreeSql.Tests.Odbc.KingbaseES
[Fact] [Fact]
public void GetDatabases() public void GetDatabases()
{ {
var t1 = g.kingbaseES.DbFirst.GetDatabases(); var t1 = g.kingbaseES.DbFirst.GetDatabases();
} }
[Fact] [Fact]
public void GetTablesByDatabase() public void GetTablesByDatabase()
{ {
var t2 = g.kingbaseES.DbFirst.GetTablesByDatabase();
//var t2 = g.kingbaseES.DbFirst.GetTablesByDatabase();
//var tb = g.kingbaseES.Ado.ExecuteArray(System.Data.CommandType.Text, "select * from \"tb_dbfirst\""); //var tb = g.kingbaseES.Ado.ExecuteArray(System.Data.CommandType.Text, "select * from \"tb_dbfirst\"");
} }
} }

View File

@ -39,7 +39,6 @@ namespace FreeSql.Odbc.KingbaseES
if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false)) if (mapType != null && mapType != param.GetType() && (param is IEnumerable == false))
param = Utils.GetDataReaderValue(mapType, param); param = Utils.GetDataReaderValue(mapType, param);
bool isdic;
if (param is bool || param is bool?) if (param is bool || param is bool?)
return (bool)param ? "'t'" : "'f'"; return (bool)param ? "'t'" : "'f'";
else if (param is string || param is char) else if (param is string || param is char)

View File

@ -42,7 +42,7 @@ namespace FreeSql.Odbc.KingbaseES
{ typeof(bool).FullName, CsToDb.New(OdbcType.Bit, "bool","bool NOT NULL", null, false, false) },{ typeof(bool?).FullName, CsToDb.New(OdbcType.Bit, "bool","bool", null, true, null) }, { typeof(bool).FullName, CsToDb.New(OdbcType.Bit, "bool","bool NOT NULL", null, false, false) },{ typeof(bool?).FullName, CsToDb.New(OdbcType.Bit, "bool","bool", null, true, null) },
{ typeof(Byte[]).FullName, CsToDb.New(OdbcType.VarBinary, "bytea", "bytea", false, null, new byte[0]) }, { typeof(Byte[]).FullName, CsToDb.New(OdbcType.VarBinary, "bytea", "bytea", false, null, new byte[0]) },
{ typeof(Guid).FullName, CsToDb.New(OdbcType.UniqueIdentifier, "char", "char(36) NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, CsToDb.New(OdbcType.UniqueIdentifier, "char", "char(36)", false, true, null) }, { typeof(Guid).FullName, CsToDb.New(OdbcType.UniqueIdentifier, "uuid", "uuid NOT NULL", false, false, Guid.Empty) },{ typeof(Guid?).FullName, CsToDb.New(OdbcType.UniqueIdentifier, "uuid", "uuid", false, true, null) },
}; };
public override DbInfoResult GetDbInfo(Type type) public override DbInfoResult GetDbInfo(Type type)
@ -75,18 +75,9 @@ namespace FreeSql.Odbc.KingbaseES
protected override string GetComparisonDDLStatements(params TypeAndName[] objects) protected override string GetComparisonDDLStatements(params TypeAndName[] objects)
{ {
var userId = (_orm.Ado.MasterPool as OdbcKingbaseESConnectionPool)?.UserId;
if (string.IsNullOrEmpty(userId))
using (var conn = _orm.Ado.MasterPool.Get())
{
userId = OdbcKingbaseESConnectionPool.GetUserId(conn.Value.ConnectionString);
}
var defaultSchema = "PUBLIC";
var seqcols = new List<NaviteTuple<ColumnInfo, string[], bool>>(); //序列:列,表,自增
var seqnameDel = new List<string>(); //要删除的序列+触发器
var sb = new StringBuilder(); var sb = new StringBuilder();
var seqcols = new List<NaviteTuple<ColumnInfo, string[], bool>>(); //序列
foreach (var obj in objects) foreach (var obj in objects)
{ {
if (sb.Length > 0) sb.Append("\r\n"); if (sb.Length > 0) sb.Append("\r\n");
@ -94,42 +85,40 @@ namespace FreeSql.Odbc.KingbaseES
if (tb == null) throw new Exception($"类型 {obj.entityType.FullName} 不可迁移"); if (tb == null) throw new Exception($"类型 {obj.entityType.FullName} 不可迁移");
if (tb.Columns.Any() == false) throw new Exception($"类型 {obj.entityType.FullName} 不可迁移可迁移属性0个"); if (tb.Columns.Any() == false) throw new Exception($"类型 {obj.entityType.FullName} 不可迁移可迁移属性0个");
var tbname = _commonUtils.SplitTableName(tb.DbName); var tbname = _commonUtils.SplitTableName(tb.DbName);
if (tbname?.Length == 1) tbname = new[] { defaultSchema, tbname[0] }; if (tbname?.Length == 1) tbname = new[] { "PUBLIC", tbname[0] };
var tboldname = _commonUtils.SplitTableName(tb.DbOldName); //旧表名 var tboldname = _commonUtils.SplitTableName(tb.DbOldName); //旧表名
if (tboldname?.Length == 1) tboldname = new[] { defaultSchema, tboldname[0] }; if (tboldname?.Length == 1) tboldname = new[] { "PUBLIC", tboldname[0] };
var primaryKeyName = (obj.entityType.GetCustomAttributes(typeof(OraclePrimaryKeyNameAttribute), false)?.FirstOrDefault() as OraclePrimaryKeyNameAttribute)?.Name;
if (string.IsNullOrEmpty(obj.tableName) == false) if (string.IsNullOrEmpty(obj.tableName) == false)
{ {
var tbtmpname = _commonUtils.SplitTableName(obj.tableName); var tbtmpname = _commonUtils.SplitTableName(obj.tableName);
if (tbtmpname?.Length == 1) tbtmpname = new[] { defaultSchema, tbtmpname[0] }; if (tbtmpname?.Length == 1) tbtmpname = new[] { "PUBLIC", tbtmpname[0] };
if (tbname[0] != tbtmpname[0] || tbname[1] != tbtmpname[1]) if (tbname[0] != tbtmpname[0] || tbname[1] != tbtmpname[1])
{ {
tbname = tbtmpname; tbname = tbtmpname;
tboldname = null; tboldname = null;
primaryKeyName = null;
} }
} }
//codefirst 不支持表名中带 . //codefirst 不支持表名、模式名、数据库名中带 .
if (string.Compare(tbname[0], defaultSchema) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" SELECT 1 FROM information_schema.schemata WHERE schema_name={0}", tbname[0])) == null) //创建数据库 if (string.Compare(tbname[0], "PUBLIC", true) != 0 && _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(" select 1 from sys_namespace where nspname={0}", 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, _commonUtils.FormatSql(" select 1 from information_schema.tables where table_schema={0} and table_name={1}", tbname)) == null) if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format(" select 1 from sys_tables a inner join sys_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, _commonUtils.FormatSql(" select 1 from information_schema.tables where table_schema={0} and table_name={1}", tboldname)) == null) if (_orm.Ado.ExecuteScalar(CommandType.Text, string.Format(" select 1 from sys_tables a inner join sys_namespace b on b.nspname = a.schemaname where b.nspname || '.' || a.tablename = '{0}.{1}'", tboldname)) == null)
//模式或表不存在 //表不存在
tboldname = null; tboldname = null;
} }
if (tboldname == null) if (tboldname == null)
{ {
//创建表 //创建表
var createTableName = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"); var createTableName = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
sb.Append("CREATE TABLE ").Append(createTableName).Append(" ( "); sb.Append("CREATE TABLE IF NOT EXISTS ").Append(createTableName).Append(" ( ");
foreach (var tbcol in tb.ColumnsByPosition) foreach (var tbcol in tb.ColumnsByPosition)
{ {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
@ -137,13 +126,13 @@ namespace FreeSql.Odbc.KingbaseES
} }
if (tb.Primarys.Any()) if (tb.Primarys.Any())
{ {
var pkname = primaryKeyName ?? $"{tbname[0]}_{tbname[1]}_PK1"; var pkname = $"{tbname[0]}_{tbname[1]}_PKEY";
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(pkname)).Append(" PRIMARY KEY ("); sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(pkname)).Append(" PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),"); sb.Remove(sb.Length - 2, 2).Append("),");
} }
sb.Remove(sb.Length - 1, 1); sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n);\r\n"); sb.Append("\r\n) WITH (OIDS=FALSE);\r\n");
//创建表的索引 //创建表的索引
foreach (var uk in tb.Indexes) foreach (var uk in tb.Indexes)
{ {
@ -168,7 +157,7 @@ namespace FreeSql.Odbc.KingbaseES
sb.Append("COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment)).Append(";\r\n"); sb.Append("COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment)).Append(";\r\n");
continue; continue;
} }
//如果新表,旧表在一个模式下,直接修改表名 //如果新表,旧表在一个数据库和模式下,直接修改表名
if (string.Compare(tbname[0], tboldname[0], true) == 0) 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[1]}")).Append(";\r\n"); sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}")).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName($"{tbname[1]}")).Append(";\r\n");
else else
@ -181,32 +170,53 @@ namespace FreeSql.Odbc.KingbaseES
tboldname = null; //如果新表已经存在,不走改表名逻辑 tboldname = null; //如果新表已经存在,不走改表名逻辑
//对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段 //对比字段,只可以修改类型、增加字段、有限的修改字段名;保证安全不删除字段
var sql = _commonUtils.FormatSql($@" var sql = _commonUtils.FormatSql(@"
select select
a.column_name, a.attname,
a.data_type, t.typname,
a.data_length, case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
a.data_precision, case when t.typelem > 0 and t.typinput::varchar = 'ARRAY_IN' then t2.typname else t.typname end,
a.data_scale, case when a.attnotnull then '0' else '1' end as is_nullable,
a.char_used, --e.adsrc,
case when a.nullable = 'N' then 0 else 1 end, (select sys_get_expr(adbin, adrelid) from sys_attrdef where adrelid = e.adrelid limit 1) is_identity,
nvl((select 1 from user_sequences where upper(sequence_owner)={{0}} and upper(sequence_name)=upper({{2}}||'_'||{{1}}||'_seq_'||a.column_name) limit 1), 0), a.attndims,
b.comments d.description as comment
from all_tab_columns a from sys_class c
left join all_col_comments b on b.owner = a.owner and b.table_name = a.table_name and b.column_name = a.column_name inner join sys_attribute a on a.attnum > 0 and a.attrelid = c.oid
where a.owner={{0}} and a.table_name={{1}}", userId, (tboldname ?? tbname)[1], (tboldname ?? tbname)[0]); inner join sys_type t on t.oid = a.atttypid
left join sys_type t2 on t2.oid = t.typelem
left join sys_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
left join sys_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
inner join sys_namespace ns on ns.oid = c.relnamespace
inner join sys_namespace ns2 on ns2.oid = t.typnamespace
where ns.nspname = {0} and c.relname = {1}", tboldname ?? tbname);
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds.Length != ds.Select(a => string.Concat(a[0])).Count()) throw new Exception("检查到多个模式下存在相同的表名,无法完成对比结构");
var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a => var tbstruct = ds.ToDictionary(a => string.Concat(a[0]), a =>
{ {
var sqlType = GetKingbaseESSqlTypeFullName(a); var attndims = int.Parse(string.Concat(a[6]));
var type = string.Concat(a[1]);
var sqlType = string.Concat(a[3]);
var max_length = long.Parse(string.Concat(a[2]));
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 (type.StartsWith("_"))
{
type = type.Substring(1);
if (attndims == 0) attndims++;
}
if (sqlType.StartsWith("_")) sqlType = sqlType.Substring(1);
return new return new
{ {
column = string.Concat(a[0]), column = string.Concat(a[0]),
sqlType, sqlType = string.Concat(sqlType),
is_nullable = string.Concat(a[6]) == "1", max_length = long.Parse(string.Concat(a[2])),
is_identity = string.Concat(a[7]) == "1", is_nullable = string.Concat(a[4]) == "1",
comment = string.Concat(a[8]) is_identity = string.Concat(a[5]).StartsWith(@"NEXTVAL('") && string.Concat(a[5]).EndsWith(@"'::REGCLASS)"),
attndims,
comment = string.Concat(a[7])
}; };
}, StringComparer.CurrentCultureIgnoreCase); }, StringComparer.CurrentCultureIgnoreCase);
@ -214,71 +224,51 @@ where a.owner={{0}} and a.table_name={{1}}", userId, (tboldname ?? tbname)[1], (
{ {
foreach (var tbcol in tb.ColumnsByPosition) foreach (var tbcol in tb.ColumnsByPosition)
{ {
var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"NOT\s+NULL", "NULL");
if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) || if (tbstruct.TryGetValue(tbcol.Attribute.Name, out var tbstructcol) ||
string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol)) string.IsNullOrEmpty(tbcol.Attribute.OldName) == false && tbstruct.TryGetValue(tbcol.Attribute.OldName, out tbstructcol))
{ {
var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? ""); var isCommentChanged = tbstructcol.comment != (tbcol.Comment ?? "");
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false ||
{ tbcol.Attribute.DbType.Contains("[]") != (tbstructcol.attndims > 0))
istmpatler = true; sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TYPE ").Append(tbcol.Attribute.DbType.Split(' ').First()).Append(";\r\n");
if (istmpatler && tbcol.Attribute.DbType.StartsWith("varchar", StringComparison.CurrentCultureIgnoreCase) && tbstructcol.sqlType.StartsWith("varchar", StringComparison.CurrentCultureIgnoreCase)
&& Regex.Match(tbcol.Attribute.DbType, @"\(\d+").Groups[0].Value == Regex.Match(tbstructcol.sqlType, @"\(\d+").Groups[0].Value)
istmpatler = false;
if (istmpatler && Regex.IsMatch(tbcol.Attribute.DbType, @"\(\d+") == false && Regex.IsMatch(tbstructcol.sqlType, @"\(\d+")
&& string.Compare(tbcol.Attribute.DbType, Regex.Replace(tbstructcol.sqlType, @"\([^\)]+\)", ""), StringComparison.CurrentCultureIgnoreCase) == 0)
istmpatler = false;
if (istmpatler)
break;
}
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
{ {
if (tbcol.Attribute.IsNullable == false) if (tbcol.Attribute.IsNullable != true || tbcol.Attribute.IsNullable == true && tbcol.Attribute.IsPrimary == false)
sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" = ").Append(tbcol.DbDefaultValue).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" IS NULL;\r\n"); {
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(tbcol.Attribute.IsNullable == true ? " DROP NOT NULL" : " SET NOT NULL").Append(";\r\n"); if (tbcol.Attribute.IsNullable == false)
sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" = ").Append(tbcol.DbDefaultValue).Append(" WHERE ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" IS NULL;\r\n");
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" ").Append(tbcol.Attribute.IsNullable == true ? "DROP" : "SET").Append(" NOT NULL;\r\n");
}
} }
if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0) if (string.Compare(tbstructcol.column, tbcol.Attribute.OldName, true) == 0)
{
if (tbstructcol.is_identity)
seqnameDel.Add(Utils.GetCsName($"{tbname[1]}_seq_{tbstructcol.column}"));
//修改列名 //修改列名
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n"); sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" RENAME COLUMN ").Append(_commonUtils.QuoteSqlName(tbstructcol.column)).Append(" TO ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(";\r\n");
if (tbcol.Attribute.IsIdentity)
seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
}
else if (tbcol.Attribute.IsIdentity != tbstructcol.is_identity)
seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
if (isCommentChanged) if (isCommentChanged)
sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")).Append(";\r\n"); sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n");
continue; continue;
} }
//添加列 //添加列
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ADD (").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(dbtypeNoneNotNull).Append(");\r\n"); 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");
if (tbcol.Attribute.IsNullable == false) sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(tbcol.DbDefaultValue).Append(";\r\n");
{ if (tbcol.Attribute.IsNullable == false) sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" SET NOT NULL;\r\n");
sbalter.Append("UPDATE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" SET ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" = ").Append(tbcol.DbDefaultValue).Append(";\r\n");
sbalter.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" ALTER COLUMN ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" SET NOT NULL;\r\n");
}
if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true)); if (tbcol.Attribute.IsIdentity == true) seqcols.Add(NaviteTuple.Create(tbcol, tbname, tbcol.Attribute.IsIdentity == true));
if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment ?? "")).Append(";\r\n"); if (string.IsNullOrEmpty(tbcol.Comment) == false) sbalter.Append("COMMENT ON COLUMN ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}.{tbcol.Attribute.Name}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tbcol.Comment)).Append(";\r\n");
} }
}
if (istmpatler == false)
{
var dsuksql = _commonUtils.FormatSql(@" var dsuksql = _commonUtils.FormatSql(@"
select select
c.column_name, c.attname,
a.index_name, b.relname,
case when c.descend = 'DESC' then 1 else 0 end, case when sys_index_column_has_property(b.oid, c.attnum, 'desc') = 't' then 1 else 0 end IsDesc,
case when a.uniqueness = 'UNIQUE' then 1 else 0 end case when indisunique = 't' then 1 else 0 end IsUnique
from all_indexes a, from sys_index a
all_ind_columns c inner join sys_class b on b.oid = a.indexrelid
where a.index_name = c.index_name inner join sys_attribute c on c.attnum > 0 and c.attrelid = b.oid
and a.table_owner = c.table_owner inner join sys_namespace ns on ns.oid = b.relnamespace
and a.table_name = c.table_name inner join sys_class d on d.oid = a.indrelid
and a.owner in ({0}) and a.table_name in ({1}) where ns.nspname in ({0}) and d.relname in ({1}) and a.indisprimary = 'f'", tboldname ?? tbname);
and not exists(select 1 from all_constraints where index_name = a.index_name and constraint_type = 'P')", userId, (tboldname ?? tbname)[1]); var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]), string.Concat(a[1]), string.Concat(a[2]), string.Concat(a[3]) });
var dsuk = _orm.Ado.ExecuteArray(CommandType.Text, dsuksql).Select(a => new[] { string.Concat(a[0]).Trim('"'), string.Concat(a[1]), string.Concat(a[2]), string.Concat(a[3]) }).ToArray();
foreach (var uk in tb.Indexes) foreach (var uk in tb.Indexes)
{ {
if (string.IsNullOrEmpty(uk.Name) || uk.Columns.Any() == false) continue; if (string.IsNullOrEmpty(uk.Name) || uk.Columns.Any() == false) continue;
@ -301,22 +291,32 @@ and not exists(select 1 from all_constraints where index_name = a.index_name and
} }
if (istmpatler == false) if (istmpatler == false)
{ {
var dbcomment = string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@" select comments from all_tab_comments where owner = {0} and table_name = {1} and table_type = 'TABLE'", userId, tbname[1]))); var dbcomment = string.Concat(_orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@" select
d.description
from sys_class a
inner join sys_namespace b on b.oid = a.relnamespace
left join sys_description d on d.objoid = a.oid and objsubid = 0
where b.nspname not in ('SYS_CATALOG', 'INFORMATION_SCHEMA', 'TOPOLOGY', 'SYSAUDIT', 'SYSLOGICAL', 'SYS_TEMP_1', 'SYS_TOAST', 'SYS_TOAST_TEMP_1', 'XLOG_RECORD_READ') and a.relkind in ('r') and b.nspname = {0} and a.relname = {1}
and b.nspname || '.' || a.relname not in ('PUBLIC.GEOGRAPHY_COLUMNS','PUBLIC.GEOMETRY_COLUMNS','PUBLIC.RASTER_COLUMNS','PUBLIC.RASTER_OVERVIEWS')", tbname[0], tbname[1])));
if (dbcomment != (tb.Comment ?? "")) if (dbcomment != (tb.Comment ?? ""))
sb.Append("COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment)).Append(";\r\n"); sb.Append("COMMENT ON TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" IS ").Append(_commonUtils.FormatSql("{0}", tb.Comment)).Append(";\r\n");
sb.Append(sbalter); sb.Append(sbalter);
continue; continue;
} }
var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@" select constraint_name from user_constraints where owner={0} and table_name={1} and constraint_type='P'", userId, tbname[1]))?.ToString(); var oldpk = _orm.Ado.ExecuteScalar(CommandType.Text, _commonUtils.FormatSql(@" select sys_constraint.conname as pk_name from sys_constraint
inner join sys_class on sys_constraint.conrelid = sys_class.oid
inner join sys_namespace on sys_namespace.oid = sys_class.relnamespace
where sys_namespace.nspname={0} and sys_class.relname={1} and sys_constraint.contype='p'
", tbname))?.ToString();
if (string.IsNullOrEmpty(oldpk) == false) if (string.IsNullOrEmpty(oldpk) == false)
sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(_commonUtils.QuoteSqlName(oldpk)).Append(";\r\n"); sb.Append("ALTER TABLE ").Append(_commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}")).Append(" DROP CONSTRAINT ").Append(oldpk).Append(";\r\n");
//创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名 //创建临时表,数据导进临时表,然后删除原表,将临时表改名为原表名
var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}"); var tablename = tboldname == null ? _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}") : _commonUtils.QuoteSqlName($"{tboldname[0]}.{tboldname[1]}");
var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}"); var tmptablename = _commonUtils.QuoteSqlName($"{tbname[0]}.FTmp_{tbname[1]}");
//创建临时表 //创建临时表
sb.Append("CREATE TABLE ").Append(tmptablename).Append(" ( "); sb.Append("CREATE TABLE IF NOT EXISTS ").Append(tmptablename).Append(" ( ");
foreach (var tbcol in tb.ColumnsByPosition) foreach (var tbcol in tb.ColumnsByPosition)
{ {
sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(","); sb.Append(" \r\n ").Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(" ").Append(tbcol.Attribute.DbType).Append(",");
@ -324,13 +324,13 @@ and not exists(select 1 from all_constraints where index_name = a.index_name and
} }
if (tb.Primarys.Any()) if (tb.Primarys.Any())
{ {
var pkname = primaryKeyName ?? $"{tbname[0]}_{tbname[1]}_PK2"; var pkname = $"{tbname[0]}_{tbname[1]}_pkey";
sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(pkname)).Append(" PRIMARY KEY ("); sb.Append(" \r\n CONSTRAINT ").Append(_commonUtils.QuoteSqlName(pkname)).Append(" PRIMARY KEY (");
foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", "); foreach (var tbcol in tb.Primarys) sb.Append(_commonUtils.QuoteSqlName(tbcol.Attribute.Name)).Append(", ");
sb.Remove(sb.Length - 2, 2).Append("),"); sb.Remove(sb.Length - 2, 2).Append("),");
} }
sb.Remove(sb.Length - 1, 1); sb.Remove(sb.Length - 1, 1);
sb.Append("\r\n);\r\n"); sb.Append("\r\n) WITH (OIDS=FALSE);\r\n");
//备注 //备注
foreach (var tbcol in tb.ColumnsByPosition) foreach (var tbcol in tb.ColumnsByPosition)
{ {
@ -352,20 +352,17 @@ and not exists(select 1 from all_constraints where index_name = a.index_name and
{ {
insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column); insertvalue = _commonUtils.QuoteSqlName(tbstructcol.column);
if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false) if (tbcol.Attribute.DbType.StartsWith(tbstructcol.sqlType, StringComparison.CurrentCultureIgnoreCase) == false)
{ insertvalue = $"cast({insertvalue} as {tbcol.Attribute.DbType.Split(' ').First()})";
var dbtypeNoneNotNull = Regex.Replace(tbcol.Attribute.DbType, @"(NOT\s+)?NULL", "");
insertvalue = $"cast({insertvalue} as {dbtypeNoneNotNull})";
}
if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable) if (tbcol.Attribute.IsNullable != tbstructcol.is_nullable)
insertvalue = $"nvl({insertvalue},{tbcol.DbDefaultValue})"; insertvalue = $"coalesce({insertvalue},{tbcol.DbDefaultValue})";
} }
else if (tbcol.Attribute.IsNullable == false) else if (tbcol.Attribute.IsNullable == false)
insertvalue = tbcol.DbDefaultValue; insertvalue = tbcol.DbDefaultValue;
sb.Append(insertvalue.Replace("'", "''")).Append(", "); sb.Append(insertvalue).Append(", ");
} }
sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n"); sb.Remove(sb.Length - 2, 2).Append(" FROM ").Append(tablename).Append(";\r\n");
sb.Append("DROP TABLE ").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[1]}")).Append(";\r\n"); sb.Append("ALTER TABLE ").Append(tmptablename).Append(" RENAME TO ").Append(_commonUtils.QuoteSqlName(tbname[1])).Append(";\r\n");
//创建表的索引 //创建表的索引
foreach (var uk in tb.Indexes) foreach (var uk in tb.Indexes)
{ {
@ -384,7 +381,7 @@ and not exists(select 1 from all_constraints where index_name = a.index_name and
foreach (var seqcol in seqcols) foreach (var seqcol in seqcols)
{ {
var tbname = seqcol.Item2; var tbname = seqcol.Item2;
var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_seq_{seqcol.Item1.Attribute.Name}").ToUpper(); var seqname = Utils.GetCsName($"{tbname[0]}.{tbname[1]}_{seqcol.Item1.Attribute.Name}_seq").ToUpper(); ;
var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}"); var tbname2 = _commonUtils.QuoteSqlName($"{tbname[0]}.{tbname[1]}");
var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name); var colname2 = _commonUtils.QuoteSqlName(seqcol.Item1.Attribute.Name);
sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT null;\r\n"); sb.Append("ALTER TABLE ").Append(tbname2).Append(" ALTER COLUMN ").Append(colname2).Append(" SET DEFAULT null;\r\n");
@ -392,68 +389,11 @@ and not exists(select 1 from all_constraints where index_name = a.index_name and
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();
} }
public override int ExecuteDDLStatements(string ddl)
{
if (string.IsNullOrEmpty(ddl)) return 0;
var scripts = ddl.Split(new string[] { ";\r\n" }, StringSplitOptions.None).Where(a => string.IsNullOrEmpty(a.Trim()) == false).ToArray();
if (scripts.Any() == false) return 0;
if (scripts.Length == 1) return base.ExecuteDDLStatements(ddl);
var affrows = 0;
foreach (var script in scripts)
affrows += base.ExecuteDDLStatements(script);
return affrows;
}
internal static string GetKingbaseESSqlTypeFullName(object[] row)
{
var a = row;
var sqlType = string.Concat(a[1]).ToUpper();
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 (sqlType.StartsWith("TIMESTAMP", StringComparison.CurrentCultureIgnoreCase))
{
}
else if (sqlType.StartsWith("BLOB"))
{
}
else if (sqlType == "DOUBLE" || sqlType == "FLOAT")
{
}
else if (sqlType == "INT2" || sqlType == "INT4" || sqlType == "INT8")
{
}
else if (sqlType == "TINYINT")
{
}
else if (sqlType == "BOOL")
{
}
else if (sqlType == "FLOAT4" || sqlType == "FLOAT8")
{
}
else if (sqlType == "TIME" || sqlType == "TIMESTAMP")
{
}
else if (sqlType == "NUMERIC")
sqlType += $"({data_precision},{data_scale})";
else if (data_precision > 0 && data_scale > 0)
sqlType += $"({data_precision},{data_scale})";
else if (data_precision > 0)
sqlType += $"({data_precision})";
else
sqlType += $"({data_length})";
return sqlType;
}
} }
} }

View File

@ -105,16 +105,396 @@ namespace FreeSql.Odbc.KingbaseES
public List<string> GetDatabases() public List<string> GetDatabases()
{ {
var sql = @" select schema_name from information_schema.schemata where schema_owner<>'SYSTEM'"; var sql = @" select datname from sys_database where datname not in ('TEMPLATE1', 'TEMPLATE0', 'TEMPLATE2')";
var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql); var ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
return new[] { "PUBLIC" }.Concat(ds.Select(a => a.FirstOrDefault()?.ToString())).ToList(); return ds.Select(a => a.FirstOrDefault()?.ToString()).ToList();
} }
public List<DbTableInfo> GetTablesByDatabase(params string[] database2) => throw new NotImplementedException(); public List<DbTableInfo> GetTablesByDatabase(params string[] database)
{
var olddatabase = "";
using (var conn = _orm.Ado.MasterPool.Get(TimeSpan.FromSeconds(5)))
{
olddatabase = conn.Value.Database;
}
var dbs = database == null || database.Any() == false ? new[] { olddatabase } : database;
var tables = new List<DbTableInfo>();
foreach (var db in dbs)
{
if (string.IsNullOrEmpty(db) || string.Compare(db, olddatabase, true) != 0) continue;
var loc1 = new List<DbTableInfo>();
var loc2 = new Dictionary<string, DbTableInfo>();
var loc3 = new Dictionary<string, Dictionary<string, DbColumnInfo>>();
var sql = $@"
select
b.nspname || '.' || a.tablename,
a.schemaname,
a.tablename ,
d.description,
'TABLE'
from sys_tables a
inner join sys_namespace b on b.nspname = a.schemaname
inner join sys_class c on c.relnamespace = b.oid and c.relname = a.tablename
left join sys_description d on d.objoid = c.oid and objsubid = 0
where a.schemaname not in ('SYS_CATALOG', 'INFORMATION_SCHEMA', 'TOPOLOGY', 'SYSAUDIT', 'SYSLOGICAL', 'SYS_TEMP_1', 'SYS_TOAST', 'SYS_TOAST_TEMP_1', 'XLOG_RECORD_READ')
and b.nspname || '.' || a.tablename not in ('PUBLIC.SPATIAL_REF_SYS')
union all
select
b.nspname || '.' || a.relname,
b.nspname,
a.relname,
d.description,
'VIEW'
from sys_class a
inner join sys_namespace b on b.oid = a.relnamespace
left join sys_description d on d.objoid = a.oid and objsubid = 0
where b.nspname not in ('SYS_CATALOG', 'INFORMATION_SCHEMA', 'TOPOLOGY', 'SYSAUDIT', 'SYSLOGICAL', 'SYS_TEMP_1', 'SYS_TOAST', 'SYS_TOAST_TEMP_1', 'XLOG_RECORD_READ') 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[]>();
var loc6_1000 = new List<string>();
var loc66_1000 = 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]);
var comment = string.Concat(row[3]);
Enum.TryParse<DbTableType>(string.Concat(row[4]), out var type);
loc2.Add(object_id, new DbTableInfo { Id = object_id.ToString(), Schema = owner, Name = table, Comment = comment, Type = type });
loc3.Add(object_id, new Dictionary<string, DbColumnInfo>());
switch (type)
{
case DbTableType.VIEW:
case DbTableType.TABLE:
loc6_1000.Add(object_id);
if (loc6_1000.Count >= 500)
{
loc6.Add(loc6_1000.ToArray());
loc6_1000.Clear();
}
break;
case DbTableType.StoreProcedure:
loc66_1000.Add(object_id);
if (loc66_1000.Count >= 500)
{
loc66.Add(loc66_1000.ToArray());
loc66_1000.Clear();
}
break;
}
}
if (loc6_1000.Count > 0) loc6.Add(loc6_1000.ToArray());
if (loc66_1000.Count > 0) loc66.Add(loc66_1000.ToArray());
if (loc6.Count == 0) return loc1;
var loc8 = new StringBuilder().Append("(");
for (var loc8idx = 0; loc8idx < loc6.Count; loc8idx++)
{
if (loc8idx > 0) loc8.Append(" OR ");
loc8.Append("a.table_name in (");
for (var loc8idx2 = 0; loc8idx2 < loc6[loc8idx].Length; loc8idx2++)
{
if (loc8idx2 > 0) loc8.Append(",");
loc8.Append($"'{loc6[loc8idx][loc8idx2]}'");
}
loc8.Append(")");
}
loc8.Append(")");
sql = $@"
select
ns.nspname || '.' || c.relname as id,
a.attname,
t.typname,
case when a.atttypmod > 0 and a.atttypmod < 32767 then a.atttypmod - 4 else a.attlen end len,
case when t.typelem = 0 then t.typname else t2.typname end,
case when a.attnotnull then 0 else 1 end as is_nullable,
--e.adsrc as is_identity, pg12以下
(select sys_get_expr(adbin, adrelid) from sys_attrdef where adrelid = e.adrelid limit 1) is_identity,
d.description as comment,
a.attndims,
case when t.typelem = 0 then t.typtype else t2.typtype end,
ns2.nspname,
a.attnum
from sys_class c
inner join sys_attribute a on a.attnum > 0 and a.attrelid = c.oid
inner join sys_type t on t.oid = a.atttypid
left join sys_type t2 on t2.oid = t.typelem
left join sys_description d on d.objoid = a.attrelid and d.objsubid = a.attnum
left join sys_attrdef e on e.adrelid = a.attrelid and e.adnum = a.attnum
inner join sys_namespace ns on ns.oid = c.relnamespace
inner join sys_namespace ns2 on ns2.oid = t.typnamespace
where {loc8.ToString().Replace("a.table_name", "ns.nspname || '.' || c.relname")}";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var position = 0;
foreach (object[] row in ds)
{
var object_id = string.Concat(row[0]);
var column = string.Concat(row[1]);
var type = string.Concat(row[2]);
var max_length = int.Parse(string.Concat(row[3]));
var sqlType = string.Concat(row[4]);
var is_nullable = string.Concat(row[5]) == "1";
var is_identity = string.Concat(row[6]).StartsWith(@"NEXTVAL('") && string.Concat(row[6]).EndsWith(@"'::REGCLASS)");
var comment = string.Concat(row[7]);
var defaultValue = string.Concat(row[6]);
int attndims = int.Parse(string.Concat(row[8]));
string typtype = string.Concat(row[9]);
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);
if (max_length > 0)
{
switch (sqlType.ToLower())
{
//case "numeric": sqlType += $"({max_length})"; break;
case "bpchar": case "varchar": case "bytea": case "bit": case "varbit": sqlType += $"({max_length})"; break;
}
}
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,
DefaultValue = defaultValue,
Position = ++position
});
loc3[object_id][column].DbType = this.GetDbType(loc3[object_id][column]);
loc3[object_id][column].CsType = this.GetCsTypeInfo(loc3[object_id][column]);
}
sql = $@"
select
ns.nspname || '.' || d.relname as table_id,
c.attname,
b.relname as index_id,
case when a.indisunique then 1 else 0 end IsUnique,
case when a.indisprimary then 1 else 0 end IsPrimary,
case when a.indisclustered then 0 else 1 end IsClustered,
case when sys_index_column_has_property(b.oid, c.attnum, 'desc') = 't' then 1 else 0 end IsDesc,
a.indkey::text,
c.attnum
from sys_index a
inner join sys_class b on b.oid = a.indexrelid
inner join sys_attribute c on c.attnum > 0 and c.attrelid = b.oid
inner join sys_namespace ns on ns.oid = b.relnamespace
inner join sys_class d on d.oid = a.indrelid
where {loc8.ToString().Replace("a.table_name", "ns.nspname || '.' || d.relname")}
";
ds = _orm.Ado.ExecuteArray(CommandType.Text, sql);
if (ds == null) return loc1;
var indexColumns = new Dictionary<string, Dictionary<string, DbIndexInfo>>();
var uniqueColumns = new Dictionary<string, Dictionary<string, DbIndexInfo>>();
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 = string.Concat(row[6]) == "1";
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, DbIndexInfo> loc10 = null;
DbIndexInfo loc11 = null;
if (!indexColumns.TryGetValue(object_id, out loc10))
indexColumns.Add(object_id, loc10 = new Dictionary<string, DbIndexInfo>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new DbIndexInfo());
loc11.Columns.Add(new DbIndexColumnInfo { Column = loc9, IsDesc = is_desc });
if (is_unique && !is_primary_key)
{
if (!uniqueColumns.TryGetValue(object_id, out loc10))
uniqueColumns.Add(object_id, loc10 = new Dictionary<string, DbIndexInfo>());
if (!loc10.TryGetValue(index_id, out loc11))
loc10.Add(index_id, loc11 = new DbIndexInfo());
loc11.Columns.Add(new DbIndexColumnInfo { Column = loc9, IsDesc = is_desc });
}
}
foreach (var object_id in indexColumns.Keys)
{
foreach (var column in indexColumns[object_id])
loc2[object_id].IndexesDict.Add(column.Key, column.Value);
}
foreach (var object_id in uniqueColumns.Keys)
{
foreach (var column in uniqueColumns[object_id])
{
column.Value.Columns.Sort((c1, c2) => c1.Column.Name.CompareTo(c2.Column.Name));
loc2[object_id].UniquesDict.Add(column.Key, column.Value);
}
}
sql = $@"
select
ns.nspname || '.' || b.relname as table_id,
array(select attname from sys_attribute where attrelid = a.conrelid and attnum = any(a.conkey)) as column_name,
a.conname as FKId,
ns2.nspname || '.' || c.relname as ref_table_id,
1 as IsForeignKey,
array(select attname from sys_attribute where attrelid = a.confrelid and attnum = any(a.confkey)) as ref_column,
null ref_sln,
null ref_table
from sys_constraint a
inner join sys_class b on b.oid = a.conrelid
inner join sys_class c on c.oid = a.confrelid
inner join sys_namespace ns on ns.oid = b.relnamespace
inner join sys_namespace ns2 on ns2.oid = c.relnamespace
where {loc8.ToString().Replace("a.table_name", "ns.nspname || '.' || b.relname")}
";
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])
loc2[table_id].ForeignsDict.Add(fk.Key, fk.Value);
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.UniquesDict.Count > 0)
//{
// foreach (var loc5 in loc4.UniquesDict.First().Value.Columns)
// {
// loc5.Column.IsPrimary = true;
// loc4.Primarys.Add(loc5.Column);
// }
//}
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.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c1.Name).Any()).Any();
bool b2 = loc4.ForeignsDict.Values.Where(fk => fk.Columns.Where(c3 => c3.Name == c2.Name).Any()).Any();
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;
});
loc2.Clear();
loc3.Clear();
tables.AddRange(loc1);
}
return tables;
}
public class GetEnumsByDatabaseQueryInfo
{
public string name { get; set; }
public string label { get; set; }
}
public List<DbEnumInfo> GetEnumsByDatabase(params string[] database) public List<DbEnumInfo> GetEnumsByDatabase(params string[] database)
{ {
return new List<DbEnumInfo>(); if (database == null || database.Length == 0) return new List<DbEnumInfo>();
var drs = _orm.Ado.Query<GetEnumsByDatabaseQueryInfo>(CommandType.Text, _commonUtils.FormatSql(@"
select
ns.nspname || '.' || a.typname AS name,
b.enumlabel AS label
from sys_type a
inner join sys_enum b on b.enumtypid = a.oid
inner join sys_namespace ns on ns.oid = a.typnamespace
where a.typtype = 'e' and ns.nspname in (SELECT schema_name FROM information_schema.schemata where catalog_name in {0})", database));
var ret = new Dictionary<string, Dictionary<string, string>>();
foreach (var dr in drs)
{
if (ret.TryGetValue(dr.name, out var labels) == false) ret.Add(dr.name, labels = new Dictionary<string, string>());
var key = dr.label;
if (Regex.IsMatch(key, @"^[\u0391-\uFFE5a-zA-Z_\$][\u0391-\uFFE5a-zA-Z_\$\d]*$") == false)
key = $"Unkown{ret[dr.name].Count + 1}";
if (labels.ContainsKey(key) == false) labels.Add(key, dr.label);
}
return ret.Select(a => new DbEnumInfo { Name = a.Key, Labels = a.Value }).ToList();
} }
} }
} }

View File

@ -113,7 +113,7 @@ namespace FreeSql.Odbc.KingbaseES
public override string[] SplitTableName(string name) => GetSplitTableNames(name, '"', '"', 2); public override string[] SplitTableName(string name) => GetSplitTableNames(name, '"', '"', 2);
public override string QuoteParamterName(string name) => $"@{name.ToUpper()}"; public override string QuoteParamterName(string name) => $"@{name.ToUpper()}";
public override string IsNull(string sql, object value) => $"coalesce({sql}, {value})"; public override string IsNull(string sql, object value) => $"coalesce({sql}, {value})";
public override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs)}"; public override string StringConcat(string[] objs, Type[] types) => $"{string.Join(" || ", objs.Select((a, b) => b == 0 ? $"{a}::varchar" : a))}"; //First ::varchar
public override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}"; public override string Mod(string left, string right, Type leftType, Type rightType) => $"{left} % {right}";
public override string Div(string left, string right, Type leftType, Type rightType) => $"{left} / {right}"; public override string Div(string left, string right, Type leftType, Type rightType) => $"{left} / {right}";
public override string Now => "current_timestamp"; public override string Now => "current_timestamp";