Browse Source

feat(quartz): Added automatic migration of Quartz database

pull/1161/head
colin 10 months ago
parent
commit
a1beec4be9
  1. 3
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xml
  2. 30
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN.Abp.Quartz.MySqlInstaller.csproj
  3. 30
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/AbpQuartzMySqlInstallerModule.cs
  4. 136
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/QuartzMySqlInstaller.cs
  5. 181
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql
  6. 3
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/FodyWeavers.xml
  7. 30
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN.Abp.Quartz.SqlServerInstaller.csproj
  8. 30
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/AbpQuartzSqlServerInstallerModule.cs
  9. 136
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/QuartzSqlServerInstaller.cs
  10. 370
      aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql

3
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN.Abp.Quartz.MySqlInstaller.csproj

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Quartz.MySqlInstaller</AssemblyName>
<PackageId>LINGYUN.Abp.Quartz.MySqlInstaller</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Quartz\MySqlInstaller\Scripts\Initial.sql" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Quartz\MySqlInstaller\Scripts\Initial.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Quartz" />
<PackageReference Include="Volo.Abp.VirtualFileSystem" />
<PackageReference Include="MySqlConnector" />
</ItemGroup>
</Project>

30
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/AbpQuartzMySqlInstallerModule.cs

@ -0,0 +1,30 @@
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Quartz;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Quartz.MySqlInstaller;
[DependsOn(
typeof(AbpQuartzModule),
typeof(AbpVirtualFileSystemModule))]
public class AbpQuartzMySqlInstallerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpQuartzMySqlInstallerModule>();
});
}
public async override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
// 初始化 Quartz Mysql 数据库
await context.ServiceProvider
.GetRequiredService<QuartzMySqlInstaller>()
.InstallAsync();
}
}

136
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/QuartzMySqlInstaller.cs

@ -0,0 +1,136 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using MySqlConnector;
using System;
using System.Data;
using System.Threading.Tasks;
using Volo.Abp.Quartz;
using Volo.Abp.VirtualFileSystem;
using static Quartz.SchedulerBuilder;
namespace LINGYUN.Abp.Quartz.MySqlInstaller;
public class QuartzMySqlInstaller
{
public ILogger<QuartzMySqlInstaller> Logger { protected get; set; }
private readonly IVirtualFileProvider _virtualFileProvider;
private readonly AbpQuartzOptions _quartzOptions;
public QuartzMySqlInstaller(
IVirtualFileProvider virtualFileProvider,
IOptions<AbpQuartzOptions> quartzOptions)
{
_quartzOptions = quartzOptions.Value;
_virtualFileProvider = virtualFileProvider;
Logger = NullLogger<QuartzMySqlInstaller>.Instance;
}
public async virtual Task InstallAsync()
{
var dataSource = _quartzOptions.Properties["quartz.jobStore.dataSource"] ?? AdoProviderOptions.DefaultDataSourceName;
var connectionString = _quartzOptions.Properties[$"quartz.dataSource.{dataSource}.connectionString"];
var tablePrefix = _quartzOptions.Properties["quartz.jobStore.tablePrefix"] ?? "QRTZ_";
if (connectionString.IsNullOrWhiteSpace())
{
Logger.LogWarning($"Please configure the `{dataSource}` database connection string in `quartz.jobStore.dataSource`!");
throw new ArgumentNullException(nameof(connectionString));
}
Logger.LogInformation("Install Quartz MySql...");
var builder = new MySqlConnectionStringBuilder(connectionString);
var dataBaseName = await CreateDataBaseIfNotExists(builder.Database, builder);
builder.Database = dataBaseName;
using var mySqlConnection = new MySqlConnection(builder.ConnectionString);
if (mySqlConnection.State == ConnectionState.Closed)
{
await mySqlConnection.OpenAsync();
}
using (var mySqlCommand = new MySqlCommand("SELECT COUNT(1) FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = @DataBaseName;", mySqlConnection))
{
mySqlCommand.Parameters.Add("@DataBaseName", MySqlDbType.String).Value = dataBaseName;
var rowsAffects = await mySqlCommand.ExecuteScalarAsync() as long?;
if (rowsAffects > 0)
{
Logger.LogInformation($"The `{dataBaseName}` tables has already exists.");
return;
}
}
var sqlScript = await GetInitSqlScript();
// USE `${DataBase}` -> USE `Workflow`;
sqlScript = sqlScript.ReplaceFirst("${DataBase}", dataBaseName);
// CREATE TABLE $(TablePrefix)JOB_DETAILS` -> CREATE TABLE QRTZ_JOB_DETAILS;
sqlScript = sqlScript.Replace("${TablePrefix}", tablePrefix);
using (var mySqlCommand = new MySqlCommand(sqlScript, mySqlConnection))
{
Logger.LogInformation("The database initialization script `Initial.sql` starts...");
await mySqlCommand.ExecuteNonQueryAsync();
}
Logger.LogInformation("Database initialization script `Initial.sql` complete!");
}
public async virtual Task<string> CreateDataBaseIfNotExists(string dataBase, MySqlConnectionStringBuilder connectionStringBuilder)
{
// 切换主数据库查询数据库是否存在
connectionStringBuilder.Database = "mysql";
using var mySqlConnection = new MySqlConnection(connectionStringBuilder.ConnectionString);
if (mySqlConnection.State == ConnectionState.Closed)
{
await mySqlConnection.OpenAsync();
}
var checkDataBaseName = "";
using (var mySqlCommand = new MySqlCommand("SELECT `SCHEMA_NAME` FROM `information_schema`.`SCHEMATA` WHERE `SCHEMA_NAME` = @DataBaseName;", mySqlConnection))
{
var dataBaseParamter = mySqlCommand.Parameters.Add("DataBaseName", DbType.String);
dataBaseParamter.Value = dataBase;
checkDataBaseName = await mySqlCommand.ExecuteScalarAsync() as string;
}
if (checkDataBaseName.IsNullOrWhiteSpace())
{
using (var mySqlCommand = new MySqlCommand($"CREATE DATABASE `{dataBase}` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';", mySqlConnection))
{
await mySqlCommand.ExecuteNonQueryAsync();
}
}
return dataBase;
}
public async virtual Task<string> GetInitSqlScript()
{
var sqlScriptFileInfo = _virtualFileProvider.GetFileInfo("/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql");
if (!sqlScriptFileInfo.Exists || sqlScriptFileInfo.IsDirectory)
{
Logger.LogWarning("Please Check that the `Initial.sql` file exists!");
throw new InvalidOperationException("The `Initial.sql` database initialization script file does not exist or is not valid!");
}
var sqlScript = await sqlScriptFileInfo.ReadAsStringAsync();
if (sqlScript.IsNullOrWhiteSpace())
{
Logger.LogWarning("The contents of the `Initial.sql` file are empty or invalid!");
throw new InvalidOperationException("The contents of the `Initial.sql` file are empty or invalid!");
}
return sqlScript;
}
}

181
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.MySqlInstaller/LINGYUN/Abp/Quartz/MySqlInstaller/Scripts/Initial.sql

@ -0,0 +1,181 @@
# By: Ron Cordell - roncordell
# I didn't see this anywhere, so I thought I'd post it here. This is the script from Quartz to create the tables in a MySQL database, modified to use INNODB instead of MYISAM.
# make sure you have UTF-8 collaction for best .NET interoperability
# CREATE DATABASE quartznet CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `${DataBase}`;
DROP TABLE IF EXISTS ${TablePrefix}FIRED_TRIGGERS;
DROP TABLE IF EXISTS ${TablePrefix}PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS ${TablePrefix}SCHEDULER_STATE;
DROP TABLE IF EXISTS ${TablePrefix}LOCKS;
DROP TABLE IF EXISTS ${TablePrefix}SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS ${TablePrefix}SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS ${TablePrefix}CRON_TRIGGERS;
DROP TABLE IF EXISTS ${TablePrefix}BLOB_TRIGGERS;
DROP TABLE IF EXISTS ${TablePrefix}TRIGGERS;
DROP TABLE IF EXISTS ${TablePrefix}JOB_DETAILS;
DROP TABLE IF EXISTS ${TablePrefix}CALENDARS;
CREATE TABLE ${TablePrefix}JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE BOOLEAN NOT NULL,
IS_NONCONCURRENT BOOLEAN NOT NULL,
IS_UPDATE_DATA BOOLEAN NOT NULL,
REQUESTS_RECOVERY BOOLEAN NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(19) NULL,
PREV_FIRE_TIME BIGINT(19) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(19) NOT NULL,
END_TIME BIGINT(19) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES ${TablePrefix}JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 BOOLEAN NULL,
BOOL_PROP_2 BOOLEAN NULL,
TIME_ZONE_ID VARCHAR(80) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(140) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(19) NOT NULL,
SCHED_TIME BIGINT(19) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT BOOLEAN NULL,
REQUESTS_RECOVERY BOOLEAN NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(19) NOT NULL,
CHECKIN_INTERVAL BIGINT(19) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE ${TablePrefix}LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_${TablePrefix}J_REQ_RECOVERY ON ${TablePrefix}JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_${TablePrefix}J_GRP ON ${TablePrefix}JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_${TablePrefix}T_J ON ${TablePrefix}TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_${TablePrefix}T_JG ON ${TablePrefix}TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_${TablePrefix}T_C ON ${TablePrefix}TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_${TablePrefix}T_G ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_${TablePrefix}T_STATE ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_${TablePrefix}T_N_STATE ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_${TablePrefix}T_N_G_STATE ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_${TablePrefix}T_NEXT_FIRE_TIME ON ${TablePrefix}TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_${TablePrefix}T_NFT_ST ON ${TablePrefix}TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_${TablePrefix}T_NFT_MISFIRE ON ${TablePrefix}TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_${TablePrefix}T_NFT_ST_MISFIRE ON ${TablePrefix}TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_${TablePrefix}T_NFT_ST_MISFIRE_GRP ON ${TablePrefix}TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_${TablePrefix}FT_TRIG_INST_NAME ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_${TablePrefix}FT_INST_JOB_REQ_RCVRY ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_${TablePrefix}FT_J_G ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_${TablePrefix}FT_JG ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_${TablePrefix}FT_T_G ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_${TablePrefix}FT_TG ON ${TablePrefix}FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;

3
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN.Abp.Quartz.SqlServerInstaller.csproj

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Quartz.SqlServerInstaller</AssemblyName>
<PackageId>LINGYUN.Abp.Quartz.SqlServerInstaller</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Quartz\SqlServerInstaller\Scripts\Initial.sql" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\Quartz\SqlServerInstaller\Scripts\Initial.sql" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Quartz" />
<PackageReference Include="Volo.Abp.VirtualFileSystem" />
<PackageReference Include="Microsoft.Data.SqlClient" />
</ItemGroup>
</Project>

30
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/AbpQuartzSqlServerInstallerModule.cs

@ -0,0 +1,30 @@
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Quartz;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Quartz.SqlServerInstaller;
[DependsOn(
typeof(AbpQuartzModule),
typeof(AbpVirtualFileSystemModule))]
public class AbpQuartzSqlServerInstallerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpQuartzSqlServerInstallerModule>();
});
}
public async override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
// 初始化 Quartz SqlServer 数据库
await context.ServiceProvider
.GetRequiredService<QuartzSqlServerInstaller>()
.InstallAsync();
}
}

136
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/QuartzSqlServerInstaller.cs

@ -0,0 +1,136 @@
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using System;
using System.Data;
using System.Threading.Tasks;
using Volo.Abp.Quartz;
using Volo.Abp.VirtualFileSystem;
using static Quartz.SchedulerBuilder;
namespace LINGYUN.Abp.Quartz.SqlServerInstaller;
public class QuartzSqlServerInstaller
{
public ILogger<QuartzSqlServerInstaller> Logger { protected get; set; }
private readonly IVirtualFileProvider _virtualFileProvider;
private readonly AbpQuartzOptions _quartzOptions;
public QuartzSqlServerInstaller(
IVirtualFileProvider virtualFileProvider,
IOptions<AbpQuartzOptions> quartzOptions)
{
_quartzOptions = quartzOptions.Value;
_virtualFileProvider = virtualFileProvider;
Logger = NullLogger<QuartzSqlServerInstaller>.Instance;
}
public async virtual Task InstallAsync()
{
var dataSource = _quartzOptions.Properties["quartz.jobStore.dataSource"] ?? AdoProviderOptions.DefaultDataSourceName;
var connectionString = _quartzOptions.Properties[$"quartz.dataSource.{dataSource}.connectionString"];
var tablePrefix = _quartzOptions.Properties["quartz.jobStore.tablePrefix"] ?? "QRTZ_";
if (connectionString.IsNullOrWhiteSpace())
{
Logger.LogWarning($"Please configure the `{dataSource}` database connection string in `quartz.jobStore.dataSource`!");
throw new ArgumentNullException(nameof(connectionString));
}
Logger.LogInformation("Install Quartz SqlServer...");
var builder = new SqlConnectionStringBuilder(connectionString);
var dataBaseName = await CreateDataBaseIfNotExists(builder.InitialCatalog, builder);
builder.InitialCatalog = dataBaseName;
using var sqlConnection = new SqlConnection(builder.ConnectionString);
if (sqlConnection.State == ConnectionState.Closed)
{
await sqlConnection.OpenAsync();
}
using (var sqlCommand = new SqlCommand("SELECT COUNT(1) FROM [sys].[objects] WHERE type=N'U'", sqlConnection))
{
sqlCommand.Parameters.Add("@DataBaseName", SqlDbType.NVarChar).Value = dataBaseName;
var rowsAffects = await sqlCommand.ExecuteScalarAsync() as long?;
if (rowsAffects > 0)
{
Logger.LogInformation($"The `{dataBaseName}` tables has already exists.");
return;
}
}
var sqlScript = await GetInitSqlScript();
// USE `${DataBase}` -> USE `Workflow`;
sqlScript = sqlScript.ReplaceFirst("${DataBase}", dataBaseName);
// CREATE TABLE $(TablePrefix)JOB_DETAILS` -> CREATE TABLE QRTZ_JOB_DETAILS;
sqlScript = sqlScript.Replace("${TablePrefix}", tablePrefix);
using (var sqlCommand = new SqlCommand(sqlScript, sqlConnection))
{
Logger.LogInformation("The database initialization script `Initial.sql` starts...");
await sqlCommand.ExecuteNonQueryAsync();
}
Logger.LogInformation("Database initialization script `Initial.sql` complete!");
}
public async virtual Task<string> CreateDataBaseIfNotExists(string dataBase, SqlConnectionStringBuilder connectionStringBuilder)
{
// 切换主数据库查询数据库是否存在
connectionStringBuilder.InitialCatalog = "master";
using var sqlConnection = new SqlConnection(connectionStringBuilder.ConnectionString);
if (sqlConnection.State == ConnectionState.Closed)
{
await sqlConnection.OpenAsync();
}
var checkDataBaseName = "";
using (var sqlCommand = new SqlCommand("SELECT [name] FROM [master].[dbo].[sysdatabases] WHERE [name] = @DataBaseName;", sqlConnection))
{
var dataBaseParamter = sqlCommand.Parameters.Add("DataBaseName", SqlDbType.NVarChar);
dataBaseParamter.Value = dataBase;
checkDataBaseName = await sqlCommand.ExecuteScalarAsync() as string;
}
if (checkDataBaseName.IsNullOrWhiteSpace())
{
using (var sqlCommand = new SqlCommand($"CREATE DATABASE {dataBase};", sqlConnection))
{
await sqlCommand.ExecuteNonQueryAsync();
}
}
return dataBase;
}
public async virtual Task<string> GetInitSqlScript()
{
var sqlScriptFileInfo = _virtualFileProvider.GetFileInfo("/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql");
if (!sqlScriptFileInfo.Exists || sqlScriptFileInfo.IsDirectory)
{
Logger.LogWarning("Please Check that the `Initial.sql` file exists!");
throw new InvalidOperationException("The `Initial.sql` database initialization script file does not exist or is not valid!");
}
var sqlScript = await sqlScriptFileInfo.ReadAsStringAsync();
if (sqlScript.IsNullOrWhiteSpace())
{
Logger.LogWarning("The contents of the `Initial.sql` file are empty or invalid!");
throw new InvalidOperationException("The contents of the `Initial.sql` file are empty or invalid!");
}
return sqlScript;
}
}

370
aspnet-core/modules/task-management/LINGYUN.Abp.Quartz.SqlServerInstaller/LINGYUN/Abp/Quartz/SqlServerInstaller/Scripts/Initial.sql

@ -0,0 +1,370 @@
-- this script is for SQL Server and Azure SQL
-- This initializes the database to pristine for Quartz, by first removing any existing Quartz tables
-- and then recreating them from scratch.
-- Should you only require it to create the tables, set @DropDb to 0.
USE [${DataBase}];
GO
DECLARE @DropDb BIT = 1; -- Set this to 0 to skip DROP statements, 1 to include them
IF @DropDb = 1
BEGIN
-- drop indexes if they exist and rebuild if current ones
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_J] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_JG] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_C] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_G] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_G_J] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_STATE] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_N_STATE] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_N_G_STATE] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NEXT_FIRE_TIME] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_ST] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_MISFIRE] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_ST_MISFIRE] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}T_NFT_ST_MISFIRE_GRP] ON [dbo].[${TablePrefix}TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_TRIG_INST_NAME] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_INST_JOB_REQ_RCVRY] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_J_G] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_JG] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_T_G] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_TG] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_G_J] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
DROP INDEX IF EXISTS [IDX_${TablePrefix}FT_G_T] ON [dbo].[${TablePrefix}FIRED_TRIGGERS];
IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}TRIGGERS_${TablePrefix}JOB_DETAILS]', N'F') IS NOT NULL
ALTER TABLE [dbo].[${TablePrefix}TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}TRIGGERS_${TablePrefix}JOB_DETAILS];
IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}CRON_TRIGGERS_${TablePrefix}TRIGGERS]', N'F') IS NOT NULL
ALTER TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}CRON_TRIGGERS_${TablePrefix}TRIGGERS];
IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}SIMPLE_TRIGGERS_${TablePrefix}TRIGGERS]', N'F') IS NOT NULL
ALTER TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}SIMPLE_TRIGGERS_${TablePrefix}TRIGGERS];
IF OBJECT_ID(N'[dbo].[FK_${TablePrefix}SIMPROP_TRIGGERS_${TablePrefix}TRIGGERS]', N'F') IS NOT NULL
ALTER TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] DROP CONSTRAINT [FK_${TablePrefix}SIMPROP_TRIGGERS_${TablePrefix}TRIGGERS];
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_${TablePrefix}JOB_LISTENERS_${TablePrefix}JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[${TablePrefix}JOB_LISTENERS]'))
ALTER TABLE [dbo].[${TablePrefix}JOB_LISTENERS] DROP CONSTRAINT [FK_${TablePrefix}JOB_LISTENERS_${TablePrefix}JOB_DETAILS];
IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_${TablePrefix}TRIGGER_LISTENERS_${TablePrefix}TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[${TablePrefix}TRIGGER_LISTENERS]'))
ALTER TABLE [dbo].[${TablePrefix}TRIGGER_LISTENERS] DROP CONSTRAINT [FK_${TablePrefix}TRIGGER_LISTENERS_${TablePrefix}TRIGGERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}CALENDARS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}CALENDARS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}CRON_TRIGGERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}CRON_TRIGGERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}BLOB_TRIGGERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}BLOB_TRIGGERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}FIRED_TRIGGERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}FIRED_TRIGGERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}JOB_LISTENERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}JOB_LISTENERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}SCHEDULER_STATE]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}SCHEDULER_STATE];
IF OBJECT_ID(N'[dbo].[${TablePrefix}LOCKS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}LOCKS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}TRIGGER_LISTENERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}TRIGGER_LISTENERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}JOB_DETAILS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}JOB_DETAILS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}SIMPLE_TRIGGERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}SIMPROP_TRIGGERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS];
IF OBJECT_ID(N'[dbo].[${TablePrefix}TRIGGERS]', N'U') IS NOT NULL
DROP TABLE [dbo].[${TablePrefix}TRIGGERS];
END
CREATE TABLE [dbo].[${TablePrefix}CALENDARS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[CALENDAR_NAME] nvarchar(200) NOT NULL,
[CALENDAR] varbinary(max) NOT NULL
);
CREATE TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[TRIGGER_NAME] nvarchar(150) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL,
[CRON_EXPRESSION] nvarchar(120) NOT NULL,
[TIME_ZONE_ID] nvarchar(80)
);
CREATE TABLE [dbo].[${TablePrefix}FIRED_TRIGGERS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[ENTRY_ID] nvarchar(140) NOT NULL,
[TRIGGER_NAME] nvarchar(150) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL,
[INSTANCE_NAME] nvarchar(200) NOT NULL,
[FIRED_TIME] bigint NOT NULL,
[SCHED_TIME] bigint NOT NULL,
[PRIORITY] int NOT NULL,
[STATE] nvarchar(16) NOT NULL,
[JOB_NAME] nvarchar(150) NULL,
[JOB_GROUP] nvarchar(150) NULL,
[IS_NONCONCURRENT] bit NULL,
[REQUESTS_RECOVERY] bit NULL
);
CREATE TABLE [dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL
);
CREATE TABLE [dbo].[${TablePrefix}SCHEDULER_STATE] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[INSTANCE_NAME] nvarchar(200) NOT NULL,
[LAST_CHECKIN_TIME] bigint NOT NULL,
[CHECKIN_INTERVAL] bigint NOT NULL
);
CREATE TABLE [dbo].[${TablePrefix}LOCKS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[LOCK_NAME] nvarchar(40) NOT NULL
);
CREATE TABLE [dbo].[${TablePrefix}JOB_DETAILS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[JOB_NAME] nvarchar(150) NOT NULL,
[JOB_GROUP] nvarchar(150) NOT NULL,
[DESCRIPTION] nvarchar(250) NULL,
[JOB_CLASS_NAME] nvarchar(250) NOT NULL,
[IS_DURABLE] bit NOT NULL,
[IS_NONCONCURRENT] bit NOT NULL,
[IS_UPDATE_DATA] bit NOT NULL,
[REQUESTS_RECOVERY] bit NOT NULL,
[JOB_DATA] varbinary(max) NULL
);
CREATE TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[TRIGGER_NAME] nvarchar(150) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL,
[REPEAT_COUNT] int NOT NULL,
[REPEAT_INTERVAL] bigint NOT NULL,
[TIMES_TRIGGERED] int NOT NULL
);
CREATE TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[TRIGGER_NAME] nvarchar(150) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL,
[STR_PROP_1] nvarchar(512) NULL,
[STR_PROP_2] nvarchar(512) NULL,
[STR_PROP_3] nvarchar(512) NULL,
[INT_PROP_1] int NULL,
[INT_PROP_2] int NULL,
[LONG_PROP_1] bigint NULL,
[LONG_PROP_2] bigint NULL,
[DEC_PROP_1] numeric(13,4) NULL,
[DEC_PROP_2] numeric(13,4) NULL,
[BOOL_PROP_1] bit NULL,
[BOOL_PROP_2] bit NULL,
[TIME_ZONE_ID] nvarchar(80) NULL
);
CREATE TABLE [dbo].[${TablePrefix}BLOB_TRIGGERS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[TRIGGER_NAME] nvarchar(150) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL,
[BLOB_DATA] varbinary(max) NULL
);
CREATE TABLE [dbo].[${TablePrefix}TRIGGERS] (
[SCHED_NAME] nvarchar(120) NOT NULL,
[TRIGGER_NAME] nvarchar(150) NOT NULL,
[TRIGGER_GROUP] nvarchar(150) NOT NULL,
[JOB_NAME] nvarchar(150) NOT NULL,
[JOB_GROUP] nvarchar(150) NOT NULL,
[DESCRIPTION] nvarchar(250) NULL,
[NEXT_FIRE_TIME] bigint NULL,
[PREV_FIRE_TIME] bigint NULL,
[PRIORITY] int NULL,
[TRIGGER_STATE] nvarchar(16) NOT NULL,
[TRIGGER_TYPE] nvarchar(8) NOT NULL,
[START_TIME] bigint NOT NULL,
[END_TIME] bigint NULL,
[CALENDAR_NAME] nvarchar(200) NULL,
[MISFIRE_INSTR] int NULL,
[JOB_DATA] varbinary(max) NULL
);
GO
ALTER TABLE [dbo].[${TablePrefix}CALENDARS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}CALENDARS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[CALENDAR_NAME]
);
GO
ALTER TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}CRON_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}FIRED_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}FIRED_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[ENTRY_ID]
);
GO
ALTER TABLE [dbo].[${TablePrefix}PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}SCHEDULER_STATE] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}SCHEDULER_STATE] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[INSTANCE_NAME]
);
GO
ALTER TABLE [dbo].[${TablePrefix}LOCKS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}LOCKS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[LOCK_NAME]
);
GO
ALTER TABLE [dbo].[${TablePrefix}JOB_DETAILS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}JOB_DETAILS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}BLOB_TRIGGERS] WITH NOCHECK ADD
CONSTRAINT [PK_${TablePrefix}BLOB_TRIGGERS] PRIMARY KEY CLUSTERED
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
);
GO
ALTER TABLE [dbo].[${TablePrefix}CRON_TRIGGERS] ADD
CONSTRAINT [FK_${TablePrefix}CRON_TRIGGERS_${TablePrefix}TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[${TablePrefix}TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[${TablePrefix}SIMPLE_TRIGGERS] ADD
CONSTRAINT [FK_${TablePrefix}SIMPLE_TRIGGERS_${TablePrefix}TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[${TablePrefix}TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[${TablePrefix}SIMPROP_TRIGGERS] ADD
CONSTRAINT [FK_${TablePrefix}SIMPROP_TRIGGERS_${TablePrefix}TRIGGERS] FOREIGN KEY
(
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) REFERENCES [dbo].[${TablePrefix}TRIGGERS] (
[SCHED_NAME],
[TRIGGER_NAME],
[TRIGGER_GROUP]
) ON DELETE CASCADE;
GO
ALTER TABLE [dbo].[${TablePrefix}TRIGGERS] ADD
CONSTRAINT [FK_${TablePrefix}TRIGGERS_${TablePrefix}JOB_DETAILS] FOREIGN KEY
(
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
) REFERENCES [dbo].[${TablePrefix}JOB_DETAILS] (
[SCHED_NAME],
[JOB_NAME],
[JOB_GROUP]
);
GO
-- Create indexes
CREATE INDEX [IDX_${TablePrefix}T_G_J] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, JOB_GROUP, JOB_NAME);
CREATE INDEX [IDX_${TablePrefix}T_C] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, CALENDAR_NAME);
CREATE INDEX [IDX_${TablePrefix}T_N_G_STATE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_GROUP, TRIGGER_STATE);
CREATE INDEX [IDX_${TablePrefix}T_STATE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_STATE);
CREATE INDEX [IDX_${TablePrefix}T_N_STATE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP, TRIGGER_STATE);
CREATE INDEX [IDX_${TablePrefix}T_NEXT_FIRE_TIME] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, NEXT_FIRE_TIME);
CREATE INDEX [IDX_${TablePrefix}T_NFT_ST] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, TRIGGER_STATE, NEXT_FIRE_TIME);
CREATE INDEX [IDX_${TablePrefix}T_NFT_ST_MISFIRE] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_STATE);
CREATE INDEX [IDX_${TablePrefix}T_NFT_ST_MISFIRE_GRP] ON [dbo].[${TablePrefix}TRIGGERS](SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_GROUP, TRIGGER_STATE);
CREATE INDEX [IDX_${TablePrefix}FT_INST_JOB_REQ_RCVRY] ON [dbo].[${TablePrefix}FIRED_TRIGGERS](SCHED_NAME, INSTANCE_NAME, REQUESTS_RECOVERY);
CREATE INDEX [IDX_${TablePrefix}FT_G_J] ON [dbo].[${TablePrefix}FIRED_TRIGGERS](SCHED_NAME, JOB_GROUP, JOB_NAME);
CREATE INDEX [IDX_${TablePrefix}FT_G_T] ON [dbo].[${TablePrefix}FIRED_TRIGGERS](SCHED_NAME, TRIGGER_GROUP, TRIGGER_NAME);
GO
Loading…
Cancel
Save