Skip to content

Commit

Permalink
瀚高(HighGo)、人大金仓(KingBase)增加 BuildDeleteSql 支持
Browse files Browse the repository at this point in the history
  • Loading branch information
ligengrong committed Jun 4, 2024
1 parent d845cf3 commit c3c406f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 53 deletions.
11 changes: 11 additions & 0 deletions XCode/DataAccessLayer/Database/HighGo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public override String FormatLike(IDataColumn column, String format)
format = format.Replace("'%{", "'%' || {").Replace("}%'", "} || '%'").Replace("'{", "{").Replace("}'", "}");
return base.FormatLike(column, format);
}
public override String? BuildDeleteSql(String tableName, String where, Int32 batchSize)
{
if (batchSize <= 0) return base.BuildDeleteSql(tableName, where, 0);
var sb = Pool.StringBuilder.Get();
var xWhere = string.Empty;
var xTable = this.FormatName(tableName);
if (!string.IsNullOrWhiteSpace(where)) xWhere = " Where " + where;
var sql = $"WITH to_delete AS (SELECT \"ctid\" FROM {xTable} {xWhere} LIMIT {batchSize}) ";
sql += $"DELETE FROM {xTable} where \"ctid\" in (SELECT \"ctid\" from to_delete)";
return sql;
}
#endregion

protected override void OnSetConnectionString(ConnectionStringBuilder builder) => base.OnSetConnectionString(builder);
Expand Down
61 changes: 37 additions & 24 deletions XCode/DataAccessLayer/Database/KingBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,33 @@ internal class KingBase : RemoteDb
#endregion

#region 数据库特性
protected override String ReservedWordsStr =>
"ABORT,ABSOLUTE,ACCESS,ACTION,ADD,AFTER,ALL,ALLOCATE,ALTER,AND,ANY,ARE,ARRAY,AS,ASC,ASSERTION,AT,AUTHORIZATION,AVG,BEFORE,BEGIN,BETWEEN,BIT,BIT_LENGTH,BOTH,BY,CASCADE,CASCADED,CASE,CAST,CATALOG,CHAR,CHAR_LENGTH,CHARACTER,CHARACTER_LENGTH,CHECK,CLOSE,COALESCE,COLLATE,COLLATION,COLUMN,COMMIT,CONNECT,CONNECTION,CONSTRAINT,CONSTRAINTS,CONTINUE,CONVERT,CORRESPONDING,COUNT,CREATE,CROSS,CURRENT,CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURRENT_USER,CURSOR,DATE,DAY,DEALLOCATE,DEC,DECIMAL,DECLARE,DEFAULT,DEFERRABLE,DEFERRED,DELETE,DESC,DESCRIBE,DESCRIPTOR,DIAGNOSTICS,DISCONNECT,DISTINCT,DOMAIN,DOUBLE,DROP,ELSE,END,END-EXEC,ESCAPE,EXCEPT,EXCEPTION,EXEC,EXECUTE,EXISTS,EXTERNAL,EXTRACT,FALSE,FETCH,FIRST,FLOAT,FOR,FOREIGN,FOUND,FROM,FULL,GET,GLOBAL,GO,GOTO,GRANT,GROUP,HAVING,HOUR,IDENTITY,IMMEDIATE,IN,INDICATOR,INITIALLY,INNER,INPUT,INSENSITIVE,INSERT,INT,INTEGER,INTERSECT,INTERVAL,INTO,IS,ISOLATION,JOIN,KEY,LANGUAGE,LAST,LEADING,LEFT,LEVEL,LIKE,LOCAL,LOWER,MATCH,MAX,MIN,MINUTE,MODULE,MONTH,NAMES,NATIONAL,NATURAL,NCHAR,NEXT,NO,NOT,NULL,NULLIF,NUMERIC,OCTET_LENGTH,OF,ON,ONLY,OPEN,OPTION,OR,ORDER,OUTER,OUTPUT,OVERLAPS,PAD,PARTIAL,POSITION,PRECISION,PREPARE,PRESERVE,PRIMARY,PRIOR,PRIVILEGES,PROCEDURE,PUBLIC,READ,REAL,REFERENCES,RELATIVE,RESTRICT,REVOKE,RIGHT,ROLLBACK,ROWS,SCHEMA,SCROLL,SECOND,SECTION,SELECT,SESSION,SESSION_USER,SET,SIZE,SMALLINT,SOME,SPACE,SQL,SQLCODE,SQLERROR,SQLSTATE,SUBSTRING,SUM,SYSTEM_USER,TABLE,TEMPORARY,THEN,TIME,TIMESTAMP,TIMEZONE_HOUR,TIMEZONE_MINUTE,TO,TRAILING,TRANSACTION,TRANSLATE,TRANSLATION,TRIM,TRUE,UNION,UNIQUE,UNKNOWN,UPDATE,UPPER,USAGE,USER,USING,VALUE,VALUES,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,WRITE,YEAR,ZONE";

public override String FormatName(String name)
{
if (name.IsNullOrWhiteSpace()) { return name; }
if (name[0] == '"' && name[name.Length - 1] == '"') { return name; }
return $"\"{name}\"";
}
protected override String ReservedWordsStr =>
"ABORT,ABSOLUTE,ACCESS,ACTION,ADD,AFTER,ALL,ALLOCATE,ALTER,AND,ANY,ARE,ARRAY,AS,ASC,ASSERTION,AT,AUTHORIZATION,AVG,BEFORE,BEGIN,BETWEEN,BIT,BIT_LENGTH,BOTH,BY,CASCADE,CASCADED,CASE,CAST,CATALOG,CHAR,CHAR_LENGTH,CHARACTER,CHARACTER_LENGTH,CHECK,CLOSE,COALESCE,COLLATE,COLLATION,COLUMN,COMMIT,CONNECT,CONNECTION,CONSTRAINT,CONSTRAINTS,CONTINUE,CONVERT,CORRESPONDING,COUNT,CREATE,CROSS,CURRENT,CURRENT_DATE,CURRENT_TIME,CURRENT_TIMESTAMP,CURRENT_USER,CURSOR,DATE,DAY,DEALLOCATE,DEC,DECIMAL,DECLARE,DEFAULT,DEFERRABLE,DEFERRED,DELETE,DESC,DESCRIBE,DESCRIPTOR,DIAGNOSTICS,DISCONNECT,DISTINCT,DOMAIN,DOUBLE,DROP,ELSE,END,END-EXEC,ESCAPE,EXCEPT,EXCEPTION,EXEC,EXECUTE,EXISTS,EXTERNAL,EXTRACT,FALSE,FETCH,FIRST,FLOAT,FOR,FOREIGN,FOUND,FROM,FULL,GET,GLOBAL,GO,GOTO,GRANT,GROUP,HAVING,HOUR,IDENTITY,IMMEDIATE,IN,INDICATOR,INITIALLY,INNER,INPUT,INSENSITIVE,INSERT,INT,INTEGER,INTERSECT,INTERVAL,INTO,IS,ISOLATION,JOIN,KEY,LANGUAGE,LAST,LEADING,LEFT,LEVEL,LIKE,LOCAL,LOWER,MATCH,MAX,MIN,MINUTE,MODULE,MONTH,NAMES,NATIONAL,NATURAL,NCHAR,NEXT,NO,NOT,NULL,NULLIF,NUMERIC,OCTET_LENGTH,OF,ON,ONLY,OPEN,OPTION,OR,ORDER,OUTER,OUTPUT,OVERLAPS,PAD,PARTIAL,POSITION,PRECISION,PREPARE,PRESERVE,PRIMARY,PRIOR,PRIVILEGES,PROCEDURE,PUBLIC,READ,REAL,REFERENCES,RELATIVE,RESTRICT,REVOKE,RIGHT,ROLLBACK,ROWS,SCHEMA,SCROLL,SECOND,SECTION,SELECT,SESSION,SESSION_USER,SET,SIZE,SMALLINT,SOME,SPACE,SQL,SQLCODE,SQLERROR,SQLSTATE,SUBSTRING,SUM,SYSTEM_USER,TABLE,TEMPORARY,THEN,TIME,TIMESTAMP,TIMEZONE_HOUR,TIMEZONE_MINUTE,TO,TRAILING,TRANSACTION,TRANSLATE,TRANSLATION,TRIM,TRUE,UNION,UNIQUE,UNKNOWN,UPDATE,UPPER,USAGE,USER,USING,VALUE,VALUES,VARYING,VIEW,WHEN,WHENEVER,WHERE,WITH,WORK,WRITE,YEAR,ZONE";

public override String? BuildDeleteSql(String tableName, String where, Int32 batchSize)
{
if (batchSize <= 0) return base.BuildDeleteSql(tableName, where, 0);
var sb = Pool.StringBuilder.Get();
var xWhere = string.Empty;
var xTable = this.FormatName(tableName);
if (!string.IsNullOrWhiteSpace(where)) xWhere = " Where " + where;
var sql = $"WITH to_delete AS (SELECT \"ctid\" FROM {xTable} {xWhere} LIMIT {batchSize}) ";
sql += $"DELETE FROM {xTable} where \"ctid\" in (SELECT \"ctid\" from to_delete)";
return sql;
}

public override String FormatLike(IDataColumn column, String format)
{
format = format.Replace("'%{", "'%' || {").Replace("}%'", "} || '%'").Replace("'{", "{").Replace("}'", "}");
return base.FormatLike(column, format);
}
#endregion
protected override void OnSetConnectionString(ConnectionStringBuilder builder) => base.OnSetConnectionString(builder);

Expand All @@ -57,12 +76,6 @@ public override String FormatName(String name)
/// <summary>创建数据库会话</summary>
protected override IDbSession OnCreateSession() => new KingBaseSession(this);

public override String FormatLike(IDataColumn column, String format)
{
format = format.Replace("'%{", "'%' || {").Replace("}%'", "} || '%'").Replace("'{", "{").Replace("}'", "}");
return base.FormatLike(column, format);
}

#region 分页
public override SelectBuilder PageSplit(SelectBuilder builder, Int64 startRowIndex, Int64 maximumRows) => PostgreSQL.PageSplitByOffsetLimit(builder, startRowIndex, maximumRows);
public override String PageSplit(String sql, Int64 startRowIndex, Int64 maximumRows, String keyColumn) => PostgreSQL.PageSplitByOffsetLimit(sql, startRowIndex, maximumRows);
Expand Down Expand Up @@ -247,18 +260,18 @@ string GetIndexsSql
/// <summary>数据类型映射</summary>
static readonly Dictionary<Type, String[]> _DataTypes = new()
{
{ typeof(Byte[]), new String[] { "BYTEA", "BLOB", "CLOB", "NCLOB", "BIT({0})", "BIT VARYING({0})" } },
{ typeof(Byte), new String[] { "TINYINT", "INT1" } },
{ typeof(Int16), new String[] { "SMALLINT", "INT2", "SMALLSERIAL" } },
{ typeof(Int32), new String[] { "INTEGER", "INT4", "TINYINT", "YEAR", "MEDIUMINT", "MIDDLEINT", "INT3" } },
{ typeof(Int64), new String[] { "BIGINT", "BIGSERIAL", "INT8" } },
{ typeof(Single), new String[] { "REAL", "FLOAT", "FLOAT4" } },
{ typeof(Double), new String[] { "DOUBLE PRECISION", "FLOAT8" } },
{ typeof(Decimal), new String[] { "NUMERIC({0}, {1})", "DECIMAL({0}, {1})", "NUMBER({0}, {1})", "FIXED({0}, {1})" } },
{ typeof(DateTime), new String[] { "DATETIME", "DATE", "TIME", "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMPTZ", "TIMESTAMP WITHOUT TIME ZONE", "TIME WITH TIME ZONE" , "TIMETZ", "TIME WITHOUT TIME ZONE" } },
{ typeof(Boolean), new String[] { "BOOLEAN", "BOOL" } },
{ typeof(Guid), new String[] { "UUID" } },
{ typeof(String), new String[] { "VARCHAR({0})","TEXT", "NVARCHAR({0})", "CHARACTER({0})", "CHARACTER VARYING({0})", "CHAR({0})", "NAME", "LONGTEXT", "MEDIUMTEXT", "TINYTEXT", "XML", "JSON", "ROWID"} },
{ typeof(Byte[]), new String[] { "bytea", "blob", "clob", "nclob", "bit({0})", "bit varying({0})" } },
{ typeof(Byte), new String[] { "tinyint", "int1" } },
{ typeof(Int16), new String[] { "smallint", "int2", "smallserial" } },
{ typeof(Int32), new String[] { "integer", "int4", "tinyint", "year", "mediumint", "middleint", "int3" } },
{ typeof(Int64), new String[] { "bigint", "bigserial", "int8" } },
{ typeof(Single), new String[] { "real", "float", "float4" } },
{ typeof(Double), new String[] { "double precision", "float8" } },
{ typeof(Decimal), new String[] { "numeric({0}, {1})", "decimal({0}, {1})", "number({0}, {1})", "fixed({0}, {1})" } },
{ typeof(DateTime), new String[] { "datetime", "date", "time", "timestamp", "timestamp with time zone", "timestamptz", "timestamp without time zone", "time with time zone" , "timetz", "time without time zone" } },
{ typeof(Boolean), new String[] { "boolean", "bool" } },
{ typeof(Guid), new String[] { "uuid" } },
{ typeof(String), new String[] { "varchar({0})","text", "nvarchar({0})", "character({0})", "character varying({0})", "char({0})", "name", "longtext", "mediumtext", "tinytext", "xml", "json", "rowid" } },
};
#endregion

Expand All @@ -274,7 +287,7 @@ void DataBaseModel()
{
"mysql" => DatabaseType.MySql,
"oracle" => DatabaseType.Oracle,
"postgresql" => DatabaseType.PostgreSQL,
"pg" => DatabaseType.PostgreSQL,
_ => DatabaseType.None
};
}
Expand Down Expand Up @@ -429,9 +442,9 @@ public override IList<String> GetTableNames()
{
if (field.Identity)
{
if (field.DataType == typeof(Int16)) { return "SMALLSERIAL"; }
if (field.DataType == typeof(Int32)) { return "SERIAL"; }
if (field.DataType == typeof(Int64)) { return "BIGSERIAL"; }
if (field.DataType == typeof(Int16)) { return "smallserial"; }
if (field.DataType == typeof(Int32)) { return "serial"; }
if (field.DataType == typeof(Int64)) { return "bigserial"; }
}
return base.GetFieldType(field);
}
Expand Down
11 changes: 11 additions & 0 deletions XUnitTest.XCode/DataAccessLayer/HighGoTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,4 +331,15 @@ public void CreateTableWithStringLength()
)";
Assert.Equal(targetSql, sql, true);
}

[Fact(Skip = "跳过")]
public void BuildDeleteSql()
{
DAL.AddConnStr("HighGo", _ConnStr, null, "HighGo");
var dal = DAL.Create("HighGo");
Role.Meta.ConnName = "HighGo";
Role.Meta.Session.InitData();
var count = Role.Delete(Role._.Name == "管理员");
Assert.Equal(count, 1);
}
}
69 changes: 40 additions & 29 deletions XUnitTest.XCode/DataAccessLayer/KingBaseTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -257,22 +258,22 @@ public void QuerySqlTest()

DAL.AddConnStr("Membership", connStr, null, "KingBase");
var dal = DAL.Create("Membership");
var a = dal.Query<Role>("select * from Role order by id");
var a = dal.Query<Role>("select * from \"Role\" order by \"ID\"");

var p1 = new PageParameter() { PageSize = 20, PageIndex = 1, Sort = "Id", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from Role ", null, p1);
var p1 = new PageParameter() { PageSize = 20, PageIndex = 1, Sort = "\"ID\"", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from \"Role\" ", null, p1);

var p2 = new PageParameter() { PageSize = 20, PageIndex = 1, Sort = "Id", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from Role", null, p2);
var p2 = new PageParameter() { PageSize = 20, PageIndex = 1, Sort = "\"ID\"", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from \"Role\"", null, p2);


dal.Query<Role>("select * from Role order by id");
dal.Query<Role>("select * from \"Role\" order by \"ID\"");

var p11 = new PageParameter() { PageSize = 20, PageIndex = 2, Sort = "Id", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from Role ", null, p11);
var p11 = new PageParameter() { PageSize = 20, PageIndex = 2, Sort = "\"ID\"", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from \"Role\" ", null, p11);

var p21 = new PageParameter() { PageSize = 20, PageIndex = 2, Sort = "Id", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from Role", null, p21);
var p21 = new PageParameter() { PageSize = 20, PageIndex = 2, Sort = "\"ID\"", RetrieveTotalCount = true, Desc = false };
a = dal.Query<Role>("select * from \"Role\"", null, p21);
// 清理现场
//try
//{
Expand All @@ -290,7 +291,7 @@ public void CreateTableWithStringLength()

var str = """
<EntityModel>
<Table Name="ActEvtLog" TableName="ACT_EVT_LOG" DbType="KingBase">
<Table Name="ActEvtLog" TableName="ACT_EVT_LOG" DbType="HighGo">
<Columns>
<Column Name="LogNr" ColumnName="LOG_NR_" DataType="Int32" RawType="numeric(19, 0)" Identity="True" PrimaryKey="True" />
<Column Name="Type" ColumnName="TYPE_" DataType="String" Length="64" />
Expand All @@ -300,7 +301,7 @@ public void CreateTableWithStringLength()
<Column Name="TaskId" ColumnName="TASK_ID_" DataType="String" Length="64" />
<Column Name="TimeStamp" ColumnName="TIME_STAMP_" DataType="DateTime" Scale="3" Nullable="False" />
<Column Name="UserId" ColumnName="USER_ID_" DataType="String" Length="255" />
<Column Name="Data" ColumnName="DATA_" DataType="Byte[]" RawType="varbinary(-1)" Length="-1" />
<Column Name="Data" ColumnName="DATA_" DataType="Byte[]" />
<Column Name="LockOwner" ColumnName="LOCK_OWNER_" DataType="String" Length="255" />
<Column Name="LockTime" ColumnName="LOCK_TIME_" DataType="DateTime" Scale="3" />
<Column Name="IsProcessed" ColumnName="IS_PROCESSED_" DataType="Byte" Nullable="True" />
Expand All @@ -312,27 +313,37 @@ public void CreateTableWithStringLength()
Assert.NotNull(table);
Assert.Equal("ActEvtLog", table.Name);
Assert.Equal("ACT_EVT_LOG", table.TableName);
Assert.Equal(DatabaseType.KingBase, table.DbType);
Assert.Equal(DatabaseType.HighGo, table.DbType);

var db = DbFactory.Create(DatabaseType.KingBase);
var db = DbFactory.Create(DatabaseType.HighGo);
var meta = db.CreateMetaData();
var sql = meta.GetSchemaSQL(DDLSchema.CreateTable, table);

var targetSql = @$"Create Table If Not Exists ""ACT_EVT_LOG""(
""LOG_NR_"" SERIAL NOT NULL,
""TYPE_"" VARCHAR(64),
""PROC_DEF_ID_"" VARCHAR(64),
""PROC_INST_ID_"" VARCHAR(64),
""EXECUTION_ID_"" VARCHAR(64),
""TASK_ID_"" VARCHAR(64),
""TIME_STAMP_"" DATETIME NOT NULL DEFAULT '0001-01-01',
""USER_ID_"" VARCHAR(255),
""DATA_"" varbinary(-1),
""LOCK_OWNER_"" VARCHAR(255),
""LOCK_TIME_"" DATETIME,
""IS_PROCESSED_"" TINYINT,
Primary Key (""LOG_NR_"")
);";
var targetSql = @$"Create Table ""ACT_EVT_LOG""(
""LOG_NR_"" serial Primary Key,
""TYPE_"" varchar(64) NULL,
""PROC_DEF_ID_"" varchar(64) NULL,
""PROC_INST_ID_"" varchar(64) NULL,
""EXECUTION_ID_"" varchar(64) NULL,
""TASK_ID_"" varchar(64) NULL,
""TIME_STAMP_"" timestamp NOT NULL DEFAULT '0001-01-01',
""USER_ID_"" varchar(255) NULL,
""DATA_"" bytea NULL,
""LOCK_OWNER_"" varchar(255) NULL,
""LOCK_TIME_"" timestamp NULL,
""IS_PROCESSED_"" bit null
)";
Assert.Equal(targetSql, sql);
}

[Fact(Skip = "跳过")]
public void BuildDeleteSql()
{
DAL.AddConnStr("KingBase", _ConnStr, null, "KingBase");
var dal = DAL.Create("KingBase");
Role.Meta.ConnName = "KingBase";
Role.Meta.Session.InitData();
var count = Role.Delete(Role._.Name == "管理员");
Assert.Equal(count, 1);
}
}

0 comments on commit c3c406f

Please sign in to comment.