committed by
GitHub
49 changed files with 1932 additions and 31 deletions
@ -0,0 +1,315 @@ |
|||
-- basic script |
|||
|
|||
USE `${DataBase}`; |
|||
|
|||
CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` ( |
|||
`MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL, |
|||
CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER DATABASE CHARACTER SET utf8mb4; |
|||
|
|||
CREATE TABLE `Bookmarks` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`TenantId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Hash` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`Model` longtext CHARACTER SET utf8mb4 NOT NULL, |
|||
`ModelType` longtext CHARACTER SET utf8mb4 NOT NULL, |
|||
`ActivityType` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ActivityId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`WorkflowInstanceId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`CorrelationId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
CONSTRAINT `PK_Bookmarks` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE TABLE `WorkflowDefinitions` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`DefinitionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`TenantId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Name` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`DisplayName` longtext CHARACTER SET utf8mb4 NULL, |
|||
`Description` longtext CHARACTER SET utf8mb4 NULL, |
|||
`Version` int NOT NULL, |
|||
`IsSingleton` tinyint(1) NOT NULL, |
|||
`PersistenceBehavior` int NOT NULL, |
|||
`DeleteCompletedInstances` tinyint(1) NOT NULL, |
|||
`IsPublished` tinyint(1) NOT NULL, |
|||
`IsLatest` tinyint(1) NOT NULL, |
|||
`Tag` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Data` longtext CHARACTER SET utf8mb4 NULL, |
|||
CONSTRAINT `PK_WorkflowDefinitions` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE TABLE `WorkflowExecutionLogRecords` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`TenantId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`WorkflowInstanceId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ActivityId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ActivityType` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`Timestamp` datetime(6) NOT NULL, |
|||
`EventName` longtext CHARACTER SET utf8mb4 NULL, |
|||
`Message` longtext CHARACTER SET utf8mb4 NULL, |
|||
`Source` longtext CHARACTER SET utf8mb4 NULL, |
|||
`Data` longtext CHARACTER SET utf8mb4 NULL, |
|||
CONSTRAINT `PK_WorkflowExecutionLogRecords` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE TABLE `WorkflowInstances` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`DefinitionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`TenantId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Version` int NOT NULL, |
|||
`WorkflowStatus` int NOT NULL, |
|||
`CorrelationId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`ContextType` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`ContextId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Name` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`CreatedAt` datetime(6) NOT NULL, |
|||
`LastExecutedAt` datetime(6) NULL, |
|||
`FinishedAt` datetime(6) NULL, |
|||
`CancelledAt` datetime(6) NULL, |
|||
`FaultedAt` datetime(6) NULL, |
|||
`Data` longtext CHARACTER SET utf8mb4 NULL, |
|||
CONSTRAINT `PK_WorkflowInstances` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE INDEX `IX_Bookmark_ActivityId` ON `Bookmarks` (`ActivityId`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_ActivityType` ON `Bookmarks` (`ActivityType`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_ActivityType_TenantId_Hash` ON `Bookmarks` (`ActivityType`, `TenantId`, `Hash`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_CorrelationId` ON `Bookmarks` (`CorrelationId`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_Hash` ON `Bookmarks` (`Hash`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_Hash_CorrelationId_TenantId` ON `Bookmarks` (`Hash`, `CorrelationId`, `TenantId`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_TenantId` ON `Bookmarks` (`TenantId`); |
|||
|
|||
CREATE INDEX `IX_Bookmark_WorkflowInstanceId` ON `Bookmarks` (`WorkflowInstanceId`); |
|||
|
|||
CREATE UNIQUE INDEX `IX_WorkflowDefinition_DefinitionId_VersionId` ON `WorkflowDefinitions` (`DefinitionId`, `Version`); |
|||
|
|||
CREATE INDEX `IX_WorkflowDefinition_IsLatest` ON `WorkflowDefinitions` (`IsLatest`); |
|||
|
|||
CREATE INDEX `IX_WorkflowDefinition_IsPublished` ON `WorkflowDefinitions` (`IsPublished`); |
|||
|
|||
CREATE INDEX `IX_WorkflowDefinition_Name` ON `WorkflowDefinitions` (`Name`); |
|||
|
|||
CREATE INDEX `IX_WorkflowDefinition_Tag` ON `WorkflowDefinitions` (`Tag`); |
|||
|
|||
CREATE INDEX `IX_WorkflowDefinition_TenantId` ON `WorkflowDefinitions` (`TenantId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowDefinition_Version` ON `WorkflowDefinitions` (`Version`); |
|||
|
|||
CREATE INDEX `IX_WorkflowExecutionLogRecord_ActivityId` ON `WorkflowExecutionLogRecords` (`ActivityId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowExecutionLogRecord_ActivityType` ON `WorkflowExecutionLogRecords` (`ActivityType`); |
|||
|
|||
CREATE INDEX `IX_WorkflowExecutionLogRecord_TenantId` ON `WorkflowExecutionLogRecords` (`TenantId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowExecutionLogRecord_Timestamp` ON `WorkflowExecutionLogRecords` (`Timestamp`); |
|||
|
|||
CREATE INDEX `IX_WorkflowExecutionLogRecord_WorkflowInstanceId` ON `WorkflowExecutionLogRecords` (`WorkflowInstanceId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_ContextId` ON `WorkflowInstances` (`ContextId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_ContextType` ON `WorkflowInstances` (`ContextType`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_CorrelationId` ON `WorkflowInstances` (`CorrelationId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_CreatedAt` ON `WorkflowInstances` (`CreatedAt`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_DefinitionId` ON `WorkflowInstances` (`DefinitionId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_FaultedAt` ON `WorkflowInstances` (`FaultedAt`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_FinishedAt` ON `WorkflowInstances` (`FinishedAt`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_LastExecutedAt` ON `WorkflowInstances` (`LastExecutedAt`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_Name` ON `WorkflowInstances` (`Name`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_TenantId` ON `WorkflowInstances` (`TenantId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_WorkflowStatus` ON `WorkflowInstances` (`WorkflowStatus`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_WorkflowStatus_DefinitionId` ON `WorkflowInstances` (`WorkflowStatus`, `DefinitionId`); |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_WorkflowStatus_DefinitionId_Version` ON `WorkflowInstances` (`WorkflowStatus`, `DefinitionId`, `Version`); |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20210523093427_Initial', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER TABLE `WorkflowInstances` MODIFY COLUMN `CorrelationId` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT ''; |
|||
|
|||
ALTER TABLE `WorkflowInstances` ADD `LastExecutedActivityId` longtext CHARACTER SET utf8mb4 NULL; |
|||
|
|||
ALTER TABLE `WorkflowDefinitions` ADD `OutputStorageProviderName` longtext CHARACTER SET utf8mb4 NULL; |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20210611200027_Update21', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER TABLE `WorkflowDefinitions` DROP COLUMN `OutputStorageProviderName`; |
|||
|
|||
ALTER TABLE `WorkflowInstances` RENAME `WorkflowInstances`; |
|||
|
|||
ALTER TABLE `WorkflowExecutionLogRecords` RENAME `WorkflowExecutionLogRecords`; |
|||
|
|||
ALTER TABLE `WorkflowDefinitions` RENAME `WorkflowDefinitions`; |
|||
|
|||
ALTER TABLE `Bookmarks` RENAME `Bookmarks`; |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20210923112211_Update23', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER TABLE `WorkflowInstances` ADD `DefinitionVersionId` longtext CHARACTER SET utf8mb4 NOT NULL; |
|||
|
|||
ALTER TABLE `Bookmarks` MODIFY COLUMN `CorrelationId` varchar(255) CHARACTER SET utf8mb4 NOT NULL DEFAULT ''; |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20211215100204_Update24', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER TABLE `WorkflowInstances` MODIFY COLUMN `DefinitionVersionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL; |
|||
|
|||
CREATE INDEX `IX_WorkflowInstance_DefinitionVersionId` ON `WorkflowInstances` (`DefinitionVersionId`); |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20220120170050_Update241', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
CREATE TABLE `Triggers` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`TenantId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Hash` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`Model` longtext CHARACTER SET utf8mb4 NOT NULL, |
|||
`ModelType` longtext CHARACTER SET utf8mb4 NOT NULL, |
|||
`ActivityType` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ActivityId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`WorkflowDefinitionId` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
CONSTRAINT `PK_Triggers` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE INDEX `IX_Trigger_ActivityId` ON `Triggers` (`ActivityId`); |
|||
|
|||
CREATE INDEX `IX_Trigger_ActivityType` ON `Triggers` (`ActivityType`); |
|||
|
|||
CREATE INDEX `IX_Trigger_ActivityType_TenantId_Hash` ON `Triggers` (`ActivityType`, `TenantId`, `Hash`); |
|||
|
|||
CREATE INDEX `IX_Trigger_Hash` ON `Triggers` (`Hash`); |
|||
|
|||
CREATE INDEX `IX_Trigger_Hash_TenantId` ON `Triggers` (`Hash`, `TenantId`); |
|||
|
|||
CREATE INDEX `IX_Trigger_TenantId` ON `Triggers` (`TenantId`); |
|||
|
|||
CREATE INDEX `IX_Trigger_WorkflowDefinitionId` ON `Triggers` (`WorkflowDefinitionId`); |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20220120204150_Update25', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER TABLE `WorkflowDefinitions` ADD `CreatedAt` datetime(6) NOT NULL DEFAULT '0001-01-01 00:00:00'; |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20220512203646_Update28', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
|
|||
-- webhooks |
|||
|
|||
CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` ( |
|||
`MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL, |
|||
CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER DATABASE CHARACTER SET utf8mb4; |
|||
|
|||
CREATE TABLE `WebhookDefinitions` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`TenantId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Name` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`Path` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`Description` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`PayloadTypeName` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`IsEnabled` tinyint(1) NOT NULL, |
|||
CONSTRAINT `PK_WebhookDefinitions` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE INDEX `IX_WebhookDefinition_Description` ON `WebhookDefinitions` (`Description`); |
|||
|
|||
CREATE INDEX `IX_WebhookDefinition_IsEnabled` ON `WebhookDefinitions` (`IsEnabled`); |
|||
|
|||
CREATE INDEX `IX_WebhookDefinition_Name` ON `WebhookDefinitions` (`Name`); |
|||
|
|||
CREATE INDEX `IX_WebhookDefinition_Path` ON `WebhookDefinitions` (`Path`); |
|||
|
|||
CREATE INDEX `IX_WebhookDefinition_PayloadTypeName` ON `WebhookDefinitions` (`PayloadTypeName`); |
|||
|
|||
CREATE INDEX `IX_WebhookDefinition_TenantId` ON `WebhookDefinitions` (`TenantId`); |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20210604065041_Initial', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
|
|||
|
|||
-- workflow-settings |
|||
|
|||
CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` ( |
|||
`MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL, |
|||
`ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL, |
|||
CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
START TRANSACTION; |
|||
|
|||
ALTER DATABASE CHARACTER SET utf8mb4; |
|||
|
|||
CREATE TABLE `WorkflowSettings` ( |
|||
`Id` varchar(255) CHARACTER SET utf8mb4 NOT NULL, |
|||
`WorkflowBlueprintId` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Key` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
`Value` varchar(255) CHARACTER SET utf8mb4 NULL, |
|||
CONSTRAINT `PK_WorkflowSettings` PRIMARY KEY (`Id`) |
|||
) CHARACTER SET utf8mb4; |
|||
|
|||
CREATE INDEX `IX_WorkflowSetting_Key` ON `WorkflowSettings` (`Key`); |
|||
|
|||
CREATE INDEX `IX_WorkflowSetting_Value` ON `WorkflowSettings` (`Value`); |
|||
|
|||
CREATE INDEX `IX_WorkflowSetting_WorkflowBlueprintId` ON `WorkflowSettings` (`WorkflowBlueprintId`); |
|||
|
|||
INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) |
|||
VALUES ('20210730112043_Initial', '5.0.10'); |
|||
|
|||
COMMIT; |
|||
@ -0,0 +1,130 @@ |
|||
using LINGYUN.Abp.Elsa.EntityFrameworkCore.Migrations; |
|||
using Microsoft.Extensions.FileProviders; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using MySqlConnector; |
|||
using System; |
|||
using System.Data; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.EntityFrameworkCore.MySql.Migrations; |
|||
|
|||
[Dependency(ReplaceServices = true)] |
|||
public class MySqlElsaDataBaseInstaller : IElsaDataBaseInstaller, ITransientDependency |
|||
{ |
|||
public ILogger<MySqlElsaDataBaseInstaller> Logger { protected get; set; } |
|||
|
|||
private readonly IVirtualFileProvider _virtualFileProvider; |
|||
private readonly IConnectionStringResolver _connectionStringResolver; |
|||
|
|||
public MySqlElsaDataBaseInstaller( |
|||
IVirtualFileProvider virtualFileProvider, |
|||
IConnectionStringResolver connectionStringResolver) |
|||
{ |
|||
_virtualFileProvider = virtualFileProvider; |
|||
_connectionStringResolver = connectionStringResolver; |
|||
|
|||
Logger = NullLogger<MySqlElsaDataBaseInstaller>.Instance; |
|||
} |
|||
|
|||
public async virtual Task InstallAsync() |
|||
{ |
|||
var connectionString = await _connectionStringResolver.ResolveAsync("Workflow"); |
|||
if (connectionString.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogWarning("Please configure the `Workflow` database connection string Workflow!"); |
|||
throw new ArgumentNullException(nameof(connectionString)); |
|||
} |
|||
|
|||
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}` database has already exists."); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
var sqlScript = await GetInitSqlScript(); |
|||
|
|||
// USE `${DataBase}` -> USE `Workflow`;;
|
|||
sqlScript = sqlScript.ReplaceFirst("${DataBase}", dataBaseName); |
|||
|
|||
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/Elsa/EntityFrameworkCore/MySql/Migrations/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; |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Elsa.EntityFrameworkCore.Migrations; |
|||
|
|||
public interface IElsaDataBaseInstaller |
|||
{ |
|||
Task InstallAsync(); |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
using Volo.Abp.Auditing; |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public class TenantConnectionStringCheckInput |
|||
{ |
|||
[Required] |
|||
public string Provider { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
[Required] |
|||
[DisableAuditing] |
|||
[DynamicStringLength(typeof(TenantConnectionStringConsts), nameof(TenantConnectionStringConsts.MaxValueLength))] |
|||
public string ConnectionString { get; set; } |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public class TenantConnectionStringCheckResultDto |
|||
{ |
|||
public bool Connected { get; set; } |
|||
public TenantConnectionStringCheckResultDto() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public TenantConnectionStringCheckResultDto(bool connected) |
|||
{ |
|||
Connected = connected; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,28 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net9.0</TargetFramework> |
|||
<AssemblyName>LINGYUN.Abp.Saas.DbChecker</AssemblyName> |
|||
<PackageId>LINGYUN.Abp.Saas.DbChecker</PackageId> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="MySqlConnector" /> |
|||
<PackageReference Include="Oracle.ManagedDataAccess.Core" /> |
|||
<PackageReference Include="Npgsql" /> |
|||
<PackageReference Include="Microsoft.Data.SqlClient" /> |
|||
<PackageReference Include="Microsoft.Data.Sqlite.Core" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.Saas.Domain\LINGYUN.Abp.Saas.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,24 @@ |
|||
using LINGYUN.Abp.Saas.MySql; |
|||
using LINGYUN.Abp.Saas.Oracle; |
|||
using LINGYUN.Abp.Saas.PostgreSql; |
|||
using LINGYUN.Abp.Saas.Sqlite; |
|||
using LINGYUN.Abp.Saas.SqlServer; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.Saas; |
|||
|
|||
[DependsOn(typeof(AbpSaasDomainModule))] |
|||
public class AbpSaasDbCheckerModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpSaasConnectionStringCheckOptions>(options => |
|||
{ |
|||
options.ConnectionStringCheckers["mysql"] = new MySqlConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["oracle"] = new OracleConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["postgres"] = new NpgsqlConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["sqlite"] = new SqliteConnectionStringChecker(); |
|||
options.ConnectionStringCheckers["sqlserver"] = new SqlServerConnectionStringChecker(); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using MySqlConnector; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Saas.MySql; |
|||
|
|||
public class MySqlConnectionStringChecker : IDataBaseConnectionStringChecker |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new MySqlConnectionStringBuilder(connectionString) |
|||
{ |
|||
ConnectionLifeTime = 1 |
|||
}; |
|||
|
|||
var oldDatabaseName = connString.Database; |
|||
connString.Database = "mysql"; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new MySqlConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
await conn.ChangeDatabaseAsync(oldDatabaseName); |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Oracle.ManagedDataAccess.Client; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Oracle; |
|||
|
|||
public class OracleConnectionStringChecker : IDataBaseConnectionStringChecker |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new OracleConnectionStringBuilder(connectionString) |
|||
{ |
|||
ConnectionTimeout = 1 |
|||
}; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new OracleConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Npgsql; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Saas.PostgreSql; |
|||
|
|||
public class NpgsqlConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new NpgsqlConnectionStringBuilder(connectionString) |
|||
{ |
|||
Timeout = 1 |
|||
}; |
|||
|
|||
var oldDatabaseName = connString.Database; |
|||
connString.Database = "postgres"; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new NpgsqlConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
await conn.ChangeDatabaseAsync(oldDatabaseName!); |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Microsoft.Data.SqlClient; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Saas.SqlServer; |
|||
|
|||
public class SqlServerConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
var connString = new SqlConnectionStringBuilder(connectionString) |
|||
{ |
|||
ConnectTimeout = 1 |
|||
}; |
|||
|
|||
var oldDatabaseName = connString.InitialCatalog; |
|||
connString.InitialCatalog = "master"; |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new SqlConnection(connString.ConnectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
await conn.ChangeDatabaseAsync(oldDatabaseName); |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using Microsoft.Data.Sqlite; |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Sqlite; |
|||
|
|||
public class SqliteConnectionStringChecker : IDataBaseConnectionStringChecker, ITransientDependency |
|||
{ |
|||
public virtual async Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString) |
|||
{ |
|||
var result = new DataBaseConnectionStringCheckResult(); |
|||
|
|||
try |
|||
{ |
|||
await using var conn = new SqliteConnection(connectionString); |
|||
await conn.OpenAsync(); |
|||
result.Connected = true; |
|||
result.DatabaseExists = true; |
|||
|
|||
await conn.CloseAsync(); |
|||
|
|||
return result; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
result.Error = e; |
|||
return result; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,15 @@ |
|||
using LINGYUN.Abp.Saas.Tenants; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Abp.Saas; |
|||
|
|||
public class AbpSaasConnectionStringCheckOptions |
|||
{ |
|||
public IDictionary<string, IDataBaseConnectionStringChecker> ConnectionStringCheckers { get; } |
|||
|
|||
public AbpSaasConnectionStringCheckOptions() |
|||
{ |
|||
ConnectionStringCheckers = new Dictionary<string, IDataBaseConnectionStringChecker>(StringComparer.InvariantCultureIgnoreCase); |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System; |
|||
using Volo.Abp.Data; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public class DataBaseConnectionStringCheckResult : AbpConnectionStringCheckResult |
|||
{ |
|||
public Exception Error { get; set; } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.Saas.Tenants; |
|||
|
|||
public interface IDataBaseConnectionStringChecker |
|||
{ |
|||
Task<DataBaseConnectionStringCheckResult> CheckAsync(string connectionString); |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -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> |
|||
@ -0,0 +1,35 @@ |
|||
using Microsoft.Extensions.Configuration; |
|||
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) |
|||
{ |
|||
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>(); |
|||
if (configuration.GetValue("Quartz:UsePersistentStore", false)) |
|||
{ |
|||
// 初始化 Quartz Mysql 数据库
|
|||
await context.ServiceProvider |
|||
.GetRequiredService<QuartzMySqlInstaller>() |
|||
.InstallAsync(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
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.DependencyInjection; |
|||
using Volo.Abp.Quartz; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
using static Quartz.SchedulerBuilder; |
|||
|
|||
namespace LINGYUN.Abp.Quartz.MySqlInstaller; |
|||
|
|||
public class QuartzMySqlInstaller : ITransientDependency |
|||
{ |
|||
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; |
|||
} |
|||
} |
|||
@ -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; |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -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> |
|||
@ -0,0 +1,35 @@ |
|||
using Microsoft.Extensions.Configuration; |
|||
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) |
|||
{ |
|||
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>(); |
|||
if (configuration.GetValue("Quartz:UsePersistentStore", false)) |
|||
{ |
|||
// 初始化 Quartz SqlServer 数据库
|
|||
await context.ServiceProvider |
|||
.GetRequiredService<QuartzSqlServerInstaller>() |
|||
.InstallAsync(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,137 @@ |
|||
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.DependencyInjection; |
|||
using Volo.Abp.Quartz; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
using static Quartz.SchedulerBuilder; |
|||
|
|||
namespace LINGYUN.Abp.Quartz.SqlServerInstaller; |
|||
|
|||
public class QuartzSqlServerInstaller : ITransientDependency |
|||
{ |
|||
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; |
|||
} |
|||
} |
|||
@ -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…
Reference in new issue